Helm chart
Production Kubernetes deployment: one all-in-one workload scaled by replicaCount, a leader-elected scheduler, External Secrets integration, and the graceful-shutdown behaviour upgrades depend on.
Install
# The chart is published to the OCI registry — there is no classic Helm repo to add.
helm install cap oci://ghcr.io/cloudnativeworks/charts/certautopilot \
--namespace cap --create-namespace \
--version <chart-version> \
-f values.yaml
Minimum values.yaml
image:
tag: "1.4.0"
replicaCount: 2 # backend replicas; the scheduler inside them is leader-elected
externalMongodb:
enabled: true
uri: mongodb://mongo-rs-0.mongo:27017,mongo-rs-1.mongo:27017,mongo-rs-2.mongo:27017/certautopilot?replicaSet=rs0
secrets:
jwt:
secret: "<random string>" # required in release mode unless secrets.existingSecret is set
encryption:
provider: env
currentVersion: 1 # seeds the first install only; the keystore is authoritative afterwards
kekVersions:
"1": "<64 hex chars>" # every version existing data references must stay listed
scheduler:
leaderLockTTL: "90s" # chart default is 2h — see below
externalMongodb.uri is rendered into a ConfigMap in plaintextIt is not a Secret path. If the connection string carries credentials, they end up readable by anyone who can read ConfigMaps in the namespace.
scheduler.leaderLockTTLThe chart ships 2h, while the code's own default is 90 s. Left alone, a scheduler failover on
Kubernetes can take up to two hours. Set it to 90s unless you have a reason not to.
Workloads
The chart deploys two Deployments and two Services, plus an optional ServiceMonitor and PrometheusRule.
| Workload | Mode | Notes |
|---|---|---|
| backend | all — fixed | Runs API, worker and scheduler in one process. Scale with replicaCount; the scheduler is leader-elected via MongoDB, so extra replicas are safe. |
| frontend | — | Serves the React bundle. |
There is no Ingress, no HorizontalPodAutoscaler and no PodDisruptionBudget in the chart — add
your own if you need them. There is also no per-mode split: the backend's arguments are fixed at
serve --mode=all, so api: / worker: / scheduler: value keys do nothing.
External Secrets
In release mode the chart requires either plaintext secrets.jwt.secret and secrets.encryption.kekVersions in values, or secrets.existingSecret naming a pre-created Secret — rendering fails with an explicit error if neither is present. Use existingSecret to keep secrets out of values.yaml entirely. Most users wire them up via External Secrets Operator pulling from AWS Secrets Manager, GCP SM, or Vault.
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: {name: cap-kek, namespace: cap}
spec:
refreshInterval: 1h
secretStoreRef: {name: aws-sm, kind: ClusterSecretStore}
target: {name: cap-kek}
data:
- secretKey: encryption-env-kek-v1 # 64 hex chars, not raw bytes
remoteRef: {key: certautopilot/prod/kek-v1}
- secretKey: encryption-current-version
remoteRef: {key: certautopilot/prod/kek-current-version}
- secretKey: jwt-secret
remoteRef: {key: certautopilot/prod/jwt}
Point the chart at it with secrets.existingSecret: cap-kek and
secrets.existingSecretVersions: [1]. The key names are fixed — the chart reads
encryption-env-kek-v{N}, one per version, and refuses to render if
kekVersions is empty while provider: env.
Metrics
/metrics is served over HTTPS on the backend's own port (config.server.port, 8181 by
default) — not on a separate 9090. Set serviceMonitor.enabled=true (note: top-level, not
metrics.serviceMonitor) to deploy the ServiceMonitor for Prometheus Operator users.
Draining nodes
The chart ships no PodDisruptionBudget. On SIGTERM the worker waits up to 55 seconds for its
in-flight job to finish and only then releases the lock. The chart, however, sets
terminationGracePeriodSeconds: 30 and installs no preStop hook — so a job still running at 30
seconds is SIGKILLed, and its lock is only reclaimed after the 5-minute lock TTL expires.
Raise terminationGracePeriodSeconds to 60 if your jobs routinely run longer than 30 seconds.
Size drain windows against the 5-minute TTL either way, and add your own PDB if you need to bound
simultaneous evictions.
Upgrade
helm upgrade cap oci://ghcr.io/cloudnativeworks/charts/certautopilot \
--namespace cap \
--version <chart-version> \
-f values.yaml \
--atomic --wait
There is no migration job — the chart ships none, and there are no schema migrations to run. --atomic rolls back if the rollout fails.
See also
- Requirements & sizing — host requirements, topology choice, and capacity planning
- High availability
- Architecture
- KEK rotation