Learn how to sync Kubernetes secrets from AWS Secrets Manager using the External Secrets Operator—so you can keep credentials out of Git and manage them centrally across dev, stage, and production.
In most enterprise systems, release cycles use separate environments (dev, stage, live), each with its own configuration. An application might need three different sets of database credentials—one per environment—so developers work against a dedicated database without touching production. Managing these credentials securely is where Kubernetes External Secrets and AWS Secrets Manager fit in.
Kubernetes Secrets store sensitive data in your cluster. They are native resources in the cluster data store (etcd) and can be mounted into containers at runtime. Managing them by hand is error-prone and doesn’t scale. This guide shows how to use External Secrets to pull secrets from AWS Secrets Manager into Kubernetes automatically.
The External Secrets Operator lets you use external secret backends—such as AWS Secrets Manager, GCP Secret Manager, or HashiCorp Vault—to populate Kubernetes Secrets. You declare what to fetch; the controller keeps the cluster in sync.
An ExternalSecret declares how to fetch the secret data; the controller turns those into standard Kubernetes Secrets. Pods use Secrets as usual—no code changes. By default, Secrets are not encrypted at rest in etcd and can be exposed via the API or etcd backups. To harden this, use an external KMS plugin to encrypt Secrets in etcd.
How External Secrets Work (High-Level)
ExternalSecretsare added in the cluster (e.g.kubectl apply -f external-secret-example.yml)- Controller fetches
ExternalSecretsusing the Kubernetes API - Controller uses
ExternalSecretsto fetch secret data from external providers (e.g, AWS Secrets Manager) - Controller upserts
Secrets - Pods consume the synced Secrets as normal Kubernetes Secrets.
Related reading:
- How to use External Secrets with GCP Secrets manager
- How to create and manage Secrets in GCP Secret Manager using Terraform
1. Configure AWS Access for Secrets Manager
Create an IAM policy that allows reading from AWS Secrets Manager. Start by creating a policy named secrets-reader:
| |
We now create a group that will use this policy:
| |
Next, create an IAM user and add it to the group:
| |
Create access keys for that user and store them in a Kubernetes secret (the key names must match the SecretStore refs below):
| |
Next, add a secret in AWS Secrets Manager that we will sync into Kubernetes:
| |
2. Install the External Secrets Operator
The External Secrets Operator is available as a Helm chart. Add the repo and install it in your cluster:
| |
To install without Helm, template the manifests and apply them with kubectl:
| |
Apply the manifests in ./output_dir to deploy the operator.
3. Create a SecretStore (AWS Secrets Manager Backend)
A SecretStore is a namespaced resource that defines how the External Secrets controller authenticates to your secret backend (here, AWS Secrets Manager). It holds the backend configuration and references a Kubernetes Secret that contains the AWS credentials.
External Secrets also supports ClusterSecretStore, a cluster-wide store that any namespace can use. For a single namespace we use a namespaced SecretStore.
Create a SecretStore named aws-secret-manager that uses the aws-secret we created earlier:
| |
Note: For a ClusterSecretStore, you must set namespace in both accessKeyIDSecretRef and secretAccessKeySecretRef to the namespace where the credential Secret lives.
| |
Verify the SecretStore is valid:
| |
4. Create an ExternalSecret (Sync One Secret as a Single Key)
An ExternalSecret declares which secret to fetch from AWS Secrets Manager and which Kubernetes Secret to create. It uses the SecretStore for authentication.
Create an ExternalSecret that pulls the AWS secret live/citizix-db-secret (created above) and writes it into a Kubernetes Secret citizix-db-secret under the key db-url:
| |
Check that the ExternalSecret synced successfully:
| |
Confirm the Kubernetes Secret was created:
| |
Inspect the secret (values are base64-encoded):
| |
5. Extract JSON Keys into Separate Secret Keys
When the value in AWS Secrets Manager is JSON, you can map each key to a separate key in the Kubernetes Secret using dataFrom and extract. Here we use the same live/citizix-db-secret (it’s JSON with password, host, port, db, user) and create a Secret whose keys are those JSON fields:
| |
Verify the ExternalSecret status:
| |
Confirm the Kubernetes Secret has one key per JSON field:
| |
Describe the secret to see the keys (password, host, port, db, user):
| |
Summary and Next Steps
You now have Kubernetes External Secrets syncing from AWS Secrets Manager: IAM and a SecretStore for access, ExternalSecrets for full-value and JSON key extraction, and Kubernetes Secrets updated on the configured refresh interval.
Next steps:
- Use IRSA (IAM Roles for Service Accounts) on EKS instead of long-lived access keys for better security.
- Restrict the IAM policy to specific secret ARNs or prefixes instead of
"*". - Enable encryption at rest for Kubernetes Secrets (e.g. with a KMS provider and etcd encryption).
- Reuse the same pattern for other backends (e.g. External Secrets with GCP Secret Manager).