Bitnami Sealed Secrets:K8s 加密 Secret 管理实战(Git 安全存储 Kubernetes 密钥)

Bitnami Sealed Secrets:K8s 加密 Secret 管理实战(Git 安全存储 Kubernetes 密钥)

在 Kubernetes 集群中管理 Secret 是一个长期困扰运维团队的难题。原生的 Secret 资源仅经过 Base64 编码,本质上是明文存储,直接提交到 Git 仓库存在极大的安全隐患。Bitnami 开源的 Sealed Secrets 项目正是为解决这一问题而生——它允许你将加密后的 Secret 安全地存储在版本控制系统中,真正实现 GitOps 安全闭环。

Sealed Secrets 的工作原理是将敏感数据使用集群中控制器持有的非对称密钥加密,生成 SealedSecret 自定义资源。只有对应集群的 controller 才能解密,攻击者即便拿到 Git 仓库中的 YAML 文件也无法还原原始数据。配合 ArgoCD 或 Flux 等 GitOps 工具,可以构建从代码提交到集群部署的完整自动化链路,且全程不暴露任何敏感信息。

本教程将覆盖 Sealed Secrets 的完整实战流程:从集群安装、kubeseal CLI 使用,到密钥轮换策略和 GitOps 集成实践,帮助团队建立一套可靠的 K8s Secret 管理规范。

环境要求

本教程推荐在雨云服务器 rainyun-com 上搭建实验环境,注册填优惠码 2026off 领 5 折优惠券。推荐配置为 K3s 集群控制节点,选择 2 核 4GB 内存机型,该配置完全满足 K3s 单节点集群及 Sealed Secrets controller 的运行需求。

软件要求:

  • K3s v1.28+ 或任意 Kubernetes v1.20+ 集群
  • kubectl 已配置好集群访问权限
  • Helm v3.12+
  • kubeseal CLI(与服务端版本匹配)
  • Git 仓库(GitHub/Gitea 均可)

系统要求:

  • Ubuntu 22.04 LTS(推荐)
  • 磁盘剩余空间 ≥ 20GB

安装

安装 K3s(若尚未安装)

curl -sfL https://get.k3s.io | sh -
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get nodes

通过 Helm 安装 Sealed Secrets Controller

helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm repo update

helm install sealed-secrets sealed-secrets/sealed-secrets \
  --namespace kube-system \
  --set fullnameOverride=sealed-secrets-controller

验证 controller 是否正常运行:

kubectl get pods -n kube-system -l app.kubernetes.io/name=sealed-secrets
# 输出示例:
# NAME                                         READY   STATUS    RESTARTS   AGE
# sealed-secrets-controller-6b9f4d8c9b-xk2p9  1/1     Running   0          2m

安装 kubeseal CLI

# 获取最新版本号
KUBESEAL_VERSION=$(curl -s https://api.github.com/repos/bitnami-labs/sealed-secrets/releases/latest \
  | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')

# 下载并安装
curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION#v}-linux-amd64.tar.gz"
tar -xvzf kubeseal-*.tar.gz kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal

# 验证
kubeseal --version

核心配置

创建并加密第一个 Secret

首先创建一个普通的 Kubernetes Secret(不要直接提交到 Git!):

kubectl create secret generic my-app-secret \
  --from-literal=db-password='S3cur3P@ssw0rd!' \
  --from-literal=api-key='abc123xyz456' \
  --dry-run=client \
  -o yaml > my-secret.yaml

使用 kubeseal 加密:

kubeseal --format yaml \
  --controller-name=sealed-secrets-controller \
  --controller-namespace=kube-system \
  < my-secret.yaml > my-sealed-secret.yaml

生成的 my-sealed-secret.yaml 内容示例:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: my-app-secret
  namespace: default
spec:
  encryptedData:
    api-key: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq...
    db-password: AgAKAAMCAQIwggFiAgEAMIIBWzANBgkq...
  template:
    metadata:
      name: my-app-secret
      namespace: default

此文件可以安全地提交到 Git 仓库:

git add my-sealed-secret.yaml
git commit -m "feat: add encrypted app secret"

应用加密后的 Secret

kubectl apply -f my-sealed-secret.yaml

# 验证 Secret 是否被自动解密创建
kubectl get secret my-app-secret -o jsonpath='{.data.db-password}' | base64 -d

作用域控制

kubeseal 支持三种作用域,控制 Secret 的可移植性:

# strict(默认):绑定到特定 namespace 和 name
kubeseal --scope strict < my-secret.yaml > sealed.yaml

# namespace-wide:可在同一 namespace 下任意 name 使用
kubeseal --scope namespace-wide < my-secret.yaml > sealed.yaml

# cluster-wide:集群范围内任意 namespace/name 可用(慎用)
kubeseal --scope cluster-wide < my-secret.yaml > sealed.yaml

实战演练

场景一:数据库连接串管理

# 创建包含多个字段的数据库 Secret
kubectl create secret generic postgres-credentials \
  --from-literal=host='db.internal.example.com' \
  --from-literal=port='5432' \
  --from-literal=username='appuser' \
  --from-literal=password='Pg@ssw0rd2026!' \
  --from-literal=database='production_db' \
  --namespace=production \
  --dry-run=client -o yaml | \
  kubeseal --format yaml \
    --controller-namespace=kube-system \
    --controller-name=sealed-secrets-controller \
  > postgres-sealed-secret.yaml

场景二:TLS 证书存储

# 加密已有的 TLS Secret
kubectl create secret tls my-tls-secret \
  --cert=./tls.crt \
  --key=./tls.key \
  --dry-run=client -o yaml | \
  kubeseal --format yaml > my-tls-sealed-secret.yaml

场景三:从文件加密

# 直接从文件内容加密(不经过 Secret 对象)
kubeseal --raw \
  --name my-app-secret \
  --namespace default \
  --from-file=config.json \
  --controller-namespace kube-system

进阶用法

密钥轮换(Key Rotation)

Sealed Secrets controller 默认每 30 天自动生成新的加密密钥对,旧密钥仍会保留用于解密已有的 SealedSecret。如需手动触发轮换:

# 查看当前所有密钥
kubectl get secret -n kube-system \
  -l sealedsecrets.bitnami.com/sealed-secrets-key \
  -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.creationTimestamp}{"\n"}{end}'

# 手动触发密钥轮换(重启 controller)
kubectl rollout restart deployment/sealed-secrets-controller -n kube-system

# 轮换后,旧 SealedSecret 仍可正常解密
# 建议在轮换后用新密钥重新加密所有 SealedSecret

备份密钥(极其重要,迁移集群时需要):

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

# 在新集群恢复
kubectl apply -f sealed-secrets-keys-backup.yaml
kubectl rollout restart deployment/sealed-secrets-controller -n kube-system

GitOps 集成(ArgoCD)

创建 ArgoCD Application 自动同步 SealedSecret:

# argocd-app-secrets.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-secrets
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/k8s-secrets-repo
    targetRevision: main
    path: secrets/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

获取公钥用于离线加密

团队成员可以在不访问集群的情况下加密 Secret:

# 导出公钥
kubeseal --fetch-cert \
  --controller-name=sealed-secrets-controller \
  --controller-namespace=kube-system \
  > sealed-secrets-pub.pem

# 离线加密(使用公钥文件)
kubeseal --cert sealed-secrets-pub.pem \
  --format yaml < my-secret.yaml > my-sealed-secret.yaml

常见问题

Q:提示 “cannot get sealed secret service” 错误

检查 controller 是否运行,以及 kubeseal 连接的 controller 名称和 namespace 是否正确:

kubectl get svc -n kube-system | grep sealed
kubeseal --controller-name=sealed-secrets-controller \
         --controller-namespace=kube-system \
         --fetch-cert

Q:解密失败,Secret 一直处于 Error 状态

# 查看 controller 日志
kubectl logs -n kube-system \
  -l app.kubernetes.io/name=sealed-secrets --tail=50

# 常见原因:SealedSecret 的 namespace/name 与创建时不匹配(strict 模式)

Q:如何更新已加密的 Secret 中的某个字段

重新生成整个 SealedSecret,kubeseal 不支持增量更新单个字段,必须重新加密完整的 Secret 对象。

Q:迁移到新集群后 SealedSecret 无法解密

需要先将旧集群的密钥备份恢复到新集群,再重启 controller。若旧集群密钥丢失,则必须重新加密所有 SealedSecret。

Q:kubeseal 版本与 controller 版本不匹配

# 查看 controller 版本
kubectl get deployment sealed-secrets-controller \
  -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}'

# 下载对应版本的 kubeseal CLI

Bitnami Sealed Secrets 是 Kubernetes 生态中最成熟的 GitOps Secret 管理方案之一,轻量、无依赖、原生集成。如果你正在寻找一台稳定的服务器来搭建 K3s 集群并实践上述教程,推荐选择雨云服务器 rainyun-com2 核 4GB 机型,注册时填入优惠码 2026off 可领取 5 折优惠券,以极低的成本拥有一台高性能的 K3s 控制节点,让你的 GitOps 安全实践从零开始。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值