《UNIX/Linux系统管理技术手册-读书笔记-第二十六章
持续集成与交付(CI/CD)
1. CI/CD概述
1.1 三个核心概念
| 概念 |
说明 |
能做什么 |
| 持续集成(CI) |
开发人员频繁(每天多次)将代码合并到共享仓库,并自动触发构建和测试 |
及早发现集成错误,减少“集成地狱” |
| 持续交付(CD) |
CI完成后自动将构建部署到非生产环境(开发/测试/预发布) |
软件始终处于可发布状态,部署过程自动化 |
| 持续部署(CD) |
持续交付的延伸——通过所有测试后自动部署到生产环境 |
新特性在数分钟/数小时内上线(需高度自动化测试信任) |
💡 组织可根据风险承受能力选择在流水线何处暂停——非所有站点都必须实现持续部署。
1.2 核心原则
| 原则 |
说明 |
| 版本控制 |
所有代码、配置、基础设施定义都存储在Git等版本控制系统中(单一可信数据源) |
| 一次构建,多次部署 |
构建产物(制品)一经生成,在流水线所有阶段使用同一制品,确保测试对象=部署对象 |
| 端到端自动化 |
构建、测试、部署全自动运行(生产部署可由人工触发,但过程无人值守) |
| 构建每一次集成提交 |
每次向集成分支的提交都触发构建;构建失败是团队共同责任,需立即修复 |
| 快速构建,快速修复 |
构建应在数分钟内完成,开发人员记忆犹新时修复问题 |
| 审计与可追溯 |
每个发布的完整历史(代码→制品→部署),确保可审计和可回滚 |
| 分担责任 |
整个团队(开发+运维)共同维护流水线健康 |
1.3 环境(Environment)
| 环境 |
目的 |
特点 |
| 开发(Dev) |
集成多开发人员更新,测试基础设施改动 |
快速迭代,允许不稳定 |
| 预发布(Stage/Test) |
自动化+手动测试,业务验收,安全检查 |
尽可能接近生产环境 |
| 生产(Prod) |
服务真实用户 |
高可用、高性能、严格安全 |
环境一致性(Environment Parity) :
- 下游环境与生产环境差异 → 测试结果不可靠 → 生产故障
- 策略:定期从生产匿名化数据快照 → 复制到测试环境
- 配置项通过配置管理统一管理,避免硬编码环境差异
1.4 特性标志(Feature Flag)
| 概念 |
说明 |
能做什么 |
| 特性标志 |
通过配置开关控制特性启用/禁用,无需重新部署 |
生产环境中安全测试新特性,异常时立即关闭 |
| 典型工作流 |
新特性代码提前部署到所有环境,仅在Dev/Stage启用,Prod关闭 → 验证完成后一键启用 |
降低发布风险,解耦部署与发布 |
2. CI/CD流水线
2.1 流水线三个阶段
源代码提交 → 构建(Build) → 测试(Test) → 部署(Deploy) → 生产
| 阶段 |
输入 |
输出 |
说明 |
| 构建(Build) |
源代码 |
构建制品(.jar/.deb/容器镜像/机器镜像等) |
编译、打包、生成可部署软件 |
| 测试(Test) |
构建制品 |
测试报告(通过/失败) |
多层次验证(单元/集成/验收/性能) |
| 部署(Deploy) |
通过测试的制品 |
运行中的服务 |
安装到目标环境,启动服务 |
制品类型示例(表26.1):
.jar/.war(Java)
.rpm/.deb(Linux包)
pip/gem包(Python/Ruby)
- 容器镜像(Docker)
- 虚拟机镜像(AMI/机器镜像)
2.2 测试类型
| 测试类型 |
说明 |
速度 |
失败含义 |
| 静态代码分析 |
检查语法错误、安全漏洞、代码重复、复杂度 |
快 |
代码质量问题 |
| 单元测试 |
测试单个函数/方法的输入输出(开发人员编写) |
快 |
代码逻辑错误 |
| 集成测试 |
测试应用+框架+外部依赖(数据库/API/缓存) |
中 |
组件间接口问题 |
| 验收测试 |
模拟用户行为(如Selenium浏览器自动化) |
慢 |
用户路径不工作 |
| 性能测试 |
模拟负载,检测性能退化(JMeter/Gatling) |
很慢 |
性能瓶颈/回归 |
| 基础设施测试 |
验证云基础设施配置正确性(Serverspec) |
中 |
基础设施即代码错误 |
黄金规则:测试失败 → 立即修复流水线,绝不容忍“忽略”失败测试。
2.3 零停机部署技术
| 技术 |
说明 |
适用场景 |
| 蓝/绿部署 |
备用系统(绿)部署新版本→测试→负载均衡器切换流量→旧系统(蓝)下线 |
微服务、负载均衡环境 |
| 滚动部署 |
逐个从负载均衡器摘除节点→更新→重新加入 |
可容忍多版本同时运行 |
| 金丝雀发布 |
新版本先部署到少数节点→监控→逐步扩大范围 |
生产验证,降低风险 |
3. Jenkins自动化服务器
3.1 核心概念
| 概念 |
说明 |
| Jenkins |
Java编写的开源自动化服务器,最流行的CI/CD工具 |
| 项目/作业 |
相互关联的构建步骤集合,通常对应一个应用 |
| 触发器 |
启动构建的信号(GitHub Webhook、轮询SCM、定时、手动) |
| 构建步骤 |
流水线中的具体任务(编译、测试、打包、部署) |
| 分布式构建 |
Master(调度)+ Agent(执行),通过标签匹配能力 |
3.2 快速启动
1
2
3
4
|
# 容器运行Jenkins
docker run -p 8080:8080 --name jenkins jenkinsci/jenkins
# 访问 http://localhost:8080
# 初始管理员密码在容器日志中
|
3.3 Jenkinsfile(流水线即代码)
核心优势:流水线定义与代码一同存储在版本控制中,可审计、可回滚。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'make'
}
}
stage('Test') {
steps {
sh 'make test'
}
}
stage('Deploy') {
steps {
sh 'deploy.sh'
}
}
}
}
|
关键概念:
pipeline:顶层定义
agent any:任何可用构建代理执行
stages:阶段列表(串行执行)
stage:单个阶段(构建/测试/部署)
steps:阶段内的具体命令
environment:定义环境变量(可从凭证存储读取敏感数据)
4. CI/CD实战案例(UlsahGo)
4.1 流水线概览
GitHub提交 → Jenkins检出代码 → 单元测试(go test) → 构建(go build)
→ Packer构建DigitalOcean镜像 → Terraform创建单Droplet测试环境
→ 集成测试(健康检查+功能验证) → 销毁测试Droplet
→ Terraform创建生产环境(2 Droplets + 负载均衡器)
→ 生产验证 → 部署完成
4.2 工具栈
| 工具 |
用途 |
| GitHub |
源代码仓库(包含应用代码 + Jenkinsfile + Packer模板 + Terraform配置) |
| Jenkins |
CI/CD流水线编排(Jenkinsfile) |
| Packer |
构建DigitalOcean虚拟机镜像(构建制品) |
| Terraform |
按需创建/销毁基础设施(Dev环境和Prod环境) |
| DigitalOcean |
云平台(Droplet虚拟机 + 负载均衡器) |
4.3 关键技术点
| 技术点 |
实现方式 |
| 流水线即代码 |
Jenkinsfile存储在Git仓库中 |
| 敏感凭证 |
Jenkins凭证存储(不写入代码) + 环境变量传递 |
| 制品传递 |
镜像ID从Packer阶段 → 文本文件 → Terraform阶段 |
| 环境隔离 |
Dev(单Droplet)和Prod(2 Droplet + LB)使用不同Terraform配置 |
| 健康检查 |
应用提供/healthy端点,负载均衡器用于健康检查 |
| 集成测试 |
curl验证HTTP状态码(200/404) |
Jenkinsfile片段(凭证传递) :
1
2
3
4
5
6
7
8
9
10
11
12
13
|
pipeline {
environment {
DO_TOKEN = credentials('do-token') // 从Jenkins凭证存储读取
SSH_FINGERPRINT = credentials('ssh-fingerprint')
}
stages {
stage('Create droplet') {
steps {
sh 'bash pipeline/testing/tf_testing.sh'
}
}
}
}
|
Packer配置示例(DigitalOcean镜像) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
"builders": [{
"type": "digitalocean",
"api_token": "{{user `do_token`}}",
"region": "sfo2",
"size": "512mb",
"image": "ubuntu-16-04-x64",
"snapshot_name": "ulsahgo-latest"
}],
"provisioners": [
{"type": "file", "source": "ulsahgo", "destination": "/tmp/ulsahgo"},
{"type": "file", "source": "ulsahgo.service", "destination": "/etc/systemd/system/"},
{"type": "shell", "script": "provisioner.sh"}
]
}
|
Terraform配置(生产环境) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
resource "digitalocean_droplet" "ulsahgo-a" {
image = var.do_image
name = "ulsahgo-a"
region = "sfo2"
size = "512mb"
ssh_keys = [var.ssh_fingerprint]
}
resource "digitalocean_loadbalancer" "public" {
name = "ulsahgo-lb"
region = "sfo2"
forwarding_rule {
entry_port = 80
target_port = 8000
}
healthcheck {
port = 8000
path = "/healthy"
}
droplet_ids = [digitalocean_droplet.ulsahgo-a.id, digitalocean_droplet.ulsahgo-b.id]
}
|
5. 容器与CI/CD
5.1 容器如何简化CI/CD
| 场景 |
传统方式 |
容器方式 |
| 构建环境 |
CI代理需安装所有工具链和依赖(冲突风险) |
每个构建在独立容器中运行,代理保持干净 |
| 测试环境 |
为每个项目配置独立的数据库/缓存服务器 |
短期容器(PostgreSQL/Redis)按需创建/销毁 |
| 制品 |
复杂的包管理(.deb/.rpm) |
容器镜像是制品,通过registry分发 |
| 部署 |
配置管理 + 滚动更新 |
容器编排平台(Kubernetes/Swarm)API调用 |
5.2 基于容器的CI/CD工作流
(1) 在构建容器中编译应用
(2) 创建包含应用+依赖的容器镜像
(3) 推送到镜像Registry
(4) 通过容器编排API部署到生产
优点:
- 构建环境隔离,无依赖冲突
- 制品(容器镜像)统一格式,跨环境一致
- 部署速度极快(容器启动<1秒)
- 回滚简单(切换镜像tag)
5.3 容器化CI/CD工具
| 工具 |
特点 |
| Jenkins + Docker插件 |
流水线原生支持容器构建和测试 |
| Drone |
专为容器设计的CI/CD平台 |
6. CI/CD最佳实践总结
| 实践 |
说明 |
| 单一可信数据源 |
所有代码、配置、基础设施定义在版本控制中 |
| 快速反馈 |
构建<10分钟,测试<30分钟,问题越早发现修复成本越低 |
| 不跳过失败测试 |
流水线失败立即修复,不容忍“已知失败” |
| 环境平等 |
Dev/Stage尽可能接近Prod(数据匿名化、配置一致) |
| 不可变部署 |
服务器一旦初始化不再修改,新部署=新服务器(云原生最佳实践) |
| 蓝/绿部署 |
零停机发布的标准方法 |
| 监控与可观测性 |
部署过程中监控关键指标,异常自动回滚 |
| 持续改进 |
逐步优化流水线,消除瓶颈 |
7. 本章核心命令速查表
| 命令/操作 |
功能 |
docker run -p 8080:8080 jenkinsci/jenkins |
快速启动Jenkins |
packer build template.json |
构建虚拟机镜像 |
terraform apply -var "key=value" |
创建/更新云基础设施 |
terraform destroy |
销毁基础设施 |
terraform show |
查看当前状态(用于提取IP等) |
go test |
运行Go单元测试 |
go build |
构建Go二进制文件 |
curl -D - -s http://host/endpoint | grep "HTTP/1.1 200" |
验证HTTP端点状态 |
DBA视角补充:
- 数据库变更与CI/CD:传统数据库变更(DDL/Schema迁移)常成为CI/CD流水线的瓶颈。使用迁移工具(如Flyway、Liquibase)将数据库变更纳入版本控制,并在流水线中自动执行迁移+验证,实现数据库CI/CD。
- 测试环境数据库:CI/CD测试阶段需要数据库时,使用临时容器数据库(如
docker run postgres)或测试实例,避免污染共享测试数据库。
- 数据匿名化:从生产环境复制数据到测试环境时,必须匿名化敏感数据(姓名、邮箱、电话、密码等),符合合规要求(GDPR/PCI-DSS)。
- 迁移回滚策略:数据库迁移应可回滚(如Flyway的
undo),与蓝/绿部署或金丝雀发布配合,确保新版本数据库变更不影响旧版本应用。
- 性能测试环境:数据库性能测试需要与生产环境接近的数据量和查询模式。使用生产数据匿名化样本或生成合成数据,确保性能测试结果可信。
- 监控数据库部署:流水线部署数据库变更后,监控慢查询日志、连接数、锁等待等指标,异常时自动触发回滚。将数据库监控指标集成到CI/CD流水线的健康检查中,可作为金丝雀发布的判断依据。
- 基础设施即代码的DBA视角:数据库服务器的配置(
my.cnf/postgresql.conf、备份策略、监控Agent)应通过Terraform/Ansible等工具定义在代码中,与应用代码一同版本控制,确保数据库服务器配置可追溯和可复现。