Flux CD Flux CD

使用 SOPS 和 age 在 Git 中管理密钥

在提交之前加密 Kubernetes Secret,并让 Flux 在集群中解密它们。

12 min 中级

GitOps 将集群的配置放进 Git,其中也包括 Secret。提交一个普通的 Kubernetes Secret 会把它的值暴露给任何能读取该仓库的人,因为 Secret 数据只是经过了 base64 编码。Flux 的 kustomize-controller 可以解密用 Mozilla SOPS 加密的文件,所以你可以提交加密后的 Secret,并让整个系统都保留在 Git 中。本指南使用 age 密钥,这是最简单的选项。

安装工具并创建密钥

安装 age 和 sops(例如 brew install age sops),然后生成一个密钥对:

age-keygen -o age.agekey

输出文件保存私钥,同时命令会打印公钥(以 age1 开头)。不要把私钥放进 Git。请把它备份到安全的地方,因为一旦丢失,你就无法解密你的密钥了。Flux 2.9 还增加了对 age 后量子密码的支持,如果你的策略有此要求的话。

把私钥交给集群

将私钥作为 Secret 存放在使用它的 Flux Kustomization 所在的同一个命名空间中:

kubectl create secret generic sops-age \
  --namespace=flux-system \
  --from-file=age.agekey=/dev/stdin < age.agekey

Secret 中的键必须以 .agekey 结尾。在它被安全地存储到别处之后,删除本地的 age.agekey 文件,或将它移到密码管理器中。

在仓库中配置 SOPS

在仓库根目录创建 .sops.yaml,让每个人都以同样的方式加密。把其中的密钥替换为你的公钥:

creation_rules:
  - path_regex: .*\.yaml
    encrypted_regex: ^(data|stringData)$
    age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

encrypted_regex 只加密 data 和 stringData 字段,所以清单的其余部分保持可读,以便审查和让 Flux 处理。你可以列出多个 age 接收者(以逗号分隔),这样团队成员和集群密钥都能解密。

加密 Secret

在本地编写 Secret 清单,例如 apps/webapp/db-credentials.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: webapp
stringData:
  username: webapp
  password: s3cr3t-value

就地加密:

sops --encrypt --in-place apps/webapp/db-credentials.yaml

打开该文件:username 和 password 的值现在是密文,并且添加了一个带有元数据的 sops: 块。现在可以安全地提交它了。之后若要编辑,请运行 sops apps/webapp/db-credentials.yaml,它会在你的编辑器中解密,并在保存时重新加密。要检查你即将提交的内容,请确认其中的值已不再可读。

告诉 Flux 解密

在应用该文件夹的 Flux Kustomization 中添加 decryption 块:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: webapp
  namespace: flux-system
spec:
  interval: 10m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/webapp
  prune: true
  decryption:
    provider: sops
    secretRef:
      name: sops-age

提交并推送。在协调期间,kustomize-controller 会在内存中解密该文件,并将一个普通的 Secret 应用到集群。验证:

flux reconcile kustomization webapp --with-source
kubectl get secret db-credentials -n webapp

排查与良好实践

如果 Kustomization 报告解密错误,请检查 sops-age Secret 是否存在于与该 Kustomization 相同的命名空间中,它的键名是否以 .agekey 结尾,以及文件是否是针对匹配的公钥加密的。kubectl describe kustomization webapp -n flux-system 会显示错误。

  • 每个环境使用不同的密钥,这样 dev 密钥就无法读取 production 的 Secret。
  • 轮换密钥的方法是添加新的接收者,重新加密(sops updatekeys),然后移除旧的。
  • 云 KMS 密钥(AWS KMS、Azure Key Vault、Google Cloud KMS)以及 HashiCorp Vault 或 OpenBao 同样可用,并且避免了分发密钥文件。请通过工作负载身份来配置它们,在平台提供凭据的地方省略 secretRef。
  • 如果你更愿意让密钥完全不进入 Git,请使用 External Secrets Operator 从保管库同步它们,让 Flux 只管理 ExternalSecret 对象。

热门指南