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 的日志定位流程。