Kubernetes
Run meilisearch-cdc as a single-replica Deployment with a persistent volume for its embedded state store, and pass secrets as files.
Exactly one replica
All state (tasks, checkpoints, users) lives in one embedded database file that a single process locks. Do not scale the Deployment above one replica, and use the Recreate strategy so the old pod releases the volume before the new one starts. For more throughput, raise the per-task batching settings or run separate installations with separate data directories.
Secrets
Generate an encryption key once and keep it outside the cluster as well: without it, stored credentials cannot be decrypted.
kubectl create namespace cdc
kubectl -n cdc create secret generic meilisearch-cdc \
--from-literal=secret-key="$(openssl rand -base64 32)" \
--from-literal=admin-token="$(openssl rand -hex 32)" \
--from-literal=admin-password='choose-a-strong-password'
A base64 string that decodes to exactly 32 bytes is used as the AES-256 key directly; any other value is treated as a passphrase and stretched with argon2id.
Manifests
apiVersion: v1
kind: PersistentVolumeClaim
metadata: {name: meilisearch-cdc-data, namespace: cdc}
spec:
accessModes: [ReadWriteOnce]
resources: {requests: {storage: 2Gi}}
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: meilisearch-cdc, namespace: cdc}
spec:
replicas: 1 # never more: the state store is single-writer
strategy: {type: Recreate}
selector: {matchLabels: {app: meilisearch-cdc}}
template:
metadata: {labels: {app: meilisearch-cdc}}
spec:
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
terminationGracePeriodSeconds: 45 # CDC_STOP_TIMEOUT (20s) + 10s + margin
containers:
- name: cdc
image: ghcr.io/ja7ad/meilisearch-cdc:1.2.3
ports: [{name: http, containerPort: 8080}]
env:
- {name: CDC_DATA_DIR, value: /data}
- {name: CDC_LOG_FORMAT, value: json}
- {name: CDC_PUBLIC_URL, value: https://cdc.example.com}
- {name: CDC_TRUST_PROXY, value: "true"}
- {name: CDC_COOKIE_SECURE, value: "true"}
- {name: CDC_ADMIN_EMAIL, value: admin@example.com}
- {name: CDC_SECRET_KEY_FILE, value: /run/secrets/cdc/secret-key}
- {name: CDC_ADMIN_TOKEN_FILE, value: /run/secrets/cdc/admin-token}
- {name: CDC_ADMIN_PASSWORD_FILE, value: /run/secrets/cdc/admin-password}
- {name: GOMEMLIMIT, value: 400MiB}
volumeMounts:
- {name: data, mountPath: /data}
- {name: secrets, mountPath: /run/secrets/cdc, readOnly: true}
resources:
requests: {cpu: 100m, memory: 128Mi}
limits: {memory: 512Mi}
livenessProbe:
httpGet: {path: /healthz, port: http}
periodSeconds: 10
readinessProbe:
httpGet: {path: /healthz, port: http}
periodSeconds: 5
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: {drop: [ALL]}
volumes:
- name: data
persistentVolumeClaim: {claimName: meilisearch-cdc-data}
- name: secrets
secret: {secretName: meilisearch-cdc, defaultMode: 0400}
---
apiVersion: v1
kind: Service
metadata: {name: meilisearch-cdc, namespace: cdc}
spec:
selector: {app: meilisearch-cdc}
ports: [{name: http, port: 80, targetPort: http}]
Notes
- Probes.
/healthzneeds no authentication and answersokwhile the HTTP server runs. Do not use/api/v1/healthas a liveness probe: it also checks Meilisearch, and a Meilisearch outage should not restart this pod. - Admin account.
CDC_ADMIN_EMAILwithCDC_ADMIN_PASSWORD_FILEcreates the first admin on start when no user exists; afterwards they are ignored. - Metrics.
/metricsrequires authentication. Give Prometheus the admin token as a bearer token; see Prometheus. - Admin CLI.
kubectl -n cdc exec -it deploy/meilisearch-cdc -- meilisearch-cdc admin users listtalks to the running service over its socket in/data. - Declarative tasks. Mount a ConfigMap with a tasks file and set
CDC_TASKS_FILE; credentials come from environment variables expanded with${VAR}. See Declarative tasks file. - Server-Sent Events. If an Ingress controller buffers responses, the dashboard's live updates stall. For ingress-nginx, set the annotations
nginx.ingress.kubernetes.io/proxy-buffering: "off"and a longproxy-read-timeout. See Reverse proxy and TLS.
Backups
Snapshot the volume while the pod is scaled to zero, or copy /data/cdc.db as described in Backups and upgrades. The key lives in the Secret, so back that up too.