温馨提示×

centos jenkins蓝绿部署策略

小樊
57
2026-01-08 05:10:04
栏目: 智能运维

CentOS 下基于 Jenkins 的蓝绿部署落地方案

一 架构与前置条件

  • 架构要点:准备两套完全一致的生产环境,分别为Blue/Green;通过一个负载均衡器(Nginx/HAProxy/硬件LB)统一入口;上线时先部署非活跃色,完成健康检查后一次性切换流量,异常则立即切回,实现快速回滚用户无感。蓝绿部署的优势是切换/回滚快、验证充分;代价是需要约两倍资源并在切换窗口内存在资源闲置。

  • 基础环境(CentOS 7/8 建议):

    • 安装 Java 11JenkinsGit、(可选)Docker;Jenkins 建议使用 YUM 安装并配置开机自启,安装常用插件:GitPipelineSSH、(可选)Docker Pipeline
    • 目标主机(Blue/Green 各一组)与 Nginx/HAProxy 已就绪,应用可通过 systemd/Tomcat 等方式启动;Jenkins 通过 SSHAnsible 推送版本与执行切换。

二 方案一 非容器化实现 Nginx 手动切换

  • 目录与版本管理约定(两台目标机分别属于 Blue/Green):

    • 部署根目录:/opt/app/;版本目录:/opt/app/blue//opt/app/green/;当前发布链接:/opt/app/current(符号链接指向 blue 或 green)。
    • 示例服务:Tomcat 应用包 app.war,分别发布到对应版本目录后由 current 指向生效版本。
  • Nginx 负载均衡配置要点(示例):

    • 定义 upstream 指向两个实例(同一台物理机可用不同端口区分,如 8080/8081):
      upstream backend {
          server 10.0.0.11:8080 max_fails=2 fail_timeout=30s;
          server 10.0.0.12:8081 max_fails=2 fail_timeout=30s;
      }
      server {
          listen 80;
          location / {
              proxy_pass http://backend;
              proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              health_check interval=10 uri=/health fails=2 passes=2;
          }
      }
      
    • 如需“原子切换”,可用两个 server 块分别监听 80/8080,通过 iptables DNAT 或 **Nginx 动态 upstream(商业版/OpenResty)**切换;简单做法是将 server_name 指向不同目录后热重载(短时可接受短暂中断)。
  • Jenkins 关键步骤与脚本(Freestyle 或 Pipeline 均可):

    • 参数化构建:选择目标色 DEPLOY_COLOR=blue|green,构建号 BUILD_ID
    • 部署阶段(SSH 到目标机执行):
      #!/usr/bin/env bash
      set -e
      COLOR=$1; BUILD_ID=$2
      APP_DIR=/opt/app
      VERSION_DIR=$APP_DIR/$COLOR
      CURRENT_LINK=$APP_DIR/current
      
      # 1) 停止目标色实例(避免文件占用)
      if systemctl is-active --quiet tomcat; then
        systemctl stop tomcat || true
      fi
      
      # 2) 部署新版本
      rm -rf $VERSION_DIR/*
      cp -r $WORKSPACE/target/*.war $VERSION_DIR/app.war
      # 如有需要可执行数据库迁移(务必可回滚)
      
      # 3) 启动目标色实例
      systemctl start tomcat
      sleep 10
      
      # 4) 健康检查(示例)
      for i in {1..30}; do
        if curl -sf http://localhost:8080/health; then
          echo "Health check OK"; break
        fi
        sleep 5
      done
      
      # 5) 原子切换 current 链接(避免并发写)
      ln -sfn $VERSION_DIR $CURRENT_LINK
      
    • 流量切换:
      • 简单做法:在 Nginx 上为 Blue/Green 各配置一个 server 块(不同端口),通过修改 server_nameiptables 规则将 80 端口流量指向新色实例,然后 nginx -s reload
      • 更平滑:使用支持动态 upstream 的方案(如 Nginx PlusOpenResty balancer_by_lua)实现运行时摘除/接入。
    • 回滚:将 DEPLOY_COLOR 指回旧色,重复“健康检查 + 切换 current/路由”流程,通常可在秒级完成。

三 方案二 容器化实现 Kubernetes 一键切换

  • 思路:为应用准备两套 Deployment(blue/green) 与同一 Service(通过 label selector 选择版本);部署新色后执行 readiness/liveness 探针确认健康,再通过修改 Service 的 selector 一次性切流;失败立即改回旧 selector 完成回滚。
  • 关键资源示例(片段):
    # Deployment: myapp-green
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-green
      labels: {app: myapp, version: green}
    spec:
      replicas: 3
      selector: {matchLabels: {app: myapp, version: green}}
      template:
        metadata: {labels: {app: myapp, version: green}}
        spec:
          containers:
          - name: app
            image: harbor.example.com/ns/myapp:${GIT_COMMIT}
            ports: [{containerPort: 8080}]
            readinessProbe:
              httpGet: {path: /health, port: 8080}
              initialDelaySeconds: 10
              periodSeconds: 5
            livenessProbe:
              httpGet: {path: /health, port: 8080}
              initialDelaySeconds: 20
              periodSeconds: 10
    
    # Service: myapp(统一入口)
    apiVersion: v1
    kind: Service
    metadata:
      name: myapp
    spec:
      selector: {app: myapp, version: blue}   # 初始指向 blue
      ports: [{protocol: TCP, port: 80, targetPort: 8080}]
    
  • Jenkins 流水线关键片段(声明式 Pipeline):
    pipeline {
      agent any
      environment {
        IMAGE = "harbor.example.com/ns/myapp:${env.GIT_COMMIT}"
        K8S_NS = "prod"
      }
      stages {
        stage('Build & Push') {
          steps {
            sh 'docker build -t $IMAGE .'
            sh 'docker push $IMAGE'
          }
        }
        stage('Deploy Green') {
          steps {
            script {
              sh """
                kubectl -n $K8S_NS apply -f k8s/deploy-green.yaml
                kubectl -n $K8S_NS rollout status deploy/myapp-green --timeout=300s
              """
            }
          }
        }
        stage('Switch Traffic') {
          steps {
            script {
              // 原子切换:将 Service selector 指向 green
              sh """
                kubectl -n $K8S_NS patch svc myapp \
                  -p '{"spec":{"selector":{"app":"myapp","version":"green"}}}'
              """
              // 可选:观察一段时间后再清理 blue
              // sh "kubectl -n $K8S_NS delete deploy myapp-blue"
            }
          }
        }
      }
      post {
        failure {
          script {
            // 回滚:切回 blue
            sh """
              kubectl -n $K8S_NS patch svc myapp \
                -p '{"spec":{"selector":{"app":"myapp","version":"blue"}}}'
            """
          }
        }
      }
    }
    
  • 说明:Kubernetes 原生 Service 切换是“原子级”的;如需渐进式切流(如先 10%→50%→100%),可引入 Istio/VirtualServiceNginx Ingress 权重路由。

四 健康检查 回滚与风险控制

  • 健康检查:为应用提供 /health/actuator/health 端点,包含对下游依赖(数据库、缓存、消息队列)的可用性探测;在切换前必须连续通过多次探测,避免把故障引入生产。
  • 自动化回滚:
    • 非容器化:Jenkins 捕获健康检查失败即执行“切换 current 回旧色 + 重启旧色实例”;必要时保留最近 N 个版本包以便快速回滚。
    • Kubernetes:切换后持续观察 readiness/liveness 与业务指标;失败即执行“patch Service 改回旧版本 selector”,并保留旧 ReplicaSet 以便快速回滚。
  • 数据与配置治理:
    • 数据库迁移需可回滚(如双写、版本化迁移、回滚脚本);配置隔离(按环境/版本管理),避免切换时误用错误配置。
    • 有状态服务需保证会话亲和(如 Nginx ip_hash/会话粘滞)或在无状态化前提下避免会话依赖;必要时在切换前预热缓存
  • 发布窗口与监控:选择低峰时段发布;上线后密集监控错误率、延迟、CPU/内存、下游依赖成功率;保留 Blue 作为热备一段时间再下线,降低风险。

0