apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "svcforge.fullname" . }}-worker labels: {{- include "svcforge.labels" . | nindent 4 }} app.kubernetes.io/component: worker spec: # Plain replicas, no HPA. Concurrency is bounded twice over — by replicas here and by a # semaphore inside the claim loop — and the SKIP LOCKED claim makes both safe. The day # replicas: 2 stops keeping up, add an HPA. Not before. replicas: {{ .Values.worker.replicas }} selector: matchLabels: {{- include "svcforge.selectorLabels" (dict "ctx" $ "component" "worker") | nindent 6 }} template: metadata: labels: {{- include "svcforge.labels" . | nindent 8 }} {{- include "svcforge.selectorLabels" (dict "ctx" $ "component" "worker") | nindent 8 }} spec: serviceAccountName: {{ include "svcforge.serviceAccountName" (dict "ctx" $ "component" "worker") }} {{- with .Values.image.pullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} # The load-bearing one. On SIGTERM the loop stops claiming and finishes the task in # hand; 60s is the budget for that. Chaos experiment 2 asserts the pod exits 0 inside # it. Lower this and a rolling deploy starts orphaning tasks to lease expiry. terminationGracePeriodSeconds: 60 securityContext: {{- include "svcforge.podSecurityContext" . | nindent 8 }} containers: - name: worker image: {{ include "svcforge.image" (dict "ctx" $ "component" "worker") }} imagePullPolicy: {{ .Values.image.pullPolicy }} securityContext: {{- include "svcforge.containerSecurityContext" . | nindent 12 }} ports: - name: metrics containerPort: 9000 envFrom: - secretRef: name: {{ include "svcforge.secretName" . }} env: {{- include "svcforge.env" . | nindent 12 }} # The claim loop stamps locked_by with this. Per-pod, so a stuck lease names # the pod that holds it — runbook entry 1 depends on that. - name: SVCFORGE_WORKER_ID valueFrom: fieldRef: fieldPath: metadata.name - name: SVCFORGE_WORKER_CONCURRENCY value: {{ .Values.worker.concurrency | quote }} - name: OTEL_SERVICE_NAME value: svcforge-worker # No liveness probe. A worker mid-provision is legitimately busy for minutes; # a probe here is a way to kill a healthy provision and learn nothing. resources: {{- toYaml .Values.worker.resources | nindent 12 }} volumeMounts: - name: tmp mountPath: /tmp # helm writes cache/config/repositories under $HELM_*_HOME, which the image # points at /tmp/helm. Without this, every helm call fails on a read-only fs. - name: helm-home mountPath: /tmp/helm volumes: - name: tmp emptyDir: {} - name: helm-home emptyDir: {} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }}