Encrypting Kubernetes Secrets with Sealed Secrets, Helm Secrets, and Kamus
This article explains three practical methods—Sealed Secrets, Helm Secrets, and Kamus—for encrypting Kubernetes secrets, covering their principles, encryption and decryption processes, installation steps, and usage examples with full command‑line and manifest snippets to securely store sensitive data in GitOps workflows.
Kubernetes has become the de‑facto standard for cloud‑native deployments, but its built‑in Secret objects only encode data, leaving sensitive information exposed when stored in version‑control systems. To address this, three encryption solutions are introduced: Sealed Secrets, Helm Secrets, and Kamus.
1. Sealed Secrets
Sealed Secrets uses a Custom Resource Definition (CRD) to create a SealedSecret object that stores encrypted data. Only the controller running in the target cluster can decrypt it using a private key, while the public key is used by the client tool kubeseal to encrypt the original secret.
Principle : The controller generates a key pair; kubeseal encrypts the secret with the public key, producing a SealedSecret . When applied, the controller decrypts it and creates a regular Secret .
Installation :
$ kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.14.1/controller.yaml
$ kubectl -n kube-system get pods | grep seal
$ brew install kubeseal # macOS example
$ kubeseal --versionUsage :
apiVersion: v1
data:
username: eGlhb21hZ2U=
password: cGFzc3cwcmQ=
kind: Secret
metadata:
name: seal-test-secret
namespace: test
type: OpaqueEncrypt with:
$ kubeseal < test-secret.yaml > test-seal-secret.yamlApply the sealed secret:
$ kubectl -n test apply -f test-seal-secret.yamlReference the secret in a Deployment via envFrom and verify the injected environment variables.
2. Helm Secrets
Helm Secrets is a Helm plugin that encrypts values files (typically secrets.yaml ) using sops . Encrypted values are stored in the chart and decrypted automatically during helm install/upgrade .
Principle : sops encrypts selected keys (e.g., username , password ) with a GPG public key. The plugin stores the ciphertext in the chart; during deployment the controller uses the private key to decrypt and populate values.yaml .
Installation :
$ helm plugin install https://github.com/zendesk/helm-secretsGenerate a GPG key pair, create .sops.yaml with encryption rules, and encrypt a secrets.yaml file:
$ gpg --full-generate-key
$ cat <
.sops.yaml
creation_rules:
- encrypted_regex: '^(username|password)$'
pgp: 'B1C77B2CCF5575FAF0DA6B882CA51446C98C9D85'
EOF
$ sops -e secrets.yamlUsage :
apiVersion: v1
kind: Secret
metadata:
name: test
labels:
app: devsecops
type: Opaque
data:
{{- range $key, $value := .Values.secret_data}}
{{ $key }}: {{ $value | b64enc | quote}}
{{- end}}Deploy with:
$ helm secrets install test . --namespace test -f helm_vars/secrets.yaml -f values.yaml3. Kamus
Kamus provides a zero‑trust approach to secret encryption in Kubernetes. It offers two usage patterns: an init‑container that decrypts a ConfigMap at pod start, or a custom KamusSecret CRD that automatically creates a regular secret.
Principle : The client tool kamus-cli encrypts data using the cluster’s public key. The controller stores the ciphertext in a ConfigMap or KamusSecret . During pod creation, the controller’s decryptor uses the private key to produce a plain secret.
Installation :
$ helm repo add soluto https://charts.soluto.io
$ helm install kamus --namespace kamus soluto/kamus
$ npm install -g @soluto-asurion/kamus-cliInit‑container usage (encrypt values, store in a ConfigMap, mount, and decrypt):
apiVersion: v1
kind: ConfigMap
metadata:
name: kamus-encrypted-secrets-cm
namespace: test
data:
username: CxujUBK4jgdjt+wP5mXyDA==:+CoXRDJVtW3EZ2FpterVTA==
password: ChmNEPM8Nj7Huh1YwO5xOA==:r9MHhEyTIEaQ4hw837lA9w==Pod spec with init container:
apiVersion: v1
kind: Pod
metadata:
name: kamus-pod
namespace: test
spec:
serviceAccountName: xiaomage
initContainers:
- name: kamus-init
image: soluto/kamus-init-container:latest
env:
- name: KAMUS_URL
value: http://kamus-decryptor.kamus.svc.cluster.local/
volumeMounts:
- name: encrypted-secrets
mountPath: /encrypted-secrets
- name: decrypted-secrets
mountPath: /decrypted-secrets
args: ["-e","/encrypted-secrets","-d","/decrypted-secrets","-n","config.json"]
containers:
- name: app
image: dllhb/devopsday:v0.6
volumeMounts:
- name: decrypted-secrets
mountPath: /secrets
volumes:
- name: encrypted-secrets
configMap:
name: kamus-encrypted-secrets-cm
- name: decrypted-secrets
emptyDir:
medium: MemoryKamusSecret usage :
apiVersion: soluto.com/v1alpha2
kind: KamusSecret
metadata:
name: kamus-test
namespace: test
type: Opaque
stringData:
username: CxujUBK4jgdjt+wP5mXyDA==:+CoXRDJVtW3EZ2FpterVTA==
password: ChmNEPM8Nj7Huh1YwO5xOA==:r9MHhEyTIEaQ4hw837lA9w==
serviceAccount: xiaomageApplying the CR creates a regular secret that can be referenced like any other Kubernetes secret.
Conclusion
All three tools leverage Kubernetes extensibility to store encrypted data and generate standard Secret objects for consumption. They differ in workflow—Sealed Secrets encrypts whole manifests, Helm Secrets integrates with Helm charts, and Kamus offers both init‑container and CRD approaches—allowing teams to choose the best fit for GitOps‑friendly secret management.
DevOps
Share premium content and events on trends, applications, and practices in development efficiency, AI and related technologies. The IDCF International DevOps Coach Federation trains end‑to‑end development‑efficiency talent, linking high‑performance organizations and individuals to achieve excellence.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.