《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等工具定义在代码中,与应用代码一同版本控制,确保数据库服务器配置可追溯和可复现。