18.3.6 失败处理、回滚与质量门禁策略

失败处理、回滚与质量门禁策略#

失败处理原则与阶段化策略#

  • 快速失败(Fail Fast):在代码检查、单元测试、静态扫描阶段尽早失败,减少资源浪费。
  • 分层隔离:构建、测试、发布分离,失败时仅影响当前阶段并记录上下文。
  • 可恢复性:流水线具备重试能力、幂等脚本与自动清理机制,避免“半成功”状态。

原理草图(失败处理与门禁路径)

文章图片

常用失败处理机制#

  • 重试与超时:对不稳定步骤设置重试与超时控制。
  • 错误捕获与继续执行:使用 catchErrorunstable 将非关键错误标记为不稳定而非直接失败。
  • 构建中断与终止条件:设置手动中止与质量门禁不通过的自动终止。
  • 通知与可观测性:失败时记录详细日志、归档制品与测试报告,触发告警。

Jenkinsfile 示例(失败处理与超时/重试)

// Jenkinsfile
pipeline {
  agent any
  options {
    timeout(time: 30, unit: 'MINUTES')
    buildDiscarder(logRotator(numToKeepStr: '20'))
  }
  stages {
    stage('Checkout') {
      steps {
        checkout scm
      }
    }
    stage('Build') {
      steps {
        retry(2) {
          sh 'mvn -B -DskipTests clean package'
        }
      }
    }
    stage('UnitTest') {
      steps {
        catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') {
          sh 'mvn -B test'
        }
        junit 'target/surefire-reports/*.xml'
      }
    }
    stage('QualityGate') {
      steps {
        timeout(time: 5, unit: 'MINUTES') {
          sh './ci/check_quality_gate.sh'
        }
      }
    }
  }
  post {
    failure {
      archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
      mail to: 'ops@example.com', subject: "Build Failed: ${env.JOB_NAME}",
           body: "See ${env.BUILD_URL}"
    }
    unstable {
      echo 'Build marked UNSTABLE, please review reports.'
    }
  }
}

关键命令解释

# Maven 构建:-B 非交互模式,-DskipTests 跳过测试
mvn -B -DskipTests clean package

# Jenkins 测试报告归档
# 需要 Surefire 输出 XML 到 target/surefire-reports

回滚策略设计#

  • 回滚触发条件:部署失败、健康检查异常、质量门禁不通过、关键指标退化。
  • 回滚方式
  • 版本回滚:回退到上一稳定制品(制品库保留最近 N 个可用版本)。
  • 配置回滚:通过 Git 版本控制回退配置变更。
  • 蓝绿/金丝雀回滚:通过流量切换恢复到旧版本。
  • 回滚步骤标准化:回滚前检查、回滚后验证、回滚结果通知。

示例:Kubernetes 回滚

# 查看历史版本
kubectl rollout history deployment/myapp -n prod

# 回滚到上一版本
kubectl rollout undo deployment/myapp -n prod

# 回滚到指定版本
kubectl rollout undo deployment/myapp --to-revision=3 -n prod

# 验证状态
kubectl rollout status deployment/myapp -n prod
kubectl get pods -n prod -l app=myapp

示例:Docker 回滚(基于制品标签)

# 拉取上一稳定版本
docker pull registry.example.com/myapp:1.2.3

# 停止当前容器并替换
docker stop myapp && docker rm myapp
docker run -d --name myapp -p 8080:8080 registry.example.com/myapp:1.2.3

示例:Nginx 蓝绿切换回滚

# upstream 切换回旧版本
cat >/etc/nginx/conf.d/upstream.conf <<'EOF'
upstream app_backend {
  server 10.0.0.11:8080; # old
  server 10.0.0.12:8080; # old
}
EOF

# 检查并重载
nginx -t && systemctl reload nginx

质量门禁策略#

  • 静态代码扫描:SonarQube 等工具设置阈值(覆盖率、漏洞级别)。
  • 测试质量:单测覆盖率、集成测试通过率、性能基线。
  • 安全合规:依赖漏洞扫描、镜像安全扫描、许可证合规检查。
  • 发布前门禁:在“部署到生产”阶段设置人工审批或自动门禁。

安装示例:SonarQube(Docker)

# 1) 启动 SonarQube
docker run -d --name sonarqube -p 9000:9000 sonarqube:lts

# 2) 访问并生成 Token
# 浏览器访问 http://<host>:9000 生成 token

# 3) 项目扫描(示例为 Java)
mvn -B sonar:sonar \
  -Dsonar.host.url=http://<host>:9000 \
  -Dsonar.login=<TOKEN>

质量门禁脚本示例(与 Jenkins 结合)

# ./ci/check_quality_gate.sh
set -e
SONAR_URL="http://<host>:9000"
PROJECT_KEY="myapp"
TOKEN="<TOKEN>"

# 查询门禁状态
STATUS=$(curl -s -u ${TOKEN}: \
  "${SONAR_URL}/api/qualitygates/project_status?projectKey=${PROJECT_KEY}" \
  | jq -r '.projectStatus.status')

echo "QualityGate: ${STATUS}"
if [ "${STATUS}" != "OK" ]; then
  echo "Quality Gate FAILED"
  exit 1
fi

回滚与门禁落地实践#

  • 流水线阶段示例设计
    1. 构建与制品归档
    2. 单元测试与质量扫描
    3. 部署到测试/预生产
    4. 自动化验证
    5. 质量门禁
    6. 生产发布
    7. 监控与回滚
  • 统一状态管理:失败时更新制品元数据与发布记录,确保追溯。
  • 指标驱动回滚:接入监控告警(CPU、错误率、延迟)触发自动回滚。

流水线片段(质量门禁 + 回滚触发)

stage('Deploy-Prod') {
  steps {
    sh './ci/deploy_prod.sh'
  }
}
stage('Post-Deploy-Check') {
  steps {
    sh './ci/health_check.sh'
  }
}
post {
  failure {
    sh './ci/rollback.sh'
  }
}

示例:健康检查与回滚脚本

# ./ci/health_check.sh
set -e
curl -fsS http://prod.example.com/healthz

# ./ci/rollback.sh
set -e
kubectl rollout undo deployment/myapp -n prod
kubectl rollout status deployment/myapp -n prod

故障排查要点#

  • 门禁一直超时:检查 SonarQube 状态、网络连通、Token 权限。
  • 回滚不生效:核对 Deployment revision、镜像标签是否可用。
  • 流水线卡死:检查 timeout 是否设置、外部依赖是否不可达。
  • 日志缺失:确认 archiveArtifactsjunit 路径是否正确。

排错命令

# Jenkins Agent 网络与端口
curl -I http://<sonar_host>:9000

# 查看 Kubernetes deployment revision
kubectl rollout history deployment/myapp -n prod

# Nginx 配置校验
nginx -t

练习#

  1. 编写 Jenkinsfile,加入 retrytimeout,模拟网络失败并观察结果。
  2. 使用 SonarQube 配置一个覆盖率门禁(如 ≥80%),让一次构建触发门禁失败。
  3. 在 K8s 中部署应用并触发回滚,记录 rollout history 的版本变化。
  4. 配置 Nginx 蓝绿切换,手动回滚并验证 /healthz 返回值。