Jenkins脚本如何实现蓝绿部署策略

wen 实用脚本 3

本文目录导读:

Jenkins脚本如何实现蓝绿部署策略

  1. 基础架构与核心概念
  2. Jenkins Pipeline 实现示例(Kubernetes 环境)
  3. 基于 Nginx 负载均衡的实现
  4. 基于 Docker Compose 的实现
  5. 关键最佳实践
  6. 注意事项

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}"
            )
        }
    }
}

注意事项

  1. 状态管理:确保新环境能够共享会话状态(使用Redis等)
  2. 数据库操作:避免破坏性迁移,保持前后兼容
  3. 监控告警:部署过程中密切监控错误率和响应时间
  4. 超时处理:设置合理的超时时间,避免部署卡死
  5. 资源配置:确保有足够的资源同时运行两套环境

通过上述实现,Jenkins 可以安全地执行蓝绿部署,实现零停机发布和快速回滚。

抱歉,评论功能暂时关闭!