External Secrets Operator
Render ExternalSecret objects from image-source env.store entries — and apply ESO manifests from git
External Secrets Operator
The External Secrets Operator (ESO) syncs secrets from external providers into Kubernetes Secrets. Wardn integrates at two levels: env.store entries on image sources render ExternalSecret objects for ESO to resolve, and ExternalSecret/SecretStore manifests committed to git are applied like any other resource.
How It Works
┌────────────────┐ env.store ┌──────────────┐ renders ┌───────────────┐
│ App spec │────────────────▶│ Operator │────────────▶│ ExternalSecret│
│ (Image source) │ {id,path,key} │ renderer │ │ objects │
└────────────────┘ └──────────────┘ └───────┬───────┘
│
┌────────────────┐ ▼
│ ESO operator │ ◀─────────────── resolves ────────────── K8s Secret
│ (in-cluster) │ │
└────────────────┘ ▼
Deployment envFrom- You write
env.storeon the image workload —{id: <eso store>, path: <remote key>, key: <data key>} - The operator renders an
ExternalSecretalongside the Deployment/Service - ESO resolves the remote path from its provider and writes the K8s Secret
- Your pod references that secret via
envFrom/secretKeyRefas usual
The eso store
An eso-type secret store marks where env.store entries should point:
curl -X POST http://localhost:8080/api/v1/secret-stores -b cookies.txt \
-H "Content-Type: application/json" \
-d '{"name":"prod-eso","type":"eso","provider":"eso"}'The eso store carries no credentials — ESO authenticates to providers via its own SecretStore/ClusterSecretStore manifests in the cluster. Wardn's Test on an eso store returns untested by design.
App config — image source
spec:
source:
type: Image
image:
repository: ghcr.io/acme/api
workload:
env:
- name: DB_PASSWORD
store:
id: sts_eso… # the eso store's id
path: prod/my-app/db # remote provider key
key: password # data key → env valueRendered output includes an ExternalSecret pointing remoteRef.key at prod/my-app/db and secretKey at password; the Deployment gets DB_PASSWORD via secretKeyRef.
Git-source apps
Commit ESO manifests directly — they apply like any resource:
# external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: db-credentials
data:
- secretKey: password
remoteRef:
key: prod/my-app/db-passwordHealth caveat — 🚧
ExternalSecret objects get the default verdict — Healthy if they exist, Missing if not. Wardn does not read ESO's Ready/SecretSyncedError conditions today, so a broken ESO sync won't degrade app health unless the object itself is absent. Track kind-aware ESO health on the Roadmap.
Install ESO
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
-n external-secrets --create-namespaceESO's provider list (AWS Secrets Manager, GCP Secret Manager, Vault, Azure KV, Kubernetes, etc.) is ESO's own — Wardn doesn't gate it.
Troubleshooting
ExternalSecret exists but Secret doesn't
kubectl describe externalsecret db-credentials -n <ns>
kubectl logs -n external-secrets deployment/external-secrets --tail=50Common causes: provider IAM/RBAC, wrong remoteRef.key, misconfigured SecretStore. All ESO-side — Wardn applied the object fine.
env.store entry doesn't render
- The
idmust be aneso-type store —vault/sopsstores take the vault-fetch path instead (or400on create of an invalid ref) - Check
status.resources[]on theApp— theExternalSecretappears there once rendered
Related
- Secret Management Overview — compare the three layers
- Vault Direct — fetch without ESO (image env only)
- Configuration —
workload.env[].storereference