← 返回首页
🔄

零停机部署策略

📂 devops ⏱ 2 min 360 words

零停机部署策略

部署策略对比

策略 停机时间 风险 复杂度
滚动更新
蓝绿部署
金丝雀发布
A/B测试

Kubernetes滚动更新

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # 最多多出1个Pod
      maxUnavailable: 0  # 不允许不可用
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: myapp
          image: myapp:v2
          lifecycle:
            preStop:
              exec:
                command: ["/bin/sh", "-c", "sleep 15"]

蓝绿部署

# 蓝色版本(当前)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: blue
  template:
    metadata:
      labels:
        app: myapp
        version: blue
    spec:
      containers:
        - name: myapp
          image: myapp:v1

---
# 绿色版本(新)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: green
  template:
    metadata:
      labels:
        app: myapp
        version: green
    spec:
      containers:
        - name: myapp
          image: myapp:v2

---
# 服务
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
    version: blue  # 切换到green进行部署
  ports:
    - port: 80
      targetPort: 8080

切换脚本

#!/bin/bash

CURRENT_VERSION=$1
NEW_VERSION=$2

echo "切换从 $CURRENT_VERSION 到 $NEW_VERSION"

# 更新Service
kubectl patch service myapp -p "{\"spec\":{\"selector\":{\"version\":\"$NEW_VERSION\"}}}"

# 等待新版本就绪
kubectl rollout status deployment/myapp-$NEW_VERSION

# 验证健康
kubectl exec -it deploy/myapp-$NEW_VERSION -- curl -f http://localhost:8080/health

# 如果失败,回滚
if [ $? -ne 0 ]; then
    echo "健康检查失败,回滚..."
    kubectl patch service myapp -p "{\"spec\":{\"selector\":{\"version\":\"$CURRENT_VERSION\"}}}"
fi

金丝雀发布

# Istio金丝雀配置
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
    - myapp
  http:
    - route:
        - destination:
            host: myapp
            subset: v1
          weight: 90
        - destination:
            host: myapp
            subset: v2
          weight: 10

---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: myapp
spec:
  host: myapp
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2

实践:Flagger金丝雀

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: myapp
  namespace: production
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  progressDeadlineSeconds: 600
  service:
    port: 80
    targetPort: 8080
  analysis:
    interval: 1m
    threshold: 5
    maxWeight: 50
    stepWeight: 10
    metrics:
      - name: request-success-rate
        thresholdRange:
          min: 99
        interval: 1m
      - name: request-duration
        thresholdRange:
          max: 500
        interval: 30s
    webhooks:
      - name: load-test
        url: http://flagger-loadtester.test/
        timeout: 5s
        metadata:
          type: cmd
          cmd: "hey -z 1m -q 10 -c 2 http://myapp-canary.test/"

优雅终止

# Python示例
import signal
import sys
from flask import Flask

app = Flask(__name__)

def shutdown(signum, frame):
    # 完成正在处理的请求
    # 关闭数据库连接
    # 通知负载均衡器
    sys.exit(0)

signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)

@app.route('/healthz')
def healthz():
    return 'OK', 200

最佳实践

  1. 配置健康检查
  2. 实现优雅终止
  3. 渐进式发布
  4. 监控关键指标
  5. 准备回滚方案

总结

零停机部署是现代应用的必备能力。通过滚动更新、蓝绿部署和金丝雀发布等策略,可以实现安全、可靠的应用更新。