# Stafett on Kubernetes: enqueue and deliver, one Deployment and one image # per role, against a Postgres you already run. Served as # https://stafett.dev/charts/install.yaml. These are the objects the Helm # chart renders with its defaults and release name stafett-worker; CI checks # they match, so change both together. # # The images are not published yet. Download this file and edit the four # image: lines to point at a registry your cluster can pull from. # # Create the Secret by hand (a committed Secret manifest is the secret in # plain text), then apply. DATABASE_URL must be a direct connection, not a # pooler. Leave out STAFETT_SIGNING_SECRET to deliver unsigned. # # kubectl create namespace stafett # kubectl -n stafett create secret generic stafett-worker \ # --from-literal=DATABASE_URL='postgresql://user:password@host:5432/db' \ # --from-literal=STAFETT_SIGNING_SECRET="whsec_$(openssl rand -base64 24)" # curl -fsSLO https://stafett.dev/charts/install.yaml # then edit image: # kubectl -n stafett apply -f install.yaml # # Apps in the cluster enqueue at http://stafett-worker-enqueue.stafett:8000/enqueue. # No Ingress: the API has no auth (ADR 0004), so keep it in-cluster. apiVersion: v1 kind: Service metadata: name: stafett-worker-enqueue spec: selector: app.kubernetes.io/name: stafett-worker app.kubernetes.io/component: enqueue ports: - name: http port: 8000 targetPort: http --- apiVersion: apps/v1 kind: Deployment metadata: name: stafett-worker-enqueue spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: stafett-worker app.kubernetes.io/component: enqueue template: metadata: labels: app.kubernetes.io/name: stafett-worker app.kubernetes.io/component: enqueue spec: automountServiceAccountToken: false # Service links inject _PORT=tcp://... variables; a Service # named "stafett" would collide with STAFETT_PORT. enableServiceLinks: false securityContext: runAsNonRoot: true runAsUser: 10001 seccompProfile: type: RuntimeDefault # pgqueuer's upgrade into schema "stafett" (ADR 0004). Both roles run it, # so neither starts on a schema older than its image; it is idempotent # and pgqueuer's schema lock serialises concurrent runs. initContainers: - name: setup image: ghcr.io/janbjorge/stafett-enqueue:edge args: ["setup"] env: - name: DATABASE_URL valueFrom: secretKeyRef: {name: stafett-worker, key: DATABASE_URL} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: {drop: ["ALL"]} resources: requests: {cpu: 50m, memory: 128Mi} limits: {memory: 256Mi} containers: - name: enqueue image: ghcr.io/janbjorge/stafett-enqueue:edge # No signing secret: only deliver signs. env: - name: DATABASE_URL valueFrom: secretKeyRef: {name: stafett-worker, key: DATABASE_URL} ports: - name: http containerPort: 8000 readinessProbe: httpGet: {path: /healthz, port: http} livenessProbe: httpGet: {path: /healthz, port: http} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: {drop: ["ALL"]} resources: requests: {cpu: 50m, memory: 128Mi} limits: {memory: 256Mi} --- apiVersion: apps/v1 kind: Deployment metadata: name: stafett-worker-deliver spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: stafett-worker app.kubernetes.io/component: deliver template: metadata: labels: app.kubernetes.io/name: stafett-worker app.kubernetes.io/component: deliver spec: automountServiceAccountToken: false enableServiceLinks: false securityContext: runAsNonRoot: true runAsUser: 10001 seccompProfile: type: RuntimeDefault # Above the 30s delivery timeout, so deliveries in flight finish on # SIGTERM instead of being retried as duplicates. terminationGracePeriodSeconds: 60 initContainers: - name: setup image: ghcr.io/janbjorge/stafett-deliver:edge args: ["setup"] env: - name: DATABASE_URL valueFrom: secretKeyRef: {name: stafett-worker, key: DATABASE_URL} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: {drop: ["ALL"]} resources: requests: {cpu: 50m, memory: 128Mi} limits: {memory: 256Mi} containers: - name: deliver image: ghcr.io/janbjorge/stafett-deliver:edge env: - name: DATABASE_URL valueFrom: secretKeyRef: {name: stafett-worker, key: DATABASE_URL} - name: STAFETT_SIGNING_SECRET valueFrom: # Without the key, deliveries go out unsigned (ADR 0003). secretKeyRef: {name: stafett-worker, key: STAFETT_SIGNING_SECRET, optional: true} # /healthz fails once the delivery loop stops, so the kubelet # restarts a pod that answers HTTP but no longer delivers. ports: - name: http containerPort: 8000 livenessProbe: httpGet: {path: /healthz, port: http} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: {drop: ["ALL"]} resources: requests: {cpu: 50m, memory: 128Mi} limits: {memory: 256Mi}