本文目录导读:

在Jenkins中实现滚动更新策略,通常需要结合Kubernetes、Docker Swarm或自定义脚本来完成,以下是几种常见场景的实现方式:
Kubernetes 滚动更新(最推荐)
如果你的应用部署在Kubernetes上,Jenkins可以通过kubectl命令直接触发滚动更新。
Pipeline示例:
pipeline {
agent any
environment {
K8S_NAMESPACE = 'production'
DEPLOYMENT_NAME = 'my-app'
IMAGE_TAG = "${BUILD_NUMBER}"
REGISTRY = 'myregistry.com'
}
stages {
stage('构建镜像') {
steps {
sh "docker build -t ${REGISTRY}/${DEPLOYMENT_NAME}:${IMAGE_TAG} ."
sh "docker push ${REGISTRY}/${DEPLOYMENT_NAME}:${IMAGE_TAG}"
}
}
stage('滚动更新部署') {
steps {
sh """
kubectl set image deployment/${DEPLOYMENT_NAME} \
${DEPLOYMENT_NAME}=${REGISTRY}/${DEPLOYMENT_NAME}:${IMAGE_TAG} \
--namespace=${K8S_NAMESPACE} \
--record
"""
// 监控滚动更新状态
sh "kubectl rollout status deployment/${DEPLOYMENT_NAME} --namespace=${K8S_NAMESPACE}"
}
}
stage('验证部署') {
steps {
sh "kubectl rollout history deployment/${DEPLOYMENT_NAME} --namespace=${K8S_NAMESPACE}"
}
}
}
}
配置Kubernetes滚动更新策略:
# deployment.yaml
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 可超出副本数的最大实例数
maxUnavailable: 0 # 最大不可用实例数(0表示无中断更新)
template:
spec:
containers:
- name: my-app
image: myregistry.com/my-app:latest
Docker Swarm 滚动更新
如果使用Docker Swarm管理容器,Jenkins可以执行服务更新命令。
Pipeline示例:
pipeline {
agent any
environment {
STACK_NAME = 'my-stack'
SERVICE_NAME = 'web'
IMAGE_TAG = "${BUILD_NUMBER}"
DOCKER_REGISTRY = 'myregistry.com'
}
stages {
stage('构建镜像') {
steps {
sh "docker build -t ${DOCKER_REGISTRY}/${SERVICE_NAME}:${IMAGE_TAG} ."
sh "docker push ${DOCKER_REGISTRY}/${SERVICE_NAME}:${IMAGE_TAG}"
}
}
stage('滚动更新服务') {
steps {
sh """
docker service update \
--image ${DOCKER_REGISTRY}/${SERVICE_NAME}:${IMAGE_TAG} \
--update-parallelism 2 \
--update-delay 10s \
--update-order start-first \
${STACK_NAME}_${SERVICE_NAME}
"""
// 等待更新完成
sh "docker service ps ${STACK_NAME}_${SERVICE_NAME}"
}
}
}
}
自定义滚动更新脚本(负载均衡器模式)
如果使用Nginx、HAProxy等负载均衡器,可以实现自定义的滚动更新逻辑。
自定义Shell脚本方式:
pipeline {
agent any
stages {
stage('滚动更新') {
steps {
script {
def servers = ['server1', 'server2', 'server3']
def upstream = 'backend_servers'
servers.each { server ->
// 1. 从负载均衡器中移除节点
sh "ansible-playbook remove-from-upstream.yml -e server=${server}"
// 2. 等待连接耗尽
sleep(time: 10, unit: 'SECONDS')
// 3. 更新节点上的应用
sh "ansible-playbook deploy-app.yml -e server=${server} -e version=${BUILD_NUMBER}"
// 4. 健康检查
sh "curl -f http://${server}:8080/health"
// 5. 重新加入负载均衡器
sh "ansible-playbook add-to-upstream.yml -e server=${server}"
// 6. 等待负载均衡器收敛
sleep(time: 5, unit: 'SECONDS')
}
}
}
}
}
}
完整的Jenkins Pipeline高级示例
结合多个组件和错误处理的完整示例:
pipeline {
agent any
parameters {
string(name: 'ROLLBACK_ON_FAILURE', defaultValue: 'true',
description: '失败时自动回滚')
choice(name: 'UPDATE_PARALLELISM',
choices: ['1', '2', '3', '4'],
description: '并行更新实例数')
}
environment {
KUBE_CONFIG = credentials('kubernetes-cluster-config')
DOCKER_REGISTRY = 'myregistry.com'
PROJECT_NAME = 'my-app'
NAMESPACE = 'production'
}
stages {
stage('安全检查') {
steps {
script {
// 检查部署是否存在
def deploymentExists = sh(
script: "kubectl get deployment ${PROJECT_NAME} -n ${NAMESPACE} --no-headers",
returnStatus: true
) == 0
if (!deploymentExists) {
error "部署 ${PROJECT_NAME} 在namespace ${NAMESPACE}中不存在"
}
}
}
}
stage('构建与测试') {
parallel {
stage('单元测试') {
steps {
sh 'npm test'
}
}
stage('构建镜像') {
steps {
sh """
docker build -t ${DOCKER_REGISTRY}/${PROJECT_NAME}:${BUILD_NUMBER} .
docker push ${DOCKER_REGISTRY}/${PROJECT_NAME}:${BUILD_NUMBER}
"""
}
}
}
}
stage('滚动更新') {
steps {
script {
try {
// 设置滚动更新参数
sh """
kubectl set image deployment/${PROJECT_NAME} \
${PROJECT_NAME}=${DOCKER_REGISTRY}/${PROJECT_NAME}:${BUILD_NUMBER} \
-n ${NAMESPACE} \
--record
"""
// 监控滚动更新(带超时)
timeout(time: 30, unit: 'MINUTES') {
sh "kubectl rollout status deployment/${PROJECT_NAME} -n ${NAMESPACE}"
}
// 验证新版本
def newReplicas = sh(
script: "kubectl get deployment ${PROJECT_NAME} -n ${NAMESPACE} -o jsonpath='{.spec.replicas}'",
returnStdout: true
).trim()
if (!newReplicas || newReplicas.toInteger() < 1) {
error "部署后副本数为0,滚动更新可能失败"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
if (params.ROLLBACK_ON_FAILURE == 'true') {
echo "滚动更新失败,执行回滚..."
// 回滚到上一个版本
sh "kubectl rollout undo deployment/${PROJECT_NAME} -n ${NAMESPACE}"
// 等待回滚完成
sh "kubectl rollout status deployment/${PROJECT_NAME} -n ${NAMESPACE}"
// 发送告警
emailext(
to: 'team@company.com',
subject: "🚨 滚动更新失败,已自动回滚 - ${PROJECT_NAME} #${BUILD_NUMBER}",
body: "错误: ${e.message}\nJob URL: ${env.BUILD_URL}"
)
}
throw e
}
}
}
}
stage('集成测试') {
steps {
sh """
# 执行自动化集成测试
./run-integration-tests.sh ${BUILD_NUMBER}
"""
}
}
stage('性能验证') {
steps {
script {
// 检查新Pod的CPU/内存使用情况
def cpuUsage = sh(
script: "kubectl top pods -n ${NAMESPACE} -l app=${PROJECT_NAME} --no-headers | awk '{print \$3}'",
returnStdout: true
).trim()
echo "新Pod CPU使用率: ${cpuUsage}"
}
}
}
}
post {
success {
echo "滚动更新成功完成!"
// 清理旧镜像(保留最近5个版本)
sh """
docker images ${DOCKER_REGISTRY}/${PROJECT_NAME} \
--format '{{.ID}} {{.Tag}}' | \
sort -k2 -rn | \
awk 'NR>5 {print \$1}' | \
xargs -r docker rmi
"""
}
failure {
echo "滚动更新失败,请检查日志"
}
always {
// 清理工作空间
cleanWs()
}
}
}
关键配置说明
Kubernetes滚动更新参数:
- maxSurge: 滚动更新期间可以超出预期副本数的最大实例数(百分比或绝对数)
- maxUnavailable: 滚动更新期间最大不可用实例数(百分比或绝对数)
- minReadySeconds: 新Pod被视为可用前的最小运行时间
最佳实践:
- 使用Blue/Green或Canary策略:对于敏感应用,考虑先部署少量新版本验证
- 设置合理的超时时间:避免滚动更新无限等待
- 自动回滚机制:失败时自动回滚到上一个稳定版本
- 健康检查:确保应用有正确的readiness和liveness探针
- 渐进式更新:通过
parallelism和delay控制更新速度
选择哪种实现方式主要取决于你的基础设施,Kubernetes是当前最主流的容器编排平台,强烈推荐使用它的内置滚动更新机制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播