From 90fa5ada17c21ca734e473d2180b02b3c08b90c9 Mon Sep 17 00:00:00 2001 From: waleedlatif Date: Mon, 28 Jul 2025 16:26:25 -0700 Subject: [PATCH 1/2] feat(helm): added helm charts for self-hosting --- .gitignore | 5 +- .../emails/batch-invitation-email.tsx | 4 +- helm/sim/.helmignore | 28 + helm/sim/Chart.yaml | 22 + helm/sim/README.md | 619 ++++++++++++++++++ helm/sim/examples/values-aws.yaml | 234 +++++++ helm/sim/examples/values-azure.yaml | 172 +++++ helm/sim/examples/values-development.yaml | 111 ++++ helm/sim/examples/values-external-db.yaml | 152 +++++ helm/sim/examples/values-gcp.yaml | 251 +++++++ helm/sim/examples/values-production.yaml | 210 ++++++ helm/sim/templates/NOTES.txt | 73 +++ helm/sim/templates/_helpers.tpl | 303 +++++++++ helm/sim/templates/deployment-app.yaml | 117 ++++ helm/sim/templates/deployment-ollama.yaml | 112 ++++ helm/sim/templates/deployment-realtime.yaml | 92 +++ helm/sim/templates/gpu-device-plugin.yaml | 100 +++ helm/sim/templates/hpa.yaml | 85 +++ helm/sim/templates/ingress.yaml | 55 ++ helm/sim/templates/networkpolicy.yaml | 242 +++++++ helm/sim/templates/serviceaccount.yaml | 13 + helm/sim/templates/servicemonitor.yaml | 79 +++ helm/sim/templates/services.yaml | 83 +++ helm/sim/templates/shared-storage.yaml | 48 ++ .../sim/templates/statefulset-postgresql.yaml | 194 ++++++ helm/sim/templates/telemetry.yaml | 206 ++++++ helm/sim/values.schema.json | 539 +++++++++++++++ helm/sim/values.yaml | 596 +++++++++++++++++ 28 files changed, 4742 insertions(+), 3 deletions(-) create mode 100644 helm/sim/.helmignore create mode 100644 helm/sim/Chart.yaml create mode 100644 helm/sim/README.md create mode 100644 helm/sim/examples/values-aws.yaml create mode 100644 helm/sim/examples/values-azure.yaml create mode 100644 helm/sim/examples/values-development.yaml create mode 100644 helm/sim/examples/values-external-db.yaml create mode 100644 helm/sim/examples/values-gcp.yaml create mode 100644 helm/sim/examples/values-production.yaml create mode 100644 helm/sim/templates/NOTES.txt create mode 100644 helm/sim/templates/_helpers.tpl create mode 100644 helm/sim/templates/deployment-app.yaml create mode 100644 helm/sim/templates/deployment-ollama.yaml create mode 100644 helm/sim/templates/deployment-realtime.yaml create mode 100644 helm/sim/templates/gpu-device-plugin.yaml create mode 100644 helm/sim/templates/hpa.yaml create mode 100644 helm/sim/templates/ingress.yaml create mode 100644 helm/sim/templates/networkpolicy.yaml create mode 100644 helm/sim/templates/serviceaccount.yaml create mode 100644 helm/sim/templates/servicemonitor.yaml create mode 100644 helm/sim/templates/services.yaml create mode 100644 helm/sim/templates/shared-storage.yaml create mode 100644 helm/sim/templates/statefulset-postgresql.yaml create mode 100644 helm/sim/templates/telemetry.yaml create mode 100644 helm/sim/values.schema.json create mode 100644 helm/sim/values.yaml diff --git a/.gitignore b/.gitignore index 08dedb8678c..d486100979d 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,7 @@ start-collector.sh .turbo # VSCode -.vscode \ No newline at end of file +.vscode + +## Helm Chart Tests +helm/sim/test \ No newline at end of file diff --git a/apps/sim/components/emails/batch-invitation-email.tsx b/apps/sim/components/emails/batch-invitation-email.tsx index 0fa5bbfe61f..aa4eecc0e6b 100644 --- a/apps/sim/components/emails/batch-invitation-email.tsx +++ b/apps/sim/components/emails/batch-invitation-email.tsx @@ -73,7 +73,7 @@ export const BatchInvitationEmail = ({ src='https://simstudio.ai/logo.png' width='120' height='36' - alt='SimStudio' + alt='Sim Studio' style={logo} /> @@ -82,7 +82,7 @@ export const BatchInvitationEmail = ({ {inviterName} has invited you to join{' '} - {organizationName} on SimStudio. + {organizationName} on Sim Studio. {/* Organization Invitation Details */} diff --git a/helm/sim/.helmignore b/helm/sim/.helmignore new file mode 100644 index 00000000000..b7ed70ccb6b --- /dev/null +++ b/helm/sim/.helmignore @@ -0,0 +1,28 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# Examples directory (included in chart but ignored during packaging) +examples/ +# Test files +*_test.yaml +test/ \ No newline at end of file diff --git a/helm/sim/Chart.yaml b/helm/sim/Chart.yaml new file mode 100644 index 00000000000..2ad365b6699 --- /dev/null +++ b/helm/sim/Chart.yaml @@ -0,0 +1,22 @@ +apiVersion: v2 +name: sim +description: A Helm chart for Sim Studio - AI agent workflow platform +type: application +version: 0.1.0 +appVersion: "1.0.0" +home: https://simstudio.ai +sources: + - https://github.com/simstudioai/sim +maintainers: + - name: Sim Studio Team + email: help@simstudio.ai + url: https://simstudio.ai +keywords: + - ai + - workflow + - automation + - agents + - nextjs +annotations: + category: AI/ML Platform + licenses: Apache-2.0 \ No newline at end of file diff --git a/helm/sim/README.md b/helm/sim/README.md new file mode 100644 index 00000000000..67451e1fe69 --- /dev/null +++ b/helm/sim/README.md @@ -0,0 +1,619 @@ +# Sim Studio Helm Chart + +This Helm chart deploys Sim Studio, a lightweight AI agent workflow platform, on Kubernetes. + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ +- PV provisioner support in the underlying infrastructure (for persistent storage) + +## Installation + +### Quick Start + +1. Add the chart repository (if using a separate repo): +```bash +helm repo add simstudio https://charts.simstudio.ai +helm repo update +``` + +2. Install the chart: +```bash +helm install sim simstudio/sim +``` + +### Local Installation + +If using the chart from this repository: + +```bash +# From the repository root +helm install sim ./helm/sim +``` + +### Custom Configuration + +Install with custom values: + +```bash +helm install sim ./helm/sim -f custom-values.yaml +``` + +## Configuration Examples + +The chart includes several pre-configured values files for different scenarios: + +| Example File | Description | Use Case | +|-------------|-------------|----------| +| `values-development.yaml` | Minimal resources, no SSL | Local development and testing | +| `values-production.yaml` | High availability, security-focused | Generic production deployment | +| `values-external-db.yaml` | External database configuration | Production with managed database | +| `values-azure.yaml` | Azure AKS optimized | Azure Kubernetes Service | +| `values-aws.yaml` | AWS EKS optimized | Amazon Elastic Kubernetes Service | +| `values-gcp.yaml` | GCP GKE optimized | Google Kubernetes Engine | + +### Development Environment + +```bash +helm install sim-dev ./helm/sim \ + --values ./helm/sim/examples/values-development.yaml \ + --namespace simstudio-dev --create-namespace +``` + +### Production Environment + +```bash +helm install sim-prod ./helm/sim \ + --values ./helm/sim/examples/values-production.yaml \ + --namespace simstudio-prod --create-namespace +``` + +### Azure Environment + +```bash +helm install sim-azure ./helm/sim \ + --values ./helm/sim/examples/values-azure.yaml \ + --namespace simstudio --create-namespace +``` + +### AWS Environment (EKS) + +```bash +helm install sim-aws ./helm/sim \ + --values ./helm/sim/examples/values-aws.yaml \ + --namespace simstudio --create-namespace +``` + +### GCP Environment (GKE) + +```bash +helm install sim-gcp ./helm/sim \ + --values ./helm/sim/examples/values-gcp.yaml \ + --namespace simstudio --create-namespace +``` + +### External Database (Managed Services) + +```bash +helm install sim-prod ./helm/sim \ + --values ./helm/sim/examples/values-external-db.yaml \ + --set externalDatabase.host="your-rds-endpoint.com" \ + --set externalDatabase.username="simstudio_user" \ + --set externalDatabase.password="secure-password" \ + --set externalDatabase.database="simstudio_prod" \ + --namespace simstudio --create-namespace +``` + +## Cloud-Specific Features + +Each cloud platform example includes optimized configurations: + +### Azure (AKS) +- **Storage**: Premium managed disks (`managed-csi-premium`) +- **Node Selectors**: Role-based node targeting (`node-role: application`, `node-role: datalake`) +- **GPU Support**: NVIDIA GPU nodes with tolerations +- **Ingress**: NGINX ingress controller with SSL redirect + +### AWS (EKS) +- **Storage**: EBS GP3 volumes for optimal performance +- **Node Selectors**: Instance type targeting (`t3.large`, `r5.large`, `g4dn.xlarge`) +- **GPU Support**: GPU-optimized instances (G4, P3 families) +- **Ingress**: Application Load Balancer (ALB) with AWS Certificate Manager +- **IAM**: Service Account annotations for IAM roles + +### GCP (GKE) +- **Storage**: Persistent Disk with standard and premium options +- **Node Selectors**: Node pool and machine family targeting +- **GPU Support**: Tesla T4/V100 GPUs with GKE accelerator labels +- **Ingress**: Google Cloud Load Balancer with managed certificates +- **Workload Identity**: Service Account annotations for GCP IAM + +## Configuration + +The following table lists the configurable parameters and their default values. + +### Global Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `global.imageRegistry` | Global Docker image registry | `"ghcr.io"` | +| `global.useRegistryForAllImages` | Use custom registry for all images (not just simstudioai/*) | `false` | +| `global.imagePullSecrets` | Global Docker registry secret names | `[]` | +| `global.storageClass` | Global storage class for PVCs | `""` | +| `global.commonLabels` | Common labels to add to all resources | `{}` | + +### Application Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `app.enabled` | Enable the main application | `true` | +| `app.replicaCount` | Number of app replicas | `1` | +| `app.image.repository` | App image repository | `simstudioai/simstudio` | +| `app.image.tag` | App image tag | `latest` | +| `app.image.pullPolicy` | App image pull policy | `Always` | +| `app.resources` | App resource limits and requests | See values.yaml | +| `app.nodeSelector` | App node selector | `{}` | +| `app.podSecurityContext` | App pod security context | `fsGroup: 1001` | +| `app.securityContext` | App container security context | `runAsNonRoot: true, runAsUser: 1001` | +| `app.service.type` | App service type | `ClusterIP` | +| `app.service.port` | App service port | `3000` | +| `app.service.targetPort` | App service target port | `3000` | +| `app.livenessProbe` | App liveness probe configuration | See values.yaml | +| `app.readinessProbe` | App readiness probe configuration | See values.yaml | +| `app.env` | App environment variables | See values.yaml | + +### Realtime Service Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `realtime.enabled` | Enable the realtime service | `true` | +| `realtime.replicaCount` | Number of realtime replicas | `1` | +| `realtime.image.repository` | Realtime image repository | `simstudioai/realtime` | +| `realtime.image.tag` | Realtime image tag | `latest` | +| `realtime.image.pullPolicy` | Realtime image pull policy | `Always` | +| `realtime.resources` | Realtime resource limits and requests | See values.yaml | +| `realtime.nodeSelector` | Realtime node selector | `{}` | +| `realtime.podSecurityContext` | Realtime pod security context | `fsGroup: 1001` | +| `realtime.securityContext` | Realtime container security context | `runAsNonRoot: true, runAsUser: 1001` | +| `realtime.service.type` | Realtime service type | `ClusterIP` | +| `realtime.service.port` | Realtime service port | `3002` | +| `realtime.service.targetPort` | Realtime service target port | `3002` | +| `realtime.livenessProbe` | Realtime liveness probe configuration | See values.yaml | +| `realtime.readinessProbe` | Realtime readiness probe configuration | See values.yaml | +| `realtime.env` | Realtime environment variables | See values.yaml | + +### PostgreSQL Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `postgresql.enabled` | Enable internal PostgreSQL | `true` | +| `postgresql.image.repository` | PostgreSQL image repository | `pgvector/pgvector` | +| `postgresql.image.tag` | PostgreSQL image tag | `pg17` | +| `postgresql.image.pullPolicy` | PostgreSQL image pull policy | `IfNotPresent` | +| `postgresql.auth.username` | PostgreSQL username | `postgres` | +| `postgresql.auth.password` | PostgreSQL password | `CHANGE-ME-SECURE-PASSWORD` | +| `postgresql.auth.database` | PostgreSQL database name | `simstudio` | +| `postgresql.nodeSelector` | PostgreSQL node selector | `{}` | +| `postgresql.resources` | PostgreSQL resource limits and requests | See values.yaml | +| `postgresql.podSecurityContext` | PostgreSQL pod security context | `fsGroup: 999` | +| `postgresql.securityContext` | PostgreSQL container security context | `runAsUser: 999` | +| `postgresql.persistence.enabled` | Enable PostgreSQL persistence | `true` | +| `postgresql.persistence.storageClass` | PostgreSQL storage class | `""` | +| `postgresql.persistence.size` | PostgreSQL PVC size | `10Gi` | +| `postgresql.persistence.accessModes` | PostgreSQL PVC access modes | `["ReadWriteOnce"]` | +| `postgresql.tls.enabled` | Enable PostgreSQL SSL/TLS | `false` | +| `postgresql.tls.certificatesSecret` | PostgreSQL TLS certificates secret | `postgres-tls-secret` | +| `postgresql.config.maxConnections` | PostgreSQL max connections | `1000` | +| `postgresql.config.sharedBuffers` | PostgreSQL shared buffers | `"1280MB"` | +| `postgresql.config.maxWalSize` | PostgreSQL max WAL size | `"4GB"` | +| `postgresql.config.minWalSize` | PostgreSQL min WAL size | `"80MB"` | +| `postgresql.service.type` | PostgreSQL service type | `ClusterIP` | +| `postgresql.service.port` | PostgreSQL service port | `5432` | +| `postgresql.service.targetPort` | PostgreSQL service target port | `5432` | +| `postgresql.livenessProbe` | PostgreSQL liveness probe configuration | See values.yaml | +| `postgresql.readinessProbe` | PostgreSQL readiness probe configuration | See values.yaml | + +### External Database Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `externalDatabase.enabled` | Use external database instead of internal PostgreSQL | `false` | +| `externalDatabase.host` | External database host | `"external-db.example.com"` | +| `externalDatabase.port` | External database port | `5432` | +| `externalDatabase.username` | External database username | `postgres` | +| `externalDatabase.password` | External database password | `""` | +| `externalDatabase.database` | External database name | `simstudio` | +| `externalDatabase.sslMode` | External database SSL mode | `require` | + +### Ollama Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `ollama.enabled` | Enable Ollama for local AI models | `false` | +| `ollama.image.repository` | Ollama image repository | `ollama/ollama` | +| `ollama.image.tag` | Ollama image tag | `latest` | +| `ollama.image.pullPolicy` | Ollama image pull policy | `Always` | +| `ollama.replicaCount` | Number of Ollama replicas | `1` | +| `ollama.gpu.enabled` | Enable GPU support for Ollama | `false` | +| `ollama.gpu.count` | Number of GPUs to allocate | `1` | +| `ollama.nodeSelector` | Ollama node selector | `accelerator: nvidia` | +| `ollama.tolerations` | Ollama tolerations for GPU nodes | See values.yaml | +| `ollama.resources` | Ollama resource limits and requests | See values.yaml | +| `ollama.env` | Ollama environment variables | See values.yaml | +| `ollama.persistence.enabled` | Enable Ollama persistence | `true` | +| `ollama.persistence.storageClass` | Ollama storage class | `""` | +| `ollama.persistence.size` | Ollama PVC size | `100Gi` | +| `ollama.persistence.accessModes` | Ollama PVC access modes | `["ReadWriteOnce"]` | +| `ollama.service.type` | Ollama service type | `ClusterIP` | +| `ollama.service.port` | Ollama service port | `11434` | +| `ollama.service.targetPort` | Ollama service target port | `11434` | +| `ollama.startupProbe` | Ollama startup probe configuration | See values.yaml | +| `ollama.livenessProbe` | Ollama liveness probe configuration | See values.yaml | +| `ollama.readinessProbe` | Ollama readiness probe configuration | See values.yaml | + +### Ingress Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `ingress.enabled` | Enable ingress | `false` | +| `ingress.className` | Ingress class name | `nginx` | +| `ingress.annotations` | Ingress annotations | See values.yaml | +| `ingress.app.host` | App ingress hostname | `simstudio.local` | +| `ingress.app.paths` | App ingress paths | `[{path: "/", pathType: "Prefix"}]` | +| `ingress.realtime.host` | Realtime ingress hostname | `simstudio-ws.local` | +| `ingress.realtime.paths` | Realtime ingress paths | `[{path: "/", pathType: "Prefix"}]` | +| `ingress.tls.enabled` | Enable TLS for ingress | `false` | +| `ingress.tls.secretName` | TLS secret name | `simstudio-tls-secret` | + +### Autoscaling Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `autoscaling.enabled` | Enable Horizontal Pod Autoscaler | `false` | +| `autoscaling.minReplicas` | Minimum number of replicas | `1` | +| `autoscaling.maxReplicas` | Maximum number of replicas | `10` | +| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization | `80` | +| `autoscaling.targetMemoryUtilizationPercentage` | Target memory utilization | `80` | +| `autoscaling.customMetrics` | Custom metrics for scaling | `[]` | +| `autoscaling.behavior` | Scaling behavior configuration | `{}` | + +### Monitoring Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `monitoring.serviceMonitor.enabled` | Enable ServiceMonitor for Prometheus | `false` | +| `monitoring.serviceMonitor.labels` | Additional labels for ServiceMonitor | `{}` | +| `monitoring.serviceMonitor.annotations` | Additional annotations for ServiceMonitor | `{}` | +| `monitoring.serviceMonitor.path` | Metrics endpoint path | `/metrics` | +| `monitoring.serviceMonitor.interval` | Scrape interval | `30s` | +| `monitoring.serviceMonitor.scrapeTimeout` | Scrape timeout | `10s` | +| `monitoring.serviceMonitor.targetLabels` | Target labels to add to scraped metrics | `[]` | +| `monitoring.serviceMonitor.metricRelabelings` | Metric relabeling configurations | `[]` | +| `monitoring.serviceMonitor.relabelings` | Relabeling configurations | `[]` | + +### Security Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `networkPolicy.enabled` | Enable network policies | `false` | +| `networkPolicy.ingress` | Custom ingress rules | `[]` | +| `networkPolicy.egress` | Custom egress rules | `[]` | +| `podDisruptionBudget.enabled` | Enable pod disruption budget | `false` | +| `podDisruptionBudget.minAvailable` | Minimum available pods | `1` | + +### Migration Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `migrations.enabled` | Enable database migrations job | `true` | +| `migrations.image.repository` | Migrations image repository | `simstudioai/migrations` | +| `migrations.image.tag` | Migrations image tag | `latest` | +| `migrations.image.pullPolicy` | Migrations image pull policy | `Always` | +| `migrations.resources` | Migrations resource limits and requests | See values.yaml | +| `migrations.podSecurityContext` | Migrations pod security context | `fsGroup: 1001` | +| `migrations.securityContext` | Migrations container security context | `runAsNonRoot: true, runAsUser: 1001` | + +### Shared Storage Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `sharedStorage.enabled` | Enable shared storage for multi-pod data sharing | `false` | +| `sharedStorage.storageClass` | Storage class for shared volumes (must support ReadWriteMany) | `""` | +| `sharedStorage.defaultAccessModes` | Default access modes for shared volumes | `["ReadWriteMany"]` | +| `sharedStorage.volumes` | Array of shared volume definitions | `[]` | +| `sharedStorage.volumes[].name` | Shared volume name | Required | +| `sharedStorage.volumes[].size` | Shared volume size | Required | +| `sharedStorage.volumes[].accessModes` | Shared volume access modes | Uses default | +| `sharedStorage.volumes[].storageClass` | Shared volume storage class | Uses global | +| `sharedStorage.volumes[].annotations` | Shared volume annotations | `{}` | +| `sharedStorage.volumes[].selector` | Shared volume selector | `{}` | + +### Telemetry Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `telemetry.enabled` | Enable telemetry and observability collection | `false` | +| `telemetry.replicaCount` | Number of telemetry collector replicas | `1` | +| `telemetry.image.repository` | Telemetry collector image repository | `otel/opentelemetry-collector-contrib` | +| `telemetry.image.tag` | Telemetry collector image tag | `0.91.0` | +| `telemetry.image.pullPolicy` | Telemetry collector image pull policy | `IfNotPresent` | +| `telemetry.resources` | Telemetry collector resource limits and requests | See values.yaml | +| `telemetry.nodeSelector` | Telemetry collector node selector | `{}` | +| `telemetry.tolerations` | Telemetry collector tolerations | `[]` | +| `telemetry.affinity` | Telemetry collector affinity | `{}` | +| `telemetry.service.type` | Telemetry collector service type | `ClusterIP` | +| `telemetry.jaeger.enabled` | Enable Jaeger tracing backend | `false` | +| `telemetry.jaeger.endpoint` | Jaeger collector endpoint | `"http://jaeger-collector:14250"` | +| `telemetry.jaeger.tls.enabled` | Enable TLS for Jaeger connection | `false` | +| `telemetry.prometheus.enabled` | Enable Prometheus metrics backend | `false` | +| `telemetry.prometheus.endpoint` | Prometheus remote write endpoint | `"http://prometheus-server/api/v1/write"` | +| `telemetry.prometheus.auth` | Prometheus authentication header | `""` | +| `telemetry.otlp.enabled` | Enable generic OTLP backend | `false` | +| `telemetry.otlp.endpoint` | OTLP collector endpoint | `"http://otlp-collector:4317"` | +| `telemetry.otlp.tls.enabled` | Enable TLS for OTLP connection | `false` | + +### Service Account Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `serviceAccount.create` | Create a service account | `true` | +| `serviceAccount.annotations` | Service account annotations | `{}` | +| `serviceAccount.name` | Service account name (auto-generated if empty) | `""` | + +### Common Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `nameOverride` | Override the name of the chart | `""` | +| `fullnameOverride` | Override the fullname of the chart | `""` | +| `extraVolumes` | Additional volumes for all pods | `[]` | +| `extraVolumeMounts` | Additional volume mounts for all containers | `[]` | +| `extraEnvVars` | Additional environment variables for all containers | `[]` | +| `podAnnotations` | Additional annotations for all pods | `{}` | +| `podLabels` | Additional labels for all pods | `{}` | +| `affinity` | Affinity settings for all pods | `{}` | +| `tolerations` | Tolerations for all pods | `[]` | + +## Enterprise Features + +### Autoscaling + +Enable automatic horizontal scaling based on CPU and memory usage: + +```yaml +autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 80 +``` + +### Shared Storage + +Enable shared storage for multi-pod data sharing and enterprise workflows: + +```yaml +sharedStorage: + enabled: true + storageClass: "managed-csi-premium" + volumes: + - name: output-share + size: 100Gi + accessModes: + - ReadWriteMany + - name: model-share + size: 200Gi + accessModes: + - ReadWriteMany + - name: logs-share + size: 50Gi + accessModes: + - ReadWriteMany +``` + +This creates persistent volume claims that can be shared across multiple pods for: +- Output data sharing between workflow steps +- Model storage and caching +- Centralized logging and audit trails +- Temporary data exchange + +### Telemetry and Observability + +Enable comprehensive telemetry collection with OpenTelemetry: + +```yaml +telemetry: + enabled: true + resources: + limits: + memory: "1Gi" + cpu: "500m" + requests: + memory: "512Mi" + cpu: "200m" + + # Enable Jaeger for distributed tracing + jaeger: + enabled: true + endpoint: "http://jaeger-collector:14250" + + # Enable Prometheus for metrics + prometheus: + enabled: true + endpoint: "http://prometheus-server/api/v1/write" + auth: "Bearer your-prometheus-token" + + # Enable generic OTLP for flexibility + otlp: + enabled: true + endpoint: "http://otlp-collector:4317" +``` + +This automatically configures: +- OpenTelemetry Collector for metrics, traces, and logs +- Automatic service discovery for SimStudio components +- Environment variable injection for applications +- Support for multiple observability backends + +### GPU Support + +Enable GPU device plugin support for AI workloads: + +```yaml +ollama: + enabled: true + gpu: + enabled: true + count: 1 + nodeSelector: + accelerator: nvidia + tolerations: + - key: "sku" + operator: "Equal" + value: "gpu" + effect: "NoSchedule" +``` + +This deploys: +- NVIDIA Device Plugin DaemonSet +- RuntimeClass for NVIDIA container runtime +- Proper node scheduling and resource allocation + +### Monitoring Integration + +Enable Prometheus monitoring with ServiceMonitor: + +```yaml +monitoring: + serviceMonitor: + enabled: true + labels: + monitoring: "prometheus" + interval: 15s +``` + +### Network Security + +Enable network policies for micro-segmentation: + +```yaml +networkPolicy: + enabled: true +``` + +This creates network policies that: +- Allow communication between SimStudio components +- Restrict unnecessary network access +- Permit DNS resolution and HTTPS egress +- Support custom ingress/egress rules + +### High Availability + +Configure pod disruption budgets and anti-affinity: + +```yaml +podDisruptionBudget: + enabled: true + minAvailable: 1 + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: ["simstudio"] + topologyKey: kubernetes.io/hostname +``` + +## Upgrading + +To upgrade your release: + +```bash +helm upgrade sim ./helm/sim +``` + +## Uninstalling + +To uninstall/delete the release: + +```bash +helm uninstall sim +``` + +## Security Considerations + +### Production Secrets + +For production deployments, make sure to: + +1. **Change default secrets**: Update `BETTER_AUTH_SECRET` and `ENCRYPTION_KEY` with secure, randomly generated values +2. **Use strong database passwords**: Set `postgresql.auth.password` to a strong password +3. **Enable TLS**: Configure `postgresql.tls.enabled=true` and provide proper certificates +4. **Configure ingress TLS**: Enable HTTPS with proper SSL certificates + +### Example secure values: + +```yaml +app: + env: + BETTER_AUTH_SECRET: "your-secure-random-string-here" + ENCRYPTION_KEY: "your-secure-encryption-key-here" + +postgresql: + auth: + password: "your-secure-database-password" + tls: + enabled: true + certificatesSecret: "postgres-tls-secret" + +ingress: + enabled: true + tls: + enabled: true + secretName: "simstudio-tls-secret" +``` + +## Troubleshooting + +### Common Issues + +1. **Database Connection Issues** + - Check if PostgreSQL pod is running: `kubectl get pods -l app.kubernetes.io/component=postgresql` + - Verify database credentials in the secret: `kubectl get secret -postgresql-secret -o yaml` + +2. **Migration Issues** + - Check migration job logs: `kubectl logs job/-migrations` + - Ensure database is accessible from the migration job + +3. **Image Pull Issues** + - Verify image names and tags in values.yaml + - Check if image pull secrets are configured correctly + +### Getting Logs + +```bash +# App logs +kubectl logs deployment/-app + +# Realtime logs +kubectl logs deployment/-realtime + +# PostgreSQL logs +kubectl logs statefulset/-postgresql + +# Migration logs +kubectl logs job/-migrations +``` + +## Support + +- Documentation: https://docs.simstudio.ai +- GitHub Issues: https://github.com/simstudioai/sim/issues +- Discord: https://discord.gg/Hr4UWYEcTT \ No newline at end of file diff --git a/helm/sim/examples/values-aws.yaml b/helm/sim/examples/values-aws.yaml new file mode 100644 index 00000000000..5210497f66a --- /dev/null +++ b/helm/sim/examples/values-aws.yaml @@ -0,0 +1,234 @@ +# AWS-specific values for Sim Studio +# Example configuration for Amazon EKS deployment + +# Global configuration +global: + imageRegistry: "ghcr.io" + storageClass: "gp3" + +# Main application +app: + enabled: true + replicaCount: 2 + + # Node selector for application pods (customize based on your EKS node labels) + nodeSelector: + kubernetes.io/arch: amd64 + node.kubernetes.io/instance-type: "t3.large" + + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + # Production URLs (REQUIRED - update with your actual domain names) + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + SOCKET_SERVER_URL: "https://simstudio-ws.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + + # Security settings (REQUIRED - replace with your own secure secrets) + BETTER_AUTH_SECRET: "your-secure-production-auth-secret-here" + ENCRYPTION_KEY: "your-secure-production-encryption-key-here" + + NODE_ENV: "production" + NEXT_TELEMETRY_DISABLED: "1" + + # AWS-specific environment variables + AWS_REGION: "us-west-2" + +# Realtime service +realtime: + enabled: true + replicaCount: 2 + + # Node selector for realtime pods (customize based on your EKS node labels) + nodeSelector: + kubernetes.io/arch: amd64 + node.kubernetes.io/instance-type: "t3.medium" + + resources: + limits: + memory: "4Gi" + cpu: "1000m" + requests: + memory: "2Gi" + cpu: "500m" + + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + BETTER_AUTH_SECRET: "your-secure-production-auth-secret-here" + ALLOWED_ORIGINS: "https://simstudio.acme.com" + NODE_ENV: "production" + +# Database migrations +migrations: + enabled: true + + resources: + limits: + memory: "2Gi" + cpu: "1000m" + requests: + memory: "1Gi" + cpu: "500m" + +# PostgreSQL database +postgresql: + enabled: true + + # Node selector for database pods (recommended: memory-optimized EC2 instances) + nodeSelector: + node.kubernetes.io/instance-type: "r5.large" + + # Database authentication (REQUIRED - set secure credentials) + auth: + username: postgres + password: "your-secure-postgres-password" + database: simstudio + + # Resource allocation optimized for AWS EKS + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + # Persistent storage using AWS EBS GP3 volumes + persistence: + enabled: true + storageClass: "gp3" + size: 50Gi + accessModes: + - ReadWriteOnce + + # SSL/TLS configuration + tls: + enabled: true + certificatesSecret: postgres-tls-secret + + # PostgreSQL performance tuning for AWS infrastructure + config: + maxConnections: 1000 + sharedBuffers: "2GB" + maxWalSize: "8GB" + minWalSize: "160MB" + +# Ollama AI models with GPU acceleration (AWS EC2 GPU instances) +ollama: + enabled: true + replicaCount: 1 + + # GPU node targeting (recommended: g4dn.xlarge or p3.2xlarge instances) + nodeSelector: + node.kubernetes.io/instance-type: "g4dn.xlarge" + kubernetes.io/arch: amd64 + + tolerations: + - key: "nvidia.com/gpu" + operator: "Equal" + value: "true" + effect: "NoSchedule" + + # GPU resource allocation for AI model serving + gpu: + enabled: true + count: 1 + + resources: + limits: + memory: "16Gi" + cpu: "4000m" + nvidia.com/gpu: "1" + requests: + memory: "8Gi" + cpu: "2000m" + + # High-performance storage for AI models + persistence: + enabled: true + storageClass: "gp3" + size: 100Gi + accessModes: + - ReadWriteOnce + + env: + NVIDIA_DRIVER_CAPABILITIES: "all" + OLLAMA_LOAD_TIMEOUT: "-1" + OLLAMA_KEEP_ALIVE: "-1" + OLLAMA_DEBUG: "1" + +# Ingress using AWS Application Load Balancer (ALB) +ingress: + enabled: true + className: alb + + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/ssl-redirect: "443" + alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:us-west-2:123456789012:certificate/your-cert-arn" + + # Main application + app: + host: simstudio.acme.com + paths: + - path: / + pathType: Prefix + + # Realtime service + realtime: + host: simstudio-ws.acme.com + paths: + - path: / + pathType: Prefix + + # TLS configuration + tls: + enabled: true + secretName: simstudio-tls-secret + +# Pod disruption budget for high availability +podDisruptionBudget: + enabled: true + minAvailable: 1 + +# Network policies +networkPolicy: + enabled: true + +# Pod anti-affinity for high availability across AWS Availability Zones +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: ["simstudio"] + topologyKey: kubernetes.io/hostname + - weight: 50 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: ["simstudio"] + topologyKey: topology.kubernetes.io/zone + +# Service Account with IAM roles for service account (IRSA) integration +serviceAccount: + create: true + annotations: + eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/SimStudioServiceRole" \ No newline at end of file diff --git a/helm/sim/examples/values-azure.yaml b/helm/sim/examples/values-azure.yaml new file mode 100644 index 00000000000..b3226ace5e6 --- /dev/null +++ b/helm/sim/examples/values-azure.yaml @@ -0,0 +1,172 @@ +# Azure-specific values for Sim Studio +# Example configuration for Azure AKS deployment + +# Global configuration +global: + imageRegistry: "ghcr.io" + storageClass: "managed-csi-premium" + +# Main application +app: + enabled: true + replicaCount: 1 + + # Node selector for application pods (customize based on your AKS node labels) + nodeSelector: + node-role: application + + resources: + limits: + memory: "4Gi" + requests: + memory: "2Gi" + cpu: "500m" + + # Production URLs (REQUIRED - update with your actual domain names) + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + SOCKET_SERVER_URL: "https://simstudio-ws.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + + # Security settings (REQUIRED - replace with your own secure secrets) + BETTER_AUTH_SECRET: "your-secure-production-auth-secret-here" + ENCRYPTION_KEY: "your-secure-production-encryption-key-here" + + NODE_ENV: "production" + NEXT_TELEMETRY_DISABLED: "1" + +# Realtime service +realtime: + enabled: true + replicaCount: 1 + + # Node selector for application pods (customize based on your AKS node labels) + nodeSelector: + node-role: application + + resources: + limits: + memory: "4Gi" + requests: + memory: "1Gi" + cpu: "250m" + + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + BETTER_AUTH_SECRET: "your-secure-production-auth-secret-here" + ALLOWED_ORIGINS: "https://simstudio.acme.com" + NODE_ENV: "production" + +# Database migrations +migrations: + enabled: true + +# PostgreSQL database +postgresql: + enabled: true + + # Node selector for database pods (recommended: memory-optimized VM sizes) + nodeSelector: + node-role: datalake + + # Database authentication (REQUIRED - set secure credentials) + auth: + username: postgres + password: "your-secure-postgres-password" + database: simstudio + + # Resource allocation for production workloads + resources: + limits: + memory: "2Gi" + requests: + memory: "1Gi" + cpu: "500m" + + # Persistent storage using Azure Premium SSD + persistence: + enabled: true + storageClass: "managed-csi-premium" + size: 10Gi + + # SSL/TLS configuration (recommended for production) + tls: + enabled: true + certificatesSecret: postgres-tls-secret + + # PostgreSQL performance tuning for Azure infrastructure + config: + maxConnections: 1000 + sharedBuffers: "1280MB" + maxWalSize: "4GB" + minWalSize: "80MB" + +# Ollama AI models with GPU acceleration (Azure NC-series VMs) +ollama: + enabled: true + replicaCount: 1 + + # GPU node targeting (recommended: NC6s_v3 or NC12s_v3 VMs) + nodeSelector: + accelerator: nvidia + + tolerations: + - key: "sku" + operator: "Equal" + value: "gpu" + effect: "NoSchedule" + + # GPU resource allocation for AI model serving + gpu: + enabled: true + count: 1 + + resources: + limits: + memory: "8Gi" + nvidia.com/gpu: "1" + requests: + memory: "4Gi" + cpu: "1000m" + + # High-performance storage for AI models + persistence: + enabled: true + storageClass: "managed-csi-premium" + size: 100Gi + + env: + NVIDIA_DRIVER_CAPABILITIES: "all" + OLLAMA_LOAD_TIMEOUT: "-1" + OLLAMA_KEEP_ALIVE: "-1" + OLLAMA_DEBUG: "1" + +# Ingress configuration for Azure Application Gateway +ingress: + enabled: true + className: nginx + + annotations: + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + + # Main application + app: + host: simstudio.acme.com + paths: + - path: / + pathType: Prefix + + # Realtime service + realtime: + host: simstudio-ws.acme.com + paths: + - path: / + pathType: Prefix + + # TLS configuration + tls: + enabled: true + secretName: simstudio-tls-secret \ No newline at end of file diff --git a/helm/sim/examples/values-development.yaml b/helm/sim/examples/values-development.yaml new file mode 100644 index 00000000000..e5c3116b334 --- /dev/null +++ b/helm/sim/examples/values-development.yaml @@ -0,0 +1,111 @@ +# Development values for Sim Studio +# This configuration is suitable for development and testing + +# Global configuration +global: + imageRegistry: "ghcr.io" + +# Main application +app: + enabled: true + replicaCount: 1 + + # Resource allocation for development environment + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + # Development URLs + env: + NEXT_PUBLIC_APP_URL: "http://localhost:3000" + BETTER_AUTH_URL: "http://localhost:3000" + NEXT_PUBLIC_SOCKET_URL: "http://localhost:3002" + + # Example secrets for development (replace with secure values for production) + BETTER_AUTH_SECRET: "dev-32-char-auth-secret-not-secure-dev" + ENCRYPTION_KEY: "dev-32-char-encryption-key-not-secure" + +# Realtime service +realtime: + enabled: true + replicaCount: 1 + + # Resource allocation for realtime WebSocket service in development + resources: + limits: + memory: "2Gi" + cpu: "1000m" + requests: + memory: "1Gi" + cpu: "500m" + + env: + NEXT_PUBLIC_APP_URL: "http://localhost:3000" + BETTER_AUTH_URL: "http://localhost:3000" + NEXT_PUBLIC_SOCKET_URL: "http://localhost:3002" + BETTER_AUTH_SECRET: "dev-32-char-auth-secret-not-secure-dev" + ALLOWED_ORIGINS: "http://localhost:3000" + +# Database migrations +migrations: + enabled: true + +# PostgreSQL database +postgresql: + enabled: true + + # Simple authentication for development + auth: + username: postgres + password: "postgres" + database: simstudio + + # PostgreSQL with pgvector extension for vector operations + image: + repository: pgvector/pgvector + tag: pg17 + pullPolicy: IfNotPresent + + # Minimal resource allocation for development PostgreSQL + resources: + limits: + memory: "1Gi" + cpu: "500m" + requests: + memory: "512Mi" + cpu: "250m" + + # Persistence disabled for easier development (data will be lost on restart) + persistence: + enabled: false + + # SSL/TLS disabled for local development + tls: + enabled: false + + # Minimal PostgreSQL configuration for development + config: + maxConnections: 100 + sharedBuffers: "256MB" + maxWalSize: "1GB" + minWalSize: "80MB" + +# Ollama AI models (disabled by default for development) +ollama: + enabled: false + +# Ingress (disabled for development - use port-forward for local access) +ingress: + enabled: false + +# Pod disruption budget (disabled for development) +podDisruptionBudget: + enabled: false + +# Network policies (disabled for development) +networkPolicy: + enabled: false \ No newline at end of file diff --git a/helm/sim/examples/values-external-db.yaml b/helm/sim/examples/values-external-db.yaml new file mode 100644 index 00000000000..6face37f814 --- /dev/null +++ b/helm/sim/examples/values-external-db.yaml @@ -0,0 +1,152 @@ +# External Database Example for SimStudio +# Use this configuration when connecting to a managed database service +# (AWS RDS, Azure Database, Google Cloud SQL, etc.) + +# Global configuration +global: + imageRegistry: "ghcr.io" + +# Main application +app: + enabled: true + replicaCount: 2 + + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + SOCKET_SERVER_URL: "https://simstudio-ws.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + + # Security settings (REQUIRED - replace with your own secure secrets) + BETTER_AUTH_SECRET: "" # Set via --set flag or external secret manager + ENCRYPTION_KEY: "" # Set via --set flag or external secret manager + + NODE_ENV: "production" + NEXT_TELEMETRY_DISABLED: "1" + +# Realtime service +realtime: + enabled: true + replicaCount: 2 + + resources: + limits: + memory: "4Gi" + cpu: "1000m" + requests: + memory: "2Gi" + cpu: "500m" + + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + BETTER_AUTH_SECRET: "" # Must match main app secret - set via --set flag + ALLOWED_ORIGINS: "https://simstudio.acme.com" + NODE_ENV: "production" + +# Database migrations +migrations: + enabled: true + + resources: + limits: + memory: "2Gi" + cpu: "1000m" + requests: + memory: "1Gi" + cpu: "500m" + +# Disable internal PostgreSQL +postgresql: + enabled: false + +# Configure external database connection +externalDatabase: + enabled: true + + # Database connection details (REQUIRED - configure for your external database) + host: "" # Database hostname (e.g., "postgres.acme.com" or RDS endpoint) + port: 5432 + username: "" # Database username (e.g., "simstudio_user") + password: "" # Database password - set via --set flag or external secret + database: "" # Database name (e.g., "simstudio_production") + + # SSL mode for database connections (recommended: 'require' for production) + sslMode: "require" # Options: disable, allow, prefer, require, verify-ca, verify-full + +# Ollama (optional for AI models) +ollama: + enabled: false + +# Ingress configuration +ingress: + enabled: true + className: nginx + + annotations: + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" + + app: + host: simstudio.acme.com + paths: + - path: / + pathType: Prefix + + realtime: + host: simstudio-ws.acme.com + paths: + - path: / + pathType: Prefix + + tls: + enabled: true + secretName: simstudio-tls-secret + +# Production-ready features (autoscaling, monitoring, etc.) +autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 80 + +podDisruptionBudget: + enabled: true + minAvailable: 1 + +monitoring: + serviceMonitor: + enabled: true + labels: + monitoring: "prometheus" + interval: 15s + +networkPolicy: + enabled: true + # Custom egress rules to allow database connectivity + egress: + - to: [] # Allow outbound connections to external database + ports: + - protocol: TCP + port: 5432 + +# Example deployment command with secure secret generation: +# helm install simstudio ./charts/simstudio \ +# --values ./charts/simstudio/examples/values-external-db.yaml \ +# --set externalDatabase.host="your-db-host.com" \ +# --set externalDatabase.username="your-db-user" \ +# --set externalDatabase.password="your-db-password" \ +# --set externalDatabase.database="your-db-name" \ +# --set app.env.BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ +# --set app.env.ENCRYPTION_KEY="$(openssl rand -hex 32)" \ +# --set realtime.env.BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ No newline at end of file diff --git a/helm/sim/examples/values-gcp.yaml b/helm/sim/examples/values-gcp.yaml new file mode 100644 index 00000000000..01dc5bc9006 --- /dev/null +++ b/helm/sim/examples/values-gcp.yaml @@ -0,0 +1,251 @@ +# GCP-specific values for Sim Studio +# Example configuration for Google Kubernetes Engine (GKE) deployment + +# Global configuration +global: + imageRegistry: "ghcr.io" + storageClass: "standard-rwo" + +# Main application +app: + enabled: true + replicaCount: 2 + + # Node selector for application pods (customize based on your GKE node labels) + nodeSelector: + kubernetes.io/arch: amd64 + cloud.google.com/gke-nodepool: "default-pool" + + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + # Production URLs (REQUIRED - update with your actual domain names) + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + SOCKET_SERVER_URL: "https://simstudio-ws.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + + # Security settings (REQUIRED - replace with your own secure secrets) + BETTER_AUTH_SECRET: "your-secure-production-auth-secret-here" + ENCRYPTION_KEY: "your-secure-production-encryption-key-here" + + NODE_ENV: "production" + NEXT_TELEMETRY_DISABLED: "1" + + # GCP-specific environment variables + GOOGLE_CLOUD_PROJECT: "your-project-id" + GOOGLE_CLOUD_REGION: "us-central1" + +# Realtime service +realtime: + enabled: true + replicaCount: 2 + + # Node selector for realtime pods (customize based on your GKE node labels) + nodeSelector: + kubernetes.io/arch: amd64 + cloud.google.com/gke-nodepool: "default-pool" + + resources: + limits: + memory: "4Gi" + cpu: "1000m" + requests: + memory: "2Gi" + cpu: "500m" + + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + BETTER_AUTH_SECRET: "your-secure-production-auth-secret-here" + ALLOWED_ORIGINS: "https://simstudio.acme.com" + NODE_ENV: "production" + +# Database migrations +migrations: + enabled: true + + resources: + limits: + memory: "2Gi" + cpu: "1000m" + requests: + memory: "1Gi" + cpu: "500m" + +# PostgreSQL database +postgresql: + enabled: true + + # Node selector for database pods (recommended: memory-optimized machine types) + nodeSelector: + cloud.google.com/gke-nodepool: "database-pool" + cloud.google.com/machine-family: "n2" + + # Database authentication (REQUIRED - set secure credentials) + auth: + username: postgres + password: "your-secure-postgres-password" + database: simstudio + + # Resource allocation optimized for GKE + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + # Persistent storage using Google Cloud Persistent Disk + persistence: + enabled: true + storageClass: "standard-rwo" + size: 50Gi + accessModes: + - ReadWriteOnce + + # SSL/TLS configuration + tls: + enabled: true + certificatesSecret: postgres-tls-secret + + # PostgreSQL performance tuning for GCP infrastructure + config: + maxConnections: 1000 + sharedBuffers: "2GB" + maxWalSize: "8GB" + minWalSize: "160MB" + +# Ollama AI models with GPU acceleration (GCP GPU instances) +ollama: + enabled: true + replicaCount: 1 + + # GPU node targeting (recommended: T4 or V100 GPU instances) + nodeSelector: + cloud.google.com/gke-nodepool: "gpu-pool" + cloud.google.com/gke-accelerator: "nvidia-tesla-t4" + + tolerations: + - key: "nvidia.com/gpu" + operator: "Equal" + value: "present" + effect: "NoSchedule" + + # GPU resource allocation for AI model serving + gpu: + enabled: true + count: 1 + + resources: + limits: + memory: "16Gi" + cpu: "4000m" + nvidia.com/gpu: "1" + requests: + memory: "8Gi" + cpu: "2000m" + + # High-performance SSD storage for AI models + persistence: + enabled: true + storageClass: "premium-rwo" + size: 100Gi + accessModes: + - ReadWriteOnce + + env: + NVIDIA_DRIVER_CAPABILITIES: "all" + OLLAMA_LOAD_TIMEOUT: "-1" + OLLAMA_KEEP_ALIVE: "-1" + OLLAMA_DEBUG: "1" + +# Ingress using Google Cloud Load Balancer +ingress: + enabled: true + className: gce + + annotations: + kubernetes.io/ingress.class: gce + kubernetes.io/ingress.global-static-ip-name: "simstudio-ip" + networking.gke.io/managed-certificates: "simstudio-ssl-cert" + kubernetes.io/ingress.allow-http: "false" + + # Main application + app: + host: simstudio.acme.com + paths: + - path: / + pathType: Prefix + + # Realtime service + realtime: + host: simstudio-ws.acme.com + paths: + - path: / + pathType: Prefix + + # TLS configuration + tls: + enabled: true + secretName: simstudio-tls-secret + +# Pod disruption budget for high availability +podDisruptionBudget: + enabled: true + minAvailable: 1 + +# Network policies +networkPolicy: + enabled: true + +# Pod anti-affinity for high availability across GCP zones +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: ["simstudio"] + topologyKey: kubernetes.io/hostname + - weight: 50 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: ["simstudio"] + topologyKey: topology.gke.io/zone + +# Service Account with Workload Identity integration +serviceAccount: + create: true + annotations: + iam.gke.io/gcp-service-account: "simstudio@your-project-id.iam.gserviceaccount.com" + +# Additional environment variables for GCP service integration +extraEnvVars: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: "/var/secrets/google/key.json" + +# Additional volumes for service account credentials +extraVolumes: + - name: google-cloud-key + secret: + secretName: google-service-account-key + +extraVolumeMounts: + - name: google-cloud-key + mountPath: /var/secrets/google + readOnly: true \ No newline at end of file diff --git a/helm/sim/examples/values-production.yaml b/helm/sim/examples/values-production.yaml new file mode 100644 index 00000000000..a2915083e4c --- /dev/null +++ b/helm/sim/examples/values-production.yaml @@ -0,0 +1,210 @@ +# Production values for Sim Studio +# This configuration is suitable for production deployments + +# Global configuration +global: + imageRegistry: "ghcr.io" + storageClass: "managed-csi-premium" + +# Main application +app: + enabled: true + replicaCount: 2 + + resources: + limits: + memory: "6Gi" + cpu: "2000m" + requests: + memory: "4Gi" + cpu: "1000m" + + # Production URLs (REQUIRED - update with your actual domain names) + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + SOCKET_SERVER_URL: "https://simstudio-ws.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + + # Security settings (REQUIRED - replace with your own secure secrets) + BETTER_AUTH_SECRET: "your-production-auth-secret-here" + ENCRYPTION_KEY: "your-production-encryption-key-here" + + # Optional third-party service integrations (configure as needed) + RESEND_API_KEY: "your-resend-api-key" + GOOGLE_CLIENT_ID: "your-google-client-id" + GOOGLE_CLIENT_SECRET: "your-google-client-secret" + +# Realtime service +realtime: + enabled: true + replicaCount: 2 + + resources: + limits: + memory: "4Gi" + cpu: "1000m" + requests: + memory: "2Gi" + cpu: "500m" + + env: + NEXT_PUBLIC_APP_URL: "https://simstudio.acme.com" + BETTER_AUTH_URL: "https://simstudio.acme.com" + NEXT_PUBLIC_SOCKET_URL: "https://simstudio-ws.acme.com" + BETTER_AUTH_SECRET: "your-production-auth-secret-here" + ALLOWED_ORIGINS: "https://simstudio.acme.com" + +# Database migrations +migrations: + enabled: true + resources: + limits: + memory: "2Gi" + cpu: "1000m" + requests: + memory: "1Gi" + cpu: "500m" + +# PostgreSQL database +postgresql: + enabled: true + + # Database authentication (REQUIRED - set secure credentials) + auth: + username: postgres + password: "your-secure-postgres-password" + database: simstudio + + # Resource allocation for production workloads + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + # Persistent storage configuration + persistence: + enabled: true + storageClass: "managed-csi-premium" + size: 50Gi + + # SSL/TLS configuration (recommended for production) + tls: + enabled: true + certificatesSecret: postgres-tls-secret + + # PostgreSQL performance configuration for production + config: + maxConnections: 1000 + sharedBuffers: "2GB" + maxWalSize: "8GB" + minWalSize: "160MB" + +# Ollama AI models (optional - enable if you need local AI model serving) +ollama: + enabled: false + +# Ingress configuration +ingress: + enabled: true + className: nginx + + annotations: + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" + + # Main application + app: + host: simstudio.acme.com + paths: + - path: / + pathType: Prefix + + # Realtime service + realtime: + host: simstudio-ws.acme.com + paths: + - path: / + pathType: Prefix + + # TLS configuration + tls: + enabled: true + secretName: simstudio-tls-secret + +# Horizontal Pod Autoscaler (automatically scales pods based on CPU/memory usage) +autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 80 + behavior: + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 50 + periodSeconds: 60 + scaleUp: + stabilizationWindowSeconds: 60 + policies: + - type: Percent + value: 100 + periodSeconds: 15 + - type: Pods + value: 2 + periodSeconds: 60 + +# Pod disruption budget (ensures minimum availability during cluster maintenance) +podDisruptionBudget: + enabled: true + minAvailable: 1 + +# Monitoring integration with Prometheus +monitoring: + serviceMonitor: + enabled: true + labels: + monitoring: "prometheus" + interval: 15s + scrapeTimeout: 10s + +# Network policies (restricts pod-to-pod communication for security) +networkPolicy: + enabled: true + +# Shared storage for data sharing between pods (enterprise feature) +sharedStorage: + enabled: true + storageClass: "managed-csi-premium" + volumes: + - name: output-share + size: 100Gi + accessModes: + - ReadWriteMany + - name: model-share + size: 200Gi + accessModes: + - ReadWriteMany + +# Telemetry and observability (comprehensive monitoring and tracing) +telemetry: + enabled: true + resources: + limits: + memory: "1Gi" + cpu: "500m" + requests: + memory: "512Mi" + cpu: "200m" + # Configure endpoints based on your observability infrastructure + prometheus: + enabled: true + endpoint: "http://prometheus-server/api/v1/write" + jaeger: + enabled: true + endpoint: "http://jaeger-collector:14250" \ No newline at end of file diff --git a/helm/sim/templates/NOTES.txt b/helm/sim/templates/NOTES.txt new file mode 100644 index 00000000000..97468be200b --- /dev/null +++ b/helm/sim/templates/NOTES.txt @@ -0,0 +1,73 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} + http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.app.host }} +{{- else if contains "NodePort" .Values.app.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "simstudio.fullname" . }}-app) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.app.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "simstudio.fullname" . }}-app' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "simstudio.fullname" . }}-app --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.app.service.port }} +{{- else if contains "ClusterIP" .Values.app.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "{{ include "simstudio.app.selectorLabels" . }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} + +{{- if .Values.realtime.enabled }} + +2. Realtime service is available at: +{{- if .Values.ingress.enabled }} + http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.realtime.host }} +{{- else }} + Use port-forwarding: kubectl port-forward svc/{{ include "simstudio.fullname" . }}-realtime 3002:3002 +{{- end }} +{{- end }} + +{{- if .Values.postgresql.enabled }} + +3. PostgreSQL database is running internally and accessible to the application. + Database: {{ .Values.postgresql.auth.database }} + Username: {{ .Values.postgresql.auth.username }} +{{- end }} + +{{- if .Values.ollama.enabled }} + +4. Ollama service is available internally for AI model operations. +{{- end }} + +{{- if not .Values.postgresql.enabled }} + +WARNING: You have disabled the internal PostgreSQL database. +Make sure to configure an external database connection in your values.yaml file. +{{- end }} + +{{- if not .Values.app.env.BETTER_AUTH_SECRET }} + +⚠️ SECURITY WARNING: Required secrets are not configured! + +Please set the following REQUIRED values for production use: + + helm upgrade {{ .Release.Name }} ./charts/simstudio \ + --set app.env.BETTER_AUTH_SECRET="your-secure-32-char-secret-here" \ + --set app.env.ENCRYPTION_KEY="your-secure-32-char-encryption-key" \ + --set realtime.env.BETTER_AUTH_SECRET="your-secure-32-char-secret-here" \ + --set postgresql.auth.password="your-secure-database-password" + +Generate secure secrets using: + openssl rand -hex 32 + +{{- end }} + +{{- if not .Values.postgresql.enabled }} + +⚠️ DATABASE WARNING: You have disabled the internal PostgreSQL database. +Make sure to configure an external database connection in your values.yaml file. +{{- end }} + +For more information and configuration options, see: +- Chart documentation: https://github.com/simstudioai/sim/tree/main/charts/simstudio +- Sim Studio documentation: https://docs.simstudio.ai \ No newline at end of file diff --git a/helm/sim/templates/_helpers.tpl b/helm/sim/templates/_helpers.tpl new file mode 100644 index 00000000000..6526177532e --- /dev/null +++ b/helm/sim/templates/_helpers.tpl @@ -0,0 +1,303 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "simstudio.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "simstudio.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "simstudio.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "simstudio.labels" -}} +helm.sh/chart: {{ include "simstudio.chart" . }} +{{ include "simstudio.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.global.commonLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "simstudio.selectorLabels" -}} +app.kubernetes.io/name: {{ include "simstudio.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +App specific labels +*/}} +{{- define "simstudio.app.labels" -}} +{{ include "simstudio.labels" . }} +app.kubernetes.io/component: app +{{- end }} + +{{/* +App selector labels +*/}} +{{- define "simstudio.app.selectorLabels" -}} +{{ include "simstudio.selectorLabels" . }} +app.kubernetes.io/component: app +{{- end }} + +{{/* +Realtime specific labels +*/}} +{{- define "simstudio.realtime.labels" -}} +{{ include "simstudio.labels" . }} +app.kubernetes.io/component: realtime +{{- end }} + +{{/* +Realtime selector labels +*/}} +{{- define "simstudio.realtime.selectorLabels" -}} +{{ include "simstudio.selectorLabels" . }} +app.kubernetes.io/component: realtime +{{- end }} + +{{/* +PostgreSQL specific labels +*/}} +{{- define "simstudio.postgresql.labels" -}} +{{ include "simstudio.labels" . }} +app.kubernetes.io/component: postgresql +{{- end }} + +{{/* +PostgreSQL selector labels +*/}} +{{- define "simstudio.postgresql.selectorLabels" -}} +{{ include "simstudio.selectorLabels" . }} +app.kubernetes.io/component: postgresql +{{- end }} + +{{/* +Ollama specific labels +*/}} +{{- define "simstudio.ollama.labels" -}} +{{ include "simstudio.labels" . }} +app.kubernetes.io/component: ollama +{{- end }} + +{{/* +Ollama selector labels +*/}} +{{- define "simstudio.ollama.selectorLabels" -}} +{{ include "simstudio.selectorLabels" . }} +app.kubernetes.io/component: ollama +{{- end }} + +{{/* +Migrations specific labels +*/}} +{{- define "simstudio.migrations.labels" -}} +{{ include "simstudio.labels" . }} +app.kubernetes.io/component: migrations +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "simstudio.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "simstudio.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create image name with registry +Expects context with image object passed as second parameter +Usage: {{ include "simstudio.image" (dict "context" . "image" .Values.app.image) }} +*/}} +{{- define "simstudio.image" -}} +{{- $registry := "" -}} +{{- $repository := .image.repository -}} +{{- $tag := .image.tag | toString -}} +{{- /* Use global registry for simstudioai images or when explicitly set for all images */ -}} +{{- if .context.Values.global.imageRegistry -}} + {{- if or (hasPrefix "simstudioai/" $repository) .context.Values.global.useRegistryForAllImages -}} + {{- $registry = .context.Values.global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- if $registry -}} +{{- printf "%s/%s:%s" $registry $repository $tag }} +{{- else -}} +{{- printf "%s:%s" $repository $tag }} +{{- end -}} +{{- end }} + +{{/* +Database URL for internal PostgreSQL +*/}} +{{- define "simstudio.databaseUrl" -}} +{{- if .Values.postgresql.enabled }} +{{- $host := printf "%s-postgresql" (include "simstudio.fullname" .) }} +{{- $port := .Values.postgresql.service.port }} +{{- $username := .Values.postgresql.auth.username }} +{{- $database := .Values.postgresql.auth.database }} +{{- $sslMode := ternary "require" "disable" .Values.postgresql.tls.enabled }} +{{- printf "postgresql://%s:$(POSTGRES_PASSWORD)@%s:%v/%s?sslmode=%s" $username $host $port $database $sslMode }} +{{- else if .Values.externalDatabase.enabled }} +{{- $host := .Values.externalDatabase.host }} +{{- $port := .Values.externalDatabase.port }} +{{- $username := .Values.externalDatabase.username }} +{{- $database := .Values.externalDatabase.database }} +{{- $sslMode := .Values.externalDatabase.sslMode }} +{{- printf "postgresql://%s:$(EXTERNAL_DB_PASSWORD)@%s:%v/%s?sslmode=%s" $username $host $port $database $sslMode }} +{{- end }} +{{- end }} + +{{/* +Validate required secrets and reject default placeholder values +*/}} +{{- define "simstudio.validateSecrets" -}} +{{- if and .Values.app.enabled (not .Values.app.env.BETTER_AUTH_SECRET) }} +{{- fail "app.env.BETTER_AUTH_SECRET is required for production deployment" }} +{{- end }} +{{- if and .Values.app.enabled (eq .Values.app.env.BETTER_AUTH_SECRET "CHANGE-ME-32-CHAR-SECRET-FOR-PRODUCTION-USE") }} +{{- fail "app.env.BETTER_AUTH_SECRET must not use the default placeholder value. Generate a secure secret with: openssl rand -hex 32" }} +{{- end }} +{{- if and .Values.app.enabled (not .Values.app.env.ENCRYPTION_KEY) }} +{{- fail "app.env.ENCRYPTION_KEY is required for production deployment" }} +{{- end }} +{{- if and .Values.app.enabled (eq .Values.app.env.ENCRYPTION_KEY "CHANGE-ME-32-CHAR-ENCRYPTION-KEY-FOR-PROD") }} +{{- fail "app.env.ENCRYPTION_KEY must not use the default placeholder value. Generate a secure key with: openssl rand -hex 32" }} +{{- end }} +{{- if and .Values.realtime.enabled (eq .Values.realtime.env.BETTER_AUTH_SECRET "CHANGE-ME-32-CHAR-SECRET-FOR-PRODUCTION-USE") }} +{{- fail "realtime.env.BETTER_AUTH_SECRET must not use the default placeholder value. Generate a secure secret with: openssl rand -hex 32" }} +{{- end }} +{{- if and .Values.postgresql.enabled (not .Values.postgresql.auth.password) }} +{{- fail "postgresql.auth.password is required when using internal PostgreSQL" }} +{{- end }} +{{- if and .Values.postgresql.enabled (eq .Values.postgresql.auth.password "CHANGE-ME-SECURE-PASSWORD") }} +{{- fail "postgresql.auth.password must not use the default placeholder value. Set a secure password for production" }} +{{- end }} +{{- if and .Values.externalDatabase.enabled (not .Values.externalDatabase.password) }} +{{- fail "externalDatabase.password is required when using external database" }} +{{- end }} +{{- end }} + +{{/* +Ollama URL +*/}} +{{- define "simstudio.ollamaUrl" -}} +{{- if .Values.ollama.enabled }} +{{- $serviceName := printf "%s-ollama" (include "simstudio.fullname" .) }} +{{- $port := .Values.ollama.service.port }} +{{- printf "http://%s:%v" $serviceName $port }} +{{- else }} +{{- .Values.app.env.OLLAMA_URL | default "http://localhost:11434" }} +{{- end }} +{{- end }} + +{{/* +Socket Server URL (internal) +*/}} +{{- define "simstudio.socketServerUrl" -}} +{{- if .Values.realtime.enabled }} +{{- $serviceName := printf "%s-realtime" (include "simstudio.fullname" .) }} +{{- $port := .Values.realtime.service.port }} +{{- printf "http://%s:%v" $serviceName $port }} +{{- else }} +{{- .Values.app.env.SOCKET_SERVER_URL | default "http://localhost:3002" }} +{{- end }} +{{- end }} + +{{/* +Resource limits and requests +*/}} +{{- define "simstudio.resources" -}} +{{- if .resources }} +resources: + {{- if .resources.limits }} + limits: + {{- toYaml .resources.limits | nindent 4 }} + {{- end }} + {{- if .resources.requests }} + requests: + {{- toYaml .resources.requests | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} + +{{/* +Security context +*/}} +{{- define "simstudio.securityContext" -}} +{{- if .securityContext }} +securityContext: + {{- toYaml .securityContext | nindent 2 }} +{{- end }} +{{- end }} + +{{/* +Pod security context +*/}} +{{- define "simstudio.podSecurityContext" -}} +{{- if .podSecurityContext }} +securityContext: + {{- toYaml .podSecurityContext | nindent 2 }} +{{- end }} +{{- end }} + +{{/* +Node selector +*/}} +{{- define "simstudio.nodeSelector" -}} +{{- if .nodeSelector }} +nodeSelector: + {{- toYaml .nodeSelector | nindent 2 }} +{{- end }} +{{- end }} + +{{/* +Tolerations +*/}} +{{- define "simstudio.tolerations" -}} +{{- if .tolerations }} +tolerations: + {{- toYaml .tolerations | nindent 2 }} +{{- end }} +{{- end }} + +{{/* +Affinity +*/}} +{{- define "simstudio.affinity" -}} +{{- if .affinity }} +affinity: + {{- toYaml .affinity | nindent 2 }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/deployment-app.yaml b/helm/sim/templates/deployment-app.yaml new file mode 100644 index 00000000000..8d9f8ca1e39 --- /dev/null +++ b/helm/sim/templates/deployment-app.yaml @@ -0,0 +1,117 @@ +{{- if .Values.app.enabled }} +{{- include "simstudio.validateSecrets" . }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "simstudio.fullname" . }}-app + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.app.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.app.replicaCount }} + selector: + matchLabels: + {{- include "simstudio.app.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "simstudio.app.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "simstudio.serviceAccountName" . }} + {{- include "simstudio.podSecurityContext" .Values.app | nindent 6 }} + {{- include "simstudio.nodeSelector" .Values.app | nindent 6 }} + {{- include "simstudio.tolerations" .Values | nindent 6 }} + {{- include "simstudio.affinity" .Values | nindent 6 }} + {{- if .Values.migrations.enabled }} + initContainers: + - name: migrations + image: {{ include "simstudio.image" (dict "context" . "image" .Values.migrations.image) }} + imagePullPolicy: {{ .Values.migrations.image.pullPolicy }} + command: ["bun", "run", "db:migrate"] + env: + - name: DATABASE_URL + value: {{ include "simstudio.databaseUrl" . | quote }} + {{- if .Values.postgresql.enabled }} + envFrom: + - secretRef: + name: {{ include "simstudio.fullname" . }}-postgresql-secret + {{- else if .Values.externalDatabase.enabled }} + envFrom: + - secretRef: + name: {{ include "simstudio.fullname" . }}-external-db-secret + {{- end }} + {{- include "simstudio.resources" .Values.migrations | nindent 10 }} + {{- include "simstudio.securityContext" .Values.migrations | nindent 10 }} + {{- end }} + containers: + - name: app + image: {{ include "simstudio.image" (dict "context" . "image" .Values.app.image) }} + imagePullPolicy: {{ .Values.app.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.app.service.targetPort }} + protocol: TCP + env: + - name: DATABASE_URL + value: {{ include "simstudio.databaseUrl" . | quote }} + - name: SOCKET_SERVER_URL + value: {{ include "simstudio.socketServerUrl" . | quote }} + - name: OLLAMA_URL + value: {{ include "simstudio.ollamaUrl" . | quote }} + {{- range $key, $value := .Values.app.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- if .Values.telemetry.enabled }} + # OpenTelemetry configuration + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://{{ include "simstudio.fullname" . }}-otel-collector:4318" + - name: OTEL_SERVICE_NAME + value: simstudio-app + - name: OTEL_SERVICE_VERSION + value: {{ .Chart.AppVersion | quote }} + - name: OTEL_RESOURCE_ATTRIBUTES + value: "service.name=simstudio-app,service.version={{ .Chart.AppVersion }},deployment.environment={{ .Values.app.env.NODE_ENV }}" + {{- end }} + {{- with .Values.extraEnvVars }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.postgresql.enabled }} + envFrom: + - secretRef: + name: {{ include "simstudio.fullname" . }}-postgresql-secret + {{- else if .Values.externalDatabase.enabled }} + envFrom: + - secretRef: + name: {{ include "simstudio.fullname" . }}-external-db-secret + {{- end }} + {{- if .Values.app.livenessProbe }} + livenessProbe: + {{- toYaml .Values.app.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.app.readinessProbe }} + readinessProbe: + {{- toYaml .Values.app.readinessProbe | nindent 12 }} + {{- end }} + {{- include "simstudio.resources" .Values.app | nindent 10 }} + {{- include "simstudio.securityContext" .Values.app | nindent 10 }} + {{- with .Values.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.extraVolumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/deployment-ollama.yaml b/helm/sim/templates/deployment-ollama.yaml new file mode 100644 index 00000000000..097baa49c1d --- /dev/null +++ b/helm/sim/templates/deployment-ollama.yaml @@ -0,0 +1,112 @@ +{{- if .Values.ollama.enabled }} +--- +# PersistentVolumeClaim for Ollama data +{{- if .Values.ollama.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "simstudio.fullname" . }}-ollama-data + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.ollama.labels" . | nindent 4 }} +spec: + {{- if .Values.ollama.persistence.storageClass }} + {{- if (eq "-" .Values.ollama.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.ollama.persistence.storageClass | quote }} + {{- end }} + {{- else if .Values.global.storageClass }} + storageClassName: {{ .Values.global.storageClass | quote }} + {{- end }} + accessModes: + {{- range .Values.ollama.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.ollama.persistence.size | quote }} +{{- end }} + +--- +# Deployment for Ollama +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "simstudio.fullname" . }}-ollama + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.ollama.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.ollama.replicaCount }} + selector: + matchLabels: + {{- include "simstudio.ollama.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "simstudio.ollama.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "simstudio.serviceAccountName" . }} + {{- include "simstudio.nodeSelector" .Values.ollama | nindent 6 }} + {{- include "simstudio.tolerations" .Values.ollama | nindent 6 }} + {{- include "simstudio.affinity" .Values | nindent 6 }} + containers: + - name: ollama + image: {{ include "simstudio.image" (dict "context" . "image" .Values.ollama.image) }} + imagePullPolicy: {{ .Values.ollama.image.pullPolicy }} + command: ["ollama", "serve"] + ports: + - name: http + containerPort: {{ .Values.ollama.service.targetPort }} + protocol: TCP + env: + {{- range $key, $value := .Values.ollama.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- with .Values.extraEnvVars }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.ollama.startupProbe }} + startupProbe: + {{- toYaml .Values.ollama.startupProbe | nindent 12 }} + {{- end }} + {{- if .Values.ollama.livenessProbe }} + livenessProbe: + {{- toYaml .Values.ollama.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.ollama.readinessProbe }} + readinessProbe: + {{- toYaml .Values.ollama.readinessProbe | nindent 12 }} + {{- end }} + {{- include "simstudio.resources" .Values.ollama | nindent 10 }} + {{- if .Values.ollama.persistence.enabled }} + volumeMounts: + - name: ollama-data + mountPath: /root/.ollama + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.ollama.persistence.enabled }} + volumes: + - name: ollama-data + persistentVolumeClaim: + claimName: {{ include "simstudio.fullname" . }}-ollama-data + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/deployment-realtime.yaml b/helm/sim/templates/deployment-realtime.yaml new file mode 100644 index 00000000000..45386937ee1 --- /dev/null +++ b/helm/sim/templates/deployment-realtime.yaml @@ -0,0 +1,92 @@ +{{- if .Values.realtime.enabled }} +{{- include "simstudio.validateSecrets" . }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "simstudio.fullname" . }}-realtime + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.realtime.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.realtime.replicaCount }} + selector: + matchLabels: + {{- include "simstudio.realtime.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "simstudio.realtime.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "simstudio.serviceAccountName" . }} + {{- include "simstudio.podSecurityContext" .Values.realtime | nindent 6 }} + {{- include "simstudio.nodeSelector" .Values.realtime | nindent 6 }} + {{- include "simstudio.tolerations" .Values | nindent 6 }} + {{- include "simstudio.affinity" .Values | nindent 6 }} + containers: + - name: realtime + image: {{ include "simstudio.image" (dict "context" . "image" .Values.realtime.image) }} + imagePullPolicy: {{ .Values.realtime.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.realtime.service.targetPort }} + protocol: TCP + env: + - name: DATABASE_URL + value: {{ include "simstudio.databaseUrl" . | quote }} + {{- range $key, $value := .Values.realtime.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- if .Values.telemetry.enabled }} + # OpenTelemetry configuration + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://{{ include "simstudio.fullname" . }}-otel-collector:4318" + - name: OTEL_SERVICE_NAME + value: simstudio-realtime + - name: OTEL_SERVICE_VERSION + value: {{ .Chart.AppVersion | quote }} + - name: OTEL_RESOURCE_ATTRIBUTES + value: "service.name=simstudio-realtime,service.version={{ .Chart.AppVersion }},deployment.environment={{ .Values.realtime.env.NODE_ENV }}" + {{- end }} + {{- with .Values.extraEnvVars }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.postgresql.enabled }} + envFrom: + - secretRef: + name: {{ include "simstudio.fullname" . }}-postgresql-secret + {{- else if .Values.externalDatabase.enabled }} + envFrom: + - secretRef: + name: {{ include "simstudio.fullname" . }}-external-db-secret + {{- end }} + {{- if .Values.realtime.livenessProbe }} + livenessProbe: + {{- toYaml .Values.realtime.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.realtime.readinessProbe }} + readinessProbe: + {{- toYaml .Values.realtime.readinessProbe | nindent 12 }} + {{- end }} + {{- include "simstudio.resources" .Values.realtime | nindent 10 }} + {{- include "simstudio.securityContext" .Values.realtime | nindent 10 }} + {{- with .Values.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.extraVolumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/gpu-device-plugin.yaml b/helm/sim/templates/gpu-device-plugin.yaml new file mode 100644 index 00000000000..780fd3a338f --- /dev/null +++ b/helm/sim/templates/gpu-device-plugin.yaml @@ -0,0 +1,100 @@ +{{- if and .Values.ollama.enabled .Values.ollama.gpu.enabled }} +--- +# NVIDIA Device Plugin DaemonSet for GPU support +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "simstudio.fullname" . }}-nvidia-device-plugin + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.labels" . | nindent 4 }} + app.kubernetes.io/component: nvidia-device-plugin +spec: + selector: + matchLabels: + {{- include "simstudio.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: nvidia-device-plugin + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + {{- include "simstudio.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: nvidia-device-plugin + spec: + tolerations: + # Allow scheduling on GPU nodes + - key: nvidia.com/gpu + operator: Exists + effect: NoSchedule + - key: sku + operator: Equal + value: gpu + effect: NoSchedule + nodeSelector: + # Only schedule on nodes with NVIDIA GPUs + accelerator: nvidia + priorityClassName: system-node-critical + runtimeClassName: nvidia + hostNetwork: true + hostPID: true + volumes: + - name: device-plugin + hostPath: + path: /var/lib/kubelet/device-plugins + - name: dev + hostPath: + path: /dev + - name: sys + hostPath: + path: /sys + - name: proc-driver-nvidia + hostPath: + path: /proc/driver/nvidia + containers: + - name: nvidia-device-plugin + image: nvcr.io/nvidia/k8s-device-plugin:v0.14.5 + imagePullPolicy: Always + args: + - --mig-strategy=single + - --pass-device-specs=true + - --fail-on-init-error=false + - --device-list-strategy=envvar + - --nvidia-driver-root=/host-sys/fs/cgroup + env: + - name: NVIDIA_MIG_MONITOR_DEVICES + value: all + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + volumeMounts: + - name: device-plugin + mountPath: /var/lib/kubelet/device-plugins + - name: dev + mountPath: /dev + - name: sys + mountPath: /host-sys + readOnly: true + - name: proc-driver-nvidia + mountPath: /proc/driver/nvidia + readOnly: true + resources: + requests: + cpu: 50m + memory: 10Mi + limits: + cpu: 50m + memory: 20Mi + {{- if .Values.nodeSelector }} + nodeSelector: + {{- toYaml .Values.nodeSelector | nindent 8 }} + {{- end }} +--- +# RuntimeClass for NVIDIA Container Runtime +apiVersion: node.k8s.io/v1 +kind: RuntimeClass +metadata: + name: nvidia +handler: nvidia +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/hpa.yaml b/helm/sim/templates/hpa.yaml new file mode 100644 index 00000000000..12733426dc3 --- /dev/null +++ b/helm/sim/templates/hpa.yaml @@ -0,0 +1,85 @@ +{{- if .Values.autoscaling.enabled }} +--- +# HorizontalPodAutoscaler for main application +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "simstudio.fullname" . }}-app + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.app.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "simstudio.fullname" . }}-app + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} + {{- with .Values.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.autoscaling.behavior }} + behavior: + {{- toYaml .Values.autoscaling.behavior | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.autoscaling.enabled .Values.realtime.enabled }} +--- +# HorizontalPodAutoscaler for realtime service +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "simstudio.fullname" . }}-realtime + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.realtime.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "simstudio.fullname" . }}-realtime + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} + {{- with .Values.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.autoscaling.behavior }} + behavior: + {{- toYaml .Values.autoscaling.behavior | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/ingress.yaml b/helm/sim/templates/ingress.yaml new file mode 100644 index 00000000000..dae55a838a9 --- /dev/null +++ b/helm/sim/templates/ingress.yaml @@ -0,0 +1,55 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "simstudio.fullname" . }}-ingress + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.app.host }} + {{- if .Values.realtime.enabled }} + - {{ .Values.ingress.realtime.host }} + {{- end }} + secretName: {{ .Values.ingress.tls.secretName }} + {{- end }} + rules: + # Main application ingress rule + - host: {{ .Values.ingress.app.host }} + http: + paths: + {{- range .Values.ingress.app.paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "simstudio.fullname" $ }}-app + port: + number: {{ $.Values.app.service.port }} + {{- end }} + {{- if .Values.realtime.enabled }} + # Realtime service ingress rule + - host: {{ .Values.ingress.realtime.host }} + http: + paths: + {{- range .Values.ingress.realtime.paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "simstudio.fullname" $ }}-realtime + port: + number: {{ $.Values.realtime.service.port }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/networkpolicy.yaml b/helm/sim/templates/networkpolicy.yaml new file mode 100644 index 00000000000..0562075e16d --- /dev/null +++ b/helm/sim/templates/networkpolicy.yaml @@ -0,0 +1,242 @@ +{{- if .Values.networkPolicy.enabled }} +--- +# Network Policy for main application +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "simstudio.fullname" . }}-app + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.app.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "simstudio.app.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + ingress: + # Allow ingress from realtime service + {{- if .Values.realtime.enabled }} + - from: + - podSelector: + matchLabels: + {{- include "simstudio.realtime.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.app.service.targetPort }} + {{- end }} + # Allow ingress from ingress controller + {{- if .Values.ingress.enabled }} + - from: [] + ports: + - protocol: TCP + port: {{ .Values.app.service.targetPort }} + {{- end }} + # Allow custom ingress rules + {{- with .Values.networkPolicy.ingress }} + {{- toYaml . | nindent 2 }} + {{- end }} + egress: + # Allow egress to PostgreSQL + {{- if .Values.postgresql.enabled }} + - to: + - podSelector: + matchLabels: + {{- include "simstudio.postgresql.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.postgresql.service.targetPort }} + {{- end }} + # Allow egress to realtime service + {{- if .Values.realtime.enabled }} + - to: + - podSelector: + matchLabels: + {{- include "simstudio.realtime.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.realtime.service.targetPort }} + {{- end }} + # Allow egress to Ollama + {{- if .Values.ollama.enabled }} + - to: + - podSelector: + matchLabels: + {{- include "simstudio.ollama.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.ollama.service.targetPort }} + {{- end }} + # Allow DNS resolution + - to: [] + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + # Allow HTTPS egress for external APIs + - to: [] + ports: + - protocol: TCP + port: 443 + # Allow custom egress rules + {{- with .Values.networkPolicy.egress }} + {{- toYaml . | nindent 2 }} + {{- end }} + +{{- if .Values.realtime.enabled }} +--- +# Network Policy for realtime service +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "simstudio.fullname" . }}-realtime + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.realtime.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "simstudio.realtime.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + ingress: + # Allow ingress from main application + - from: + - podSelector: + matchLabels: + {{- include "simstudio.app.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.realtime.service.targetPort }} + # Allow ingress from ingress controller + {{- if .Values.ingress.enabled }} + - from: [] + ports: + - protocol: TCP + port: {{ .Values.realtime.service.targetPort }} + {{- end }} + egress: + # Allow egress to PostgreSQL + {{- if .Values.postgresql.enabled }} + - to: + - podSelector: + matchLabels: + {{- include "simstudio.postgresql.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.postgresql.service.targetPort }} + {{- end }} + # Allow DNS resolution + - to: [] + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + # Allow HTTPS egress for external APIs + - to: [] + ports: + - protocol: TCP + port: 443 +{{- end }} + +{{- if .Values.postgresql.enabled }} +--- +# Network Policy for PostgreSQL +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "simstudio.fullname" . }}-postgresql + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.postgresql.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "simstudio.postgresql.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + ingress: + # Allow ingress from main application + - from: + - podSelector: + matchLabels: + {{- include "simstudio.app.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.postgresql.service.targetPort }} + # Allow ingress from realtime service + {{- if .Values.realtime.enabled }} + - from: + - podSelector: + matchLabels: + {{- include "simstudio.realtime.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.postgresql.service.targetPort }} + {{- end }} + # Allow ingress from migrations job + {{- if .Values.migrations.enabled }} + - from: + - podSelector: + matchLabels: + {{- include "simstudio.migrations.labels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.postgresql.service.targetPort }} + {{- end }} + egress: + # Allow minimal egress (for health checks, etc.) + - to: [] + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 +{{- end }} + +{{- if .Values.ollama.enabled }} +--- +# Network Policy for Ollama +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "simstudio.fullname" . }}-ollama + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.ollama.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "simstudio.ollama.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + ingress: + # Allow ingress from main application + - from: + - podSelector: + matchLabels: + {{- include "simstudio.app.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.ollama.service.targetPort }} + egress: + # Allow DNS resolution + - to: [] + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + # Allow HTTPS egress for model downloads + - to: [] + ports: + - protocol: TCP + port: 443 +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/serviceaccount.yaml b/helm/sim/templates/serviceaccount.yaml new file mode 100644 index 00000000000..dc7e76bfa5c --- /dev/null +++ b/helm/sim/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "simstudio.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/servicemonitor.yaml b/helm/sim/templates/servicemonitor.yaml new file mode 100644 index 00000000000..b4336b3d9e0 --- /dev/null +++ b/helm/sim/templates/servicemonitor.yaml @@ -0,0 +1,79 @@ +{{- if .Values.monitoring.serviceMonitor.enabled }} +--- +# ServiceMonitor for main application +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "simstudio.fullname" . }}-app + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.app.labels" . | nindent 4 }} + {{- with .Values.monitoring.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.monitoring.serviceMonitor.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "simstudio.app.selectorLabels" . | nindent 6 }} + endpoints: + - port: http + path: {{ .Values.monitoring.serviceMonitor.path }} + interval: {{ .Values.monitoring.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.monitoring.serviceMonitor.scrapeTimeout }} + {{- with .Values.monitoring.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.monitoring.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .Values.monitoring.serviceMonitor.targetLabels }} + targetLabels: + {{- toYaml .Values.monitoring.serviceMonitor.targetLabels | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.monitoring.serviceMonitor.enabled .Values.realtime.enabled }} +--- +# ServiceMonitor for realtime service +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "simstudio.fullname" . }}-realtime + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.realtime.labels" . | nindent 4 }} + {{- with .Values.monitoring.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.monitoring.serviceMonitor.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "simstudio.realtime.selectorLabels" . | nindent 6 }} + endpoints: + - port: http + path: {{ .Values.monitoring.serviceMonitor.path }} + interval: {{ .Values.monitoring.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.monitoring.serviceMonitor.scrapeTimeout }} + {{- with .Values.monitoring.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.monitoring.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- if .Values.monitoring.serviceMonitor.targetLabels }} + targetLabels: + {{- toYaml .Values.monitoring.serviceMonitor.targetLabels | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/services.yaml b/helm/sim/templates/services.yaml new file mode 100644 index 00000000000..3089c1a01a2 --- /dev/null +++ b/helm/sim/templates/services.yaml @@ -0,0 +1,83 @@ +{{- if .Values.app.enabled }} +--- +# Service for main application +apiVersion: v1 +kind: Service +metadata: + name: {{ include "simstudio.fullname" . }}-app + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.app.labels" . | nindent 4 }} +spec: + type: {{ .Values.app.service.type }} + ports: + - port: {{ .Values.app.service.port }} + targetPort: {{ .Values.app.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "simstudio.app.selectorLabels" . | nindent 4 }} +{{- end }} + +{{- if .Values.realtime.enabled }} +--- +# Service for realtime server +apiVersion: v1 +kind: Service +metadata: + name: {{ include "simstudio.fullname" . }}-realtime + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.realtime.labels" . | nindent 4 }} +spec: + type: {{ .Values.realtime.service.type }} + ports: + - port: {{ .Values.realtime.service.port }} + targetPort: {{ .Values.realtime.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "simstudio.realtime.selectorLabels" . | nindent 4 }} +{{- end }} + +{{- if .Values.postgresql.enabled }} +--- +# Service for PostgreSQL +apiVersion: v1 +kind: Service +metadata: + name: {{ include "simstudio.fullname" . }}-postgresql + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.postgresql.labels" . | nindent 4 }} +spec: + type: {{ .Values.postgresql.service.type }} + ports: + - port: {{ .Values.postgresql.service.port }} + targetPort: {{ .Values.postgresql.service.targetPort }} + protocol: TCP + name: postgresql + selector: + {{- include "simstudio.postgresql.selectorLabels" . | nindent 4 }} +{{- end }} + +{{- if .Values.ollama.enabled }} +--- +# Service for Ollama +apiVersion: v1 +kind: Service +metadata: + name: {{ include "simstudio.fullname" . }}-ollama + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.ollama.labels" . | nindent 4 }} +spec: + type: {{ .Values.ollama.service.type }} + ports: + - port: {{ .Values.ollama.service.port }} + targetPort: {{ .Values.ollama.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "simstudio.ollama.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/shared-storage.yaml b/helm/sim/templates/shared-storage.yaml new file mode 100644 index 00000000000..85c535a3bbc --- /dev/null +++ b/helm/sim/templates/shared-storage.yaml @@ -0,0 +1,48 @@ +{{- if .Values.sharedStorage.enabled }} +{{- range .Values.sharedStorage.volumes }} +--- +# Shared Storage PVC for {{ .name }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "simstudio.fullname" $ }}-{{ .name }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "simstudio.labels" $ | nindent 4 }} + simstudio.ai/volume-type: shared-storage + simstudio.ai/volume-name: {{ .name }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .storageClass }} + {{- if (eq "-" .storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .storageClass | quote }} + {{- end }} + {{- else if $.Values.sharedStorage.storageClass }} + storageClassName: {{ $.Values.sharedStorage.storageClass | quote }} + {{- else if $.Values.global.storageClass }} + storageClassName: {{ $.Values.global.storageClass | quote }} + {{- end }} + accessModes: + {{- if .accessModes }} + {{- range .accessModes }} + - {{ . | quote }} + {{- end }} + {{- else }} + {{- range $.Values.sharedStorage.defaultAccessModes }} + - {{ . | quote }} + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .size | quote }} + {{- if .selector }} + selector: + {{- toYaml .selector | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/statefulset-postgresql.yaml b/helm/sim/templates/statefulset-postgresql.yaml new file mode 100644 index 00000000000..156d25880ea --- /dev/null +++ b/helm/sim/templates/statefulset-postgresql.yaml @@ -0,0 +1,194 @@ +{{- if .Values.postgresql.enabled }} +--- +# ConfigMap for PostgreSQL configuration +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "simstudio.fullname" . }}-postgresql-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.postgresql.labels" . | nindent 4 }} +data: + postgresql.conf: | + hba_file = '/etc/postgresql/pg_hba.conf' + listen_addresses = '0.0.0.0' + max_connections = {{ .Values.postgresql.config.maxConnections }} + tcp_keepalives_idle = 60 + tcp_keepalives_interval = 5 + tcp_keepalives_count = 3 + authentication_timeout = 1min + password_encryption = scram-sha-256 + {{- if .Values.postgresql.tls.enabled }} + ssl = on + ssl_cert_file = '/etc/postgresql/tls/tls.crt' + ssl_key_file = '/etc/postgresql/tls/tls.key' + {{- else }} + ssl = off + {{- end }} + shared_buffers = {{ .Values.postgresql.config.sharedBuffers }} + dynamic_shared_memory_type = posix + max_wal_size = {{ .Values.postgresql.config.maxWalSize }} + min_wal_size = {{ .Values.postgresql.config.minWalSize }} + log_timezone = 'Etc/UTC' + idle_in_transaction_session_timeout = 50000000 + datestyle = 'iso, mdy' + timezone = 'Etc/UTC' + lc_messages = 'en_US.utf8' + lc_monetary = 'en_US.utf8' + lc_numeric = 'en_US.utf8' + lc_time = 'en_US.utf8' + default_text_search_config = 'pg_catalog.english' + + pg_hba.conf: | + # Secure authentication for all connections + local all all scram-sha-256 + host all all 127.0.0.1/32 scram-sha-256 + host all all ::1/128 scram-sha-256 + host all all all scram-sha-256 + + # Replication connections also require authentication + local replication all scram-sha-256 + host replication all 127.0.0.1/32 scram-sha-256 + host replication all ::1/128 scram-sha-256 + +--- +# ConfigMap for PostgreSQL environment variables +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "simstudio.fullname" . }}-postgresql-env + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.postgresql.labels" . | nindent 4 }} +data: + POSTGRES_DB: {{ .Values.postgresql.auth.database | quote }} + POSTGRES_USER: {{ .Values.postgresql.auth.username | quote }} + +--- +# Secret for PostgreSQL password +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "simstudio.fullname" . }}-postgresql-secret + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.postgresql.labels" . | nindent 4 }} +type: Opaque +data: + POSTGRES_PASSWORD: {{ .Values.postgresql.auth.password | b64enc }} + +--- +# StatefulSet for PostgreSQL +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "simstudio.fullname" . }}-postgresql + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.postgresql.labels" . | nindent 4 }} +spec: + serviceName: {{ include "simstudio.fullname" . }}-postgresql + replicas: 1 + minReadySeconds: 10 + selector: + matchLabels: + {{- include "simstudio.postgresql.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "simstudio.postgresql.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "simstudio.serviceAccountName" . }} + {{- include "simstudio.podSecurityContext" .Values.postgresql | nindent 6 }} + {{- include "simstudio.nodeSelector" .Values.postgresql | nindent 6 }} + {{- include "simstudio.tolerations" .Values | nindent 6 }} + {{- include "simstudio.affinity" .Values | nindent 6 }} + containers: + - name: postgresql + image: {{ include "simstudio.image" (dict "context" . "image" .Values.postgresql.image) }} + imagePullPolicy: {{ .Values.postgresql.image.pullPolicy }} + args: ["-c", "config_file=/etc/postgresql/postgresql.conf"] + ports: + - name: postgresql + containerPort: {{ .Values.postgresql.service.targetPort }} + protocol: TCP + envFrom: + - configMapRef: + name: {{ include "simstudio.fullname" . }}-postgresql-env + - secretRef: + name: {{ include "simstudio.fullname" . }}-postgresql-secret + {{- if .Values.postgresql.livenessProbe }} + livenessProbe: + {{- toYaml .Values.postgresql.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.postgresql.readinessProbe }} + readinessProbe: + {{- toYaml .Values.postgresql.readinessProbe | nindent 12 }} + {{- end }} + {{- include "simstudio.resources" .Values.postgresql | nindent 10 }} + {{- include "simstudio.securityContext" .Values.postgresql | nindent 10 }} + volumeMounts: + {{- if .Values.postgresql.persistence.enabled }} + - name: postgresql-data + mountPath: /var/lib/postgresql/data + subPath: pgdata + {{- end }} + - name: postgresql-config + mountPath: "/etc/postgresql" + {{- if .Values.postgresql.tls.enabled }} + - name: postgresql-tls + mountPath: "/etc/postgresql/tls" + readOnly: true + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: postgresql-config + configMap: + name: {{ include "simstudio.fullname" . }}-postgresql-config + {{- if .Values.postgresql.tls.enabled }} + - name: postgresql-tls + secret: + secretName: {{ .Values.postgresql.tls.certificatesSecret }} + defaultMode: 0600 + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.postgresql.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: postgresql-data + labels: + {{- include "simstudio.postgresql.labels" . | nindent 10 }} + spec: + {{- if .Values.postgresql.persistence.storageClass }} + {{- if (eq "-" .Values.postgresql.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.postgresql.persistence.storageClass | quote }} + {{- end }} + {{- else if .Values.global.storageClass }} + storageClassName: {{ .Values.global.storageClass | quote }} + {{- end }} + accessModes: + {{- range .Values.postgresql.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.postgresql.persistence.size | quote }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/sim/templates/telemetry.yaml b/helm/sim/templates/telemetry.yaml new file mode 100644 index 00000000000..cfc1338a2ec --- /dev/null +++ b/helm/sim/templates/telemetry.yaml @@ -0,0 +1,206 @@ +{{- if .Values.telemetry.enabled }} +--- +# OpenTelemetry Collector Configuration +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "simstudio.fullname" . }}-otel-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.labels" . | nindent 4 }} + app.kubernetes.io/component: telemetry +data: + otel-config.yaml: | + receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 + prometheus: + config: + scrape_configs: + - job_name: 'simstudio-app' + static_configs: + - targets: ['{{ include "simstudio.fullname" . }}-app:{{ .Values.app.service.port }}'] + - job_name: 'simstudio-realtime' + static_configs: + - targets: ['{{ include "simstudio.fullname" . }}-realtime:{{ .Values.realtime.service.port }}'] + + processors: + batch: + timeout: 1s + send_batch_size: 1024 + memory_limiter: + limit_mib: 512 + + exporters: + {{- if .Values.telemetry.jaeger.enabled }} + jaeger: + endpoint: {{ .Values.telemetry.jaeger.endpoint }} + tls: + insecure: {{ not .Values.telemetry.jaeger.tls.enabled }} + {{- end }} + {{- if .Values.telemetry.prometheus.enabled }} + prometheusremotewrite: + endpoint: {{ .Values.telemetry.prometheus.endpoint }} + headers: + Authorization: {{ .Values.telemetry.prometheus.auth | quote }} + {{- end }} + {{- if .Values.telemetry.otlp.enabled }} + otlp: + endpoint: {{ .Values.telemetry.otlp.endpoint }} + tls: + insecure: {{ not .Values.telemetry.otlp.tls.enabled }} + {{- end }} + logging: + loglevel: info + + extensions: + health_check: + endpoint: 0.0.0.0:13133 + pprof: + endpoint: 0.0.0.0:1777 + zpages: + endpoint: 0.0.0.0:55679 + + service: + extensions: [health_check, pprof, zpages] + pipelines: + traces: + receivers: [otlp] + processors: [memory_limiter, batch] + exporters: [{{- if .Values.telemetry.jaeger.enabled }}jaeger, {{- end }}{{- if .Values.telemetry.otlp.enabled }}otlp, {{- end }}logging] + metrics: + receivers: [otlp, prometheus] + processors: [memory_limiter, batch] + exporters: [{{- if .Values.telemetry.prometheus.enabled }}prometheusremotewrite, {{- end }}{{- if .Values.telemetry.otlp.enabled }}otlp, {{- end }}logging] + logs: + receivers: [otlp] + processors: [memory_limiter, batch] + exporters: [{{- if .Values.telemetry.otlp.enabled }}otlp, {{- end }}logging] +--- +# OpenTelemetry Collector Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "simstudio.fullname" . }}-otel-collector + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.labels" . | nindent 4 }} + app.kubernetes.io/component: telemetry +spec: + replicas: {{ .Values.telemetry.replicaCount }} + selector: + matchLabels: + {{- include "simstudio.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: telemetry + template: + metadata: + labels: + {{- include "simstudio.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: telemetry + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "simstudio.serviceAccountName" . }} + securityContext: + runAsNonRoot: true + runAsUser: 10001 + fsGroup: 10001 + containers: + - name: otel-collector + image: {{ include "simstudio.image" (dict "context" . "image" .Values.telemetry.image) }} + imagePullPolicy: {{ .Values.telemetry.image.pullPolicy }} + command: + - /otelcol-contrib + - --config=/etc/otel-collector-config/otel-config.yaml + ports: + - name: otlp-grpc + containerPort: 4317 + protocol: TCP + - name: otlp-http + containerPort: 4318 + protocol: TCP + - name: health + containerPort: 13133 + protocol: TCP + - name: pprof + containerPort: 1777 + protocol: TCP + - name: zpages + containerPort: 55679 + protocol: TCP + env: + - name: GOGC + value: "80" + volumeMounts: + - name: otel-config + mountPath: /etc/otel-collector-config + readOnly: true + livenessProbe: + httpGet: + path: / + port: health + initialDelaySeconds: 10 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: health + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + resources: + {{- toYaml .Values.telemetry.resources | nindent 12 }} + volumes: + - name: otel-config + configMap: + name: {{ include "simstudio.fullname" . }}-otel-config + {{- with .Values.telemetry.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.telemetry.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.telemetry.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} +--- +# OpenTelemetry Collector Service +apiVersion: v1 +kind: Service +metadata: + name: {{ include "simstudio.fullname" . }}-otel-collector + namespace: {{ .Release.Namespace }} + labels: + {{- include "simstudio.labels" . | nindent 4 }} + app.kubernetes.io/component: telemetry +spec: + type: {{ .Values.telemetry.service.type }} + ports: + - name: otlp-grpc + port: 4317 + targetPort: otlp-grpc + protocol: TCP + - name: otlp-http + port: 4318 + targetPort: otlp-http + protocol: TCP + - name: health + port: 13133 + targetPort: health + protocol: TCP + selector: + {{- include "simstudio.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: telemetry +{{- end }} \ No newline at end of file diff --git a/helm/sim/values.schema.json b/helm/sim/values.schema.json new file mode 100644 index 00000000000..dd9493c8fb2 --- /dev/null +++ b/helm/sim/values.schema.json @@ -0,0 +1,539 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["app", "realtime"], + "properties": { + "global": { + "type": "object", + "properties": { + "imageRegistry": { + "type": "string", + "format": "hostname", + "description": "Global Docker image registry" + }, + "useRegistryForAllImages": { + "type": "boolean", + "description": "Use registry for all images, not just simstudioai/* images" + }, + "imagePullSecrets": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Global image pull secrets" + }, + "storageClass": { + "type": "string", + "description": "Global storage class for PVCs" + } + } + }, + "app": { + "type": "object", + "required": ["enabled"], + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable the main application" + }, + "replicaCount": { + "type": "integer", + "minimum": 1, + "description": "Number of app replicas" + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory limit (e.g., 4Gi, 2048Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", + "description": "CPU limit (e.g., 2000m, 2.0)" + }, + "nvidia.com/gpu": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "GPU limit" + } + } + }, + "requests": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory request (e.g., 2Gi, 1024Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^\\d+(m|\\.\\d+)?$", + "description": "CPU request (e.g., 1000m, 1.0)" + } + } + } + } + }, + "env": { + "type": "object", + "properties": { + "BETTER_AUTH_SECRET": { + "type": "string", + "minLength": 32, + "description": "Auth secret (minimum 32 characters required)" + }, + "ENCRYPTION_KEY": { + "type": "string", + "minLength": 32, + "description": "Encryption key (minimum 32 characters required)" + }, + "NEXT_PUBLIC_APP_URL": { + "type": "string", + "format": "uri", + "description": "Public application URL" + }, + "BETTER_AUTH_URL": { + "type": "string", + "format": "uri", + "description": "Authentication service URL" + }, + "SOCKET_SERVER_URL": { + "type": "string", + "format": "uri", + "description": "Socket server URL" + }, + "NEXT_PUBLIC_SOCKET_URL": { + "type": "string", + "format": "uri", + "description": "Public socket URL" + } + } + } + } + }, + "realtime": { + "type": "object", + "required": ["enabled"], + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable the realtime service" + }, + "replicaCount": { + "type": "integer", + "minimum": 1, + "description": "Number of realtime replicas" + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory limit (e.g., 2Gi, 1024Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^\\d+(m|\\.\\d+)?$", + "description": "CPU limit (e.g., 1000m, 1.0)" + } + } + }, + "requests": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory request (e.g., 1Gi, 512Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^\\d+(m|\\.\\d+)?$", + "description": "CPU request (e.g., 500m, 0.5)" + } + } + } + } + }, + "env": { + "type": "object", + "properties": { + "BETTER_AUTH_SECRET": { + "type": "string", + "minLength": 32, + "description": "Auth secret (minimum 32 characters required)" + }, + "NEXT_PUBLIC_APP_URL": { + "type": "string", + "format": "uri", + "description": "Public application URL" + }, + "BETTER_AUTH_URL": { + "type": "string", + "format": "uri", + "description": "Authentication service URL" + }, + "NEXT_PUBLIC_SOCKET_URL": { + "type": "string", + "format": "uri", + "description": "Public socket URL" + }, + "ALLOWED_ORIGINS": { + "type": "string", + "description": "CORS allowed origins" + } + } + } + } + }, + "postgresql": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable internal PostgreSQL" + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory limit (e.g., 2Gi, 1024Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^\\d+(m|\\.\\d+)?$", + "description": "CPU limit" + } + } + }, + "requests": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory request (e.g., 1Gi, 512Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^\\d+(m|\\.\\d+)?$", + "description": "CPU request (e.g., 500m, 0.5)" + } + } + } + } + }, + "persistence": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable persistent storage" + }, + "size": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei)$", + "description": "Storage size (e.g., 10Gi, 50Gi)" + } + } + }, + "auth": { + "type": "object", + "properties": { + "username": { + "type": "string", + "minLength": 1, + "description": "PostgreSQL username" + }, + "database": { + "type": "string", + "minLength": 1, + "description": "PostgreSQL database name" + }, + "password": { + "type": "string", + "minLength": 8, + "not": { + "const": "CHANGE-ME-SECURE-PASSWORD" + }, + "description": "PostgreSQL password (minimum 8 characters, must not be default placeholder)" + } + } + } + } + }, + "externalDatabase": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Use external database" + }, + "host": { + "type": "string", + "format": "hostname", + "description": "External database host" + }, + "port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "description": "External database port" + } + }, + "if": { + "properties": { + "enabled": { + "const": true + } + } + }, + "then": { + "required": ["host", "username", "password", "database"] + } + }, + "autoscaling": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable autoscaling" + }, + "minReplicas": { + "type": "integer", + "minimum": 1, + "description": "Minimum replicas" + }, + "maxReplicas": { + "type": "integer", + "minimum": 1, + "description": "Maximum replicas" + } + }, + "if": { + "properties": { + "enabled": { + "const": true + } + } + }, + "then": { + "required": ["minReplicas", "maxReplicas"] + } + }, + "ollama": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable Ollama service" + }, + "replicaCount": { + "type": "integer", + "minimum": 1, + "description": "Number of Ollama replicas" + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory limit (e.g., 8Gi, 4096Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^\\d+(m|\\.\\d+)?$", + "description": "CPU limit" + }, + "nvidia.com/gpu": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "GPU limit" + } + } + }, + "requests": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei|m|k|M|G|T|P|E)?$", + "description": "Memory request (e.g., 4Gi, 2048Mi)" + }, + "cpu": { + "type": "string", + "pattern": "^\\d+(m|\\.\\d+)?$", + "description": "CPU request (e.g., 1000m, 1.0)" + } + } + } + } + }, + "persistence": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable persistent storage" + }, + "size": { + "type": "string", + "pattern": "^[0-9]+(Ki|Mi|Gi|Ti|Pi|Ei)$", + "description": "Storage size (e.g., 100Gi, 500Gi)" + } + } + }, + "gpu": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable GPU support" + }, + "count": { + "type": "integer", + "minimum": 1, + "description": "Number of GPUs" + } + } + } + } + }, + "telemetry": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable telemetry collection" + }, + "replicaCount": { + "type": "integer", + "minimum": 1, + "description": "Number of telemetry collector replicas" + } + } + }, + "sharedStorage": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable shared storage" + }, + "volumes": { + "type": "array", + "items": { + "type": "object", + "required": ["name", "size"], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Volume name" + }, + "size": { + "type": "string", + "pattern": "^[0-9]+[KMGT]i$", + "description": "Volume size (e.g., 100Gi)" + } + } + } + } + } + }, + "ingress": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable ingress" + }, + "className": { + "type": "string", + "description": "Ingress class name" + }, + "app": { + "type": "object", + "properties": { + "host": { + "type": "string", + "format": "hostname", + "description": "Main application hostname" + } + } + }, + "realtime": { + "type": "object", + "properties": { + "host": { + "type": "string", + "format": "hostname", + "description": "Realtime service hostname" + } + } + }, + "tls": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable TLS" + }, + "secretName": { + "type": "string", + "minLength": 1, + "description": "TLS secret name" + } + } + } + } + } + }, + "allOf": [ + { + "if": { + "properties": { + "postgresql": { + "properties": { + "enabled": { + "const": false + } + } + } + } + }, + "then": { + "properties": { + "externalDatabase": { + "properties": { + "enabled": { + "const": true + } + }, + "required": ["enabled"] + } + } + } + } + ] +} diff --git a/helm/sim/values.yaml b/helm/sim/values.yaml new file mode 100644 index 00000000000..f8a220a1411 --- /dev/null +++ b/helm/sim/values.yaml @@ -0,0 +1,596 @@ +# Global configuration +global: + # Image registry and pull policy + imageRegistry: "ghcr.io" + # Use registry for all images, not just simstudioai/* images + useRegistryForAllImages: false + imagePullSecrets: [] + + # Common labels applied to all resources + commonLabels: {} + + # Storage class for persistent volumes + storageClass: "" + +# Main Sim Studio application configuration +app: + # Enable/disable the main application + enabled: true + + # Image configuration + image: + repository: simstudioai/simstudio + tag: latest + pullPolicy: Always + + # Number of replicas + replicaCount: 1 + + # Resource limits and requests + resources: + limits: + memory: "4Gi" + cpu: "2000m" + requests: + memory: "2Gi" + cpu: "1000m" + + # Node selector for pod scheduling (leave empty to allow scheduling on any node) + nodeSelector: {} + + # Pod security context + podSecurityContext: + fsGroup: 1001 + + # Container security context + securityContext: + runAsNonRoot: true + runAsUser: 1001 + + # Environment variables + env: + # Application URLs + NEXT_PUBLIC_APP_URL: "http://localhost:3000" + BETTER_AUTH_URL: "http://localhost:3000" + SOCKET_SERVER_URL: "http://localhost:3002" + NEXT_PUBLIC_SOCKET_URL: "http://localhost:3002" + + # Node environment + NODE_ENV: "production" + NEXT_TELEMETRY_DISABLED: "1" + + # Authentication and encryption secrets (REQUIRED for production) + # Generate secure 32-character secrets using: openssl rand -hex 32 + # These placeholder values MUST be replaced with your own secure secrets + BETTER_AUTH_SECRET: "CHANGE-ME-32-CHAR-SECRET-FOR-PRODUCTION-USE" + ENCRYPTION_KEY: "CHANGE-ME-32-CHAR-ENCRYPTION-KEY-FOR-PROD" + + # Optional third-party service integrations (leave empty if not using) + FREESTYLE_API_KEY: "" + GOOGLE_CLIENT_ID: "" + GOOGLE_CLIENT_SECRET: "" + GITHUB_CLIENT_ID: "" + GITHUB_CLIENT_SECRET: "" + RESEND_API_KEY: "" + + # Service configuration + service: + type: ClusterIP + port: 3000 + targetPort: 3000 + + # Health checks + livenessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 10 + periodSeconds: 90 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 10 + periodSeconds: 90 + timeoutSeconds: 5 + failureThreshold: 3 + +# Realtime socket server configuration +realtime: + # Enable/disable the realtime service + enabled: true + + # Image configuration + image: + repository: simstudioai/realtime + tag: latest + pullPolicy: Always + + # Number of replicas + replicaCount: 1 + + # Resource limits and requests + resources: + limits: + memory: "2Gi" + cpu: "1000m" + requests: + memory: "1Gi" + cpu: "500m" + + # Node selector for pod scheduling (leave empty to allow scheduling on any node) + nodeSelector: {} + + # Pod security context + podSecurityContext: + fsGroup: 1001 + + # Container security context + securityContext: + runAsNonRoot: true + runAsUser: 1001 + + # Environment variables + env: + # Application URLs + NEXT_PUBLIC_APP_URL: "http://localhost:3000" + BETTER_AUTH_URL: "http://localhost:3000" + NEXT_PUBLIC_SOCKET_URL: "http://localhost:3002" + + # Authentication secret (REQUIRED for production) + # Must match the BETTER_AUTH_SECRET value from the main app configuration + # This placeholder value MUST be replaced with your own secure secret + BETTER_AUTH_SECRET: "CHANGE-ME-32-CHAR-SECRET-FOR-PRODUCTION-USE" + + # Cross-Origin Resource Sharing (CORS) allowed origins + ALLOWED_ORIGINS: "http://localhost:3000" + + # Node environment + NODE_ENV: "production" + + # Service configuration + service: + type: ClusterIP + port: 3002 + targetPort: 3002 + + # Health checks + livenessProbe: + httpGet: + path: /health + port: 3002 + initialDelaySeconds: 10 + periodSeconds: 90 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + httpGet: + path: /health + port: 3002 + initialDelaySeconds: 10 + periodSeconds: 90 + timeoutSeconds: 5 + failureThreshold: 3 + +# Database migrations job configuration +migrations: + # Enable/disable migrations job + enabled: true + + # Image configuration + image: + repository: simstudioai/migrations + tag: latest + pullPolicy: Always + + # Resource limits and requests + resources: + limits: + memory: "1Gi" + requests: + memory: "512Mi" + cpu: "100m" + + # Pod security context + podSecurityContext: + fsGroup: 1001 + + # Container security context + securityContext: + runAsNonRoot: true + runAsUser: 1001 + +# PostgreSQL database configuration +postgresql: + # Enable/disable internal PostgreSQL deployment + enabled: true + + # Image configuration + image: + repository: pgvector/pgvector + tag: pg17 + pullPolicy: IfNotPresent + + # Authentication configuration + auth: + username: postgres + password: "CHANGE-ME-SECURE-PASSWORD" # REQUIRED - replace with a strong password for production + database: simstudio + + # Node selector for database pod scheduling (leave empty to allow scheduling on any node) + nodeSelector: {} + + # Resource limits and requests + resources: + limits: + memory: "2Gi" + requests: + memory: "1Gi" + cpu: "500m" + + # Pod security context + podSecurityContext: + fsGroup: 999 + + # Container security context + securityContext: + runAsUser: 999 + + # Persistence configuration + persistence: + enabled: true + storageClass: "" + size: 10Gi + accessModes: + - ReadWriteOnce + + # SSL/TLS configuration (enable for production deployments with certificates) + tls: + enabled: false + certificatesSecret: postgres-tls-secret + + # PostgreSQL configuration + config: + maxConnections: 1000 + sharedBuffers: "1280MB" + maxWalSize: "4GB" + minWalSize: "80MB" + + # Service configuration + service: + type: ClusterIP + port: 5432 + targetPort: 5432 + + # Health checks + livenessProbe: + exec: + command: ["pg_isready", "-U", "postgres", "-d", "simstudio"] + initialDelaySeconds: 10 + periodSeconds: 5 + + readinessProbe: + exec: + command: ["pg_isready", "-U", "postgres", "-d", "simstudio"] + initialDelaySeconds: 5 + periodSeconds: 3 + +# External database configuration (use when connecting to managed database services) +externalDatabase: + # Enable to use an external database instead of the internal PostgreSQL instance + enabled: false + + # Database connection details + host: "external-db.example.com" + port: 5432 + username: postgres + password: "" + database: simstudio + + # SSL configuration + sslMode: require + +# Ollama local AI models configuration +ollama: + # Enable/disable Ollama deployment + enabled: false + + # Image configuration + image: + repository: ollama/ollama + tag: latest + pullPolicy: Always + + # Number of replicas + replicaCount: 1 + + # GPU configuration + gpu: + enabled: false + count: 1 + + # Node selector for GPU workloads (adjust labels based on your cluster configuration) + nodeSelector: + accelerator: nvidia + + # Tolerations for GPU nodes (adjust based on your cluster's GPU node taints) + tolerations: + - key: "sku" + operator: "Equal" + value: "gpu" + effect: "NoSchedule" + + # Resource limits and requests + resources: + limits: + memory: "8Gi" + nvidia.com/gpu: "1" + requests: + memory: "4Gi" + cpu: "1000m" + + # Environment variables + env: + NVIDIA_DRIVER_CAPABILITIES: "all" + OLLAMA_LOAD_TIMEOUT: "-1" + OLLAMA_KEEP_ALIVE: "-1" + OLLAMA_DEBUG: "1" + + # Persistence configuration + persistence: + enabled: true + storageClass: "" + size: 100Gi + accessModes: + - ReadWriteOnce + + # Service configuration + service: + type: ClusterIP + port: 11434 + targetPort: 11434 + + # Health checks + startupProbe: + httpGet: + path: / + port: 11434 + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 10 + + livenessProbe: + httpGet: + path: / + port: 11434 + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + + readinessProbe: + httpGet: + path: / + port: 11434 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + +# Ingress configuration +ingress: + # Enable/disable ingress + enabled: false + + # Ingress class name + className: nginx + + # Annotations + annotations: + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + + # Main application host configuration + app: + host: simstudio.local + paths: + - path: / + pathType: Prefix + + # Realtime service host configuration + realtime: + host: simstudio-ws.local + paths: + - path: / + pathType: Prefix + + # TLS configuration + tls: + enabled: false + secretName: simstudio-tls-secret + +# Service Account configuration +serviceAccount: + # Specifies whether a service account should be created + create: true + + # Annotations to add to the service account + annotations: {} + + # The name of the service account to use + name: "" + +# Horizontal Pod Autoscaler +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + # Custom metrics for scaling (advanced users can add custom metrics here) + customMetrics: [] + # Scaling behavior configuration (customize scale-up/down policies) + # Example configuration: + # behavior: + # scaleDown: + # stabilizationWindowSeconds: 300 + # policies: + # - type: Percent + # value: 50 + # periodSeconds: 60 + # scaleUp: + # stabilizationWindowSeconds: 60 + # policies: + # - type: Percent + # value: 100 + # periodSeconds: 15 + # - type: Pods + # value: 2 + # periodSeconds: 60 + behavior: {} + +# Pod disruption budget +podDisruptionBudget: + enabled: false + minAvailable: 1 + +# Monitoring configuration +monitoring: + # ServiceMonitor for Prometheus + serviceMonitor: + enabled: false + # Additional labels for ServiceMonitor + labels: {} + # Additional annotations for ServiceMonitor + annotations: {} + # Metrics path + path: /metrics + # Scrape interval + interval: 30s + # Scrape timeout + scrapeTimeout: 10s + # Target labels to be added to scraped metrics + targetLabels: [] + # Metric relabeling configurations + metricRelabelings: [] + # Relabeling configurations + relabelings: [] + +# Network policies +networkPolicy: + enabled: false + + # Custom ingress rules + ingress: [] + + # Custom egress rules + egress: [] + +# Shared storage for enterprise workflows requiring data sharing between pods +sharedStorage: + enabled: false + # Storage class for shared volumes (must support ReadWriteMany access) + storageClass: "" + # Default access modes for shared volumes (ReadWriteMany required for multi-pod access) + defaultAccessModes: + - ReadWriteMany + # Define shared volumes for your workflows (uncomment and customize as needed) + # Example volume configurations: + # volumes: + # - name: output-share + # size: 100Gi + # accessModes: + # - ReadWriteMany + # annotations: {} + # - name: rawdata-share + # size: 500Gi + # accessModes: + # - ReadWriteMany + # - name: model-share + # size: 200Gi + # accessModes: + # - ReadWriteMany + # - name: logs-share + # size: 50Gi + # accessModes: + # - ReadWriteMany + volumes: [] + +# Additional volumes for custom configurations (advanced users) +extraVolumes: [] +extraVolumeMounts: [] + +# Additional environment variables for custom integrations +extraEnvVars: [] + +# Pod annotations for custom metadata +podAnnotations: {} + +# Pod labels for custom labeling +podLabels: {} + +# Affinity settings for advanced pod scheduling +affinity: {} + +# Tolerations for scheduling on tainted nodes +tolerations: [] + +# Observability and telemetry configuration +telemetry: + # Enable/disable telemetry collection + enabled: false + + # OpenTelemetry Collector image + image: + repository: otel/opentelemetry-collector-contrib + tag: 0.91.0 + pullPolicy: IfNotPresent + + # Number of collector replicas + replicaCount: 1 + + # Resource limits and requests + resources: + limits: + memory: "512Mi" + cpu: "500m" + requests: + memory: "256Mi" + cpu: "100m" + + # Node selector for telemetry pod scheduling (leave empty to allow scheduling on any node) + nodeSelector: {} + + # Tolerations for telemetry workloads + tolerations: [] + + # Affinity for telemetry workloads + affinity: {} + + # Service configuration + service: + type: ClusterIP + + # Jaeger tracing backend + jaeger: + enabled: false + endpoint: "http://jaeger-collector:14250" + tls: + enabled: false + + # Prometheus metrics backend + prometheus: + enabled: false + endpoint: "http://prometheus-server/api/v1/write" + auth: "" + + # Generic OTLP backend + otlp: + enabled: false + endpoint: "http://otlp-collector:4317" + tls: + enabled: false \ No newline at end of file From 5a68f8ead1dfeb351790528e23ca142dbabe05fa Mon Sep 17 00:00:00 2001 From: waleedlatif Date: Mon, 28 Jul 2025 17:52:12 -0700 Subject: [PATCH 2/2] ack PR comments, use sim instead of simstudio --- helm/sim/Chart.yaml | 5 +- helm/sim/README.md | 22 ++--- helm/sim/examples/values-aws.yaml | 2 +- helm/sim/examples/values-azure.yaml | 4 +- helm/sim/examples/values-development.yaml | 2 +- helm/sim/examples/values-external-db.yaml | 6 +- helm/sim/examples/values-gcp.yaml | 2 +- helm/sim/examples/values-production.yaml | 2 +- helm/sim/templates/NOTES.txt | 22 ++--- helm/sim/templates/_helpers.tpl | 86 +++++++++---------- helm/sim/templates/deployment-app.yaml | 54 ++++++------ helm/sim/templates/deployment-ollama.yaml | 30 +++---- helm/sim/templates/deployment-realtime.yaml | 38 ++++---- helm/sim/templates/gpu-device-plugin.yaml | 12 +-- helm/sim/templates/hpa.yaml | 12 +-- helm/sim/templates/ingress.yaml | 8 +- helm/sim/templates/networkpolicy.yaml | 44 +++++----- helm/sim/templates/serviceaccount.yaml | 4 +- helm/sim/templates/servicemonitor.yaml | 12 +-- helm/sim/templates/services.yaml | 24 +++--- helm/sim/templates/shared-storage.yaml | 8 +- .../sim/templates/statefulset-postgresql.yaml | 47 +++++----- helm/sim/templates/telemetry.yaml | 56 ++++++++---- helm/sim/values.schema.json | 31 +++++-- helm/sim/values.yaml | 26 +++--- package.json | 2 + 26 files changed, 297 insertions(+), 264 deletions(-) diff --git a/helm/sim/Chart.yaml b/helm/sim/Chart.yaml index 2ad365b6699..b21cdea25a1 100644 --- a/helm/sim/Chart.yaml +++ b/helm/sim/Chart.yaml @@ -1,14 +1,15 @@ apiVersion: v2 name: sim -description: A Helm chart for Sim Studio - AI agent workflow platform +description: A Helm chart for Sim - AI agent workflow platform type: application version: 0.1.0 appVersion: "1.0.0" home: https://simstudio.ai +icon: https://raw.githubusercontent.com/simstudioai/sim/main/apps/sim/public/sim.svg sources: - https://github.com/simstudioai/sim maintainers: - - name: Sim Studio Team + - name: Sim Team email: help@simstudio.ai url: https://simstudio.ai keywords: diff --git a/helm/sim/README.md b/helm/sim/README.md index 67451e1fe69..f5c4809603e 100644 --- a/helm/sim/README.md +++ b/helm/sim/README.md @@ -1,6 +1,6 @@ -# Sim Studio Helm Chart +# Sim Helm Chart -This Helm chart deploys Sim Studio, a lightweight AI agent workflow platform, on Kubernetes. +This Helm chart deploys Sim, a lightweight AI agent workflow platform, on Kubernetes. ## Prerequisites @@ -149,7 +149,7 @@ The following table lists the configurable parameters and their default values. |-----------|-------------|---------| | `app.enabled` | Enable the main application | `true` | | `app.replicaCount` | Number of app replicas | `1` | -| `app.image.repository` | App image repository | `simstudioai/simstudio` | +| `app.image.repository` | App image repository | `simstudioai/sim` | | `app.image.tag` | App image tag | `latest` | | `app.image.pullPolicy` | App image pull policy | `Always` | | `app.resources` | App resource limits and requests | See values.yaml | @@ -192,8 +192,8 @@ The following table lists the configurable parameters and their default values. | `postgresql.image.tag` | PostgreSQL image tag | `pg17` | | `postgresql.image.pullPolicy` | PostgreSQL image pull policy | `IfNotPresent` | | `postgresql.auth.username` | PostgreSQL username | `postgres` | -| `postgresql.auth.password` | PostgreSQL password | `CHANGE-ME-SECURE-PASSWORD` | -| `postgresql.auth.database` | PostgreSQL database name | `simstudio` | +| `postgresql.auth.password` | PostgreSQL password | `""` (REQUIRED) | +| `postgresql.auth.database` | PostgreSQL database name | `sim` | | `postgresql.nodeSelector` | PostgreSQL node selector | `{}` | | `postgresql.resources` | PostgreSQL resource limits and requests | See values.yaml | | `postgresql.podSecurityContext` | PostgreSQL pod security context | `fsGroup: 999` | @@ -223,7 +223,7 @@ The following table lists the configurable parameters and their default values. | `externalDatabase.port` | External database port | `5432` | | `externalDatabase.username` | External database username | `postgres` | | `externalDatabase.password` | External database password | `""` | -| `externalDatabase.database` | External database name | `simstudio` | +| `externalDatabase.database` | External database name | `sim` | | `externalDatabase.sslMode` | External database SSL mode | `require` | ### Ollama Parameters @@ -259,12 +259,12 @@ The following table lists the configurable parameters and their default values. | `ingress.enabled` | Enable ingress | `false` | | `ingress.className` | Ingress class name | `nginx` | | `ingress.annotations` | Ingress annotations | See values.yaml | -| `ingress.app.host` | App ingress hostname | `simstudio.local` | +| `ingress.app.host` | App ingress hostname | `sim.local` | | `ingress.app.paths` | App ingress paths | `[{path: "/", pathType: "Prefix"}]` | -| `ingress.realtime.host` | Realtime ingress hostname | `simstudio-ws.local` | +| `ingress.realtime.host` | Realtime ingress hostname | `sim-ws.local` | | `ingress.realtime.paths` | Realtime ingress paths | `[{path: "/", pathType: "Prefix"}]` | | `ingress.tls.enabled` | Enable TLS for ingress | `false` | -| `ingress.tls.secretName` | TLS secret name | `simstudio-tls-secret` | +| `ingress.tls.secretName` | TLS secret name | `sim-tls-secret` | ### Autoscaling Parameters @@ -453,7 +453,7 @@ telemetry: This automatically configures: - OpenTelemetry Collector for metrics, traces, and logs -- Automatic service discovery for SimStudio components +- Automatic service discovery for Sim components - Environment variable injection for applications - Support for multiple observability backends @@ -504,7 +504,7 @@ networkPolicy: ``` This creates network policies that: -- Allow communication between SimStudio components +- Allow communication between Sim components - Restrict unnecessary network access - Permit DNS resolution and HTTPS egress - Support custom ingress/egress rules diff --git a/helm/sim/examples/values-aws.yaml b/helm/sim/examples/values-aws.yaml index 5210497f66a..14adf139f73 100644 --- a/helm/sim/examples/values-aws.yaml +++ b/helm/sim/examples/values-aws.yaml @@ -1,4 +1,4 @@ -# AWS-specific values for Sim Studio +# AWS-specific values for Sim # Example configuration for Amazon EKS deployment # Global configuration diff --git a/helm/sim/examples/values-azure.yaml b/helm/sim/examples/values-azure.yaml index b3226ace5e6..dd3653faeb8 100644 --- a/helm/sim/examples/values-azure.yaml +++ b/helm/sim/examples/values-azure.yaml @@ -1,4 +1,4 @@ -# Azure-specific values for Sim Studio +# Azure-specific values for Sim # Example configuration for Azure AKS deployment # Global configuration @@ -144,7 +144,7 @@ ollama: OLLAMA_KEEP_ALIVE: "-1" OLLAMA_DEBUG: "1" -# Ingress configuration for Azure Application Gateway +# Ingress configuration (NGINX ingress controller on Azure AKS) ingress: enabled: true className: nginx diff --git a/helm/sim/examples/values-development.yaml b/helm/sim/examples/values-development.yaml index e5c3116b334..c2f20837eed 100644 --- a/helm/sim/examples/values-development.yaml +++ b/helm/sim/examples/values-development.yaml @@ -1,4 +1,4 @@ -# Development values for Sim Studio +# Development values for Sim # This configuration is suitable for development and testing # Global configuration diff --git a/helm/sim/examples/values-external-db.yaml b/helm/sim/examples/values-external-db.yaml index 6face37f814..c4dd7f754f7 100644 --- a/helm/sim/examples/values-external-db.yaml +++ b/helm/sim/examples/values-external-db.yaml @@ -1,4 +1,4 @@ -# External Database Example for SimStudio +# External Database Example for Sim # Use this configuration when connecting to a managed database service # (AWS RDS, Azure Database, Google Cloud SQL, etc.) @@ -141,8 +141,8 @@ networkPolicy: port: 5432 # Example deployment command with secure secret generation: -# helm install simstudio ./charts/simstudio \ -# --values ./charts/simstudio/examples/values-external-db.yaml \ +# helm install sim ./helm/sim \ +# --values ./helm/sim/examples/values-external-db.yaml \ # --set externalDatabase.host="your-db-host.com" \ # --set externalDatabase.username="your-db-user" \ # --set externalDatabase.password="your-db-password" \ diff --git a/helm/sim/examples/values-gcp.yaml b/helm/sim/examples/values-gcp.yaml index 01dc5bc9006..987bad86f37 100644 --- a/helm/sim/examples/values-gcp.yaml +++ b/helm/sim/examples/values-gcp.yaml @@ -1,4 +1,4 @@ -# GCP-specific values for Sim Studio +# GCP-specific values for Sim # Example configuration for Google Kubernetes Engine (GKE) deployment # Global configuration diff --git a/helm/sim/examples/values-production.yaml b/helm/sim/examples/values-production.yaml index a2915083e4c..dd43a078f06 100644 --- a/helm/sim/examples/values-production.yaml +++ b/helm/sim/examples/values-production.yaml @@ -1,4 +1,4 @@ -# Production values for Sim Studio +# Production values for Sim # This configuration is suitable for production deployments # Global configuration diff --git a/helm/sim/templates/NOTES.txt b/helm/sim/templates/NOTES.txt index 97468be200b..063c7b425ee 100644 --- a/helm/sim/templates/NOTES.txt +++ b/helm/sim/templates/NOTES.txt @@ -2,16 +2,16 @@ {{- if .Values.ingress.enabled }} http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.app.host }} {{- else if contains "NodePort" .Values.app.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "simstudio.fullname" . }}-app) + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "sim.fullname" . }}-app) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.app.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "simstudio.fullname" . }}-app' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "simstudio.fullname" . }}-app --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "sim.fullname" . }}-app' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "sim.fullname" . }}-app --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") echo http://$SERVICE_IP:{{ .Values.app.service.port }} {{- else if contains "ClusterIP" .Values.app.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "{{ include "simstudio.app.selectorLabels" . }}" -o jsonpath="{.items[0].metadata.name}") + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "{{ include "sim.app.selectorLabels" . }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT @@ -23,7 +23,7 @@ {{- if .Values.ingress.enabled }} http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.realtime.host }} {{- else }} - Use port-forwarding: kubectl port-forward svc/{{ include "simstudio.fullname" . }}-realtime 3002:3002 + Use port-forwarding: kubectl port-forward svc/{{ include "sim.fullname" . }}-realtime 3002:3002 {{- end }} {{- end }} @@ -51,7 +51,7 @@ Make sure to configure an external database connection in your values.yaml file. Please set the following REQUIRED values for production use: - helm upgrade {{ .Release.Name }} ./charts/simstudio \ + helm upgrade {{ .Release.Name }} ./helm/sim \ --set app.env.BETTER_AUTH_SECRET="your-secure-32-char-secret-here" \ --set app.env.ENCRYPTION_KEY="your-secure-32-char-encryption-key" \ --set realtime.env.BETTER_AUTH_SECRET="your-secure-32-char-secret-here" \ @@ -62,12 +62,6 @@ Generate secure secrets using: {{- end }} -{{- if not .Values.postgresql.enabled }} - -⚠️ DATABASE WARNING: You have disabled the internal PostgreSQL database. -Make sure to configure an external database connection in your values.yaml file. -{{- end }} - For more information and configuration options, see: -- Chart documentation: https://github.com/simstudioai/sim/tree/main/charts/simstudio -- Sim Studio documentation: https://docs.simstudio.ai \ No newline at end of file +- Chart documentation: https://github.com/simstudioai/sim/tree/main/helm/sim +- Sim documentation: https://docs.sim.ai \ No newline at end of file diff --git a/helm/sim/templates/_helpers.tpl b/helm/sim/templates/_helpers.tpl index 6526177532e..dd61cb770d8 100644 --- a/helm/sim/templates/_helpers.tpl +++ b/helm/sim/templates/_helpers.tpl @@ -1,7 +1,7 @@ {{/* Expand the name of the chart. */}} -{{- define "simstudio.name" -}} +{{- define "sim.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} @@ -10,7 +10,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "simstudio.fullname" -}} +{{- define "sim.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} @@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "simstudio.chart" -}} +{{- define "sim.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} -{{- define "simstudio.labels" -}} -helm.sh/chart: {{ include "simstudio.chart" . }} -{{ include "simstudio.selectorLabels" . }} +{{- define "sim.labels" -}} +helm.sh/chart: {{ include "sim.chart" . }} +{{ include "sim.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} @@ -48,89 +48,89 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} {{/* Selector labels */}} -{{- define "simstudio.selectorLabels" -}} -app.kubernetes.io/name: {{ include "simstudio.name" . }} +{{- define "sim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "sim.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* App specific labels */}} -{{- define "simstudio.app.labels" -}} -{{ include "simstudio.labels" . }} +{{- define "sim.app.labels" -}} +{{ include "sim.labels" . }} app.kubernetes.io/component: app {{- end }} {{/* App selector labels */}} -{{- define "simstudio.app.selectorLabels" -}} -{{ include "simstudio.selectorLabels" . }} +{{- define "sim.app.selectorLabels" -}} +{{ include "sim.selectorLabels" . }} app.kubernetes.io/component: app {{- end }} {{/* Realtime specific labels */}} -{{- define "simstudio.realtime.labels" -}} -{{ include "simstudio.labels" . }} +{{- define "sim.realtime.labels" -}} +{{ include "sim.labels" . }} app.kubernetes.io/component: realtime {{- end }} {{/* Realtime selector labels */}} -{{- define "simstudio.realtime.selectorLabels" -}} -{{ include "simstudio.selectorLabels" . }} +{{- define "sim.realtime.selectorLabels" -}} +{{ include "sim.selectorLabels" . }} app.kubernetes.io/component: realtime {{- end }} {{/* PostgreSQL specific labels */}} -{{- define "simstudio.postgresql.labels" -}} -{{ include "simstudio.labels" . }} +{{- define "sim.postgresql.labels" -}} +{{ include "sim.labels" . }} app.kubernetes.io/component: postgresql {{- end }} {{/* PostgreSQL selector labels */}} -{{- define "simstudio.postgresql.selectorLabels" -}} -{{ include "simstudio.selectorLabels" . }} +{{- define "sim.postgresql.selectorLabels" -}} +{{ include "sim.selectorLabels" . }} app.kubernetes.io/component: postgresql {{- end }} {{/* Ollama specific labels */}} -{{- define "simstudio.ollama.labels" -}} -{{ include "simstudio.labels" . }} +{{- define "sim.ollama.labels" -}} +{{ include "sim.labels" . }} app.kubernetes.io/component: ollama {{- end }} {{/* Ollama selector labels */}} -{{- define "simstudio.ollama.selectorLabels" -}} -{{ include "simstudio.selectorLabels" . }} +{{- define "sim.ollama.selectorLabels" -}} +{{ include "sim.selectorLabels" . }} app.kubernetes.io/component: ollama {{- end }} {{/* Migrations specific labels */}} -{{- define "simstudio.migrations.labels" -}} -{{ include "simstudio.labels" . }} +{{- define "sim.migrations.labels" -}} +{{ include "sim.labels" . }} app.kubernetes.io/component: migrations {{- end }} {{/* Create the name of the service account to use */}} -{{- define "simstudio.serviceAccountName" -}} +{{- define "sim.serviceAccountName" -}} {{- if .Values.serviceAccount.create }} -{{- default (include "simstudio.fullname" .) .Values.serviceAccount.name }} +{{- default (include "sim.fullname" .) .Values.serviceAccount.name }} {{- else }} {{- default "default" .Values.serviceAccount.name }} {{- end }} @@ -139,9 +139,9 @@ Create the name of the service account to use {{/* Create image name with registry Expects context with image object passed as second parameter -Usage: {{ include "simstudio.image" (dict "context" . "image" .Values.app.image) }} +Usage: {{ include "sim.image" (dict "context" . "image" .Values.app.image) }} */}} -{{- define "simstudio.image" -}} +{{- define "sim.image" -}} {{- $registry := "" -}} {{- $repository := .image.repository -}} {{- $tag := .image.tag | toString -}} @@ -161,9 +161,9 @@ Usage: {{ include "simstudio.image" (dict "context" . "image" .Values.app.image) {{/* Database URL for internal PostgreSQL */}} -{{- define "simstudio.databaseUrl" -}} +{{- define "sim.databaseUrl" -}} {{- if .Values.postgresql.enabled }} -{{- $host := printf "%s-postgresql" (include "simstudio.fullname" .) }} +{{- $host := printf "%s-postgresql" (include "sim.fullname" .) }} {{- $port := .Values.postgresql.service.port }} {{- $username := .Values.postgresql.auth.username }} {{- $database := .Values.postgresql.auth.database }} @@ -182,7 +182,7 @@ Database URL for internal PostgreSQL {{/* Validate required secrets and reject default placeholder values */}} -{{- define "simstudio.validateSecrets" -}} +{{- define "sim.validateSecrets" -}} {{- if and .Values.app.enabled (not .Values.app.env.BETTER_AUTH_SECRET) }} {{- fail "app.env.BETTER_AUTH_SECRET is required for production deployment" }} {{- end }} @@ -212,9 +212,9 @@ Validate required secrets and reject default placeholder values {{/* Ollama URL */}} -{{- define "simstudio.ollamaUrl" -}} +{{- define "sim.ollamaUrl" -}} {{- if .Values.ollama.enabled }} -{{- $serviceName := printf "%s-ollama" (include "simstudio.fullname" .) }} +{{- $serviceName := printf "%s-ollama" (include "sim.fullname" .) }} {{- $port := .Values.ollama.service.port }} {{- printf "http://%s:%v" $serviceName $port }} {{- else }} @@ -225,9 +225,9 @@ Ollama URL {{/* Socket Server URL (internal) */}} -{{- define "simstudio.socketServerUrl" -}} +{{- define "sim.socketServerUrl" -}} {{- if .Values.realtime.enabled }} -{{- $serviceName := printf "%s-realtime" (include "simstudio.fullname" .) }} +{{- $serviceName := printf "%s-realtime" (include "sim.fullname" .) }} {{- $port := .Values.realtime.service.port }} {{- printf "http://%s:%v" $serviceName $port }} {{- else }} @@ -238,7 +238,7 @@ Socket Server URL (internal) {{/* Resource limits and requests */}} -{{- define "simstudio.resources" -}} +{{- define "sim.resources" -}} {{- if .resources }} resources: {{- if .resources.limits }} @@ -255,7 +255,7 @@ resources: {{/* Security context */}} -{{- define "simstudio.securityContext" -}} +{{- define "sim.securityContext" -}} {{- if .securityContext }} securityContext: {{- toYaml .securityContext | nindent 2 }} @@ -265,7 +265,7 @@ securityContext: {{/* Pod security context */}} -{{- define "simstudio.podSecurityContext" -}} +{{- define "sim.podSecurityContext" -}} {{- if .podSecurityContext }} securityContext: {{- toYaml .podSecurityContext | nindent 2 }} @@ -275,7 +275,7 @@ securityContext: {{/* Node selector */}} -{{- define "simstudio.nodeSelector" -}} +{{- define "sim.nodeSelector" -}} {{- if .nodeSelector }} nodeSelector: {{- toYaml .nodeSelector | nindent 2 }} @@ -285,7 +285,7 @@ nodeSelector: {{/* Tolerations */}} -{{- define "simstudio.tolerations" -}} +{{- define "sim.tolerations" -}} {{- if .tolerations }} tolerations: {{- toYaml .tolerations | nindent 2 }} @@ -295,7 +295,7 @@ tolerations: {{/* Affinity */}} -{{- define "simstudio.affinity" -}} +{{- define "sim.affinity" -}} {{- if .affinity }} affinity: {{- toYaml .affinity | nindent 2 }} diff --git a/helm/sim/templates/deployment-app.yaml b/helm/sim/templates/deployment-app.yaml index 8d9f8ca1e39..92931632b38 100644 --- a/helm/sim/templates/deployment-app.yaml +++ b/helm/sim/templates/deployment-app.yaml @@ -1,17 +1,17 @@ {{- if .Values.app.enabled }} -{{- include "simstudio.validateSecrets" . }} +{{- include "sim.validateSecrets" . }} apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "simstudio.fullname" . }}-app + name: {{ include "sim.fullname" . }}-app namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.app.labels" . | nindent 4 }} + {{- include "sim.app.labels" . | nindent 4 }} spec: replicas: {{ .Values.app.replicaCount }} selector: matchLabels: - {{- include "simstudio.app.selectorLabels" . | nindent 6 }} + {{- include "sim.app.selectorLabels" . | nindent 6 }} template: metadata: annotations: @@ -19,7 +19,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "simstudio.app.selectorLabels" . | nindent 8 }} + {{- include "sim.app.selectorLabels" . | nindent 8 }} {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }} @@ -28,35 +28,35 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "simstudio.serviceAccountName" . }} - {{- include "simstudio.podSecurityContext" .Values.app | nindent 6 }} - {{- include "simstudio.nodeSelector" .Values.app | nindent 6 }} - {{- include "simstudio.tolerations" .Values | nindent 6 }} - {{- include "simstudio.affinity" .Values | nindent 6 }} + serviceAccountName: {{ include "sim.serviceAccountName" . }} + {{- include "sim.podSecurityContext" .Values.app | nindent 6 }} + {{- include "sim.nodeSelector" .Values.app | nindent 6 }} + {{- include "sim.tolerations" .Values | nindent 6 }} + {{- include "sim.affinity" .Values | nindent 6 }} {{- if .Values.migrations.enabled }} initContainers: - name: migrations - image: {{ include "simstudio.image" (dict "context" . "image" .Values.migrations.image) }} + image: {{ include "sim.image" (dict "context" . "image" .Values.migrations.image) }} imagePullPolicy: {{ .Values.migrations.image.pullPolicy }} command: ["bun", "run", "db:migrate"] env: - name: DATABASE_URL - value: {{ include "simstudio.databaseUrl" . | quote }} + value: {{ include "sim.databaseUrl" . | quote }} {{- if .Values.postgresql.enabled }} envFrom: - secretRef: - name: {{ include "simstudio.fullname" . }}-postgresql-secret + name: {{ include "sim.fullname" . }}-postgresql-secret {{- else if .Values.externalDatabase.enabled }} envFrom: - secretRef: - name: {{ include "simstudio.fullname" . }}-external-db-secret + name: {{ include "sim.fullname" . }}-external-db-secret {{- end }} - {{- include "simstudio.resources" .Values.migrations | nindent 10 }} - {{- include "simstudio.securityContext" .Values.migrations | nindent 10 }} + {{- include "sim.resources" .Values.migrations | nindent 10 }} + {{- include "sim.securityContext" .Values.migrations | nindent 10 }} {{- end }} containers: - name: app - image: {{ include "simstudio.image" (dict "context" . "image" .Values.app.image) }} + image: {{ include "sim.image" (dict "context" . "image" .Values.app.image) }} imagePullPolicy: {{ .Values.app.image.pullPolicy }} ports: - name: http @@ -64,11 +64,11 @@ spec: protocol: TCP env: - name: DATABASE_URL - value: {{ include "simstudio.databaseUrl" . | quote }} + value: {{ include "sim.databaseUrl" . | quote }} - name: SOCKET_SERVER_URL - value: {{ include "simstudio.socketServerUrl" . | quote }} + value: {{ include "sim.socketServerUrl" . | quote }} - name: OLLAMA_URL - value: {{ include "simstudio.ollamaUrl" . | quote }} + value: {{ include "sim.ollamaUrl" . | quote }} {{- range $key, $value := .Values.app.env }} - name: {{ $key }} value: {{ $value | quote }} @@ -76,13 +76,13 @@ spec: {{- if .Values.telemetry.enabled }} # OpenTelemetry configuration - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: "http://{{ include "simstudio.fullname" . }}-otel-collector:4318" + value: "http://{{ include "sim.fullname" . }}-otel-collector:4318" - name: OTEL_SERVICE_NAME - value: simstudio-app + value: sim-app - name: OTEL_SERVICE_VERSION value: {{ .Chart.AppVersion | quote }} - name: OTEL_RESOURCE_ATTRIBUTES - value: "service.name=simstudio-app,service.version={{ .Chart.AppVersion }},deployment.environment={{ .Values.app.env.NODE_ENV }}" + value: "service.name=sim-app,service.version={{ .Chart.AppVersion }},deployment.environment={{ .Values.app.env.NODE_ENV }}" {{- end }} {{- with .Values.extraEnvVars }} {{- toYaml . | nindent 12 }} @@ -90,11 +90,11 @@ spec: {{- if .Values.postgresql.enabled }} envFrom: - secretRef: - name: {{ include "simstudio.fullname" . }}-postgresql-secret + name: {{ include "sim.fullname" . }}-postgresql-secret {{- else if .Values.externalDatabase.enabled }} envFrom: - secretRef: - name: {{ include "simstudio.fullname" . }}-external-db-secret + name: {{ include "sim.fullname" . }}-external-db-secret {{- end }} {{- if .Values.app.livenessProbe }} livenessProbe: @@ -104,8 +104,8 @@ spec: readinessProbe: {{- toYaml .Values.app.readinessProbe | nindent 12 }} {{- end }} - {{- include "simstudio.resources" .Values.app | nindent 10 }} - {{- include "simstudio.securityContext" .Values.app | nindent 10 }} + {{- include "sim.resources" .Values.app | nindent 10 }} + {{- include "sim.securityContext" .Values.app | nindent 10 }} {{- with .Values.extraVolumeMounts }} volumeMounts: {{- toYaml . | nindent 12 }} diff --git a/helm/sim/templates/deployment-ollama.yaml b/helm/sim/templates/deployment-ollama.yaml index 097baa49c1d..a46f2b66116 100644 --- a/helm/sim/templates/deployment-ollama.yaml +++ b/helm/sim/templates/deployment-ollama.yaml @@ -5,10 +5,10 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ include "simstudio.fullname" . }}-ollama-data + name: {{ include "sim.fullname" . }}-ollama-data namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.ollama.labels" . | nindent 4 }} + {{- include "sim.ollama.labels" . | nindent 4 }} spec: {{- if .Values.ollama.persistence.storageClass }} {{- if (eq "-" .Values.ollama.persistence.storageClass) }} @@ -33,15 +33,15 @@ spec: apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "simstudio.fullname" . }}-ollama + name: {{ include "sim.fullname" . }}-ollama namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.ollama.labels" . | nindent 4 }} + {{- include "sim.ollama.labels" . | nindent 4 }} spec: replicas: {{ .Values.ollama.replicaCount }} selector: matchLabels: - {{- include "simstudio.ollama.selectorLabels" . | nindent 6 }} + {{- include "sim.ollama.selectorLabels" . | nindent 6 }} template: metadata: annotations: @@ -49,7 +49,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "simstudio.ollama.selectorLabels" . | nindent 8 }} + {{- include "sim.ollama.selectorLabels" . | nindent 8 }} {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }} @@ -58,13 +58,13 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "simstudio.serviceAccountName" . }} - {{- include "simstudio.nodeSelector" .Values.ollama | nindent 6 }} - {{- include "simstudio.tolerations" .Values.ollama | nindent 6 }} - {{- include "simstudio.affinity" .Values | nindent 6 }} + serviceAccountName: {{ include "sim.serviceAccountName" . }} + {{- include "sim.nodeSelector" .Values.ollama | nindent 6 }} + {{- include "sim.tolerations" .Values.ollama | nindent 6 }} + {{- include "sim.affinity" .Values | nindent 6 }} containers: - name: ollama - image: {{ include "simstudio.image" (dict "context" . "image" .Values.ollama.image) }} + image: {{ include "sim.image" (dict "context" . "image" .Values.ollama.image) }} imagePullPolicy: {{ .Values.ollama.image.pullPolicy }} command: ["ollama", "serve"] ports: @@ -91,20 +91,20 @@ spec: readinessProbe: {{- toYaml .Values.ollama.readinessProbe | nindent 12 }} {{- end }} - {{- include "simstudio.resources" .Values.ollama | nindent 10 }} - {{- if .Values.ollama.persistence.enabled }} + {{- include "sim.resources" .Values.ollama | nindent 10 }} volumeMounts: + {{- if .Values.ollama.persistence.enabled }} - name: ollama-data mountPath: /root/.ollama + {{- end }} {{- with .Values.extraVolumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} - {{- end }} {{- if .Values.ollama.persistence.enabled }} volumes: - name: ollama-data persistentVolumeClaim: - claimName: {{ include "simstudio.fullname" . }}-ollama-data + claimName: {{ include "sim.fullname" . }}-ollama-data {{- with .Values.extraVolumes }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/helm/sim/templates/deployment-realtime.yaml b/helm/sim/templates/deployment-realtime.yaml index 45386937ee1..b951aee1678 100644 --- a/helm/sim/templates/deployment-realtime.yaml +++ b/helm/sim/templates/deployment-realtime.yaml @@ -1,17 +1,17 @@ {{- if .Values.realtime.enabled }} -{{- include "simstudio.validateSecrets" . }} +{{- include "sim.validateSecrets" . }} apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "simstudio.fullname" . }}-realtime + name: {{ include "sim.fullname" . }}-realtime namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.realtime.labels" . | nindent 4 }} + {{- include "sim.realtime.labels" . | nindent 4 }} spec: replicas: {{ .Values.realtime.replicaCount }} selector: matchLabels: - {{- include "simstudio.realtime.selectorLabels" . | nindent 6 }} + {{- include "sim.realtime.selectorLabels" . | nindent 6 }} template: metadata: annotations: @@ -19,7 +19,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "simstudio.realtime.selectorLabels" . | nindent 8 }} + {{- include "sim.realtime.selectorLabels" . | nindent 8 }} {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }} @@ -28,14 +28,14 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "simstudio.serviceAccountName" . }} - {{- include "simstudio.podSecurityContext" .Values.realtime | nindent 6 }} - {{- include "simstudio.nodeSelector" .Values.realtime | nindent 6 }} - {{- include "simstudio.tolerations" .Values | nindent 6 }} - {{- include "simstudio.affinity" .Values | nindent 6 }} + serviceAccountName: {{ include "sim.serviceAccountName" . }} + {{- include "sim.podSecurityContext" .Values.realtime | nindent 6 }} + {{- include "sim.nodeSelector" .Values.realtime | nindent 6 }} + {{- include "sim.tolerations" .Values | nindent 6 }} + {{- include "sim.affinity" .Values | nindent 6 }} containers: - name: realtime - image: {{ include "simstudio.image" (dict "context" . "image" .Values.realtime.image) }} + image: {{ include "sim.image" (dict "context" . "image" .Values.realtime.image) }} imagePullPolicy: {{ .Values.realtime.image.pullPolicy }} ports: - name: http @@ -43,7 +43,7 @@ spec: protocol: TCP env: - name: DATABASE_URL - value: {{ include "simstudio.databaseUrl" . | quote }} + value: {{ include "sim.databaseUrl" . | quote }} {{- range $key, $value := .Values.realtime.env }} - name: {{ $key }} value: {{ $value | quote }} @@ -51,13 +51,13 @@ spec: {{- if .Values.telemetry.enabled }} # OpenTelemetry configuration - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: "http://{{ include "simstudio.fullname" . }}-otel-collector:4318" + value: "http://{{ include "sim.fullname" . }}-otel-collector:4318" - name: OTEL_SERVICE_NAME - value: simstudio-realtime + value: sim-realtime - name: OTEL_SERVICE_VERSION value: {{ .Chart.AppVersion | quote }} - name: OTEL_RESOURCE_ATTRIBUTES - value: "service.name=simstudio-realtime,service.version={{ .Chart.AppVersion }},deployment.environment={{ .Values.realtime.env.NODE_ENV }}" + value: "service.name=sim-realtime,service.version={{ .Chart.AppVersion }},deployment.environment={{ .Values.realtime.env.NODE_ENV }}" {{- end }} {{- with .Values.extraEnvVars }} {{- toYaml . | nindent 12 }} @@ -65,11 +65,11 @@ spec: {{- if .Values.postgresql.enabled }} envFrom: - secretRef: - name: {{ include "simstudio.fullname" . }}-postgresql-secret + name: {{ include "sim.fullname" . }}-postgresql-secret {{- else if .Values.externalDatabase.enabled }} envFrom: - secretRef: - name: {{ include "simstudio.fullname" . }}-external-db-secret + name: {{ include "sim.fullname" . }}-external-db-secret {{- end }} {{- if .Values.realtime.livenessProbe }} livenessProbe: @@ -79,8 +79,8 @@ spec: readinessProbe: {{- toYaml .Values.realtime.readinessProbe | nindent 12 }} {{- end }} - {{- include "simstudio.resources" .Values.realtime | nindent 10 }} - {{- include "simstudio.securityContext" .Values.realtime | nindent 10 }} + {{- include "sim.resources" .Values.realtime | nindent 10 }} + {{- include "sim.securityContext" .Values.realtime | nindent 10 }} {{- with .Values.extraVolumeMounts }} volumeMounts: {{- toYaml . | nindent 12 }} diff --git a/helm/sim/templates/gpu-device-plugin.yaml b/helm/sim/templates/gpu-device-plugin.yaml index 780fd3a338f..df9a30b3d24 100644 --- a/helm/sim/templates/gpu-device-plugin.yaml +++ b/helm/sim/templates/gpu-device-plugin.yaml @@ -4,22 +4,22 @@ apiVersion: apps/v1 kind: DaemonSet metadata: - name: {{ include "simstudio.fullname" . }}-nvidia-device-plugin + name: {{ include "sim.fullname" . }}-nvidia-device-plugin namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.labels" . | nindent 4 }} + {{- include "sim.labels" . | nindent 4 }} app.kubernetes.io/component: nvidia-device-plugin spec: selector: matchLabels: - {{- include "simstudio.selectorLabels" . | nindent 6 }} + {{- include "sim.selectorLabels" . | nindent 6 }} app.kubernetes.io/component: nvidia-device-plugin updateStrategy: type: RollingUpdate template: metadata: labels: - {{- include "simstudio.selectorLabels" . | nindent 8 }} + {{- include "sim.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: nvidia-device-plugin spec: tolerations: @@ -95,6 +95,8 @@ spec: apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: - name: nvidia + name: {{ include "sim.fullname" . }}-nvidia + labels: + {{- include "sim.labels" . | nindent 4 }} handler: nvidia {{- end }} \ No newline at end of file diff --git a/helm/sim/templates/hpa.yaml b/helm/sim/templates/hpa.yaml index 12733426dc3..01c20058f80 100644 --- a/helm/sim/templates/hpa.yaml +++ b/helm/sim/templates/hpa.yaml @@ -4,15 +4,15 @@ apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: - name: {{ include "simstudio.fullname" . }}-app + name: {{ include "sim.fullname" . }}-app namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.app.labels" . | nindent 4 }} + {{- include "sim.app.labels" . | nindent 4 }} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment - name: {{ include "simstudio.fullname" . }}-app + name: {{ include "sim.fullname" . }}-app minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: @@ -47,15 +47,15 @@ spec: apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: - name: {{ include "simstudio.fullname" . }}-realtime + name: {{ include "sim.fullname" . }}-realtime namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.realtime.labels" . | nindent 4 }} + {{- include "sim.realtime.labels" . | nindent 4 }} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment - name: {{ include "simstudio.fullname" . }}-realtime + name: {{ include "sim.fullname" . }}-realtime minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: diff --git a/helm/sim/templates/ingress.yaml b/helm/sim/templates/ingress.yaml index dae55a838a9..3195b300ed2 100644 --- a/helm/sim/templates/ingress.yaml +++ b/helm/sim/templates/ingress.yaml @@ -2,10 +2,10 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "simstudio.fullname" . }}-ingress + name: {{ include "sim.fullname" . }}-ingress namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.labels" . | nindent 4 }} + {{- include "sim.labels" . | nindent 4 }} {{- with .Values.ingress.annotations }} annotations: {{- toYaml . | nindent 4 }} @@ -33,7 +33,7 @@ spec: pathType: {{ .pathType }} backend: service: - name: {{ include "simstudio.fullname" $ }}-app + name: {{ include "sim.fullname" $ }}-app port: number: {{ $.Values.app.service.port }} {{- end }} @@ -47,7 +47,7 @@ spec: pathType: {{ .pathType }} backend: service: - name: {{ include "simstudio.fullname" $ }}-realtime + name: {{ include "sim.fullname" $ }}-realtime port: number: {{ $.Values.realtime.service.port }} {{- end }} diff --git a/helm/sim/templates/networkpolicy.yaml b/helm/sim/templates/networkpolicy.yaml index 0562075e16d..deac5a5dba4 100644 --- a/helm/sim/templates/networkpolicy.yaml +++ b/helm/sim/templates/networkpolicy.yaml @@ -4,14 +4,14 @@ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: {{ include "simstudio.fullname" . }}-app + name: {{ include "sim.fullname" . }}-app namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.app.labels" . | nindent 4 }} + {{- include "sim.app.labels" . | nindent 4 }} spec: podSelector: matchLabels: - {{- include "simstudio.app.selectorLabels" . | nindent 6 }} + {{- include "sim.app.selectorLabels" . | nindent 6 }} policyTypes: - Ingress - Egress @@ -21,7 +21,7 @@ spec: - from: - podSelector: matchLabels: - {{- include "simstudio.realtime.selectorLabels" . | nindent 10 }} + {{- include "sim.realtime.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.app.service.targetPort }} @@ -43,7 +43,7 @@ spec: - to: - podSelector: matchLabels: - {{- include "simstudio.postgresql.selectorLabels" . | nindent 10 }} + {{- include "sim.postgresql.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.postgresql.service.targetPort }} @@ -53,7 +53,7 @@ spec: - to: - podSelector: matchLabels: - {{- include "simstudio.realtime.selectorLabels" . | nindent 10 }} + {{- include "sim.realtime.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.realtime.service.targetPort }} @@ -63,7 +63,7 @@ spec: - to: - podSelector: matchLabels: - {{- include "simstudio.ollama.selectorLabels" . | nindent 10 }} + {{- include "sim.ollama.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.ollama.service.targetPort }} @@ -91,14 +91,14 @@ spec: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: {{ include "simstudio.fullname" . }}-realtime + name: {{ include "sim.fullname" . }}-realtime namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.realtime.labels" . | nindent 4 }} + {{- include "sim.realtime.labels" . | nindent 4 }} spec: podSelector: matchLabels: - {{- include "simstudio.realtime.selectorLabels" . | nindent 6 }} + {{- include "sim.realtime.selectorLabels" . | nindent 6 }} policyTypes: - Ingress - Egress @@ -107,7 +107,7 @@ spec: - from: - podSelector: matchLabels: - {{- include "simstudio.app.selectorLabels" . | nindent 10 }} + {{- include "sim.app.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.realtime.service.targetPort }} @@ -124,7 +124,7 @@ spec: - to: - podSelector: matchLabels: - {{- include "simstudio.postgresql.selectorLabels" . | nindent 10 }} + {{- include "sim.postgresql.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.postgresql.service.targetPort }} @@ -149,14 +149,14 @@ spec: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: {{ include "simstudio.fullname" . }}-postgresql + name: {{ include "sim.fullname" . }}-postgresql namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.postgresql.labels" . | nindent 4 }} + {{- include "sim.postgresql.labels" . | nindent 4 }} spec: podSelector: matchLabels: - {{- include "simstudio.postgresql.selectorLabels" . | nindent 6 }} + {{- include "sim.postgresql.selectorLabels" . | nindent 6 }} policyTypes: - Ingress - Egress @@ -165,7 +165,7 @@ spec: - from: - podSelector: matchLabels: - {{- include "simstudio.app.selectorLabels" . | nindent 10 }} + {{- include "sim.app.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.postgresql.service.targetPort }} @@ -174,7 +174,7 @@ spec: - from: - podSelector: matchLabels: - {{- include "simstudio.realtime.selectorLabels" . | nindent 10 }} + {{- include "sim.realtime.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.postgresql.service.targetPort }} @@ -184,7 +184,7 @@ spec: - from: - podSelector: matchLabels: - {{- include "simstudio.migrations.labels" . | nindent 10 }} + {{- include "sim.migrations.labels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.postgresql.service.targetPort }} @@ -205,14 +205,14 @@ spec: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: {{ include "simstudio.fullname" . }}-ollama + name: {{ include "sim.fullname" . }}-ollama namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.ollama.labels" . | nindent 4 }} + {{- include "sim.ollama.labels" . | nindent 4 }} spec: podSelector: matchLabels: - {{- include "simstudio.ollama.selectorLabels" . | nindent 6 }} + {{- include "sim.ollama.selectorLabels" . | nindent 6 }} policyTypes: - Ingress - Egress @@ -221,7 +221,7 @@ spec: - from: - podSelector: matchLabels: - {{- include "simstudio.app.selectorLabels" . | nindent 10 }} + {{- include "sim.app.selectorLabels" . | nindent 10 }} ports: - protocol: TCP port: {{ .Values.ollama.service.targetPort }} diff --git a/helm/sim/templates/serviceaccount.yaml b/helm/sim/templates/serviceaccount.yaml index dc7e76bfa5c..6a5a635216c 100644 --- a/helm/sim/templates/serviceaccount.yaml +++ b/helm/sim/templates/serviceaccount.yaml @@ -2,10 +2,10 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: {{ include "simstudio.serviceAccountName" . }} + name: {{ include "sim.serviceAccountName" . }} namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.labels" . | nindent 4 }} + {{- include "sim.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} annotations: {{- toYaml . | nindent 4 }} diff --git a/helm/sim/templates/servicemonitor.yaml b/helm/sim/templates/servicemonitor.yaml index b4336b3d9e0..5afeca19f51 100644 --- a/helm/sim/templates/servicemonitor.yaml +++ b/helm/sim/templates/servicemonitor.yaml @@ -4,10 +4,10 @@ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: - name: {{ include "simstudio.fullname" . }}-app + name: {{ include "sim.fullname" . }}-app namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.app.labels" . | nindent 4 }} + {{- include "sim.app.labels" . | nindent 4 }} {{- with .Values.monitoring.serviceMonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} @@ -18,7 +18,7 @@ metadata: spec: selector: matchLabels: - {{- include "simstudio.app.selectorLabels" . | nindent 6 }} + {{- include "sim.app.selectorLabels" . | nindent 6 }} endpoints: - port: http path: {{ .Values.monitoring.serviceMonitor.path }} @@ -44,10 +44,10 @@ spec: apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: - name: {{ include "simstudio.fullname" . }}-realtime + name: {{ include "sim.fullname" . }}-realtime namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.realtime.labels" . | nindent 4 }} + {{- include "sim.realtime.labels" . | nindent 4 }} {{- with .Values.monitoring.serviceMonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} @@ -58,7 +58,7 @@ metadata: spec: selector: matchLabels: - {{- include "simstudio.realtime.selectorLabels" . | nindent 6 }} + {{- include "sim.realtime.selectorLabels" . | nindent 6 }} endpoints: - port: http path: {{ .Values.monitoring.serviceMonitor.path }} diff --git a/helm/sim/templates/services.yaml b/helm/sim/templates/services.yaml index 3089c1a01a2..7ce6634b777 100644 --- a/helm/sim/templates/services.yaml +++ b/helm/sim/templates/services.yaml @@ -4,10 +4,10 @@ apiVersion: v1 kind: Service metadata: - name: {{ include "simstudio.fullname" . }}-app + name: {{ include "sim.fullname" . }}-app namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.app.labels" . | nindent 4 }} + {{- include "sim.app.labels" . | nindent 4 }} spec: type: {{ .Values.app.service.type }} ports: @@ -16,7 +16,7 @@ spec: protocol: TCP name: http selector: - {{- include "simstudio.app.selectorLabels" . | nindent 4 }} + {{- include "sim.app.selectorLabels" . | nindent 4 }} {{- end }} {{- if .Values.realtime.enabled }} @@ -25,10 +25,10 @@ spec: apiVersion: v1 kind: Service metadata: - name: {{ include "simstudio.fullname" . }}-realtime + name: {{ include "sim.fullname" . }}-realtime namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.realtime.labels" . | nindent 4 }} + {{- include "sim.realtime.labels" . | nindent 4 }} spec: type: {{ .Values.realtime.service.type }} ports: @@ -37,7 +37,7 @@ spec: protocol: TCP name: http selector: - {{- include "simstudio.realtime.selectorLabels" . | nindent 4 }} + {{- include "sim.realtime.selectorLabels" . | nindent 4 }} {{- end }} {{- if .Values.postgresql.enabled }} @@ -46,10 +46,10 @@ spec: apiVersion: v1 kind: Service metadata: - name: {{ include "simstudio.fullname" . }}-postgresql + name: {{ include "sim.fullname" . }}-postgresql namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.postgresql.labels" . | nindent 4 }} + {{- include "sim.postgresql.labels" . | nindent 4 }} spec: type: {{ .Values.postgresql.service.type }} ports: @@ -58,7 +58,7 @@ spec: protocol: TCP name: postgresql selector: - {{- include "simstudio.postgresql.selectorLabels" . | nindent 4 }} + {{- include "sim.postgresql.selectorLabels" . | nindent 4 }} {{- end }} {{- if .Values.ollama.enabled }} @@ -67,10 +67,10 @@ spec: apiVersion: v1 kind: Service metadata: - name: {{ include "simstudio.fullname" . }}-ollama + name: {{ include "sim.fullname" . }}-ollama namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.ollama.labels" . | nindent 4 }} + {{- include "sim.ollama.labels" . | nindent 4 }} spec: type: {{ .Values.ollama.service.type }} ports: @@ -79,5 +79,5 @@ spec: protocol: TCP name: http selector: - {{- include "simstudio.ollama.selectorLabels" . | nindent 4 }} + {{- include "sim.ollama.selectorLabels" . | nindent 4 }} {{- end }} \ No newline at end of file diff --git a/helm/sim/templates/shared-storage.yaml b/helm/sim/templates/shared-storage.yaml index 85c535a3bbc..509af403c5a 100644 --- a/helm/sim/templates/shared-storage.yaml +++ b/helm/sim/templates/shared-storage.yaml @@ -5,12 +5,12 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ include "simstudio.fullname" $ }}-{{ .name }} + name: {{ include "sim.fullname" $ }}-{{ .name }} namespace: {{ $.Release.Namespace }} labels: - {{- include "simstudio.labels" $ | nindent 4 }} - simstudio.ai/volume-type: shared-storage - simstudio.ai/volume-name: {{ .name }} + {{- include "sim.labels" $ | nindent 4 }} + sim.ai/volume-type: shared-storage + sim.ai/volume-name: {{ .name }} {{- with .annotations }} annotations: {{- toYaml . | nindent 4 }} diff --git a/helm/sim/templates/statefulset-postgresql.yaml b/helm/sim/templates/statefulset-postgresql.yaml index 156d25880ea..f9283b6141f 100644 --- a/helm/sim/templates/statefulset-postgresql.yaml +++ b/helm/sim/templates/statefulset-postgresql.yaml @@ -4,10 +4,10 @@ apiVersion: v1 kind: ConfigMap metadata: - name: {{ include "simstudio.fullname" . }}-postgresql-config + name: {{ include "sim.fullname" . }}-postgresql-config namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.postgresql.labels" . | nindent 4 }} + {{- include "sim.postgresql.labels" . | nindent 4 }} data: postgresql.conf: | hba_file = '/etc/postgresql/pg_hba.conf' @@ -56,23 +56,24 @@ data: apiVersion: v1 kind: ConfigMap metadata: - name: {{ include "simstudio.fullname" . }}-postgresql-env + name: {{ include "sim.fullname" . }}-postgresql-env namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.postgresql.labels" . | nindent 4 }} + {{- include "sim.postgresql.labels" . | nindent 4 }} data: POSTGRES_DB: {{ .Values.postgresql.auth.database | quote }} POSTGRES_USER: {{ .Values.postgresql.auth.username | quote }} + PGDATA: "/var/lib/postgresql/data/pgdata" --- # Secret for PostgreSQL password apiVersion: v1 kind: Secret metadata: - name: {{ include "simstudio.fullname" . }}-postgresql-secret + name: {{ include "sim.fullname" . }}-postgresql-secret namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.postgresql.labels" . | nindent 4 }} + {{- include "sim.postgresql.labels" . | nindent 4 }} type: Opaque data: POSTGRES_PASSWORD: {{ .Values.postgresql.auth.password | b64enc }} @@ -82,17 +83,17 @@ data: apiVersion: apps/v1 kind: StatefulSet metadata: - name: {{ include "simstudio.fullname" . }}-postgresql + name: {{ include "sim.fullname" . }}-postgresql namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.postgresql.labels" . | nindent 4 }} + {{- include "sim.postgresql.labels" . | nindent 4 }} spec: - serviceName: {{ include "simstudio.fullname" . }}-postgresql + serviceName: {{ include "sim.fullname" . }}-postgresql replicas: 1 minReadySeconds: 10 selector: matchLabels: - {{- include "simstudio.postgresql.selectorLabels" . | nindent 6 }} + {{- include "sim.postgresql.selectorLabels" . | nindent 6 }} template: metadata: annotations: @@ -100,7 +101,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "simstudio.postgresql.selectorLabels" . | nindent 8 }} + {{- include "sim.postgresql.selectorLabels" . | nindent 8 }} {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }} @@ -109,14 +110,14 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "simstudio.serviceAccountName" . }} - {{- include "simstudio.podSecurityContext" .Values.postgresql | nindent 6 }} - {{- include "simstudio.nodeSelector" .Values.postgresql | nindent 6 }} - {{- include "simstudio.tolerations" .Values | nindent 6 }} - {{- include "simstudio.affinity" .Values | nindent 6 }} + serviceAccountName: {{ include "sim.serviceAccountName" . }} + {{- include "sim.podSecurityContext" .Values.postgresql | nindent 6 }} + {{- include "sim.nodeSelector" .Values.postgresql | nindent 6 }} + {{- include "sim.tolerations" .Values | nindent 6 }} + {{- include "sim.affinity" .Values | nindent 6 }} containers: - name: postgresql - image: {{ include "simstudio.image" (dict "context" . "image" .Values.postgresql.image) }} + image: {{ include "sim.image" (dict "context" . "image" .Values.postgresql.image) }} imagePullPolicy: {{ .Values.postgresql.image.pullPolicy }} args: ["-c", "config_file=/etc/postgresql/postgresql.conf"] ports: @@ -125,9 +126,9 @@ spec: protocol: TCP envFrom: - configMapRef: - name: {{ include "simstudio.fullname" . }}-postgresql-env + name: {{ include "sim.fullname" . }}-postgresql-env - secretRef: - name: {{ include "simstudio.fullname" . }}-postgresql-secret + name: {{ include "sim.fullname" . }}-postgresql-secret {{- if .Values.postgresql.livenessProbe }} livenessProbe: {{- toYaml .Values.postgresql.livenessProbe | nindent 12 }} @@ -136,8 +137,8 @@ spec: readinessProbe: {{- toYaml .Values.postgresql.readinessProbe | nindent 12 }} {{- end }} - {{- include "simstudio.resources" .Values.postgresql | nindent 10 }} - {{- include "simstudio.securityContext" .Values.postgresql | nindent 10 }} + {{- include "sim.resources" .Values.postgresql | nindent 10 }} + {{- include "sim.securityContext" .Values.postgresql | nindent 10 }} volumeMounts: {{- if .Values.postgresql.persistence.enabled }} - name: postgresql-data @@ -157,7 +158,7 @@ spec: volumes: - name: postgresql-config configMap: - name: {{ include "simstudio.fullname" . }}-postgresql-config + name: {{ include "sim.fullname" . }}-postgresql-config {{- if .Values.postgresql.tls.enabled }} - name: postgresql-tls secret: @@ -172,7 +173,7 @@ spec: - metadata: name: postgresql-data labels: - {{- include "simstudio.postgresql.labels" . | nindent 10 }} + {{- include "sim.postgresql.labels" . | nindent 10 }} spec: {{- if .Values.postgresql.persistence.storageClass }} {{- if (eq "-" .Values.postgresql.persistence.storageClass) }} diff --git a/helm/sim/templates/telemetry.yaml b/helm/sim/templates/telemetry.yaml index cfc1338a2ec..0f4307b8b0d 100644 --- a/helm/sim/templates/telemetry.yaml +++ b/helm/sim/templates/telemetry.yaml @@ -4,10 +4,10 @@ apiVersion: v1 kind: ConfigMap metadata: - name: {{ include "simstudio.fullname" . }}-otel-config + name: {{ include "sim.fullname" . }}-otel-config namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.labels" . | nindent 4 }} + {{- include "sim.labels" . | nindent 4 }} app.kubernetes.io/component: telemetry data: otel-config.yaml: | @@ -21,12 +21,12 @@ data: prometheus: config: scrape_configs: - - job_name: 'simstudio-app' + - job_name: 'sim-app' static_configs: - - targets: ['{{ include "simstudio.fullname" . }}-app:{{ .Values.app.service.port }}'] - - job_name: 'simstudio-realtime' + - targets: ['{{ include "sim.fullname" . }}-app:{{ .Values.app.service.port }}'] + - job_name: 'sim-realtime' static_configs: - - targets: ['{{ include "simstudio.fullname" . }}-realtime:{{ .Values.realtime.service.port }}'] + - targets: ['{{ include "sim.fullname" . }}-realtime:{{ .Values.realtime.service.port }}'] processors: batch: @@ -71,49 +71,67 @@ data: traces: receivers: [otlp] processors: [memory_limiter, batch] - exporters: [{{- if .Values.telemetry.jaeger.enabled }}jaeger, {{- end }}{{- if .Values.telemetry.otlp.enabled }}otlp, {{- end }}logging] + exporters: + - logging + {{- if .Values.telemetry.jaeger.enabled }} + - jaeger + {{- end }} + {{- if .Values.telemetry.otlp.enabled }} + - otlp + {{- end }} metrics: receivers: [otlp, prometheus] processors: [memory_limiter, batch] - exporters: [{{- if .Values.telemetry.prometheus.enabled }}prometheusremotewrite, {{- end }}{{- if .Values.telemetry.otlp.enabled }}otlp, {{- end }}logging] + exporters: + - logging + {{- if .Values.telemetry.prometheus.enabled }} + - prometheusremotewrite + {{- end }} + {{- if .Values.telemetry.otlp.enabled }} + - otlp + {{- end }} logs: receivers: [otlp] processors: [memory_limiter, batch] - exporters: [{{- if .Values.telemetry.otlp.enabled }}otlp, {{- end }}logging] + exporters: + - logging + {{- if .Values.telemetry.otlp.enabled }} + - otlp + {{- end }} --- # OpenTelemetry Collector Deployment apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "simstudio.fullname" . }}-otel-collector + name: {{ include "sim.fullname" . }}-otel-collector namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.labels" . | nindent 4 }} + {{- include "sim.labels" . | nindent 4 }} app.kubernetes.io/component: telemetry spec: replicas: {{ .Values.telemetry.replicaCount }} selector: matchLabels: - {{- include "simstudio.selectorLabels" . | nindent 6 }} + {{- include "sim.selectorLabels" . | nindent 6 }} app.kubernetes.io/component: telemetry template: metadata: labels: - {{- include "simstudio.selectorLabels" . | nindent 8 }} + {{- include "sim.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: telemetry spec: {{- with .Values.global.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "simstudio.serviceAccountName" . }} + serviceAccountName: {{ include "sim.serviceAccountName" . }} securityContext: runAsNonRoot: true runAsUser: 10001 fsGroup: 10001 containers: - name: otel-collector - image: {{ include "simstudio.image" (dict "context" . "image" .Values.telemetry.image) }} + image: {{ include "sim.image" (dict "context" . "image" .Values.telemetry.image) }} imagePullPolicy: {{ .Values.telemetry.image.pullPolicy }} command: - /otelcol-contrib @@ -162,7 +180,7 @@ spec: volumes: - name: otel-config configMap: - name: {{ include "simstudio.fullname" . }}-otel-config + name: {{ include "sim.fullname" . }}-otel-config {{- with .Values.telemetry.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} @@ -180,10 +198,10 @@ spec: apiVersion: v1 kind: Service metadata: - name: {{ include "simstudio.fullname" . }}-otel-collector + name: {{ include "sim.fullname" . }}-otel-collector namespace: {{ .Release.Namespace }} labels: - {{- include "simstudio.labels" . | nindent 4 }} + {{- include "sim.labels" . | nindent 4 }} app.kubernetes.io/component: telemetry spec: type: {{ .Values.telemetry.service.type }} @@ -201,6 +219,6 @@ spec: targetPort: health protocol: TCP selector: - {{- include "simstudio.selectorLabels" . | nindent 4 }} + {{- include "sim.selectorLabels" . | nindent 4 }} app.kubernetes.io/component: telemetry {{- end }} \ No newline at end of file diff --git a/helm/sim/values.schema.json b/helm/sim/values.schema.json index dd9493c8fb2..9f7ea1ac865 100644 --- a/helm/sim/values.schema.json +++ b/helm/sim/values.schema.json @@ -74,7 +74,7 @@ }, "cpu": { "type": "string", - "pattern": "^\\d+(m|\\.\\d+)?$", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", "description": "CPU request (e.g., 1000m, 1.0)" } } @@ -144,7 +144,7 @@ }, "cpu": { "type": "string", - "pattern": "^\\d+(m|\\.\\d+)?$", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", "description": "CPU limit (e.g., 1000m, 1.0)" } } @@ -159,7 +159,7 @@ }, "cpu": { "type": "string", - "pattern": "^\\d+(m|\\.\\d+)?$", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", "description": "CPU request (e.g., 500m, 0.5)" } } @@ -217,7 +217,7 @@ }, "cpu": { "type": "string", - "pattern": "^\\d+(m|\\.\\d+)?$", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", "description": "CPU limit" } } @@ -232,7 +232,7 @@ }, "cpu": { "type": "string", - "pattern": "^\\d+(m|\\.\\d+)?$", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", "description": "CPU request (e.g., 500m, 0.5)" } } @@ -295,6 +295,23 @@ "minimum": 1, "maximum": 65535, "description": "External database port" + }, + "username": { + "type": "string", + "description": "External database username" + }, + "password": { + "type": "string", + "description": "External database password" + }, + "database": { + "type": "string", + "description": "External database name" + }, + "sslMode": { + "type": "string", + "enum": ["disable", "allow", "prefer", "require", "verify-ca", "verify-full"], + "description": "SSL mode for database connection" } }, "if": { @@ -362,7 +379,7 @@ }, "cpu": { "type": "string", - "pattern": "^\\d+(m|\\.\\d+)?$", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", "description": "CPU limit" }, "nvidia.com/gpu": { @@ -382,7 +399,7 @@ }, "cpu": { "type": "string", - "pattern": "^\\d+(m|\\.\\d+)?$", + "pattern": "^[0-9]+(\\.[0-9]+)?m?$", "description": "CPU request (e.g., 1000m, 1.0)" } } diff --git a/helm/sim/values.yaml b/helm/sim/values.yaml index f8a220a1411..026b3ac87f1 100644 --- a/helm/sim/values.yaml +++ b/helm/sim/values.yaml @@ -12,7 +12,7 @@ global: # Storage class for persistent volumes storageClass: "" -# Main Sim Studio application configuration +# Main Sim application configuration app: # Enable/disable the main application enabled: true @@ -61,9 +61,8 @@ app: # Authentication and encryption secrets (REQUIRED for production) # Generate secure 32-character secrets using: openssl rand -hex 32 - # These placeholder values MUST be replaced with your own secure secrets - BETTER_AUTH_SECRET: "CHANGE-ME-32-CHAR-SECRET-FOR-PRODUCTION-USE" - ENCRYPTION_KEY: "CHANGE-ME-32-CHAR-ENCRYPTION-KEY-FOR-PROD" + BETTER_AUTH_SECRET: "" # REQUIRED - set via --set flag or external secret manager + ENCRYPTION_KEY: "" # REQUIRED - set via --set flag or external secret manager # Optional third-party service integrations (leave empty if not using) FREESTYLE_API_KEY: "" @@ -142,8 +141,7 @@ realtime: # Authentication secret (REQUIRED for production) # Must match the BETTER_AUTH_SECRET value from the main app configuration - # This placeholder value MUST be replaced with your own secure secret - BETTER_AUTH_SECRET: "CHANGE-ME-32-CHAR-SECRET-FOR-PRODUCTION-USE" + BETTER_AUTH_SECRET: "" # REQUIRED - set via --set flag or external secret manager # Cross-Origin Resource Sharing (CORS) allowed origins ALLOWED_ORIGINS: "http://localhost:3000" @@ -218,8 +216,8 @@ postgresql: # Authentication configuration auth: username: postgres - password: "CHANGE-ME-SECURE-PASSWORD" # REQUIRED - replace with a strong password for production - database: simstudio + password: "" # REQUIRED - set via --set flag or external secret manager + database: sim # Node selector for database pod scheduling (leave empty to allow scheduling on any node) nodeSelector: {} @@ -269,13 +267,13 @@ postgresql: # Health checks livenessProbe: exec: - command: ["pg_isready", "-U", "postgres", "-d", "simstudio"] + command: ["pg_isready", "-U", "postgres", "-d", "sim"] initialDelaySeconds: 10 periodSeconds: 5 readinessProbe: exec: - command: ["pg_isready", "-U", "postgres", "-d", "simstudio"] + command: ["pg_isready", "-U", "postgres", "-d", "sim"] initialDelaySeconds: 5 periodSeconds: 3 @@ -289,7 +287,7 @@ externalDatabase: port: 5432 username: postgres password: "" - database: simstudio + database: sim # SSL configuration sslMode: require @@ -396,14 +394,14 @@ ingress: # Main application host configuration app: - host: simstudio.local + host: sim.local paths: - path: / pathType: Prefix # Realtime service host configuration realtime: - host: simstudio-ws.local + host: sim-ws.local paths: - path: / pathType: Prefix @@ -411,7 +409,7 @@ ingress: # TLS configuration tls: enabled: false - secretName: simstudio-tls-secret + secretName: sim-tls-secret # Service Account configuration serviceAccount: diff --git a/package.json b/package.json index 1c9a1074b58..e2948154c4a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "format:check": "bunx biome format .", "lint": "bunx biome check --write --unsafe .", "lint:check": "bunx biome check --unsafe .", + "lint:helm": "helm lint ./helm/sim --strict --values ./helm/sim/test/values-lint.yaml", + "lint:all": "bun run lint && bun run lint:helm", "check": "bunx biome check --files-ignore-unknown=true", "prepare": "bun husky", "prebuild": "bun run lint:check",