第二部分:持续集成(CI)流水线设计
持续集成要求开发者频繁(每日多次)将代码合并到主干,并通过自动化构建与测试快速发现集成错误。
一、 CI 流水线的核心阶段
一个典型的 CI 流水线包含以下阶段:
代码检出(Checkout)
依赖缓存(Cache Dependencies)
静态分析(Lint, Format)
单元测试(Unit Tests)
编译/打包(Build)
镜像构建(Container Image Build)
集成测试(Integration Tests)
制品上传(Artifact Upload)
二、使用 GitHub Actions 构建 CI 流水线
以下示例为 Java Spring Boot 项目的完整 CI。
name: Java CI with Maven
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${
{ github.repository }}
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2
key: ${
{ runner.os }}-m2-${
{ hashFiles('**/pom.xml') }}
restore-keys: ${
{ runner.os }}-m2
- name: Run unit tests with coverage
run: mvn -B test jacoco:report
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
file: ./target/site/jacoco/jacoco.xml
- name: Build JAR
run: mvn -B package -DskipTests
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: app-jar
path: target/*.jar
- name: Build Docker image
run: docker build -t ${
{ env.REGISTRY }}/${
{ env.IMAGE_NAME }}:${
{ github.sha }} .
- name: Log into GitHub Container Registry
run: echo "${
{ secrets.GITHUB_TOKEN }}" | docker login ${
{ env.REGISTRY }} -u ${
{ github.actor }} --password-stdin
- name: Push image
run: docker push ${
{ env.REGISTRY }}/${
{ env.IMAGE_NAME }}:${
{ github.sha }}
三、依赖缓存策略
加速 CI 的关键:缓存依赖包(Maven .m2、npm node_modules、Go mod 等)。
Maven 缓存示例(GitLab CI 风格):
cache:
paths:
- .m2/repository
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
四、并行化与矩阵策略
大型项目可拆分测试套件并行执行。
jobs:
test:
strategy:
matrix:
node-version: [16.x, 18.x]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/setup-node@v3
with:
node-version: ${
{ matrix.node-version }}
- run: npm test
第三部分:持续交付与持续部署(CD/CD)
CD 使每个通过 CI 的制品都能自动部署到类生产环境,并最终一键或自动推向生产。
一、部署流水线设计模式
环境链:开发环境(dev) → 测试环境(staging) → 生产环境(prod)
门禁:手动批准(生产环境)、自动化测试通过率、性能基线。
部署策略:滚动更新、蓝绿部署、金丝雀发布、A/B 测试。
二、基于 ArgoCD 的 GitOps 实践
GitOps 将 Git 作为声明式基础设施和应用的单一事实来源。ArgoCD 是 Kubernetes 上的 GitOps 控制器。
# application.yaml (ArgoCD Application 定义)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-staging
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/myapp-config
targetRevision: staging
path: overlays/staging
destination:
server: https://kubernetes.default.svc
namespace: myapp-staging
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
工作流:
开发者修改应用代码,CI 构建镜像并推送到镜像仓库。
在 Git 配置 meimanke.cn 仓库中更新 kustomization.yaml 或 values.yaml 中的镜像 Tag。
ArgoCD 检测到 Git 变更(每 3 分钟或通过 Webhook),自动同步到 Kubernetes 集群。
三、Jenkins Pipeline 示例(Declarative Pipeline)
Jenkins 仍是广泛使用的 CI/CD 工具,尤其适合复杂的企业环境。
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'registry.example.com'
APP_NAME = 'order-service'
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Build') {
steps {
sh 'mvn clean package'
}
}
stage('Test') {
parallel {
stage('Unit Tests') {
steps { sh 'mvn test' }
}
stage('Integration Tests') {
steps { sh 'mvn verify -Pintegration' }
}
}
}
stage('Build Image') {
steps {
script {
docker.build("${DOCKER_REGISTRY}/${APP_NAME}:${env.BUILD_NUMBER}")
}
}
}
stage('Push to Registry') {
steps {
script {
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-credentials') {
docker.image("${DOCKER_REGISTRY}/${APP_NAME}:${env.BUILD_NUMBER}").push()
}
}
}
}
stage('Deploy to Staging') {
steps {
sh "kubectl set image deployment/${APP_NAME} ${APP_NAME}=${DOCKER_REGISTRY}/${APP_NAME}:${env.BUILD_NUMBER} -n staging"
sh "kubectl rollout status deployment/${APP_NAME} -n staging"
}
}
stage('Smoke Test') {
steps {
sh "curl -f https://staging.example.com/health || exit 1"
}
}
stage('Deploy to Production') {
when { branch 'main' }
input { message "Deploy to production?" ok "Deploy" }
steps {
sh "kubectl set image deployment/${APP_NAME} ${APP_NAME}=${DOCKER_REGISTRY}/${APP_NAME}:${env.BUILD_NUMBER} -n prod"
}
}
}
post {
failure {
slackSend channel: '#alerts', message: "Build failed: ${env.JOB_NAME} - ${env.BUILD_URL}"
}
}
}
四、数据库变更的持续交付
处理数据库迁移(Schema changes)是 CD 中的难点。推荐使用 Flyway 或 Liquibase,将迁移脚本与应用版本绑定。
Flyway 集成到 Spring Boot:
-- src/main/resources/db/migration/V1__create_order_table.sql
CREATE TABLE orders (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
amount DECIMAL(19,2) NOT NULL,
status VARCHAR(20) NOT NULL,
created_at TIMESTAMP
);
# application.yml
spring:
flyway:
enabled: true
baseline-on-migrate: true
locations: classpath:db/migration
在 CD 流水线中,应用启动前自动执行迁移(或使用独立的 Flyway 容器任务)。