蓝绿部署与金丝雀发布是DevOps实践中两种核心的零停机发布策略。在Kubernetes容器编排环境下,通过Service资源与多版本Deployment的配合,可以实现流量在版本间的精确切换。蓝绿部署适合需要快速回滚的场景,金丝雀发布适合需要渐进式验证的场景。两者结合健康检查与自动回滚机制,能够将发布事故的影响范围控制在最小。
蓝绿部署原理与Kubernetes实现方式
蓝绿部署维护两套完全相同的环境(Blue和Green),任意时刻只有一个环境接收生产流量。发布时将新版本部署到非活动环境,验证通过后通过Service的selector切换流量,旧版本保留作为回滚备份。
Kubernetes中蓝绿部署的实现方式:
# blue-deployment.yaml - 当前生产版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-blue
labels:
app: webapp
version: blue
spec:
replicas: 3
selector:
matchLabels:
app: webapp
version: blue
template:
metadata:
labels:
app: webapp
version: blue
spec:
containers:
- name: webapp
image: registry.yunthe.com/webapp:v1.2
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
# green-deployment.yaml - 新版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-green
labels:
app: webapp
version: green
spec:
replicas: 3
selector:
matchLabels:
app: webapp
version: green
template:
metadata:
labels:
app: webapp
version: green
spec:
containers:
- name: webapp
image: registry.yunthe.com/webapp:v1.3
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Service通过selector指向当前活动版本,切换时只需修改selector中的version标签:
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
selector:
app: webapp
version: blue # 切换到green即完成发布
ports:
- port: 80
targetPort: 8080
# 执行蓝绿切换
kubectl apply -f green-deployment.yaml
# 等待green环境所有Pod就绪
kubectl rollout status deployment/app-green
# 验证green环境(通过临时Service或端口转发)
kubectl port-forward svc/webapp-service-green 8080:80
# 确认无误后切换流量
kubectl patch svc webapp-service -p '{"spec":{"selector":{"version":"green"}}}'
# 如需回滚,切回blue
kubectl patch svc webapp-service -p '{"spec":{"selector":{"version":"blue"}}}'
金丝雀发布的流量分割策略配置
金丝雀发布将新版本逐步暴露给部分用户,通过监控指标判断是否继续扩大流量比例。Kubernetes原生支持通过调整新旧Deployment的副本数实现粗粒度的流量分割。
#!/bin/bash
# 金丝雀发布脚本 - 逐步增加新版本流量比例
NAMESPACE="production"
DEPLOYMENT="webapp"
NEW_VERSION="v1.3"
STAGES=(10 25 50 100)
HEALTH_CHECK_URL="http://webapp-service/health"
for percentage in "${STAGES[@]}"; do
echo "=== 金丝雀阶段: ${percentage}% ==="
TOTAL=10
NEW_REPLICAS=$((TOTAL * percentage / 100))
OLD_REPLICAS=$((TOTAL - NEW_REPLICAS))
kubectl scale deployment/${DEPLOYMENT}-canary --replicas=${NEW_REPLICAS} -n ${NAMESPACE}
kubectl scale deployment/${DEPLOYMENT}-stable --replicas=${OLD_REPLICAS} -n ${NAMESPACE}
kubectl rollout status deployment/${DEPLOYMENT}-canary -n ${NAMESPACE}
echo "观察期 120 秒..."
sleep 120
ERROR_RATE=$(curl -s "${HEALTH_CHECK_URL}/metrics" | grep error_rate | awk '{print $2}')
if (( $(echo "${ERROR_RATE} > 0.05" | bc -l) )); then
echo "错误率 ${ERROR_RATE} 超过阈值,自动回滚"
kubectl scale deployment/${DEPLOYMENT}-canary --replicas=0 -n ${NAMESPACE}
kubectl scale deployment/${DEPLOYMENT}-stable --replicas=${TOTAL} -n ${NAMESPACE}
exit 1
fi
echo "阶段 ${percentage}% 通过,继续下一阶段"
done
echo "金丝雀发布完成"
kubectl delete deployment ${DEPLOYMENT}-stable -n ${NAMESPACE}
kubectl label deployment ${DEPLOYMENT}-canary version=stable -n ${NAMESPACE}
Istio流量管理实现精确灰度
基于副本数的流量分割粒度较粗(最小10%),使用Istio的VirtualService和DestinationRule可以实现1%级别的精确流量控制。
# DestinationRule - 定义两个子集
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: webapp-dr
spec:
host: webapp-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
# VirtualService - 按权重分流
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: webapp-vs
spec:
hosts:
- webapp-service
http:
- route:
- destination:
host: webapp-service
subset: v1
weight: 90
- destination:
host: webapp-service
subset: v2
weight: 10
# 通过kubectl逐步调整流量权重
kubectl patch virtualservice webapp-vs --type='json' -p='[{"op":"replace","path":"/spec/http/0/route/0/weight","value":70},{"op":"replace","path":"/spec/http/0/route/1/weight","value":30}]'
健康检查与自动回滚机制
自动回滚是发布安全的关键保障。Kubernetes的readiness探针在Pod级别提供健康检查,结合Prometheus指标可以实现应用级别的自动回滚。
# Argo Rollouts - 金丝雀自动回滚配置
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: webapp-rollout
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10
- pause: { duration: 2m }
- setWeight: 30
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 5m }
- setWeight: 100
analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: webapp-service
selector:
matchLabels:
app: webapp
template:
spec:
containers:
- name: webapp
image: registry.yunthe.com/webapp:v1.3
readinessProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 3
periodSeconds: 10
---
# AnalysisTemplate - Prometheus成功率分析
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 30s
successCondition: result[0] >= 0.95
failureLimit: 3
provider:
prometheus:
address: http://prometheus:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",code!~"5.."}[1m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}"}[1m]))
当Prometheus查询的请求成功率低于95%且连续3次失败时,Argo Rollouts自动中止金丝雀发布并回滚到稳定版本,无需人工介入。
部署策略选型与生产环境注意事项
蓝绿部署适合版本变更大、需要快速全量回滚的场景;金丝雀发布适合增量变更、需要渐进验证的场景。生产环境中需要注意数据库迁移与部署顺序的配合:Schema变更应保证向后兼容(先加列不加约束、后删旧列),避免新旧版本同时运行时出现兼容性问题。
资源规划方面,蓝绿部署需要2倍于正常运行的资源,金丝雀发布根据灰度比例需要额外10%~50%的资源。在集群资源紧张时,可以通过HPA(水平Pod自动扩缩容)在发布期间临时增加节点,发布完成后缩回。日志和监控在发布期间应切换到DEBUG级别,便于追踪新旧版本的请求链路。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/lan-lyu-bu-shu-yu-jin-si-que-fa-bu-shi-zhan-kubernetes-liu/