Production Deployment
===================================
.. attention::
This is a complex deployment process that requires advanced knowledge of `Linux `__, `Docker `__, `Kubernetes `__,
`Helm `__, `Terraform `__, `AWS cloud infrastructure `__, `Python `__-`Django `__ applications, and `GitHub Actions `__.
Consider using one of our recommended `hosting partners `__, or a certified installation expert.
.. note::
Before beginning production deployment, you should have already installed
your production AWS cloud infrastructure using the `Smarter Official Terraform Modules `__.
Smarter runs natively on Kubernetes using `spot-priced `__
compute instances. This is a cost-effective, resilient, and
scalable architecture that requires minimal maintenance once deployed. It
natively handles multiple environments (alpha, beta, next, prod)
for the same installation, maintaining clean separation of resources and
data between environments. It also natively handles multiple installations of
Smarter (ie multiple EKS clusters) within the same AWS account.
Production deployment involves the following steps:
1. Build AWS Infrastructure using the `Smarter Official Terraform Modules `__.
2. Build and deploy the Smarter Chat ReactJS component to the CDN using `Smarter Chat `__ and `Smarter Web Integration Example `__.
3. Deploy the Smarter Platform to your Kubernetes cluster using the `Official Smarter Helm chart `__.
A modest amount of advance planning and an understanding of some basic organizational principles within Smarter will save you time and heartache.
Smarter's fundamental identification and organizational units are as follows:
.. list-table::
:widths: 20 80
* - **root_domain**
- This is the root domain that you will use for your Smarter deployment. For example,
if you want to access your Smarter instance at "platform.example.com", then your root domain
would be "example.com". This value is used in both Terraform and Helm configurations,
and it affects the naming of various resources such as DNS records and Hosted Zones.
* - **platform_name**
- Default is "smarter". Ensure that this matches in both Terraform and Helm configurations.
Within the Smarter Platform application, the platform_name is derived from the root_domain by taking the first segment.
For example, if your root domain is "example.com", then the platform_name will be "example".
* - **shared_resource_identifier**
- Default is "platform". Ensure that this matches in both Terraform and Helm configurations.
Consider using a unique identifier such as your organization's domain name or abbreviation
to avoid naming ambiguities with other Smarter deployments in your AWS account.
* - **Environment**
- One of "alpha", "beta", "next", or "prod". This is managed entirely inside the application, but affects the
names of cloud resources including but not limited to DNS records and Hosted Zones that are created
as part of normal platform operation.
* - **platform_region**
- Default is "us". Used exclusively inside of Terraform as part of naming high-level resources such
as the EKS cluster, S3 buckets, SES resources, and more. Several environment variables in Helm are based on this value.
These four organizational units are combined in various ways to create higher-level naming conventions for both cloud resources as
well as application-level resources. Some examples:
- Kubernetes namespaces are named using the convention
``{platform_name}-{shared_resource_identifier}-{environment}``
which by default would be 'smarter-platform-prod'.
- S3 buckets are named using the convention
``{environment}.{shared_resource_identifier}.{root_domain}``
which by default would be 'alpha.platform.example.com'.
- EKS clusters are named using the convention
``{platform_name}-{shared_resource_identifier}-{platform_region}-{{unique_id}}``
which by default would be 'smarter-platform-us-{{unique_id}}'.
- k8s namespaces are named using the convention
``{platform_name}-{shared_resource_identifier}-{environment}``
which by default would be 'smarter-platform-prod'.
- IAM roles are prefixed with
``{platform_name}-{shared_resource_identifier}-{platform_region}``
which by default would be 'smarter-platform-us'.
Within the Smarter application itself, these organizational units are combined to create higher-level organizational units. Examples:
- environment_namespaces are named using the convention
``{platform_name}-{shared_resource_identifier}-{environment}``
which by default would be 'smarter-platform-prod'.
- environment_platform_domain is named using the convention
``{environment}.{shared_resource_identifier}.{root_domain}``
which by default would be 'alpha.platform.example.com'.
- CDN domains are named using the convention
``cdn.{environment}.{shared_resource_identifier}.{root_domain}``
which by default would be 'cdn.alpha.platform.example.com'.
- API domains are named using the convention
``{environment}.api.{shared_resource_identifier}.{root_domain}``
which by default would be 'alpha.api.platform.example.com'.
**Example Kubernetes Deployment**
.. figure:: https://cdn.smarter.sh/images/example-kubernetes-deployment.png
:alt: Example Kubernetes Deployment
:align: center
:width: 100%
:class: img-bottom-margin
I. Infrastructure
-------------------
The entire AWS infrastructure build is fully automated using Terraform and Terragrunt
scripts. You should begin by reviewing the following documentation:
- README at `Smarter Infrastructure `__.
- `Makefile `__. This
Makefile provides working shortcuts for all major operations. You should at least cursorily review
these in order to ensure that you understand the basic intention of the Terraform scripts.
- `.env.example `__.
The Terraform scripts in this repo use environment variables for all configuration values.
You should not need to fork nor modify the code in this repo. The Makefile provides a shortcut
for getting this setup correctly.
Note that this repo uses Terragrunt, a higher level wrapper around Terraform that provides
an ability to manage multiple environments and multiple deployments with the same codebase.
Make sure that you understand the basic principles of how Terragrunt works, and how it is
being used in this repo, before proceeding.
.. warning::
Do not attempt to circumvent the official Terraform scripts. The
cloud infrastructure is complex and has many interdependencies that would
be difficult if not impossible to manage manually. Additionally, the
Terraform scripts create a detailed set of resource tags that are the
sole means of effectively tracking these resources inside your AWS account
once they've been created.
II. ReactJS Component
----------------------
The Chat functionality in the Smarter Prompt Engineer Workbench is delivered
as a ReactJS component served from a CDN at runtime. You will need to build
and deploy this component separately from the main Smarter Platform application.
The source code of this component is mature and stable, and generally
only changes in response to regular version bumps of a minimal set of
dependencies. This component can safely run for months (or even years)
without needing to be updated.
.. note::
The ReactJS component is designed to work generically with any web application.
The Smarter Project manages `@smarter.sh/ui-chat `__,
an npm package that is published to the npm registry directly from the source code
located in `smarter-sh/smarter-chat `__.
While the @smarter.sh/ui-chat npm component is not used as part of this deployment process per se,
it bears mentioning that it **can** be seamlessly integrated into any web architecture
using the patterns described below in `smarter-sh/web-integration-example `__,
including Wordpress, Joomla, Drupal, Microsoft Sharepoint, .Net, Salesforce, Squarespace,
Wix, Shopify, Angular, HubSpot, custom React applications, and more.
The Smarter Web Console is just one arbitrary example of how to do this.
Setting this up for production is a 2-step process.
First, you will use `smarter-sh/smarter-chat `__
to build and deploy the ReactJS component to your CDN (ie 'cdn.platform.example.com/ui-chat')
which should have been automatically created for you by `smarter-sh/smarter-infrastructure `__.
Afterwards, you will use `smarter-sh/web-integration-example `__
to configure and deploy the app loader that Smarter uses
to actually load the ReactJS component into the Web Console DOM.
The app loader is a small JavaScript IIFE that is referenced in the Django template
for the Web Console Prompt Engineer Workbench. It is served from the same CDN,
and is responsible for adding elements to the web console DOM for the
ReactJS component js and css build bundles.
See the script tag at the very bottom of the Django template below.
.. literalinclude:: ../../../smarter/smarter/templates/prompt/workbench.html
:language: html
The rendered html template will include a script tag similar to the following
that references the app-loader.js script.
.. code-block:: html
The IIFE in turn is responsible for adding these two elements to the DOM
at run-time:
.. code-block:: html
The js bundle, itself an IIFE, will initiate the ReactJS bootstrap process to render
the Chat app into the DOM element with the id ``{{ chatapp_workbench.div_id }}`` which
by default will resolve to ``"smarter-sh-v1-ui-chat-root"``.
This is the root div for the ReactJS app,
and is where all of the React components will be rendered as children.
This div is rendered by the Django template engine from the template above,
and all of its attributes are generated from the context variable created in
`ChatAppWorkbenchView.dispatch() `__. See below.
.. literalinclude:: ../../../smarter/smarter/apps/prompt/views.py
:language: python
:lines: 750-775
The rendered div will look something like the following.
.. code-block:: html
.. important::
The attribute value of ``id`` ('smarter-sh-v1-ui-chat-root' by default) must agree with the value of
REACT_ROOT_ELEMENT_ID in `web-integration-example/src/shared/constants.js `__
('smarter-sh-v1-ui-chat-root' unless you have modified it) as this is the
'root' element id that the IIFE in the React bundle will look for.
Smarter Chat Additional documentation:
- README at `smarter-sh/smarter-chat `__.
- `Makefile `__.
This Makefile provides working shortcuts for all major operations. Importantly,
The deployment process is fully automated and can be completed with a single command.
- `.env.example `__.
Smarter Web Integration Example Additional documentation:
- README at `smarter-sh/web-integration-example `__.
- `Makefile `__.
This Makefile provides working shortcuts for all major operations. Importantly,
The deployment process is fully automated and can be completed with a single command.
- `.env.example `__.
.. raw:: html
Smarter Prompt Engineering Workbench Demo
III. Smarter Platform Application
-----------------------------------
The Smarter Platform application is deployed to Kubernetes using the `official Helm chart `__.
The application itself consists of a Python-Django backend that supports an
API and a Web Console frontend. This single code base is deployed to Kubernetes as
an application server and also as a Celery worker and a Celery Beat worker.
The application follows 12-factor app principles and is designed to be horizontally
scalable and resilient to failure.
In most cases, you can deploy the Smarter Platform application using the official Helm
chart with minimal configuration. However, you can optionally build and deploy
from source, though this is out of the scope of this documentation.
Begin by reviewing the following documentation:
- README at `Official Smarter Helm chart `__.
- `Values.yaml `__.
This file contains the comprehensive set of configuration values for the Helm chart. These
cover not only configuration of the application itself, but also all backing services and
deployment options. Note that there are multiple options for the Database backend, including
pod-based Mysql and MariaDB, and remote AWS RDS.
- (Optional) `Source code `__. You might find some
of the source code helpful for understanding how to configure the application. Of interest
are the `Django settings files `__,
the `Smarter Settings module `__,
the `Smarter Settings documentation <../smarter-framework/smarter-settings.html>`__,
the `Python requirements `__, and the
`Dockerfile `__.
.. important::
1. You will need to create your own Deployment workflow. You can use the `Smarter GitHub Actions Deployment workflow `__
and `Smarter GitHub Deployment Action `__
in the official Smarter repo as a reference, but you should not attempt to use it directly unless you have forked
the Smarter repo. The deployment workflow depends on a number GitHub Secrets that you must configure in your own GitHub repository.
If possible, see `Smarter Settings - Secrets `__.
2. You will need an AWS IAM key-pair with sufficient permissions to deploy the application to your Kubernetes cluster.
At a minimum, this key-pair will need complete control of the EKS service, in addition to permissions to create and
manage the various resources that the application depends on such as EC2 instances, EBS volumes, S3 buckets,
SES resources, and more.
Trouble Shooting
------------------
Permissions and naming are the two most common sources of deployment-related problems. Consider the example
Kubernetes Ingress manifest below. It contains eleven references, created by either of Terraform or
the Smarter Platform application itself. These names have to agree, and must be able to "hand shake" as necessary
between Kubernetes and the Smarter Platform application.
.. figure:: https://cdn.smarter.sh/images/naming-example.png
:alt: Example Kubernetes Ingress Manifest
:align: center
:width: 100%
:class: img-bottom-margin