首页
/ Sealed Secrets 文档全景指南:安装部署、加密实战与密码学原理

Sealed Secrets 文档全景指南:安装部署、加密实战与密码学原理

2026-09-15 16:45:33作者:羿妍玫Ivan

Sealed Secrets 是一个面向 Kubernetes 的"单向加密 Secret"方案:你可以在本地使用客户端工具 kubeseal 把明文 Secret 加密为 SealedSecret,加密后的内容可以安全地提交到代码仓库,再由集群内的控制器解密并重建真正的 Kubernetes Secret。本文以官方文档索引(site/content/docs/latest/README.md)为骨架,完整串联教程、操作指南、背景知识与参考 FAQ 四大板块,并结合仓库源码深入讲解其运行原理,帮助你一次性掌握从部署、加密到密码学实现的完整链路。

文档体系总览:一份文档,四个入口

官方文档的顶层索引将全部内容按读者需求划分为四个板块,其定位清晰、层层递进:

板块 定位 适用场景
教程(Tutorials) 面向新手的动手式入门,手把手带你跑通全流程 第一次接触 Sealed Secrets
操作指南(How-to guides) 针对具体问题给出可复用的解决步骤 已有一定基础,想解决特定问题
背景(Background) 解释整体架构与实现细节,重在"建立理解" 想深入原理、评估安全性
参考(Reference) 技术参考与开发者指南(FAQ 等) 查阅设计决策与常见问题

阅读顺序建议:新手从教程的 Getting Started 起步,熟悉基本操作后按需查阅操作指南;若关心加密是否足够安全、密钥如何管理,则进入 密码学细节;遇到具体疑问时检索 FAQ

教程:从零开始使用 Sealed Secrets

前置条件

官方文档声明,使用 Sealed Secrets 需要:

  • 一个可用的 Kubernetes 集群(v1.16+),以及已安装并配置好的 kubectl CLI;
  • 若采用 Helm 方式安装控制器,需要 helm v3.1.0+;
  • 若采用 Carvel 方式安装,需要 kapp CLI。

官方文档还声明 Sealed Secrets 已在 Amazon EKS、Azure AKS、Google GKE、minikube 以及 OpenShift 等平台上完成测试。需要特别说明的是,这里要求的是"可用的集群"——因为 Sealed Secrets 的完整工作流(加密 → 提交仓库 → 控制器解密)高度依赖集群侧控制器,你至少需要一次部署控制器的机会。

两大核心组件

Sealed Secrets 由两部分组成,理解二者的分工是掌握整个项目的第一步:

  1. 集群侧控制器(sealed-secrets-controller):运行在 Kubernetes 集群中,负责持有私钥、生成证书、监听 SealedSecret 资源并解密为普通 Secret
  2. 客户端工具(kubeseal):运行在你的本机或 CI 环境中,从控制器拉取公钥证书,将明文 Secret 加密为 SealedSecret

从源码目录也能清晰看到这一分工:控制器代码位于 pkg/controllercmd/controller,而客户端逻辑位于 pkg/kubesealcmd/kubeseal

部署控制器:三种官方支持的方式

官方文档提供了三种部署控制器的途径:直接应用 YAML 清单、Helm Chart、Carvel 包。

方式一:直接应用 YAML 清单

控制器清单从项目 Releases 页面获取,分为两个版本:

  • controller.yaml:完整清单,包含控制器运行所需的全部组件,包括 ClusterRole 权限和 CRD 定义;
  • controller-norbac.yaml:受限版本,不包含 CRD 与 ClusterRole,适合在 RBAC 受限环境中按需裁剪后使用。

安装命令如下({{VERSION}} 替换为具体版本号,例如 v0.22.0):

$ kubectl apply -f https://github.com/bitnami/sealed-secrets/releases/download/{{VERSION}}/controller.yaml

role.rbac.authorization.k8s.io/sealed-secrets-service-proxier created
rolebinding.rbac.authorization.k8s.io/sealed-secrets-controller created
clusterrolebinding.rbac.authorization.k8s.io/sealed-secrets-controller created
serviceaccount/sealed-secrets-controller created
deployment.apps/sealed-secrets-controller created
customresourcedefinition.apiextensions.k8s.io/sealedsecrets.bitnami.com configured
rolebinding.rbac.authorization.k8s.io/sealed-secrets-service-proxier created
service/sealed-secrets-controller created
role.rbac.authorization.k8s.io/sealed-secrets-key-admin created
clusterrole.rbac.authorization.k8s.io/secrets-unsealer configured

从输出可见,该清单一次性地创建了 ServiceAccount、Deployment、Service、CRD sealedsecrets.bitnami.com 以及多组 RBAC 角色,控制器默认安装到 kube-system 命名空间。部署完成后,控制器会在启动后生成密钥对并进入就绪状态;若未就绪,请查看控制器日志。

GKE 集群的补充说明:在没有管理员权限的 GKE 集群上安装控制器可能受限,此时需要先为你的账号授予 cluster-admin 权限:

USER_EMAIL={{your-email}}
kubectl create clusterrolebinding $USER-cluster-admin-binding --clusterrole=cluster-admin --user=$USER_EMAIL

GKE 平台的更多细节可参考仓库中的 docs/GKE.md

方式二:Helm Chart

官方 Helm Chart 托管在本仓库的 helm/sealed-secrets 目录下,安装命令为:

helm repo add sealed-secrets https://bitnami.github.io/sealed-secrets
helm install sealed-secrets-controller sealed-secrets/sealed-secrets \
--set namespace=kube-system \

重要提示kubeseal CLI 默认假设控制器安装在 kube-system 命名空间,且 Deployment 名为 sealed-secrets-controller。上面的安装命令显式指定了相同配置,以避免使用 kubeseal 时产生不必要的摩擦。

OpenShift 集群的补充说明:OpenShift 对容器的 Security Context 有标准限制,需要做如下调整(在 Helm values 中配置):

containerSecurityContext:
  enabled: true
  readOnlyRootFilesystem: true
  runAsNonRoot: true
  runAsUser: null
podSecurityContext:

方式三:Carvel 包

Sealed Secrets 也支持以 Carvel 包 的形式安装。首先需要在目标集群部署 kapp-controller,然后应用 Package 清单:

$ kapp deploy -a kc -f https://github.com/vmware-tanzu/carvel-kapp-controller/releases/latest/download/release.yml

$ kapp deploy -a sealed-secrets-carvel -f https://raw.githubusercontent.com/bitnami/sealed-secrets/main/carvel/package.yaml
Changes

Namespace  Name                              Kind     Conds.  Age  Op      Op st.  Wait to    Rs  Ri
default    sealedsecrets.bitnami.com.2.10.0  Package  -       -    create  -       reconcile  -   -
...
Succeeded

$ kubectl get Package
NAME                               PACKAGEMETADATA NAME        VERSION   AGE
sealedsecrets.bitnami.com.2.10.0   sealedsecrets.bitnami.com   2.10.0    18s

Package 就绪后,还需按照 Carvel 官方文档执行 PackageInstall 操作才能真正安装控制器。仓库中对应的包定义位于 carvel/package.yaml

安装 kubeseal CLI:五种途径

kubeseal 是加密侧的核心工具,官方文档给出了五种安装方式:

Homebrew(macOS/Linux)

brew install kubeseal

MacPorts(macOS)

port install kubeseal

Nixpkgs(Nix 系系统)(注意:该包不由 Sealed Secrets 项目维护):

nix-env -iA nixpkgs.kubeseal

Linux(手动下载二进制)

wget https://github.com/bitnami/sealed-secrets/releases/download/<release-tag>/kubeseal-<version>-linux-amd64.tar.gz
tar -xvzf kubeseal-<version>-linux-amd64.tar.gz kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal

其中 release-tag 为 kubeseal 的版本标签,例如 v0.21.0

从源码安装(Go 环境)

go install github.com/bitnami/sealed-secrets/cmd/kubeseal@main

@main 可替换为具体的 release tag 或 commit SHA。安装完成后,二进制位于 $(go env GOPATH)/bin/kubeseal

用 kubeseal 加密本地 Secret:完整工作流

这是整个项目最核心的用法。它的价值在于:加密动作完全发生在本地,明文 Secret 从不离开你的机器。官方文档给出了完整可复现的流程:

# 1. 在本地生成一个 json/yaml 格式的 Secret
# (注意使用 --dry-run,这只是生成一个本地文件!)
echo -n bar | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json >mysecret.json

# 2. 关键步骤:用 kubeseal 将明文 Secret 加密为 SealedSecret
kubeseal -f mysecret.json -w mysealedsecret.json

# 3. 此时 mysealedsecret.json 已经可以安全地提交到代码仓库

# 4. 部署到集群(控制器会解密并重建 Secret)
kubectl create -f mysealedsecret.json

# 5. 验证结果
kubectl get secret mysecret

约束SealedSecret 与最终生成的 Secret 必须同名同命名空间。这是一个刻意设计的安全特性,防止同一集群上的其他用户复用你提交的 Sealed Secret。

从源码看,上述第 2 步对应 pkg/kubeseal/kubeseal.go 中的 Seal 函数:它读取输入的 Secret,按 scope 计算加密标签(label),然后用控制器的公钥完成混合加密并输出 SealedSecret 资源。整个加密的具体算法细节,将在下文"背景知识"部分深入展开。

操作指南:校验已有 Sealed Secret

当 SealedSecret 需要跨环境共享、或需要确认某个已存在的 SealedSecret 是否仍能被当前控制器正确解密时,官方推荐使用 kubeseal --validate 进行校验——它能验证加密/解密链路是否按预期工作。

假设有一个名为 sealed-secrets.yaml 的文件,内容如下:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: mysecret
  namespace: mynamespace
spec:
  encryptedData:
    foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....

校验命令极其简单:

$ cat sealed-secrets.yaml | kubeseal --validate

若 SealedSecret 无效(例如公钥不匹配、label 不符或数据被篡改),则会得到如下报错:

$ cat sealed-secrets.yaml | kubeseal --validate
error: unable to decrypt sealed secret

这个错误信息与源码中的实现一一对应:在 pkg/kubeseal/kubeseal.go 中,校验过程会尝试用控制器私钥解密该 SealedSecret,失败时返回 cannot validate sealed secret 类错误。由此可知,--validate 的本质不是"语法检查",而是一次真实的试解密——只有能成功解密的 SealedSecret 才是真正可用的。

背景知识:Sealed Secrets 的密码学原理

加密功能的正确性直接决定 Secrets 的安全性,因此官方专门用一篇文档讲透密码学实现,仓库源码 pkg/crypto/crypto.go 与之完全对应。

使用的协议与工具

Sealed Secrets 使用了如下密码学协议组合:

  • AES-256-GCM:使用随机生成的、一次性的 32 字节会话密钥加密 Secret 本体,保证机密性与完整性。由于会话密钥只用一次,因此不使用 nonce
  • RSA-OAEP(搭配 SHA-256):用于封装(encapsulate)AES-256-GCM 的会话密钥,即密钥封装机制(Key Encapsulation Mechanism, KEM)——用控制器的 RSA 公钥加密这个短小的会话密钥;
  • X509 证书:用于承载和管理 RSA 公钥,供 kubeseal 拉取使用。

控制器生成的证书每 30 天轮换一次,证书有效期为 10 年。

这一协议组合在源码 pkg/crypto/crypto.goHybridEncrypt 中有直接体现:先生成随机会话密钥并用 AES-GCM 加密明文,再用 RSA-OAEP(SHA-256)加密会话密钥,最终输出 RSA 密文长度 || RSA 密文 || AES 密文 的混合密文结构。

熵的来源

随机数的质量是密码学安全的基石。项目使用 Go 标准库 crypto/rand 作为熵源,其底层行为如下:

// On Linux, FreeBSD, Dragonfly and Solaris, Reader uses getrandom(2) if
// available, /dev/urandom otherwise.
// On OpenBSD and macOS, Reader uses getentropy(2).
// On other Unix-like systems, Reader reads from /dev/urandom.
// On Windows systems, Reader uses the RtlGenRandom API.
// On Wasm, Reader uses the Web Crypto API.

这些操作系统级密码学 API 都能提供良好的密码学熵,在种子未知的前提下不易受密码学攻击。

密封(Sealing)流程拆解

公私钥对管理

控制器在启动时会查找集群级公私钥对:如果找不到且未手动提供,控制器会生成一对 4096 位(默认)RSA 密钥对,并持久化到与控制器同命名空间的普通 Secret 中。

公钥(若由控制器生成,则是自签名证书形式)应公开发布给所有想使用该集群 Sealed Secrets 的用户。获取公钥有两个途径:

  • 控制器启动日志会打印证书;
  • 对控制器的 /v1/cert.pem 端点发起 HTTP GET 请求即可获取。

如果希望使用自己的 X509 证书,可以用 kubeseal 指定:

kubeseal --cert [https:/]/path/to/your-cert.pem

自带证书的完整操作流程见 docs/bring-your-own-certificates.md

Secret 加密(步骤 1)

Secret 本体使用 AES-256-GCM 加密,密钥为随机生成的单次使用 32 字节会话密钥,输出记为 AES encrypted data

会话密钥加密(步骤 2)

AES 会话密钥使用控制器的 RSA 公钥,通过 RSA-OAEP + SHA-256 封装。RSA-OAEP 的输入中有一个名为 label 的附加参数,其内容取决于控制器的 scope(作用域)配置

  • 默认(strict)scopelabel = Secret 的 namespace + name(源码实现为 namespace/name 拼接);
  • namespace-wide scopelabel = Secret 的 namespace
  • cluster-wide scopelabel 为空。

这一设计在源码 pkg/apis/sealedsecrets/v1alpha1/sealedsecret_expansion.go(scope 枚举定义)与 同文件 L90-L104 的 EncryptionLabel 函数 中均有实现:StrictScope(默认)把 SealedSecret 钉死在特定命名空间 + 特定名称;NamespaceWideScope 只钉死在特定命名空间;ClusterWideScope 允许在任何命名空间解封。这正是"同名同命名空间才能解密"这一约束的密码学根源——label 不一致,RSA-OAEP 解密就会失败。

RSA-OAEP 加密的输出记为 RSA encrypted data

Sealed Secret 存储格式

最终 Sealed Secret 的数据格式为(|| 表示拼接):

Sealed Secret data =  size of AES encrypted key (2 bytes) || RSA encrypted data || AES encrypted data

即:2 字节的 AES 加密密钥长度 + RSA 密文 + AES 密文。示意图如下:

                                Secret
                                   |
                                   │
                   K_s────────────►│
                    │              │
       K_pub───────►│              │
                    │              │ 1.
       label───────►│ 2.           │
                    │              │
     ┌──────────────────────┬───────▼───────┬──────▼───────┐
Sealed Secret data = │size of AES encrypted │ RSA encrypted │ AES encrypted│
                     │key (2 bytes)         │ data          │ data         │
                     └──────────────────────┴───────────────┴──────────────┘

K_s = 256 bits single-use session key, used by AES-GCM
K_pub = Public key from the self-signed certificate, used by RSA-OAEP
label = Additional input for RSA-OAEP encryption.
        Content differs depending on the scope configuration:
         * Default config : label = Secret's namespace || Secret's name
         * Namespace-wide : label = Secret's namespace
         * Cluster-wide : label is empty

解密流程

解密就是加密的逆过程,对应源码 pkg/crypto/crypto.go 中的 HybridDecrypt

  1. 读取前 2 字节,得到 AES 加密密钥的长度,据此把 RSA encrypted dataAES encrypted data 正确分离;
  2. 用与公钥配对的私钥,配合相同的 labelRSA encrypted data 做 RSA-OAEP 解密,恢复出 AES 会话密钥;
  3. 用该会话密钥解密 AES encrypted data,还原出原始 Secret。

后量子密码学(Post-quantum)考量

官方文档还对三个密码学组件做了后量子安全分析:

熵来源:量子随机数生成器(QRNG)虽有理论优势,但依赖物理设备,超出 Sealed Secrets 的范围,项目继续使用 crypto/rand

AES-256-GCM:分析认为 AES-256-GCM 具备量子抗性——Grover 算法可将密钥暴力破解复杂度从 2²⁵⁶ 降至 2¹²⁸,仍非常安全。但由于 AES 使用不可变的 128 位块,某些情况下复杂度可能降至 2⁶⁴;不过结合本项目 AES 的实际使用方式,2⁶⁴ 场景不太可能发生,且即便发生,当下仍可视为安全(长期则不然)。官方给出的低优先级建议是:关注能提供 128 位后量子安全强度的 AES 替代方案(如 ChaCha20-Poly1305)。

SHA-256:具备量子抗性,Grover 算法只能将暴力破解从 2²⁵⁶ 降到 2¹²⁸,且用非量子算法生成碰撞在计算上更便宜。官方结论:无需调整。

RSA-OAEP:与所有 RSA 算法一样,不具备量子抗性。Shor 算法能在合理时间内解决 RSA 所依赖的整数分解、离散对数等数学难题,因此具备量子能力的攻击者可轻松破解 RSA-OAEP。官方将其列为最高优先级的替换对象,候选方案包括 LMS、XMSS(基于格)与 McEliece(基于编码);同时强调替换需满足两个前提:业界出现明确的标准替代算法、且有兼容开源许可证的可靠 Go 实现。

参考:FAQ 中的实战要点

密钥备份与灾难恢复

解密私钥只存在于控制器管理的 Secret 中,没有后门。若丢失私钥且集群内的明文 Secret 也不可访问,则只能重新生成密码并重新密封。因此官方强烈建议备份私钥:

kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml >main.key

echo "---" >> main.key
kubectl get secret -n kube-system sealed-secrets-key -o yaml >>main.key

第二条命令仅在集群上安装过 0.9.x 之前的老版本时才需要。 该文件包含控制器的公钥与私钥,必须妥善保管。

灾难恢复时,在控制器启动前将这些 Secret 放回集群即可;若控制器已启动,则替换新生成的 Secret 后重启控制器:

kubectl apply -f main.key
kubectl delete pod -n kube-system -l name=sealed-secrets-controller

离线解密

虽然官方不推荐把 Sealed Secrets 当作长期存储系统,但确有合法场景需要在集群不可用时恢复 Secret。若已备份私钥,可使用:

kubeseal --recovery-unseal --recovery-private-key file1.key,file2.key,...

多个私钥文件用逗号分隔,适合密钥轮换后仍有旧 SealedSecret 的情况。

控制器不在 kube-system 命名空间时

若控制器安装在其它命名空间,需要告知 kubeseal。两种方式任选其一:

# 方式一:命令行参数
kubeseal --controller-namespace sealed-secrets <mysecret.json >mysealedsecret.json

# 方式二:环境变量
export SEALED_SECRETS_CONTROLLER_NAMESPACE=sealed-secrets
kubeseal <mysecret.json >mysealedsecret.json

一个控制器管理部分命名空间

若希望一个控制器服务多个(但不是全部)命名空间,可使用 --additional-namespaces 参数:

--additional-namespaces=<namespace1>,<namespace2>,<...>

同时需在目标命名空间中配置合适的 Role 与 RoleBinding,让控制器能够管理其中的 Secret。

镜像签名校验

项目的容器镜像使用 cosign 签名(v0.20.2 及更早使用 Cosign v1,更新镜像使用 Cosign v2),签名保存在 GitHub Container Registry 的 signs 路径。校验方式:

$ export COSIGN_REPOSITORY=ghcr.io/bitnami/sealed-secrets-controller/signs

$ cosign verify --key .github/workflows/cosign.pub ghcr.io/bitnami/sealed-secrets-controller:latest

Verification for ghcr.io/bitnami/sealed-secrets-controller:latest --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The signatures were verified against the specified public key
...

如何更新配置文件类 Secret 的局部字段

Kubernetes Secret 本质是扁平化的键值对映射,Sealed Secrets 只在这一层工作,无法理解值内部的结构化配置文件(JSON/YAML/TOML 等),因此不能帮你更新其中的单个字段。针对这一常见痛点,官方在 docs/examples/config-template 提供了一套可行的变通方案,其中包含 deployment.yamlsealedsecret.yaml 示例。

总结:从文档到源码的完整知识闭环

Sealed Secrets 的价值在于把"加密"与"解密"两侧彻底分离:kubeseal 在本地用控制器的公钥完成 AES-256-GCM + RSA-OAEP 混合加密,加密产物可安全入库;控制器在集群内持有私钥,按 scope 计算出的 label 严格约束解密范围,保证同名同命名空间才能解封。理解这一点,也就理解了为什么备份私钥、正确设置 controller namespace 与 scope 配置,是生产环境使用 Sealed Secrets 的三个关键操作。若想继续深入,可以直接阅读仓库中的源码:加密实现scope 与 label 逻辑kubeseal 密封流程 以及控制器入口 pkg/controller/main.go

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
34
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.21 K
2.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
949
1.87 K
docsdocs
暂无描述
Markdown
906
5.84 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
537
612
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
864
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
4.29 K
1.04 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.39 K
1.48 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
550
401
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.19 K
348