How to Sync a Kubernetes Secret to AWS Secrets Manager

A Kubernetes Secret is only base64-encoded in etcd - not versioned, rotated, or audited. This project walks you through copying a Secret value (the password s3cr3t-pw) into AWS Secrets Manager as prod/db/password so the credential has a managed home outside the cluster. Here's how to do it with kubectl and the AWS CLI.

Kubernetes Engineerkuberneteskubectlaws

Why copy a k8s Secret into Secrets Manager

A Kubernetes Secret is not encrypted by default - it is base64-encoded data sitting in etcd. Anyone who can read the Secret can decode it, and there is no built-in versioning, rotation, or audit trail. AWS Secrets Manager adds all three: automatic rotation, access logging through CloudTrail, and a single source of truth that services outside the cluster can read.

A common migration and sync task is to take a credential that already lives in a k8s Secret and give it a managed home in Secrets Manager, keeping the two values identical. This project does exactly that with one credential - the database password s3cr3t-pw.

Step 1 - create (or read) the Kubernetes Secret

Create the Secret with kubectl from a literal value:

kubectl create secret generic db-creds \
  --from-literal=password=s3cr3t-pw

If the Secret already exists, decode the value so you know exactly what you are about to store. The value in .data.password is base64-encoded, so pipe it through base64 -d:

kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d

That prints s3cr3t-pw. An empty result means the Secret does not exist yet.

Step 2 - store the same value in AWS Secrets Manager

First confirm the AWS CLI resolves credentials:

aws sts get-caller-identity

Then create the secret in Secrets Manager under the name prod/db/password, passing the decoded value as the secret string:

aws secretsmanager create-secret \
  --name prod/db/password \
  --secret-string s3cr3t-pw

create-secret fails if the secret name already exists. To make the sync re-runnable, fall back to put-secret-value, which writes a new version of an existing secret:

aws secretsmanager create-secret --name prod/db/password --secret-string s3cr3t-pw \
  || aws secretsmanager put-secret-value --secret-id prod/db/password --secret-string s3cr3t-pw

This is the idempotent pattern - the first run creates the secret, and every later run updates it in place instead of erroring out.

Step 3 - verify both values match

Read the value back out of Secrets Manager and confirm it equals the k8s Secret. The --query SecretString --output text flags strip the JSON envelope so you get the raw value:

aws secretsmanager get-secret-value \
  --secret-id prod/db/password \
  --query SecretString --output text

You should see s3cr3t-pw - the same value the k8s Secret decodes to. To list what already exists on either side while you work:

kubectl get secrets
aws secretsmanager list-secrets

With both stores holding the identical value, the credential now has a managed source of truth. In production, an external-secrets operator automates the reverse direction - pulling from Secrets Manager back into k8s Secrets - so applications keep reading a native Secret while Secrets Manager owns rotation.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

How do I store a Kubernetes Secret value in AWS Secrets Manager?

Decode the k8s Secret with kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d, then pass that value to aws secretsmanager create-secret --name prod/db/password --secret-string <value>. Read it back with get-secret-value to confirm both stores match.

What is the difference between create-secret and put-secret-value in AWS Secrets Manager?

create-secret creates a brand-new secret and fails if the name already exists. put-secret-value writes a new version of a secret that already exists. Chain create-secret with a put-secret-value fallback to make a sync script safe to re-run.

Why move a credential out of a Kubernetes Secret?

Kubernetes Secrets are only base64-encoded in etcd, with no built-in versioning, rotation, or audit trail. AWS Secrets Manager adds automatic rotation, CloudTrail access logging, and a single source of truth that services outside the cluster can read.

How do I read a value back from AWS Secrets Manager on the command line?

Run aws secretsmanager get-secret-value --secret-id prod/db/password --query SecretString --output text. The query and output flags strip the JSON envelope so you get the raw credential string, which you can compare directly against the decoded k8s Secret.

Keep learning

Inject a Kubernetes Secret as Environment VariablesKubernetes projectStore a Credential in AWS Secrets ManagerKubernetes projectRotate a JWT Signing SecretKubernetes projectKubernetes roadmapStep by step to hiredKubernetes interview questionsSTAR answersAll Kubernetes projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →