Skip to content

External Secrets

External Secrets Operator (ESO) is the bridge between Vault and Kubernetes-native Secret objects. Every other app on the platform consumes credentials by declaring an ExternalSecret, and ESO does the work of fetching from Vault and materializing the result as a regular Kubernetes Secret.

This page covers both Flux Kustomizations that make up the operator: the CRDs/operator install in wave 1 and the cluster-wide configuration in wave 2.

FieldValue
Flux pathsflux-clusters/stefanzhelev/apps/external-secrets/external-secrets-crds and …/external-secrets-config
Base pathflux-apps/external-secrets/{external-secrets-crds,external-secrets-config}
Namespaceexternal-secrets
Sync waves1 (CRDs/operator) and 2 (config)
Depends onwave 2 depends on vault and external-secrets-crds
  • HelmRelease for the external-secrets chart >= 1.0.0
  • Installs the operator, the validating webhook, and the cert-controller
  • Includes the CRDs (ExternalSecret, ClusterSecretStore, SecretStore, …)
  • Footprint: 100m CPU / 256Mi memory for the operator, 50m / 64Mi for the webhook and cert-controller
  • A ClusterSecretStore pointed at http://vault.vault.svc.cluster.local:8200
  • Vault auth via a token stored in a vault-token Secret
  • Mounts Vault’s KV v2 path secret
  • Raw manifests only — no Helm chart
  • Two-stage rollout. The operator and CRDs go in early so other wave-1 apps can declare ExternalSecret objects without Flux refusing to apply unknown kinds. The cluster-wide store lands in wave 2, after Vault is actually reachable, so the store doesn’t immediately error.
  • One ClusterSecretStore for everything. Apps reference it by name rather than each defining their own SecretStore.
  • KV v2 mount. The secret/ mount in Vault is the source for every ExternalSecret on the cluster.
  • Vault: the only secret backend, accessed by service token
  • Every app with an ExternalSecret: Authentik, Forgejo, Grafana, Airflow, Dremio, ClickStack, CloudNative-PG, and so on
Terminal window
# Check the operator
kubectl get pods -n external-secrets
# Inspect the cluster-wide store
kubectl get clustersecretstore
kubectl describe clustersecretstore <name>
# List external secrets
kubectl get externalsecret -A
# Force a refresh
kubectl annotate externalsecret <name> -n <ns> \
force-sync=$(date +%s) --overwrite