GitOps 中的密钥管理 - 安全处理敏感信息

GitOps 中的密钥管理 - 安全处理敏感信息


问题的核心:GitOps 与密钥的悖论

让我们再次明确这个核心矛盾:

  • Git 是唯一信源: 我们希望应用的整个期望状态,包括它需要加载哪些密钥,都在 Git 中声明。
  • Git 不是保险库 : 即便是私有 Git 仓库,也存在被克隆、权限泄露、开发者离职后代码留存等风险。将明文的 kind: Secret YAML 文件存入 Git,无异于将保险库的密码贴在门上。

我们需要的是一种方法,能够让我们在 Git 中安全地存储一个密钥的"表示"或"引用" ,同时确保真正的、未加密的密钥值只出现在它应该出现的地方------即运行在 Kubernetes 集群内的应用 Pod 中。

方案一:Sealed Secrets - 将加密后的密钥存入 Git

这是最直观、最容易上手的一种 GitOps 密钥管理方案。

  • 核心理念 : 一种单向加密 模型。
    1. 一个 Controller (控制器)运行在你的 Kubernetes 集群里。在启动时,它会自动生成一对公钥/私钥私钥永远不会离开集群
    2. 开发者或 CI/CD 流水线在集群外部,使用一个名为 kubeseal 的命令行工具和从集群中获取到的公钥 ,来对一个普通的、包含明文密码的 Kubernetes Secret YAML 文件进行加密。
    3. 加密后,会生成一个新的、类型为 SealedSecret 的 YAML 文件。这个文件里的数据是加密过的,因此可以安全地提交到 Git 仓库
    4. Argo CD 会像同步其他资源一样,将这个 SealedSecret 对象同步到集群中。
    5. 集群内的 Sealed Secrets Controller 会监听到这个 SealedSecret 对象,然后使用它自己保管的私钥 对其解密,最终在集群中创建一个原生的、包含明文数据的 Secret 对象
    6. 你的应用程序像往常一样,挂载和使用这个最终生成的原生 Secret 即可。

实战:安装和使用 Sealed Secrets

  1. 在集群中安装 Sealed Secrets Controller:

    bash 复制代码
    kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/latest/download/controller.yaml
  2. 安装 kubeseal 命令行工具:

    • macOS 用户 : brew install kubeseal

    • Linux 用户 : (请参考官方文档获取最新命令)

      bash 复制代码
      VERSION="v0.26.1" # Use a specific version
      wget "https://github.com/bitnami-labs/sealed-secrets/releases/download/${VERSION}/kubeseal-${VERSION}-linux-amd64.tar.gz"
      tar -xvzf kubeseal-${VERSION}-linux-amd64.tar.gz kubeseal
      sudo install -m 755 kubeseal /usr/local/bin/kubeseal
  3. 获取加密所需的公钥 :
    kubeseal 需要使用 Controller 的公钥来进行加密。我们可以从集群中获取它并保存到本地:

    bash 复制代码
    kubeseal --fetch-cert \
      --controller-name sealed-secrets-controller \
      --controller-namespace sealed-secrets \
      > pub-cert.pem
  4. 创建并加密一个 Secret:

    • 首先,创建一个包含明文密码的普通 Secret YAML 文件,例如 my-db-secret.yaml注意:这个文件永远不要提交到 Git!

      yaml 复制代码
      # my-db-secret.yaml (DO NOT COMMIT TO GIT)
      apiVersion: v1
      kind: Secret
      metadata:
        name: db-credentials
        namespace: default
      stringData:
        password: "SuperSecretPassword123"
        username: "dbuser"
    • 现在,使用 kubeseal 和我们下载的公钥来加密它:

      bash 复制代码
      kubeseal --cert pub-cert.pem --format yaml < my-db-secret.yaml > my-db-sealed-secret.yaml
    • 打开生成的 my-db-sealed-secret.yaml 文件。你会看到它的 kindSealedSecret,并且 data 字段里的内容是一长串加密后的乱码。这个文件是可以安全提交到 Git 的!

  5. 提交到 Git 并让 Argo CD 同步 :

    my-db-sealed-secret.yaml 文件添加到你的 my-gitops-manifests 仓库中,然后 git push。Argo CD 会自动检测到这个新文件并将其同步到集群。

  6. 验证结果:

    • Argo CD 同步后,Sealed Secrets Controller 会自动解密并创建原生的 Secret。
    • 运行 kubectl get secret db-credentials -n default -o yaml。你会看到 data 字段里包含了 Base64 编码后的明文密码。
    • 你的应用现在可以正常挂载和使用这个名为 db-credentials 的 Secret 了。
  • 优缺点分析 :
    • 优点: 模型简单清晰,容易理解和上手。安全可靠,私钥不出集群。无任何外部依赖,非常适合起步或中小型项目。
    • 缺点: 密钥轮换需要重新加密并提交 Git。密钥的生命周期与 Git commit 绑定。对于跨多个集群的场景,每个集群都有自己的密钥对,管理起来稍显复杂。

方案二:外部密钥管理器集成 (External Secrets Operator)

对于已经在使用或计划采用集中式密钥管理方案(如 HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault)的组织来说,这个模式是更佳的选择。

  • 核心理念: 密钥的"真实信源"是外部的专业密钥管理器。Git 中只存储一个指向外部密钥的**"引用"。

  • 工作原理 (使用 External Secrets Operator - ESO):

    1. 将真实的密钥值(如数据库密码)存储在 Vault 或云厂商的密钥管理服务中。
    2. 在 Kubernetes 集群中安装 ESO 控制器。
    3. 配置一个 SecretStoreClusterSecretStore 资源,告诉 ESO 如何连接和认证到外部的密钥管理器。
    4. 在 Git 仓库中,我们不再存储 SealedSecret,而是存储一个类型为 ExternalSecret 的 YAML 文件。这个文件描述了:"请从名为 vault-backend 的 SecretStore 中,获取路径为 secret/myapp/db 的密钥,并用它在集群中创建一个名为 db-credentials 的原生 Secret"。
    5. Argo CD 负责同步这个 ExternalSecret 对象。
    6. ESO 控制器监听到 ExternalSecret 后,会执行真正的拉取操作,并创建或更新最终的原生 Secret
  • ExternalSecret 示例:

    yaml 复制代码
    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
      name: my-app-db-secret
    spec:
      secretStoreRef:
        name: vault-backend
        kind: ClusterSecretStore
      target:
        name: db-credentials # 将要创建的原生 Secret 的名字
      dataFrom:
      - extract:
          key: secret/data/myapp/db # 从 Vault 的这个路径下提取所有 key-value
  • 优缺点分析:

    • 优点: 实现了密钥管理与应用配置的完全解耦。可以利用专业密钥管理器的所有高级功能(如集中审计、自动轮换、动态密钥等)。非常适合跨多个应用、团队和集群的复杂环境。
    • 缺点: 增加了外部依赖(需要维护一个密钥管理器),初始设置相对复杂。

方案三:Argo CD Vault Plugin (AVP)

这是一个与 Argo CD 结合更紧密的"即时注入"方案,主要针对使用 HashiCorp Vault 的用户。

  • 核心理念 : 在 Argo CD 渲染 K8s 清单文件的过程中,动态地从 Vault 中拉取密钥,并直接替换掉清单中的占位符。最终应用到集群的是已经包含了明文密钥的完整清单。

  • 工作原理 :

    1. 将 AVP 配置为 Argo CD 的一个自定义配置管理插件。
    2. 在 Git 仓库的 K8s 清单文件(如 Deployment.yaml)中,直接使用特殊的占位符来引用 Vault 中的密钥。
    3. 当 Argo CD 进行同步时,它会先将这些带有占位符的清单交给 AVP 插件处理。
    4. AVP 插件会连接到 Vault,用真实的密钥值替换掉所有占位符,然后将最终渲染好的、不含占位符的清单返回给 Argo CD,由 Argo CD 将其应用到集群。
  • 带占位符的 Deployment 示例 :

    yaml 复制代码
    # ...
    spec:
      template:
        spec:
          containers:
          - name: my-app
            env:
              - name: DB_PASSWORD
                value: <path:secret/data/myapp/db#password> # AVP 的占位符语法
    # ...
  • 优缺点分析 :

    • 优点 : 不会在集群中创建中间的原生 Secret 对象,密钥只在内存中存在于应用 Pod 的环境变量里。密钥总是在部署时获取最新的值。
    • 缺点: 与 Vault 强绑定。密钥明文会出现在 Argo CD UI 的"渲染后清单"视图中,对 Argo CD 本身的 RBAC 权限控制要求极高。清单文件带有特殊语法,可读性略差,且不易在 Argo CD 环境之外使用。

对比与选择

方案 核心模型 优点 缺点 适用场景
Sealed Secrets 加密后存入 Git 简单、自包含、无外部依赖 密钥轮换需手动、与集群绑定 中小型项目、单集群、不希望引入外部依赖
External Secrets 从外部源同步 集中管理、功能强大、解耦、可扩展性好 初始设置复杂、有外部依赖 企业级、多集群、已在使用或计划使用集中式密钥管理
Argo CD Vault Plugin 渲染时注入 无中间 Secret、密钥最新、与应用部署同步 强绑定 Vault、UI 可能暴露密钥、可移植性差 重度 Vault 用户、偏好即时注入模型的团队

总结

今天,我们成功地解决了 GitOps 流程中最棘手的密钥管理悖论。我们认识到,没有"银弹",但有多种成熟且安全的模式可供选择。我们动手实践了Sealed Secrets ,并深入理解了External Secrets OperatorArgo CD Vault Plugin这两种更高级的模式。为你的项目选择合适的密钥管理策略,是实施严肃的、生产级 GitOps 的一个至关重要的架构决策。

至此,我们的 GitOps 系统已经功能完备、配置优雅、部署安全、密钥无忧。那么,作为一个 SRE,我们还需要关心什么呢?当然是系统本身的日常运维、监控、备份恢复和最佳实践

相关推荐
tyl211023 分钟前
凌科芯安国产安全MCU简介
单片机·嵌入式硬件·安全
电院工程师1 小时前
轻量级密码算法CHAM的python实现
python·嵌入式硬件·算法·安全·密码学
云盾安全防护9 小时前
医疗行业网络安全的综合防护策略
网络·安全·web安全
安全系统学习9 小时前
网络安全之RCE简单分析
开发语言·python·算法·安全·web安全
恰薯条的屑海鸥9 小时前
零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)
学习·安全·web安全·渗透测试·网络安全学习
90wunch11 小时前
对象回调初步研究
c++·windows·安全
DFminer11 小时前
【仿生机器人】建模—— 图生3D 的几个办法
人工智能·安全·机器人
电院工程师17 小时前
SM3算法Python实现(无第三方库)
开发语言·python·算法·安全·密码学
熙客17 小时前
网络安全:OWASP防护守则
安全·web安全
藥瓿锻18 小时前
2024 CKS题库+详尽解析| 1. kube-bench 修复不安全项
运维·安全·docker·云原生·容器·kubernetes·cks