Skip to main content
  1. Index/

Sealed Secrets

Sealed Secrets is a Kubernetes controller and companion CLI tool (kubeseal) created by Bitnami that solves a specific GitOps problem: how to store Kubernetes Secret manifests in a Git repository without exposing their contents. A standard Kubernetes Secret is base64-encoded, not encrypted — anyone who can read the manifest file or the Git history can decode the values instantly. Sealed Secrets resolves this by encrypting the secret values using asymmetric cryptography before they ever leave the developer’s machine, producing a SealedSecret custom resource that contains only ciphertext and is safe to commit to any repository, public or private. The corresponding plaintext Secret is materialised exclusively inside the cluster by the controller, which holds the only private key capable of decryption.

The mechanics follow a strict one-way trust model. On installation, the Sealed Secrets controller generates an RSA key pair and stores the private key as a Kubernetes Secret inside the cluster. Developers retrieve the public key via kubeseal --fetch-cert and use it to encrypt a standard Secret manifest locally: kubeseal encrypts each value individually using the public key, embeds the cluster and namespace identity as associated data in the ciphertext (so a SealedSecret created for one namespace cannot be decrypted and applied to another, and a SealedSecret from one cluster cannot be decrypted by a different cluster’s controller), and outputs a SealedSecret YAML manifest. That manifest is committed to Git and applied to the cluster through the normal GitOps pipeline (Argo CD, Flux). When the controller detects a new or updated SealedSecret, it decrypts the values using its private key and creates or updates a standard Kubernetes Secret object in the specified namespace. From that point, pods consume the Secret in the normal way with no awareness of the Sealed Secrets layer. Key rotation is handled by the controller generating a new key pair periodically (defaulting to every 30 days); old keys are retained for decrypting existing SealedSecrets and new sealings use the latest key.

Sealed Secrets occupies a different architectural niche from ESO and the Secrets Store CSI Driver: it has no dependency on an external secret backend at runtime, making it operationally simpler — there is no Vault, no AWS Secrets Manager, no external service to be available for a pod to start. The entire system is self-contained within the cluster. The trade-off is that secret values live in the Git repository (encrypted) and in etcd (as a native Secret), rather than in a purpose-built secret store with rotation, leasing, and audit capabilities; Sealed Secrets provides no rotation lifecycle, no dynamic credentials, and no centralised audit trail beyond the Kubernetes API server’s own audit log. It is the right choice for teams adopting GitOps who want a simple, infrastructure-light path to committing secrets safely, and the wrong choice for teams who need credential rotation, short-lived secrets, or cross-cluster secret management — scenarios better served by ESO backed by Vault or a cloud secret manager.

Related

ESO (External Secrets Operator)

External Secrets Operator (ESO) is a CNCF incubating project that bridges the gap between Kubernetes-native secrets and enterprise secret management backends. Its premise is that native Kubernetes Secrets — base64-encoded values stored in etcd — are not adequate as a primary secret store: they offer no encryption at rest by default, no access audit trail, no versioning or rotation lifecycle, and no single source of truth across multiple clusters. Rather than replacing Kubernetes Secrets as a consumption mechanism (applications still mount them as environment variables or files in the familiar way), ESO replaces etcd as their source of authority, pulling the real values from a backend that does provide those properties and keeping the Kubernetes Secret as a synchronised, ephemeral projection.

KMS v2 (Kubernetes KMS Provider v2)

KMS v2 (Kubernetes KMS Provider version 2) is the stable (GA since Kubernetes 1.29, KMS v1 deprecated in 1.28 and disabled by default in 1.29) mechanism for encrypting the contents of the Kubernetes etcd datastore at rest using an external key management service. Without encryption, Kubernetes Secrets stored in etcd are base64-encoded — trivially decodable by anyone with read access to the etcd data files or a snapshot. With KMS v2 enabled, resources written to etcd — Secrets, ConfigMaps, and any other API objects selected by the EncryptionConfiguration — are encrypted before being persisted, using a unique per-object key derived locally. The envelope encryption scheme means those per-object keys are never stored in plaintext: only their encrypted form lives in etcd, and only the external KMS holds the wrapping key. The encryption configuration is declared in a file referenced by the API server’s --encryption-provider-config flag, with kms: apiVersion: v2 selecting the KMS v2 code path, and endpoint: unix:///path/to/plugin.sock pointing at the plugin’s Unix domain socket.

Secrets Store CSI Driver

Secrets Store CSI Driver (formally secrets-store.csi.k8s.io) is a Kubernetes SIG Auth project that uses the Container Storage Interface to mount secrets, certificates, and keys from external secret backends directly into pod filesystems as ephemeral tmpfs volumes, bypassing the Kubernetes Secret object and etcd entirely. The driver runs as a DaemonSet on every node; when a pod referencing a CSI volume of type secrets-store.csi.k8s.io is scheduled, the driver communicates with a provider plugin over gRPC to retrieve the secret content from the configured backend, writes it to a per-pod tmpfs mount, and makes it available inside the container at the specified path. When the pod terminates, the tmpfs is unmounted and the data is gone — secrets have no persistence beyond the lifetime of the pod that requested them.