本文目录导读:

Jenkins 实现蓝绿部署策略的核心思想是维护两个完全相同的生产环境(蓝组和绿组),通过流量切换实现零停机发布,以下是几种常见的实现方式:
基础架构与核心概念
- 蓝环境(Blue):当前运行的稳定版本
- 绿环境(Green):新版本部署的目标环境
- 负载均衡器:控制流量转发到蓝或绿环境
Jenkins Pipeline 实现示例(Kubernetes 环境)
pipeline {
agent any
parameters {
choice(name: 'ENVIRONMENT', choices: ['blue', 'green'], description: '部署目标环境')
string(name: 'IMAGE_TAG', defaultValue: 'latest', description: 'Docker镜像标签')
}
environment {
KUBE_CONFIG = credentials('kube-config')
APP_NAME = 'my-app'
NAMESPACE = 'production'
// 自动确定当前活跃环境
ACTIVE_ENV = sh(
script: "kubectl get svc ${APP_NAME} -n ${NAMESPACE} -o jsonpath='{.spec.selector.environment}'",
returnStdout: true
).trim()
}
stages {
stage('Pre-check') {
steps {
script {
// 自动选择部署到非活跃环境
if (params.ENVIRONMENT == 'auto') {
env.DEPLOY_ENV = env.ACTIVE_ENV == 'blue' ? 'green' : 'blue'
} else {
env.DEPLOY_ENV = params.ENVIRONMENT
}
echo "当前活跃环境: ${ACTIVE_ENV}"
echo "目标部署环境: ${DEPLOY_ENV}"
}
}
}
stage('Build & Push Image') {
steps {
script {
docker.build("${APP_NAME}:${IMAGE_TAG}")
docker.withRegistry('https://registry.example.com', 'docker-credentials') {
docker.push("${IMAGE_TAG}")
}
}
}
}
stage('Deploy to Environment') {
steps {
script {
// 部署到目标环境
sh """
kubectl set image deployment/${APP_NAME}-${DEPLOY_ENV} \
-n ${NAMESPACE} \
${APP_NAME}=registry.example.com/${APP_NAME}:${IMAGE_TAG}
kubectl rollout status deployment/${APP_NAME}-${DEPLOY_ENV} \
-n ${NAMESPACE} --timeout=600s
"""
}
}
}
stage('Health Check') {
steps {
script {
// 验证新版本健康状态
sh """
kubectl get pods -n ${NAMESPACE} -l app=${APP_NAME},environment=${DEPLOY_ENV}
"""
// 执行自定义健康检查
sh "curl -f http://${DEPLOY_ENV}-${APP_NAME}.example.com/health"
}
}
}
stage('Switch Traffic') {
when {
expression { return params.ENVIRONMENT != 'auto' || env.DEPLOY_ENV != env.ACTIVE_ENV }
}
steps {
script {
// 切换负载均衡器指向新环境
sh """
kubectl patch svc ${APP_NAME} -n ${NAMESPACE} \
-p '{"spec":{"selector":{"environment":"${DEPLOY_ENV}"}}}'
"""
echo "流量已切换到: ${DEPLOY_ENV}"
}
}
}
stage('Verify Production') {
steps {
script {
// 验证生产环境
sleep(time: 30, unit: 'SECONDS')
sh "curl -f http://${APP_NAME}.example.com/health"
}
}
}
stage('Cleanup Old Version') {
when {
expression { return params.ENVIRONMENT != 'auto' }
}
steps {
script {
// 保留旧版本以备回滚
echo "保留旧版本: ${ACTIVE_ENV}"
sh """
kubectl scale deployment/${APP_NAME}-${ACTIVE_ENV} \
-n ${NAMESPACE} --replicas=0
"""
}
}
}
}
post {
failure {
script {
echo "部署失败,准备回滚..."
// 自动回滚到上一个环境
sh """
kubectl patch svc ${APP_NAME} -n ${NAMESPACE} \
-p '{"spec":{"selector":{"environment":"${ACTIVE_ENV}"}}}'
"""
}
}
}
}
基于 Nginx 负载均衡的实现
pipeline {
agent any
stages {
stage('Deploy to Green') {
steps {
script {
// SSH 到服务器部署到绿色环境
sshCommand remote: webserver, command: """
# 部署到 /var/www/green
rsync -avz ./dist/ /var/www/green/
# 重启服务
systemctl restart my-app-green
"""
}
}
}
stage('Health Check Green') {
steps {
script {
// 检查绿色环境健康状态
def health = httpRequest url: 'http://green.example.com/health'
if (health.status != 200) {
error "Green 环境健康检查失败"
}
}
}
}
stage('Switch Nginx Config') {
steps {
script {
// 更新 Nginx 配置,切换上游服务器
sshCommand remote: nginxServer, script: """
# 备份当前配置
cp /etc/nginx/conf.d/myapp.conf /etc/nginx/conf.d/myapp.conf.bak
# 生成新配置指向绿色环境
cat > /etc/nginx/conf.d/myapp.conf << 'EOF'
upstream myapp {
server green.example.com:8080 weight=1;
server blue.example.com:8080 weight=0; # 保留但不使用
}
server {
listen 80;
location / {
proxy_pass http://myapp;
}
}
EOF
# 测试配置并重载
nginx -t && nginx -s reload
"""
}
}
}
stage('Monitor & Confirm') {
steps {
script {
// 监控一段时间确认稳定
sleep(time: 5, unit: 'MINUTES')
// 检查错误率
// 自动回滚逻辑
}
}
}
}
}
基于 Docker Compose 的实现
pipeline {
agent any
stages {
stage('Prepare Environment') {
steps {
script {
env.COLOR = env.ACTIVE_COLOR == 'blue' ? 'green' : 'blue'
sh "docker-compose -f docker-compose-${COLOR}.yml pull"
}
}
}
stage('Deploy') {
steps {
script {
// 启动新版本
sh "docker-compose -f docker-compose-${COLOR}.yml up -d --scale app=5"
// 等待启动完成
sh "docker-compose -f docker-compose-${COLOR}.yml exec -T app curl --retry 3 http://localhost:8080/health"
}
}
}
stage('Switch') {
steps {
script {
// 使用 HAProxy 或 Nginx 切换
sh """
echo "upstream app { server prod-${COLOR}:8080; }" > /etc/haproxy/haproxy.cfg
service haproxy reload
"""
}
}
}
stage('Cleanup') {
steps {
script {
// 停止旧版本
def oldColor = env.ACTIVE_COLOR
sh "docker-compose -f docker-compose-${oldColor}.yml down"
}
}
}
}
}
关键最佳实践
数据库兼容性
stage('Database Migration') {
steps {
script {
// 确保数据库向后兼容
sh """
# 只在非活跃环境执行迁移
if [ "${DEPLOY_ENV}" == "green" ]; then
flyway migrate -target=next;
fi
"""
}
}
}
灰度测试
stage('Canary Testing') {
steps {
script {
// 先切10%流量测试
sh """
kubectl patch svc ${APP_NAME} -n ${NAMESPACE} \
-p '{"spec":{"selector":{"environment":"${DEPLOY_ENV}"}},"one":"10%"}'
"""
input message: '是否继续全量切换?', ok: '确认'
}
}
}
自动回滚机制
post {
failure {
script {
def previousEnv = env.ACTIVE_ENV
echo "自动回滚到 ${previousEnv}"
// 恢复流量
sh """
kubectl patch svc ${APP_NAME} -n ${NAMESPACE} \
-p '{"spec":{"selector":{"environment":"${previousEnv}"}}}'
"""
// 发送告警
slackSend(
channel: '#devops',
color: 'danger',
message: "蓝绿部署失败,已回滚到 ${previousEnv}"
)
}
}
}
注意事项
- 状态管理:确保新环境能够共享会话状态(使用Redis等)
- 数据库操作:避免破坏性迁移,保持前后兼容
- 监控告警:部署过程中密切监控错误率和响应时间
- 超时处理:设置合理的超时时间,避免部署卡死
- 资源配置:确保有足够的资源同时运行两套环境
通过上述实现,Jenkins 可以安全地执行蓝绿部署,实现零停机发布和快速回滚。