Jenkins脚本如何实现灰度发布策略

wen 实用脚本 3

本文目录导读:

Jenkins脚本如何实现灰度发布策略

  1. 基础方案:基于构建参数的手动灰度
  2. 进阶方案:基于负载均衡的流量控制
  3. 高级方案:自动化灰度与金丝雀发布
  4. 通用灰度发布Pipeline模板
  5. 关键实践建议

在Jenkins中实现灰度发布策略,核心思路是控制流量权重分批次滚动更新,以下是几种常见的实现方案,从简单到复杂:

基础方案:基于构建参数的手动灰度

适用于小团队或低频发布场景,通过Jenkins参数化构建控制。

Pipeline脚本示例

pipeline {
    agent any
    parameters {
        choice(name: 'GRAY_STRATEGY', choices: ['全量发布', '10%灰度', '50%灰度', '100%发布'], description: '选择灰度策略')
        string(name: 'GRAY_TAG', defaultValue: 'latest', description: '版本标签')
    }
    stages {
        stage('构建镜像') {
            steps {
                sh "docker build -t myapp:${params.GRAY_TAG} ."
                sh "docker push myapp:${params.GRAY_TAG}"
            }
        }
        stage('灰度部署') {
            steps {
                script {
                    def replicas = 10  // 总实例数
                    def grayReplicas = 0
                    switch(params.GRAY_STRATEGY) {
                        case '10%灰度':
                            grayReplicas = 1
                            break
                        case '50%灰度':
                            grayReplicas = 5
                            break
                        case '100%发布':
                            grayReplicas = replicas
                            break
                        default:
                            grayReplicas = 0
                    }
                    // 使用Kubernetes部署示例
                    sh """
                    kubectl set image deployment/myapp-stable myapp=myapp:${params.GRAY_TAG} --record
                    kubectl scale deployment/myapp-stable --replicas=${replicas - grayReplicas}
                    kubectl scale deployment/myapp-gray --replicas=${grayReplicas}
                    """
                }
            }
        }
        stage('观察与回滚') {
            steps {
                input message: '灰度验证通过?', ok: '继续发布', 
                      submitterParameter: 'APPROVER'
                // 验证通过后全量发布
                sh "kubectl set image deployment/myapp-stable myapp=myapp:${params.GRAY_TAG}"
                sh "kubectl scale deployment/myapp-gray --replicas=0"
            }
        }
    }
}

进阶方案:基于负载均衡的流量控制

适用于微服务架构,使用网关或Service Mesh实现精确流量控制。

Nginx/Ingress权重配置

pipeline {
    agent any
    environment {
        REGISTRY = 'myregistry.com'
        PROJECT = 'myapp'
    }
    parameters {
        string(name: 'VERSION', defaultValue: '', description: '新版本号')
        string(name: 'GRAY_PERCENT', defaultValue: '10', description: '灰度百分比')
    }
    stages {
        stage('部署灰度版本') {
            steps {
                script {
                    // 部署灰度版本到指定组
                    sh """
                    kubectl apply -f k8s/deployment-gray.yaml
                    kubectl set image deployment/myapp-gray myapp=${REGISTRY}/${PROJECT}:${VERSION}
                    """
                }
            }
        }
        stage('更新流量权重') {
            steps {
                script {
                    // 更新Nginx配置或ALB权重
                    def grayWeight = params.GRAY_PERCENT.toInteger()
                    def stableWeight = 100 - grayWeight
                    sh """
                    # 更新Service Mesh配置
                    kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
  - myapp
  http:
  - route:
    - destination:
        host: myapp-stable
        subset: stable
      weight: ${stableWeight}
    - destination:
        host: myapp-gray
        subset: gray
      weight: ${grayWeight}
EOF
                    """
                }
            }
        }
        stage('灰度验证') {
            steps {
                timeout(time: 30, unit: 'MINUTES') {
                    input message: '灰度验证通过?', ok: '继续全量发布'
                }
            }
        }
        stage('全量发布') {
            steps {
                script {
                    sh """
                    # 将稳定版本更新为新版本
                    kubectl set image deployment/myapp-stable myapp=${REGISTRY}/${PROJECT}:${VERSION}
                    # 逐步增加权重
                    kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
  - myapp
  http:
  - route:
    - destination:
        host: myapp-stable
        subset: stable
      weight: 100
    - destination:
        host: myapp-gray
        subset: gray
      weight: 0
EOF
                    # 清理灰度版本
                    kubectl delete deployment myapp-gray
                    """
                }
            }
        }
    }
}

高级方案:自动化灰度与金丝雀发布

使用Jenkins + Spinnaker/ArgoCD实现自动化灰度。

基于Prometheus监控的自动化灰度

pipeline {
    agent any
    parameters {
        string(name: 'VERSION', defaultValue: '', description: '版本号')
        string(name: 'MONITOR_DURATION', defaultValue: '5', description: '监控观察时间(分钟)')
        string(name: 'ERROR_THRESHOLD', defaultValue: '0.1', description: '错误率阈值(%)')
    }
    stages {
        stage('金丝雀部署') {
            steps {
                script {
                    // 1. 部署1个金丝雀实例
                    sh "kubectl scale deployment/myapp-canary --replicas=1"
                    sh "kubectl set image deployment/myapp-canary myapp=${REGISTRY}/${PROJECT}:${VERSION}"
                    // 2. 配置5%流量到金丝雀
                    sh "kubectl apply -f canary-weight-5.yaml"
                }
            }
        }
        stage('监控与评估') {
            steps {
                script {
                    // 等待并检查指标
                    def duration = params.MONITOR_DURATION.toInteger()
                    sleep time: duration, unit: 'MINUTES'
                    // 查询Prometheus
                    def errorRate = sh(script: """
                        curl -s "http://prometheus:9090/api/v1/query?query=sum(rate(http_requests_total{status=~'5..',app='myapp'}[5m]))/sum(rate(http_requests_total{app='myapp'}[5m]))*100" | jq -r '.data.result[0].value[1]'
                    """, returnStdout: true).trim()
                    if (errorRate.toDouble() > params.ERROR_THRESHOLD.toDouble()) {
                        error "错误率过高(${errorRate}%),自动回滚!"
                    }
                }
            }
        }
        stage('逐步扩大灰度') {
            steps {
                script {
                    // 逐步增加实例和流量
                    def stages = [
                        [replicas: 3, weight: 20],
                        [replicas: 5, weight: 50],
                        [replicas: 8, weight: 80],
                    ]
                    for (stage in stages) {
                        sh """
                        kubectl scale deployment/myapp-canary --replicas=${stage.replicas}
                        kubectl apply -f canary-weight-${stage.weight}.yaml
                        """
                        // 每次扩量后等待并验证
                        sleep 2
                        verifyMetrics()
                    }
                }
            }
        }
    }
}
def verifyMetrics() {
    // 健康检查逻辑
    sh "curl -sf http://myapp/health || exit 1"
}

通用灰度发布Pipeline模板

一个适用于大多数场景的模板:

pipeline {
    agent any
    parameters {
        string(name: 'VERSION', defaultValue: '', description: '新版本号')
        choice(name: 'GRAY_TYPE', choices: ['实例灰度', '流量灰度', 'AB测试'], description: '灰度类型')
        string(name: 'GRAY_PERCENT', defaultValue: '10', description: '灰度比例(1-100)')
        string(name: 'OBSERVE_TIME', defaultValue: '30', description: '观察时间(分钟)')
    }
    stages {
        stage('构建') {
            steps {
                echo "构建版本: ${VERSION}"
            }
        }
        stage('部署') {
            steps {
                script {
                    switch(params.GRAY_TYPE) {
                        case '实例灰度':
                            // 实例级灰度
                            grayByInstance()
                            break
                        case '流量灰度':
                            // 流量级灰度
                            grayByTraffic()
                            break
                        case 'AB测试':
                            // A/B测试
                            grayByABTest()
                            break
                    }
                }
            }
        }
        stage('验证与观察') {
            steps {
                timeout(time: params.OBSERVE_TIME.toInteger(), unit: 'MINUTES') {
                    input message: "灰度验证通过?\n新版本: ${VERSION}\n灰度比例: ${GRAY_PERCENT}%", 
                          ok: '全量发布', 
                          submitterParameter: 'APPROVER'
                }
            }
        }
        stage('全量发布') {
            steps {
                script {
                    // 全量更新
                    fullRelease()
                }
            }
        }
    }
    post {
        failure {
            // 失败自动回滚
            rollback()
        }
    }
}
def grayByInstance() {
    // 实例灰度实现
    sh """
    kubectl set image deployment/myapp-stable myapp=${REGISTRY}/${PROJECT}:${VERSION}
    kubectl scale deployment/myapp-stable --replicas=${10 - (10 * ${GRAY_PERCENT} / 100).toInteger()}
    kubectl scale deployment/myapp-gray --replicas=${(10 * ${GRAY_PERCENT} / 100).toInteger()}
    """
}
def grayByTraffic() {
    // 流量灰度实现
    sh """
    kubectl apply -f k8s/service-weight-config.yaml
    kubectl patch svc myapp -p '{"spec":{"trafficPolicy":{"loadBalancer":{"weight":{\"stable\":$((100-${GRAY_PERCENT})),\"gray\":${GRAY_PERCENT}}}}}}'
    """
}
def grayByABTest() {
    // AB测试实现
    sh """
    kubectl apply -f abtest/myapp-v2-deployment.yaml
    kubectl apply -f abtest/myapp-ab-route.yaml
    """
}
def fullRelease() {
    // 全量发布
    sh """
    kubectl set image deployment/myapp-stable myapp=${REGISTRY}/${PROJECT}:${VERSION}
    kubectl scale deployment/myapp-gray --replicas=0
    """
}
def rollback() {
    // 回滚逻辑
    sh """
    kubectl set image deployment/myapp-stable myapp=${REGISTRY}/${PROJECT}:${env.OLD_VERSION}
    kubectl scale deployment/myapp-gray --replicas=0
    """
}

关键实践建议

灰度策略选择矩阵

场景 推荐方案 实现难度
单体应用 实例灰度
微服务 流量灰度 + Service Mesh
前端应用 路由灰度
核心业务 全自动金丝雀

安全措施

  1. 自动回滚条件

    def autoRollbackIf(condition) {
        if (condition) {
            currentBuild.result = 'UNSTABLE'
            error "触发自动回滚: ${condition}"
        }
    }
  2. 健康检查

    stage('健康检查') {
        steps {
            retry(3) {
                sh "curl -sf --max-time 5 http://gray-service/health || exit 1"
            }
        }
    }
  3. 操作审计

    post {
        always {
            sh """
            echo "[$(date)] 发布记录: VERSION=${VERSION}, USER=${BUILD_USER}, RESULT=${currentBuild.result}" >> /var/log/deploy.log
            """
        }
    }

Jenkins配置建议

  1. 安装插件

    • Pipeline: Stage View
    • Build Timeout
    • Build Failure Analyzer
    • Kubernetes CLI Plugin
    • HTTP Request Plugin
  2. 参数化构建

    properties([
        parameters([
            string(name: 'VERSION', defaultValue: ''),
            choice(name: 'ENV', choices: ['dev', 'test', 'prod']),
            booleanParam(name: 'DRY_RUN', defaultValue: false)
        ])
    ])

通过以上方案,可以根据团队成熟度和业务需求选择合适的灰度发布实现,建议从简单的实例灰度开始,逐步演进到自动化的金丝雀发布。

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