GitOps¶
Everything Keeper needs is declarative, so it fits a Flux or Argo CD repository: the chart in one place, stores and
policies in another, and each BackupTarget next to the database it protects.
infrastructure/keeper/
controllers/ # HelmRelease keeper (CRDs, controller, API, alerts, dashboard, policy presets)
config/
store.yaml # BackupStore: bucket, region, age recipients
secrets/ # SOPS-encrypted: S3 credentials, age identities, database users
apps/team-a/
app-database.yaml
app-backup.yaml # BackupTarget, labelled org/project/env
Flux HelmRelease (excerpt)
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata: { name: keeper, namespace: keeper-system }
spec:
interval: 10m
chart:
spec:
chart: keeper
version: "1.2.3"
sourceRef: { kind: HelmRepository, name: my-charts, namespace: flux-system }
install: { crds: CreateReplace }
upgrade: { crds: CreateReplace }
values:
image: { repository: registry.example.com/keeper/keeper, tag: v1.2.3 }
targetNamespaces: [team-a]
examplePolicies: { enabled: true, store: main }
metrics:
serviceMonitor: { enabled: true }
prometheusRule: { enabled: true }
grafanaDashboard: { enabled: true }
Tips:
- Generate secrets with
kubectl create secret … --dry-run=client -o yaml | sops --encryptso no plaintext or placeholder is ever committed. Never commit the age private keys; keep an offline copy of the backup key. - Keep Keeper in its own Flux Kustomization, outside the chain your applications depend on, so a Keeper problem never blocks a deployment.
- Restores are usually created from the console or the CLI, not from git: they are one-off actions. Declaring one in git works too.