关于 blue-green-deploy
blue-green-deploy 是一项生产系统部署策略技能,涵盖蓝绿、金丝雀、滚动和重建发布,以及健康检查、流量切换和回滚流程。
主要功能
- 01实施蓝绿环境切换
- 02配置金丝雀和滚动发布
- 03在不同部署版本间路由流量
- 04添加健康检查和部署验证
- 05规划自动及手动回滚
适用场景
- 01降低新版本发布的部署风险
- 02逐步将流量导向金丝雀版本
- 03部署失败后切换回旧版本
- 04在发布过程中验证应用健康状态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill blue-green-deploy安装后在 Claude Code 中输入/blue-green-deploy确认已加载。
详细介绍
蓝绿部署与部署策略
为生产系统实现零停机部署模式。
何时使用此技能
在以下情况下使用此技能:
- 实现零停机部署
- 降低部署风险
- 支持即时回滚
- 运行金丝雀发布
- 在生产环境中进行 A/B 测试
前提条件
- 负载均衡器或入口控制器
- 容器编排(K8s)或云平台
- CI/CD 流水线
- 健康检查端点
部署策略概览
┌─────────────────────────────────────────────────────────────┐
│ DEPLOYMENT STRATEGIES │
├─────────────┬─────────────┬─────────────┬──────────────────┤
│ Blue-Green │ Canary │ Rolling │ Recreate │
├─────────────┼─────────────┼─────────────┼──────────────────┤
│ Full env │ Gradual % │ Pod by pod │ All at once │
│ swap │ rollout │ replacement │ │
├─────────────┼─────────────┼─────────────┼──────────────────┤
│ Instant │ Slow, safe │ Moderate │ Fast, risky │
│ rollback │ rollback │ rollback │ │
├─────────────┼─────────────┼─────────────┼──────────────────┤
│ 2x resources│ +10-25% │ Same │ Same │
│ needed │ resources │ resources │ │
└─────────────┴─────────────┴─────────────┴──────────────────┘
蓝绿部署
概念
Before:
┌─────────┐ ┌───────────────┐
│ Users │────▶│ Blue (v1) │ ◀── Active
└─────────┘ └───────────────┘
┌───────────────┐
│ Green (v2) │ ◀── Staging
└───────────────┘
After Switch:
┌─────────┐ ┌───────────────┐
│ Users │ │ Blue (v1) │ ◀── Standby
└─────────┘ └───────────────┘
│ ┌───────────────┐
└────────▶│ Green (v2) │ ◀── Active
└───────────────┘
Kubernetes 实现
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-blue
labels:
app: myapp
version: blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: myapp
image: myapp:v1.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
# green-deployment.yaml
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: myapp
image: myapp:v2.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
# service.yaml - Switch by changing selector
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # Change to 'green' to switch
ports:
- port: 80
targetPort: 8080
切换脚本
#!/bin/bash
# blue-green-switch.sh
CURRENT=$(kubectl get svc myapp -o jsonpath='{.spec.selector.version}')
NEW_VERSION=$1
echo "Current version: $CURRENT"
echo "Switching to: $NEW_VERSION"
# Verify new deployment is ready
kubectl rollout status deployment/myapp-$NEW_VERSION
# Check health
HEALTH=$(kubectl exec -it deployment/myapp-$NEW_VERSION -- curl -s localhost:8080/health)
if [ "$HEALTH" != "ok" ]; then
echo "Health check failed"
exit 1
fi
# Switch traffic
kubectl patch svc myapp -p "{\"spec\":{\"selector\":{\"version\":\"$NEW_VERSION\"}}}"
echo "Switched to $NEW_VERSION"
AWS ECS 蓝绿部署
# AWS CodeDeploy appspec.yml
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "arn:aws:ecs:region:account:task-definition/myapp:2"
LoadBalancerInfo:
ContainerName: "myapp"
ContainerPort: 8080
Hooks:
- BeforeInstall: "LambdaFunctionToValidateBeforeTrafficShift"
- AfterInstall: "LambdaFunctionToValidateAfterTrafficShift"
- AfterAllowTestTraffic: "LambdaFunctionToValidateTestTraffic"
- BeforeAllowTraffic: "LambdaFunctionToValidateBeforeAllowTraffic"
- AfterAllowTraffic: "LambdaFunctionToValidateAfterAllowTraffic"
金丝雀部署
使用 Istio 的 Kubernetes
# VirtualService for traffic splitting
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: myapp
subset: canary
- route:
- destination:
host: myapp
subset: stable
weight: 90
- destination:
host: myapp
subset: canary
weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: stable
labels:
version: stable
- name: canary
labels:
version: canary
Argo Rollouts
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: myapp
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 10
- pause: {duration: 5m}
- setWeight: 25
- pause: {duration: 5m}
- setWeight: 50
- pause: {duration: 5m}
- setWeight: 75
- pause: {duration: 5m}
analysis:
templates:
- templateName: success-rate
startingStep: 2
args:
- name: service-name
value: myapp
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2.0.0
ports:
- containerPort: 8080
---
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 1m
successCondition: result[0] >= 0.95
failureLimit: 3
provider:
prometheus:
address: http://prometheus:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status=~"2.*"}[5m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
滚动部署
Kubernetes 默认配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Max pods above desired
maxUnavailable: 0 # Max pods unavailable
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
滚动更新命令
# Update image
kubectl set image deployment/myapp myapp=myapp:v2.0.0
# Watch rollout
kubectl rollout status deployment/myapp
# Pause rollout
kubectl rollout pause deployment/myapp
# Resume rollout
kubectl rollout resume deployment/myapp
# Rollback
kubectl rollout undo deployment/myapp
# Rollback to specific revision
kubectl rollout undo deployment/myapp --to-revision=2
# View history
kubectl rollout history deployment/myapp
健康检查
综合健康端点
# Flask health endpoint
from flask import Flask, jsonify
import psycopg2
import redis
app = Flask(__name__)
@app.route('/health')
def health():
"""Liveness probe - is the app running?"""
return jsonify({'status': 'healthy'}), 200
@app.route('/ready')
def ready():
"""Readiness probe - can the app serve traffic?"""
checks = {}
# Database check
try:
conn = psycopg2.connect(DATABASE_URL)
conn.close()
checks['database'] = 'ok'
except Exception as e:
checks['database'] = str(e)
return jsonify({'status': 'unhealthy', 'checks': checks}), 503
# Redis check
try:
r = redis.from_url(REDIS_URL)
r.ping()
checks['redis'] = 'ok'
except Exception as e:
checks['redis'] = str(e)
return jsonify({'status': 'unhealthy', 'checks': checks}), 503
return jsonify({'status': 'healthy', 'checks': checks}), 200
回滚流程
自动回滚
#!/bin/bash
# auto-rollback.sh
DEPLOYMENT=$1
THRESHOLD=0.95
INTERVAL=60
echo "Monitoring deployment $DEPLOYMENT"
while true; do
# Get success rate from Prometheus
SUCCESS_RATE=$(curl -s "http://prometheus:9090/api/v1/query?query=sum(rate(http_requests_total{status=~\"2.*\"}[5m]))/sum(rate(http_requests_total[5m]))" | jq -r '.data.result[0].value[1]')
echo "Current success rate: $SUCCESS_RATE"
if (( $(echo "$SUCCESS_RATE < $THRESHOLD" | bc -l) )); then
echo "Success rate below threshold! Rolling back..."
kubectl rollout undo deployment/$DEPLOYMENT
exit 1
fi
sleep $INTERVAL
done
手动回滚检查清单
## Rollback Checklist
### Before Rollback
- [ ] Confirm issue is deployment-related
- [ ] Document current error rates
- [ ] Notify team in #deployments channel
### During Rollback
- [ ] Execute rollback command
- [ ] Monitor rollback progress
- [ ] Verify old version is serving traffic
### After Rollback
- [ ] Confirm error rates normalized
- [ ] Update incident ticket
- [ ] Schedule post-mortem
常见问题
问题:部署缓慢
问题:发布耗时过长 解决方案:增大 maxSurge,减小 minReadySeconds
问题:健康检查失败
问题:Pod 未能就绪 解决方案:检查探针端点,延长超时时间
问题:回滚期间的流量
问题:切换期间出现错误 解决方案:使用连接排空,实现优雅关闭
最佳实践
- 始终实现健康检查
- 使用连接排空
- 定期测试回滚流程
- 在部署期间监控关键指标
- 实现熔断器
- 使用部署槽位/环境
- 自动化部署验证
- 记录回滚流程
相关技能
- kubernetes-ops - K8s 部署基础
- argocd-gitops - GitOps 部署
- feature-flags - 渐进式发布
评论
支持 Markdown