19.7.6 发布自动化与流水线集成

发布自动化与流水线集成是将代码变更从提交到生产部署标准化、可追溯和可回滚的关键环节。核心目标是以流水线为载体,将构建、测试、制品管理、部署与验证进行编排,减少人工操作,提高发布一致性与可靠性。

原理草图与组件关系#

文章图片

流水线设计原则#

  • 可重复:同一版本在任意环境构建结果一致,避免“本地可用、线上不可用”。
  • 可追踪:每次发布对应唯一流水线实例、制品版本与变更记录。
  • 可回滚:部署前后保持可回退路径与配置快照。
  • 可观测:关键阶段有指标与日志,失败快速定位。

关键阶段与命令示例#

1) 代码拉取与依赖锁定#

# 示例:固定依赖版本,减少构建漂移
git clone https://git.example.com/app.git
cd app
git checkout release/v1.2.3
# 预期效果:工作区固定在发布分支

2) 构建与单元测试(Docker化构建)#

# 构建镜像并运行测试
docker build -t registry.example.com/app:1.2.3 -f Dockerfile .
docker run --rm registry.example.com/app:1.2.3 ./gradlew test
# 预期效果:测试通过返回 0,失败流水线中止

3) 质量门禁(示例:依赖漏洞扫描)#

# 以 trivy 为例扫描镜像漏洞
trivy image --exit-code 1 --severity HIGH,CRITICAL \
  registry.example.com/app:1.2.3
# 预期效果:检测到高危漏洞则退出码为 1

4) 制品管理#

# 推送镜像到制品库
docker push registry.example.com/app:1.2.3
# 预期效果:仓库中存在对应 tag

5) 部署与验证(Kubernetes)#

# 使用 Helm 部署
helm upgrade --install app ./charts/app \
  --namespace prod \
  --set image.tag=1.2.3

# 健康检查
kubectl rollout status deploy/app -n prod
kubectl get pods -n prod -l app=app
# 预期效果:rollout 完成,Pods Ready

Jenkins 安装与流水线示例#

安装(Linux)#

# Debian/Ubuntu
sudo apt update
sudo apt install -y openjdk-17-jdk
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | \
  sudo tee /usr/share/keyrings/jenkins-keyring.asc >/dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/ | \
  sudo tee /etc/apt/sources.list.d/jenkins.list >/dev/null
sudo apt update
sudo apt install -y jenkins
sudo systemctl enable --now jenkins
# 预期效果:服务 8080 端口监听

Jenkinsfile 示例(含构建、扫描、部署、回滚)#

pipeline {
  agent any
  environment {
    REGISTRY = "registry.example.com"
    IMAGE = "app"
    TAG = "1.2.3"
    KUBE_NS = "prod"
  }
  stages {
    stage('Checkout') {
      steps { git branch: 'release/v1.2.3', url: 'https://git.example.com/app.git' }
    }
    stage('Build & Test') {
      steps {
        sh "docker build -t ${REGISTRY}/${IMAGE}:${TAG} ."
        sh "docker run --rm ${REGISTRY}/${IMAGE}:${TAG} ./gradlew test"
      }
    }
    stage('Scan') {
      steps { sh "trivy image --exit-code 1 ${REGISTRY}/${IMAGE}:${TAG}" }
    }
    stage('Push') {
      steps { sh "docker push ${REGISTRY}/${IMAGE}:${TAG}" }
    }
    stage('Deploy') {
      steps {
        sh "helm upgrade --install app ./charts/app --namespace ${KUBE_NS} --set image.tag=${TAG}"
        sh "kubectl rollout status deploy/app -n ${KUBE_NS}"
      }
    }
  }
  post {
    failure {
      sh "kubectl rollout undo deploy/app -n ${KUBE_NS} || true"
    }
  }
}

配置与环境解耦示例#

# values-prod.yaml
image:
  repository: registry.example.com/app
  tag: "1.2.3"

env:
  DB_HOST: "mysql.prod.svc.cluster.local"
  REDIS_HOST: "redis.prod.svc.cluster.local"
# 预期效果:发布版本与环境参数分离

部署策略与流水线编排示例#

蓝绿发布(Nginx 切流)#

# /etc/nginx/conf.d/app.conf
upstream app {
  server 10.0.1.10; # blue
  # server 10.0.2.10; # green
}
server {
  listen 80;
  location / { proxy_pass http://app; }
}
# 切换时注释/启用对应后端并 reload
sudo nginx -t && sudo systemctl reload nginx
# 预期效果:流量切到 green 或 blue

灰度发布(K8s 标签)#

kubectl label deploy/app canary=true -n prod
kubectl get deploy -n prod --show-labels
# 预期效果:仅命中带 canary 标签的发布策略

常见排错与处理#

1) 流水线卡在部署阶段

kubectl describe deploy/app -n prod | tail -n 30
kubectl get events -n prod --sort-by=.lastTimestamp | tail -n 20
  • 可能原因:镜像拉取失败、探针不通过、权限不足。

2) 镜像拉取失败

kubectl describe pod <pod-name> -n prod | grep -i image
# 检查镜像仓库凭据
kubectl get secret regcred -n prod -o yaml

3) 健康检查失败导致回滚

kubectl describe pod <pod-name> -n prod | grep -i probe -A3
# 调整探针或应用启动参数

练习#

1) 编写一个包含 Build/Test/Deploy 的 Jenkinsfile,并加入失败回滚逻辑。
2) 使用 Helm 部署应用,修改 values-prod.yaml 进行一次版本升级与回滚。
3) 在 Nginx 中实现蓝绿切流,并记录切流前后的访问结果。
4) 模拟镜像拉取失败,观察 Jenkins 与 K8s 的日志定位流程。