Learn how to automate Kubernetes secrets using HashiCorp Vault and the External Secrets Operator. Secure your infrastructure with this DevSecOps best practice.
Managing secrets in Kubernetes is a headache. If you’re still manually creating Secret objects or base64-encoding YAML files in your Git repositories, you’re doing it wrong. It’s a security risk, it’s unscalable, and frankly, it’s a manual process that doesn't belong in a modern CI/CD pipeline.
I’ve spent the last few years refining our DevSecOps posture, and the gold standard remains the same: use a dedicated secret manager like HashiCorp Vault and bridge it to Kubernetes using the External Secrets Operator (ESO).
Kubernetes Secrets are just base64-encoded strings stored in etcd. Anyone with cluster-admin access—or even a compromised pod with the right RBAC—can read your production database credentials.
HashiCorp Vault provides encryption-at-rest, audit logging, and dynamic secret generation. But Vault doesn't natively speak "Kubernetes Secret." That’s where the External Secrets Operator (ESO) comes in. It acts as the glue, watching for custom resources in your cluster and pulling the latest values from Vault to inject them as native Kubernetes secrets.
We’ll assume you have a running Kubernetes cluster (v1.27+) and a functional HashiCorp Vault instance (v1.14+).
I recommend using Helm for this. It’s the standard, it’s reliable, and it’s easy to version-control.
Bashhelm repo add external-secrets https://charts.external-secrets.io helm install external-secrets \ external-secrets/external-secrets \ -n external-secrets \ --create-namespace
The SecretStore is a namespaced resource that tells ESO how to talk to Vault. We need to authenticate using a Kubernetes ServiceAccount.
YAMLapiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend spec: provider: vault: server: "https://vault.example.com:8200" path: "secret" version: "v2" auth: kubernetes: mountPath: "kubernetes" role: "my-app-role"
This is where the magic happens. You define an ExternalSecret object that maps a key in Vault to a specific key in a Kubernetes Secret.
YAMLapiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: db-credentials spec: refreshInterval: "1h" secretStoreRef: name: vault-backend kind: SecretStore target: name: app-db-secret # The resulting K8s secret data: - secretKey: username remoteRef: key: secret/data/myapp/db property: username - secretKey: password remoteRef: key: secret/data/myapp/db property: password
When you’re implementing this, keep these three lessons in mind:
1. Use Namespace Scoping
Don't use a ClusterSecretStore unless you absolutely have to. By sticking to namespaced SecretStore objects, you enforce the principle of least privilege. If one namespace is compromised, the attacker can't necessarily pull secrets from the entire Vault instance.
2. Watch the Refresh Interval ESO defaults to a refresh interval of 1 hour. In a high-security environment, you might be tempted to set this to 30 seconds. Don't. You’ll hammer your Vault API unnecessarily. If you need secrets to rotate instantly, look into the Vault Agent Injector instead, though it’s a different architecture.
3. RBAC is your best friend
The ServiceAccount used by ESO needs specific permissions in Vault. Ensure you’ve mapped your Kubernetes ServiceAccount to a Vault policy that only grants read access to the specific paths the application needs. Never give the operator "root" access to your secret engines.
By automating Kubernetes secrets, we remove the human element. No more copy-pasting API keys into Slack or pasting them into YAML files. Everything is defined as code. If we need to rotate the database password, we update it in Vault, and within an hour, the cluster updates itself.
This is what DevSecOps is really about: building systems that are secure by default, not by manual checklist.
Master HashiCorp Vault and External Secrets Operator to automate your Kubernetes secrets management. Learn how to sync sensitive data securely in your cluster.
Read moreMaster Kubernetes Secret Management by syncing HashiCorp Vault with External Secrets Operator. Learn how to automate secure, GitOps-friendly secret injection.