Kubernetes
Kubernetes is an open-source platform designed to automate deploying, scaling, and operating containerized applications. It provides a robust framework for running distributed systems resiliently, handling scaling and failover, and managing application updates seamlessly. Kubernetes has gained popularity because it enables organizations to efficiently manage complex applications at scale. It improves resource utilization, and supports cloud-native development practices.
Kubernetes Helper Classes
The Smarter Framework provides helper classes to facilitate interaction with Kubernetes clusters, primarily via the Kubernetes API vis a vis kubectl, the command-line tool for Kubernetes.
from smarter.common.helpers.k8s_helpers import kubernetes_helper
with open("k8s/ingress.yaml.tpl", encoding="utf-8") as ingress_template:
template = Template(ingress_template.read())
manifest = template.substitute(ingress_values)
kubernetes_helper.apply_manifest(manifest)
Kubernetes Helper Class Technical Reference
Helm Chart
The Smarter Framework includes a Helm chart for deploying Smarter on Kubernetes. The chart is published at ArtifactHUB - Smarter.
Installation
helm repo add project-smarter https://project-smarter.github.io/helm-charts/
helm install my-release project-smarter/smarter -f my-values.yaml
Examples
# Example values.yaml
app:
replicaCount: 2
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "4Gi"
Links
Configuration
The chart can be configured using the following values:
# ==============================================================================
# Smarter Platform - Helm Chart Values
# ==============================================================================
#
# Default configuration values for the Smarter Platform Helm chart.
#
# This file contains all configurable parameters for deploying the Smarter
# application stack including:
# - Django application server
# - Celery workers and beat scheduler
# - Redis cache
# - Database connections
# - Third-party API integrations
# - OAuth providers
#
# IMPORTANT: Replace all "SET-ME-IN-helm/charts/smarter/values.yaml" values
# with actual credentials before deployment.
#
# Usage:
# helm install smarter . -f values.yaml
# helm upgrade smarter . -f values.yaml
#
# Documentation: https://github.com/smarter-sh/smarter
#
# Note:
# The app.kubernetes.io/application-group label is used to identify pods to Calico
# and kubernetes_network_policy_v1 resources in order to allow pod-level communication
# between backing services. If the label is missing then the network policies are
# assured to PREVENT communication.
# ==============================================================================
# -----------------------------------------------------------------------------
## @param env Environment variables for the Smarter application. If set, these
## are consumed and set automatically in the Smarter app deployment templates.
# -----------------------------------------------------------------------------
env:
AUTHENTICATION_BACKENDS: "social_core.backends.google.GoogleOAuth2,social_core.backends.github.GithubOAuth2,django.contrib.auth.backends.ModelBackend"
AWS_ACCESS_KEY_ID: "SET-ME-IN-helm/charts/smarter/values.yaml"
AWS_REGION: "us-east-1"
AWS_SECRET_ACCESS_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
CACHES_LOCATION: "SET-ME-IN-helm/charts/smarter/values.yaml"
CELERY_BROKER_URL: "SET-ME-IN-helm/charts/smarter/values.yaml"
CELERY_RESULT_BACKEND: "SET-ME-IN-helm/charts/smarter/values.yaml"
DEBUG_MODE: "false"
DJANGO_SETTINGS_MODULE: "smarter.settings.production"
DOCKERHUB_PAT: "SET-ME-IN-helm/charts/smarter/values.yaml"
DOCKERHUB_USERNAME: "SET-ME-IN-helm/charts/smarter/values.yaml"
DUMP_DEFAULTS: "False"
ENVIRONMENT: "prod"
NAMESPACE: "smarter-platform-prod"
SECRET_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_ADMIN_EMAIL: "admin@example.com"
SMARTER_ADMIN_PASSWORD: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_ADMIN_USERNAME: "admin"
SMARTER_ANTHROPIC_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_AWS_EKS_CLUSTER_NAME: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_AWS_RDS_DB_INSTANCE_IDENTIFIER: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_ADDRESS1: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_ADDRESS2: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_CITY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_STATE: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_POSTAL_CODE: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_COUNTRY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_CURRENCY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_TIMEZONE: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_CONTACT_URL: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_CORPORATE_NAME: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_SUPPORT_EMAIL: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_SUPPORT_HOURS: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_BRANDING_SUPPORT_PHONE_NUMBER: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_CACHE_EXPIRATION: "60"
SMARTER_CHAT_CACHE_EXPIRATION: "5"
SMARTER_COHERE_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_CHATBOT_CACHE_EXPIRATION: "300"
SMARTER_CHATBOT_MAX_RETURNED_HISTORY: "25"
SMARTER_CHATBOT_TASKS_CELERY_MAX_RETRIES: "3"
SMARTER_CHATBOT_TASKS_CELERY_RETRY_BACKOFF: "True"
SMARTER_CHATBOT_TASKS_CELERY_TASK_QUEUE: "default_celery_task_queue"
SMARTER_CHATBOT_TASKS_CREATE_DNS_RECORD: "True"
SMARTER_CHATBOT_TASKS_CREATE_INGRESS_MANIFEST: "True"
SMARTER_CHATBOT_TASKS_DEFAULT_TTL: "600"
SMARTER_COHERE_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_EMAIL_ADMIN: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_FERNET_ENCRYPTION_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_FIREWORKS_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_GEMINI_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_GOOGLE_MAPS_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_GOOGLE_SERVICE_ACCOUNT_B64: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_INTERNAL_IP_PREFIXES: "192.168."
SMARTER_LLAMA_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_LOGIN_URL: "https://platform.example.com/login/"
SMARTER_LOGO: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MAILCHIMP_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MAILCHIMP_LIST_ID: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MARKETING_SITE_URL: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MISTRAL_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MYSQL_DATABASE: "smarter_platform_prod"
SMARTER_MYSQL_HOST: "mysql"
SMARTER_MYSQL_PASSWORD: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MYSQL_PORT: "3306"
SMARTER_MYSQL_ROOT_PASSWORD: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MYSQL_ROOT_USERNAME: "root"
SMARTER_MYSQL_TEST_DATABASE_PASSWORD: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_MYSQL_TEST_DATABASE_SECRET_NAME: "smarter_test_db"
SMARTER_MYSQL_USER: "smarter_platform_prod"
SMARTER_NAMESPACE: "smarter-platform-alpha"
SMARTER_OPENAI_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_PINECONE_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SUBDOMAIN: "platform"
SMARTER_PINECONE_ENVIRONMENT: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_PLUGIN_MAX_DATA_RESULTS: "50"
SMARTER_REACTJS_APP_LOADER_PATH: "/ui-chat/app-loader.js"
SMARTER_ROOT_DOMAIN: "example.com"
SMARTER_S3_BUCKET: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SENSITIVE_FILES_AMNESTY_PATTERNS: "^/dashboard/account/password-reset-link/[^/]+/[^/]+/$,^/api(/.*)?$,^/admin(/.*)?$,^/plugin(/.*)?$,^/docs/manifest(/.*)?$,^/docs/json-schema(/.*)?$,.*stackademy.*,^/\\.well-known/acme-challenge(/.*)?$"
SMARTER_SETTINGS_OUTPUT: "false"
SMARTER_SMTP_FROM_EMAIL: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SMTP_PASSWORD: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SMTP_SENDER: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SMTP_USERNAME: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SOCIAL_AUTH_GITHUB_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SOCIAL_AUTH_GITHUB_SECRET: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SOCIAL_AUTH_GOOGLE_OAUTH2_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SOCIAL_AUTH_LINKEDIN_OAUTH2_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_SOCIAL_AUTH_LINKEDIN_OAUTH2_SECRET: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMARTER_TOGETHERAI_API_KEY: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMTP_HOST: "SET-ME-IN-helm/charts/smarter/values.yaml"
SMTP_PORT: "587"
SMTP_USE_SSL: "false"
SMTP_USE_TLS: "true"
# -----------------------------------------------------------------------------
# Global Configuration
# -----------------------------------------------------------------------------
global:
appName: smarter
image:
pullPolicy: Always
repository: lpm0073/smarter
tag: v0.14.0-alpha.54-alpha.53-alpha.52-alpha.51-alpha.50-alpha.49-alpha.48-alpha.47-alpha.46-alpha.45-alpha.44-alpha.43-alpha.42-alpha.41-alpha.40-alpha.39-alpha.38-alpha.37-alpha.36-alpha.35-alpha.34-alpha.33-alpha.32-alpha.31-alpha.30-alpha.29-alpha.28-alpha.27-alpha.26-alpha.25-alpha.24-alpha.23-alpha.22-alpha.21-alpha.20-alpha.19-alpha.18-alpha.17-alpha.16-alpha.15-alpha.14-alpha.13-alpha.12-alpha.11-alpha.10-alpha.9-alpha.8-alpha.7-alpha.6-alpha.5-alpha.4-alpha.3-alpha.2-alpha.1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: node-group
operator: In
values:
- smarter
defaultStorageClass: gp3
imagePullSecrets:
- name: dockerhub-secret
tolerations:
- key: "node-group"
operator: "Equal"
value: "smarter"
effect: "NoSchedule"
# -----------------------------------------------------------------------------
# Smarter Application Configuration
# -----------------------------------------------------------------------------
app:
replicaCount: 2
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "4Gi"
extraVolumeMounts: []
names:
mysqlName: mysql
mariadbName: mariadb
service:
port: 8000
targetPort: 8000
worker:
replicaCount: 1
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "2Gi"
beat:
replicaCount: 1
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "1Gi"
database:
type: mysql # Options: mysql, mariadb, external
## @param deployTimestamp Deployment timestamp for forcing pod restarts
deployTimestamp: ""
deployment:
containerPort: 8000
# -----------------------------------------------------------------------------
# Horizontal Pod Autoscaler Configuration
# ----------------------------------------------------------------------------
hpa:
minReplicas: 3
maxReplicas: 25
targetCPUUtilizationPercentage: 75
targetMemoryUtilizationPercentage: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 60
selectPolicy: Max
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
selectPolicy: Min
policies:
- type: Percent
value: 100
periodSeconds: 60
# -----------------------------------------------------------------------------
# Backing Services Configuration
# -----------------------------------------------------------------------------
databaseScheduledBackup:
enabled: true
schedule: "0 2 * * *" # Every day at 2am UTC
externalDatabase:
host: "" # Will use .Values.env.SMARTER_MYSQL_HOST if empty
port: 3306 # Will use .Values.env.SMARTER_MYSQL_PORT if empty
database: "" # Will use .Values.env.SMARTER_MYSQL_DATABASE if empty
username: "" # Will use .Values.env.SMARTER_MYSQL_USER if empty
password: "" # Will use .Values.env.SMARTER_MYSQL_PASSWORD if empty
mysql:
enabled: false
fullnameOverride: "smarter-mysql"
containerSecurityContext:
enabled: true
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
image:
pullPolicy: Always
initdbScripts: {}
livenessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
nodeSelector: {}
persistence:
enabled: true
size: 8Gi
storageClassName: "gp3"
accessModes:
- ReadWriteOnce
podSecurityContext:
enabled: true
fsGroup: 1001
resources:
requests:
memory: "1Gi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "1"
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
mariadb:
enabled: true
primary:
podLabels:
app.kubernetes.io/application-group: "{{ .Values.global.appName }}"
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: 2
memory: 4Gi
image:
pullPolicy: Always
livenessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
nodeSelector: {}
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
persistence:
enabled: true
size: 8Gi
storageClass: "gp3"
accessModes:
- ReadWriteOnce
# -----------------------------------------------------------------------------
# Redis Configuration
# -----------------------------------------------------------------------------
redis:
enabled: true
external:
host: ""
port: 6379
password: ""
fullnameOverride: "smarter-redis"
auth:
enabled: true
password: "smarter"
architecture: standalone
master:
podLabels:
app.kubernetes.io/application-group: "{{ .Values.global.appName }}"
containerSecurityContext:
enabled: true
persistence:
enabled: true
size: 10Gi
storageClass: gp3
podSecurityContext:
enabled: true
resources:
requests:
cpu: "250m"
memory: "2Gi"
limits:
cpu: "1"
memory: "4Gi"
service:
headless:
sessionAffinity: None
replica:
podLabels:
app.kubernetes.io/application-group: "{{ .Values.global.appName }}"
# ----------------------------------------------------------------------------
# Monitoring Components
# Enable/disable and configure Prometheus, Grafana, and Loki
# ----------------------------------------------------------------------------
prometheus:
enabled: false
server:
podLabels:
app.kubernetes.io/application-group: "{{ .Values.global.appName }}"
persistentVolume:
enabled: false # For demo/dev. Set to true and configure storage for production.
grafana:
enabled: false
podLabels:
app.kubernetes.io/application-group: "{{ .Values.global.appName }}"
adminPassword: "admin" # Change for production!
persistence:
enabled: false # For demo/dev. Set to true and configure storage for production.
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus-server
- name: Loki
type: loki
access: proxy
url: http://loki:3100
loki:
enabled: false
podLabels:
app.kubernetes.io/application-group: "{{ .Values.global.appName }}"
persistence:
enabled: false # For demo/dev. Set to true and configure storage for production.