在 CI 中安全存储多云 context 的 TLS 证书

解读

国内企业在多云(阿里云 ACK、腾讯云 TKE、华为云 CCE、私有云 K8s 等)场景下,CI 流水线需要频繁切换 kube-context 并携带各云厂商的 client.crt、client.key、ca.crt 等 TLS 材料。若把这些文件直接写进代码库或打包到镜像,会立刻触发安全红线:

  1. 镜像里残留证书 → 镜像仓库一旦泄露,所有集群被“横向移动”;
  2. 仓库明文存储 → GitHub/Gitee 扫描直接报警,等保 2.0 测评直接不合格;
  3. 流水线日志回显 → 审计平台抓到 base64 字符串,HR 和法务同时约谈。
    因此,面试题真正考察的是“证书生命周期管理 + CI 零敏感落盘 + 运行时最小权限”三位一体能力,而不仅仅是“放哪里”。

知识点

  1. Docker BuildKit 密钥挂载语法RUN --mount=type=secret,id=k8s-crt 实现“构建时可用、镜像层不留”。
  2. 国内云原生审计合规:等保 2.0、关基、工信部 164 号文要求“密钥不出域、不出容器镜像”。
  3. CNCF 推荐的外部 Secrets 方案:阿里云 KMS + ACK SecretStore、腾讯云 SSM + TKE CSI 0.3、Vault + Kubernetes 集成。
  4. CI 侧注入技术:GitLab CI id_tokens + 阿里云 STS AssumeRole、GitHub OIDC + 腾讯云 CAM、Jenkins 阿里云插件临时凭证。
  5. Docker Compose 多云编排docker compose --context 切换时,证书通过 DOCKER_CONTEXT 环境变量一次性挂载,而非写死。
  6. 镜像最小化与多阶段构建:使用 scratchdistroless 作为最终阶段,构建阶段证书挂载点绝不复制到最终层
  7. 国内镜像仓库的细粒度权限:阿里云 ACR 支持“按镜像签名 + RAM 最小授权”,避免 CI 账号拥有全仓库拉取权限。
  8. 故障排查:若 CI 报 x509: certificate signed by unknown authority,优先检查 OIDC 颁发的 STS 临时凭证是否过期 15 min

答案

  1. 证书托管:把多云 kubeconfig 中的三段式 TLS 证书拆成独立条目,存入国内云 KMS(阿里云 KMS、腾讯云 SSM、华为云 CSMS),并启用硬件级 HSM保护,确保“人拿不到、CI 只能临时调”。
  2. CI 零持久化
    • GitLab CI:使用 id_tokens 让 Runner 通过 OIDC 换取云厂商 STS 令牌,再调用 KMS GetSecretValue 接口,把证书只写入 Runner 内存 tmpfsafter_script 阶段立即 shred -u
    • GitHub Actions:利用 aws-actions/configure-aws-credentials@v2 同等方式,全程不落盘
  3. Docker 构建零残留
    • 在 Dockerfile 中写:RUN --mount=type=secret,id=k8s-crt,dst=/run/secrets/kube.crt --mount=type=secret,id=k8s-key,dst=/run/secrets/kube.key kubectl config set-credentials …
    • 构建命令:DOCKER_BUILDKIT=1 docker build --secret id=k8s-crt,src=<(cat $KUBE_CERT) --secret id=k8s-key,src=<(cat $KUBE_KEY) -t myapp:$CI_COMMIT_SHA .
    • 这样证书只存在于 BuildKit 的 tmpfs mount namespace,镜像层哈希里找不到任何证书内容。
  4. 运行时注入
    • 若容器运行时需要动态切换 context,使用国内云厂商的 Secrets Store CSI Driver(ACK-SSCD、TKE-SSCD)把 KMS 里的证书以 tmpfs volume 形式挂载到 /var/run/secrets/kubernetes.io/serviceaccount,容器内只读、不可拷贝。
    • 配合 fsGroup: 65534 + readOnlyRootFilesystem: true非 root 用户也无法把证书写到本地盘
  5. 审计与回滚
    • 在阿里云 ActionTrail、腾讯云 CloudAudit 中开启对 KMS 解密事件的实时日志投递到 SLS/CLS,一旦异常批量解密,立即触发函数计算吊销 STS 并通知企业微信。
    • 证书轮换策略:90 天自动轮转,CI 侧只保存**指纹(SHA256)**而非内容,实现“证书换了,CI 无需改代码”。

拓展思考

  1. 多云 Service Mesh 场景:如果后续引入 Istio,需要把上述 TLS 证书同时注入到 Gateway 的 SDS(Secret Discovery Service) 中,此时可复用同一套 KMS + CSI,做到“一套证书、多处挂载”,避免不同团队重复申请。
  2. 边缘 K8s 弱网环境:在工厂内网或 5G MEC 节点,无法实时访问公有云 KMS,可预置国密算法的本地加密机(SCM),CI 流水线通过 docker buildx --append 构建边缘版镜像,把证书加密后随镜像分发,启动时由加密机解密进入 tmpfs,既满足等保三级,又保证离线可用。
  3. GitOps 与证书漂移:Argo CD 同步时若检测到证书指纹变化,可自动触发 OCI 镜像签名验证(cosign + 阿里云 ACR Notary V2),防止“证书被轮换但镜像未重新签名”导致的回滚劫持
  4. 成本优化:KMS 调用按次计费,高并发 CI 会显著增加账单;可在国内主流云厂商的**批量解密 API(如阿里云 GetBatchSecretValue)**中一次拉取 50 个证书,把解密结果缓存到 Runner 内存 5 min,降低 70% 费用。