Kubernetes Sealed Secrets
k8s-sealed-secrets.png
Managing secrets in Kubernetes is a bit tricky. Native Secret objects are only base64-encoded—not encrypted—making them unsafe for Git-based workflows. If you’re doing GitOps (e.g., with Argo CD), committing raw secrets is not an option.
This is where Sealed Secrets comes in.
Table of Contents
Why Sealed Secret?
Sealed Secrets uses asymmetric encryption to solve one problem:
How do you safely store secrets in Git?
- Encrypt secrets outside the cluster (using a public key)
- Decrypt secrets inside the cluster only (using a private key)
Install
Cluster
Check the release page for the latest release.
1kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.36.6/controller.yaml
Client
1curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.36.6/kubeseal-0.36.6-linux-amd64.tar.gz"
2tar -xvzf kubeseal-0.36.6-linux-amd64.tar.gz kubeseal
3sudo install -m 755 kubeseal /usr/local/bin/kubeseal
Certificate
Extrat public certificate.
1kubeseal --fetch-cert \
2 --controller-name=sealed-secrets-controller \
3 --controller-namespace=kube-system \
4 > cert.pem
Key
Make sure to backup the controller private key.
1 kubectl get secret -n kube-system | grep secret
2sealed-secrets-keyfzmnz kubernetes.io/tls 2 47m
1kubectl get secret -n kube-system sealed-secrets-keyfzmnz -o yaml > sealed-secrets-key.yaml
Example
Default K8S Secrets
Let’s create a sample secret for CouchDB deployment.
1kubectl create secret generic db-secret \
2 --from-literal=COUCHDB_USER=admin \
3 --from-literal=COUCHDB_PASSWORD=averysecurepassword123 \
4 --dry-run=client -o yaml > couchdb-secret.yaml
couchdb-secret.yaml
1apiVersion: v1
2data:
3 COUCHDB_PASSWORD: YXZlcnlzZWN1cmVwYXNzd29yZDEyMw==
4 COUCHDB_USER: YWRtaW4=
5kind: Secret
6metadata:
7 name: db-secret
This is not safe to commit to your git repo, since it can be decoded.
1echo "YWRtaW4=" | base64 -d
2admin
3
4echo "YXZlcnlzZWN1cmVwYXNzd29yZDEyMw==" | base64 -d
5averysecurepassword123
Sealed Secret
Now let’s encrypt the secret.
1kubeseal --cert=cert.pem \
2 --format=yaml < couchdb-secret.yaml > couchdb-secret-sealed.yaml
couchdb-secret-sealed
1apiVersion: bitnami.com/v1alpha1
2kind: SealedSecret
3metadata:
4 name: db-secret
5 namespace: default
6spec:
7 encryptedData:
8 COUCHDB_PASSWORD: AgAgCCc+n5Ah+cnlcSGH/OIPspB9q+jn/KdNv77ltmhSHca6jq09Jy6fqV0g0Py7asvnPgHHniW6PKySqtUssUZkxi4lJ/AmnBOlkBuUGZlViUjTTk2dRf5oFFt/CP2sr8r9XAXKVDmAo9L4PVR9ZacbttaQOhe5Y/fHv7aS9ympBp2ZMkzwnQITl0X/jdiaiW6mgHCaQhfkLlChfW/dukWDfwpif2lBNL3eVoaCIAXKtPM4ndsRU3tJLg4hLVmFMJ5gvpJe1Qz+OF/lOXLAfAtIVd5Eze9BrxUw2apUoIO3xY4wMFDVdb5UdurusA3kXVIgqB69zgF+C72ECvfP+Ty5gg4HbtG10KPIUR0w40ElV/tWpRQEOtdyt4l65IUraWMqfcKn6vLKMlCEG7ppAKWXmq9tNtDO11yLGHK4Us8E3sUgtrVZtcdFMLGrFSoNYAXL7TPfCz30dtx3ZMC8466SuMwLd4Dm4nbqLjdKuBsbKyKsfCV4Psrz8yNpO7GFNjtRcVvYkhOFKCU0j/DByQABx1AzZMLw9YX4oLbErjTWge5UflciW/duwtIBOgi82YvNRm/XycS9m5YI+NSG3CMyB/hQ/WNozIWlLnDQayCdpJVSlhL+fq3POpiLo71ETvawCzvf10PWg48DM4rHM1Oe2B18ZVyvovOdDyQjKBZF6Stav5iddICht00tyvhC8MeCG35ZMNs2e9fB+GeQUOVz06dvq/0Q
9 COUCHDB_USER: AgCOBRG5gh/ndLysWJ8z39RQdwe82u7VP4K/wPOAthylumi0LZSC9De2fz0v2zzadJ/3QYe0ammlQD7MnzOKgWDo6YOO8K/kSF6kOfgyoxv2rjiQeXeN+uFDh/5gE6ZHPfkIvqo55iAGcQDQ6V8HqiC1t7in35a51Ik5hHzMvEp6eJ1Dzv+D8FgRKMStUeMR4Zo/Qdo/zcMoKx0EPesrmw21f3BSsmlcyhtMAHcCY0QU4xlbecr5tHSUabG4RJIqDxIgfcc27g9XAJ/QtwHPTb4TslLoKkTXqPSC285h68sID2Iv7AXA06GlBr0WucQgUNQeo3my0kZvPjVbs7KD7Ji59RHnjLNnieRRt43whNLRUpgRnMJyS97KEgSiGljT6tXt5phBvXOsCxM7AyVKacfU8XZRmvHOtAinhu2z7qK6UFc8pTpQd+5UqsQaAKfo7ZTawM4B+4Ia2lhXHCrW7LqG5SMoJmVYcjhy/Mhp7VUliaBDMn1Yl6Q7Npn6PJ/At9Fek5IcgjHDI3b6As9/KYMO9+wyINca69bPdSRDCXgKZ8kRGNl03J8GKdJPtRIkIyxg/CrYbPf7LgdNptfJl2DN2FhMP2n1atyp2XjYA48bxwKKxjobcIQ40gLXqG5FXDgMbbeQDCJQkOlZvkWcEiIkVCnDucW1Y8tTk6pBofTMRMeAgIuzzJlNImy8mvgrfBi67vEUng==
10 template:
11 metadata:
12 name: db-secret
13 namespace: default
Apply it to the cluster, the sealed secrete controller will automatically detect and decode it.
1kubectl create -f couchdb-secret-sealed.yaml
Git
Now this is now safe to store it to your git repository.
1git add couchdb-secret-sealed.yaml
2git commit -m 'db sealed secret'
3git push