CI/CD集成基础:CI/CD流程简介,密钥在流水线中的角色
开始聊密钥轮换之前,咱们得先把地基打牢。
CI/CD流水线,说白了就是把代码从你本地,一路自动推送到生产环境的一套“传送带”。你想想看,如果没有这条传送带,每次上线都得手动打包、手动测试、手动部署,出错的概率有多高?我个人习惯是把CI/CD看作应用的“出厂质检线”。
一条典型流水线里都有啥
每个团队的流水线细节可能不同,但核心环节八九不离十。我画了个简易图,帮你快速建立全局感。
就像你看到的,密钥几乎出现在每个环节。下面我拆开细说。
流水线各阶段的密钥角色
| 流水线阶段 | 密钥在干嘛 | 我踩过的坑 |
|---|---|---|
| 代码提交 | 触发流水线,这个阶段一般不直接用密钥 | 有人把AK/SK写死在代码里提交,扫描工具都没配置 |
| 静态扫描 | 检测代码中是否嵌入了明文密钥 | 工具只扫描最新提交,历史commit里埋着旧密钥 |
| 构建与测试 | 从密钥管理服务拉取、数据库密码 | 构建机本地缓存了密钥,下一轮构建可能还在用旧的 |
| 制品签名 | 用签名私钥对构建产物打标签 | 签名密钥轮换时,旧签名验证会失败,得提前规划兼容期 |
| 部署与测试 | 向运行时环境注入配置和密钥 | 环境变量里写死密钥,改了还得重新部署应用 |
| 生产发布 | 最终环境使用经轮换验证的最新密钥 | 灰度发布时新旧密钥同时存在,应用没做兼容处理直接报错 |
核心认知:密钥在CI/CD里不是静态配置,而是一个动态资源。它的获取、注入、验证、轮换都必须与流水线深度集成。
密钥在流水线中的三种存在形态
我习惯把密钥在流水线里的状态分成三种,方便排查问题。
- 静态存储态:密钥躺在Vault或Secrets Manager里,还没被拉取。这时候最安全,但也要确保访问策略最小化。
- 运行时注入态:流水线执行时拉出来,注入到容器环境变量或挂载为文件。注意——不要在日志里打印密钥,我在几个项目里都见过构建日志明晃晃地输出数据库密码。
- 加密签名态:用于签名制品或镜像的私钥。这种密钥一旦轮换,旧版本制品可能就无法验证了。怎么做?
一个小技巧:对于签名密钥的轮换,保留上一代公钥用于验证,新私钥用于签名。过个过渡期后再把旧公钥废弃。这样可以避免部署了一半的应用突然签名验证失败。
为什么密钥轮换必须上CI/CD
你可能觉得:密钥轮换不就是改个密码吗?手动改也行啊。
嗯,这里要注意。一个中等规模的服务,可能涉及十几个外部、数据库凭证、证书私钥。手动改一遍至少半小时,还得逐个通知团队更新配置文件。万一漏了一个,线上直接报“401 Unauthorized”。
我曾经接手过一个项目,他们的数据库密码写在20个微服务的application.yml里。轮换一次密码,需要发20个MR,一个一个审批。等全部合进去,都半夜了。更惨的是,有个服务忘记改,数据库连接池一直报错,查了三个小时才发现。
所以,密钥轮换自动化,本质上是为了解决两个问题:
- 时效性:密钥泄漏后,几分钟内就能完成更新
- 一致性:所有消费方的密钥版本统一,不会出现部分旧部分新
密钥在CI/CD中的集成模式
在不同的架构里,密钥集成方式也不一样。我列了三种常见的:
| 模式 | 做法 | 适合场景 | 注意点 |
|---|---|---|---|
| 环境变量注入 | 流水线执行阶段,从密钥管理服务获取并export | 中小型项目,12-factor应用 | 环境变量可能被子进程继承,注意清理 |
| 文件挂载 | 构建/运行容器时,把密钥文件挂载到指定路径 | Kubernetes + Sidecar模式 | 文件权限要设成400,防止其他进程读取 |
| 密钥代理服务 | 应用启动时通过本地的Agent代理拉取密钥 | 大规模微服务,动态调度环境 | 代理本身的高可用和认证也需要保护 |
警惕! 不管用哪种模式,不要在流水线的YAML配置文件中直接填写密钥。YAML文件通常会落入Git仓库,即使权限受控,历史记录里也会留下痕迹。正确的做法是在CI/CD平台的变量设置里引用密钥服务的动态引用。
给CI/CD脚本设计密钥接口
我个人会坚持一个原则:流水线脚本不直接“知道”密钥的值。它只通过引用标识符去获取。比如:
# 不好的做法
export DB_PASSWORD="SuperSecret123!" # 写在脚本里,迟早被泄露
# 好的做法
export DB_PASSWORD=$(vault kv get -field=password secret/db/prod) # 运行时动态获取
这样做的好处很明显。密钥轮换时,只需要去密钥管理服务更新,流水线里没有任何代码需要改动。下次构建自动使用新密钥。
这背后其实是一个思想:将密钥的“获取逻辑”与“使用逻辑”解耦。流水线只关心“从哪里拿密钥”,不关心“密钥是什么”。拿到的密钥生命周期由密钥管理系统统一控制。
流水线里密钥轮换的几个坏味道
如果出现以下特征,说明你的密钥集成方式该优化了:
- 每次轮换密钥都要改动CI/CD脚本
- 同一个密钥在多个流水线文件中重复定义
- 密钥轮换后,需要手动重启应用才会生效
- 构建日志里能搜到敏感字段
- 不同环境的密钥使用同一个变量名,但值混在一起
这些我早年都遇到过。有一回生产环境的轮换,结果因为流水线脚本里硬编码了一个旧密钥的引用路径,导致灰度发布后一半实例用新密钥一半用旧密钥,用户请求时好时坏。排查了整整四个小时才定位到那个路径引用。
所以,从一开始设计流水线时,就把密钥当作一等公民来对待,后面会省很多心。
一句话总结本章:CI/CD流水线是密钥轮换自动化的载体,密钥在流水线中不是静态配置,而是动态资源。从一开始就设计好获取、注入、验证的机制,轮换就只是一次配置更新,而不是一次危机处理。