apiVersion: apps/v1 kind: Deployment metadata: name: api namespace: voice-platform spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 selector: matchLabels: app.kubernetes.io/name: voice-platform-api template: metadata: annotations: prometheus.io/scrape: "true" prometheus.io/path: /metrics prometheus.io/port: "8080" labels: app.kubernetes.io/name: voice-platform-api app.kubernetes.io/component: api spec: serviceAccountName: voice-platform-api automountServiceAccountToken: false terminationGracePeriodSeconds: 30 securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532 fsGroup: 65532 seccompProfile: type: RuntimeDefault topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/name: voice-platform-api containers: - name: api image: registry.example.invalid/voice-platform/backend:0.1.0 imagePullPolicy: IfNotPresent command: ["/app/api"] envFrom: - configMapRef: name: voice-platform-config env: - name: HTTP_ADDR value: 0.0.0.0:8080 - name: DATABASE_URL_FILE value: /var/run/secrets/voice-platform/common/database-url - name: REDIS_PASSWORD_FILE value: /var/run/secrets/voice-platform/common/redis-password - name: DEVICE_CREDENTIAL_MASTER_KEY_FILE value: /var/run/secrets/voice-platform/api/device-credential-master-key - name: RTC_APP_KEY_FILE value: /var/run/secrets/voice-platform/api/rtc-app-key - name: CURSOR_SIGNING_SECRET_FILE value: /var/run/secrets/voice-platform/api/cursor-signing-secret - name: SHARE_TOKEN_SIGNING_SECRET_FILE value: /var/run/secrets/voice-platform/api/share-token-signing-secret - name: MEMORY_TOOL_SIGNING_SECRET_FILE value: /var/run/secrets/voice-platform/model-storage/memory-tool-signing-secret - name: OBJECT_STORE_ACCESS_KEY_FILE value: /var/run/secrets/voice-platform/model-storage/object-store-access-key - name: OBJECT_STORE_SECRET_KEY_FILE value: /var/run/secrets/voice-platform/model-storage/object-store-secret-key - name: ARK_API_KEY_FILE value: /var/run/secrets/voice-platform/model-storage/ark-api-key ports: - name: http containerPort: 8080 startupProbe: httpGet: path: /health/live port: http periodSeconds: 2 failureThreshold: 30 readinessProbe: httpGet: path: /health/ready port: http periodSeconds: 5 timeoutSeconds: 2 failureThreshold: 3 livenessProbe: httpGet: path: /health/live port: http periodSeconds: 15 timeoutSeconds: 2 failureThreshold: 3 resources: requests: cpu: 200m memory: 256Mi limits: cpu: "1" memory: 768Mi securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] volumeMounts: - name: common-secrets mountPath: /var/run/secrets/voice-platform/common readOnly: true - name: api-secrets mountPath: /var/run/secrets/voice-platform/api readOnly: true - name: model-storage-secrets mountPath: /var/run/secrets/voice-platform/model-storage readOnly: true volumes: - name: common-secrets secret: secretName: voice-platform-common-secrets - name: api-secrets secret: secretName: voice-platform-api-secrets - name: model-storage-secrets secret: secretName: voice-platform-model-storage-secrets --- apiVersion: apps/v1 kind: Deployment metadata: name: callbacks namespace: voice-platform spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 selector: matchLabels: app.kubernetes.io/name: voice-platform-callbacks template: metadata: annotations: prometheus.io/scrape: "true" prometheus.io/path: /metrics prometheus.io/port: "8081" labels: app.kubernetes.io/name: voice-platform-callbacks app.kubernetes.io/component: callbacks spec: serviceAccountName: voice-platform-callbacks automountServiceAccountToken: false terminationGracePeriodSeconds: 30 securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532 fsGroup: 65532 seccompProfile: type: RuntimeDefault topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/name: voice-platform-callbacks containers: - name: callbacks image: registry.example.invalid/voice-platform/backend:0.1.0 imagePullPolicy: IfNotPresent command: ["/app/callbacks"] envFrom: - configMapRef: name: voice-platform-config env: - name: HTTP_ADDR value: 0.0.0.0:8081 - name: DATABASE_URL_FILE value: /var/run/secrets/voice-platform/common/database-url - name: REDIS_PASSWORD_FILE value: /var/run/secrets/voice-platform/common/redis-password - name: PROVIDER_CALLBACK_SECRET_FILE value: /var/run/secrets/voice-platform/callbacks/provider-callback-secret - name: PLATFORM_HEALTH_CALLBACK_SECRET_FILE value: /var/run/secrets/voice-platform/callbacks/platform-health-callback-secret ports: - name: http containerPort: 8081 startupProbe: httpGet: path: /health/live port: http periodSeconds: 2 failureThreshold: 30 readinessProbe: httpGet: path: /health/ready port: http periodSeconds: 5 timeoutSeconds: 2 livenessProbe: httpGet: path: /health/live port: http periodSeconds: 15 timeoutSeconds: 2 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 384Mi securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] volumeMounts: - name: common-secrets mountPath: /var/run/secrets/voice-platform/common readOnly: true - name: callbacks-secrets mountPath: /var/run/secrets/voice-platform/callbacks readOnly: true volumes: - name: common-secrets secret: secretName: voice-platform-common-secrets - name: callbacks-secrets secret: secretName: voice-platform-callbacks-secrets --- apiVersion: apps/v1 kind: Deployment metadata: name: worker namespace: voice-platform spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 selector: matchLabels: app.kubernetes.io/name: voice-platform-worker template: metadata: annotations: prometheus.io/scrape: "true" prometheus.io/path: /metrics prometheus.io/port: "8082" labels: app.kubernetes.io/name: voice-platform-worker app.kubernetes.io/component: worker spec: serviceAccountName: voice-platform-worker automountServiceAccountToken: false terminationGracePeriodSeconds: 30 securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532 fsGroup: 65532 seccompProfile: type: RuntimeDefault topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/name: voice-platform-worker containers: - name: worker image: registry.example.invalid/voice-platform/backend:0.1.0 imagePullPolicy: IfNotPresent command: ["/app/worker"] envFrom: - configMapRef: name: voice-platform-config env: - name: HTTP_ADDR value: 0.0.0.0:8082 - name: DATABASE_URL_FILE value: /var/run/secrets/voice-platform/common/database-url - name: REDIS_PASSWORD_FILE value: /var/run/secrets/voice-platform/common/redis-password - name: VOLC_ACCESS_KEY_ID_FILE value: /var/run/secrets/voice-platform/worker/volc-access-key-id - name: VOLC_SECRET_ACCESS_KEY_FILE value: /var/run/secrets/voice-platform/worker/volc-secret-access-key - name: VOLC_VOICE_CHAT_TEMPLATE_FILE value: /var/run/secrets/voice-platform/worker/voice-chat-template.json - name: OBJECT_STORE_ACCESS_KEY_FILE value: /var/run/secrets/voice-platform/model-storage/object-store-access-key - name: OBJECT_STORE_SECRET_KEY_FILE value: /var/run/secrets/voice-platform/model-storage/object-store-secret-key - name: ARK_API_KEY_FILE value: /var/run/secrets/voice-platform/model-storage/ark-api-key - name: CONTENT_SAFETY_API_KEY_FILE value: /var/run/secrets/voice-platform/model-storage/content-safety-api-key - name: MEMORY_TOOL_SIGNING_SECRET_FILE value: /var/run/secrets/voice-platform/model-storage/memory-tool-signing-secret ports: - name: http containerPort: 8082 startupProbe: httpGet: path: /health/live port: http periodSeconds: 2 failureThreshold: 30 readinessProbe: httpGet: path: /health/ready port: http periodSeconds: 5 timeoutSeconds: 2 livenessProbe: httpGet: path: /health/live port: http periodSeconds: 15 timeoutSeconds: 2 resources: requests: cpu: 250m memory: 256Mi limits: cpu: "1" memory: 768Mi securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] volumeMounts: - name: common-secrets mountPath: /var/run/secrets/voice-platform/common readOnly: true - name: worker-secrets mountPath: /var/run/secrets/voice-platform/worker readOnly: true - name: model-storage-secrets mountPath: /var/run/secrets/voice-platform/model-storage readOnly: true volumes: - name: common-secrets secret: secretName: voice-platform-common-secrets - name: worker-secrets secret: secretName: voice-platform-worker-secrets - name: model-storage-secrets secret: secretName: voice-platform-model-storage-secrets --- apiVersion: apps/v1 kind: Deployment metadata: name: web namespace: voice-platform spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 selector: matchLabels: app.kubernetes.io/name: voice-platform-web template: metadata: labels: app.kubernetes.io/name: voice-platform-web app.kubernetes.io/component: web spec: serviceAccountName: voice-platform-web automountServiceAccountToken: false terminationGracePeriodSeconds: 30 securityContext: runAsNonRoot: true runAsUser: 101 runAsGroup: 101 fsGroup: 101 seccompProfile: type: RuntimeDefault topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app.kubernetes.io/name: voice-platform-web containers: - name: web image: registry.example.invalid/voice-platform/web:0.1.0 imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c"] args: ["/docker-entrypoint.d/40-runtime-config.sh && exec nginx -g 'daemon off;'"] envFrom: - configMapRef: name: voice-platform-web-config ports: - name: http containerPort: 8080 startupProbe: httpGet: path: /runtime-config.js port: http periodSeconds: 2 failureThreshold: 15 readinessProbe: httpGet: path: /runtime-config.js port: http periodSeconds: 5 timeoutSeconds: 2 livenessProbe: httpGet: path: /runtime-config.js port: http periodSeconds: 15 timeoutSeconds: 2 resources: requests: cpu: 50m memory: 64Mi limits: cpu: 250m memory: 192Mi securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: sizeLimit: 32Mi