正在加载,请稍候…

Kubernetes Deployment Strategies: Rolling, Blue-Green, and Canary

Implement production deployment strategies in Kubernetes — rolling updates, blue-green deployments, canary releases with Argo Rollouts, and traffic shifting with Istio.

Kubernetes Deployment Strategies

Choosing the right deployment strategy balances risk, speed, and complexity.

Rolling Update (Default)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 6
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2           # Max pods above desired during update
      maxUnavailable: 1     # Max pods unavailable during update
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: myapp/api:v2
          readinessProbe:
            httpGet:
              path: /health/ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5
            failureThreshold: 3
          livenessProbe:
            httpGet:
              path: /health/live
              port: 3000
            initialDelaySeconds: 15
            periodSeconds: 20
      terminationGracePeriodSeconds: 30  # Let requests finish
# Perform rolling update
kubectl set image deployment/api api=myapp/api:v2

# Monitor rollout
kubectl rollout status deployment/api

# Rollback if needed
kubectl rollout undo deployment/api
kubectl rollout undo deployment/api --to-revision=2

Blue-Green Deployment

# Blue (current production)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-blue
spec:
  replicas: 5
  selector:
    matchLabels:
      app: api
      version: blue

---
# Green (new version)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-green
spec:
  replicas: 5
  selector:
    matchLabels:
      app: api
      version: green

---
# Service points to blue initially
apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
    version: blue  # Change to "green" to switch traffic
  ports:
    - port: 80
      targetPort: 3000
# Switch all traffic to green
kubectl patch service api -p '{"spec":{"selector":{"version":"green"}}}'

# Verify green is working
kubectl get pods -l version=green

# Scale down blue after confirming green is stable
kubectl scale deployment api-blue --replicas=0

# Or delete blue entirely
kubectl delete deployment api-blue

Canary with Argo Rollouts

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: api
spec:
  replicas: 10
  strategy:
    canary:
      steps:
        - setWeight: 10    # 10% traffic to canary
        - pause: { duration: 5m }
        - setWeight: 30
        - pause: { duration: 10m }
        - analysis:
            templates:
              - templateName: success-rate
        - setWeight: 60
        - pause: { duration: 10m }
        - setWeight: 100
      canaryMetadata:
        labels:
          version: canary
      stableMetadata:
        labels:
          version: stable
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: myapp/api:v2

---
# Analysis template for automated promotion
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  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{job="api",status!~"5.."}[5m]))
            /
            sum(rate(http_requests_total{job="api"}[5m]))

PodDisruptionBudget

# Ensure minimum availability during voluntary disruptions
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  minAvailable: 4    # Always keep 4 pods running
  selector:
    matchLabels:
      app: api

Health Checks That Matter

// Liveness vs Readiness vs Startup probes
app.get('/health/live', (req, res) => {
  // Liveness: is the process alive? (restart if fails)
  res.json({ status: 'alive' })
})

app.get('/health/ready', async (req, res) => {
  // Readiness: can it serve traffic? (remove from LB if fails)
  try {
    await db.query('SELECT 1')
    await redis.ping()
    res.json({ status: 'ready' })
  } catch (err) {
    res.status(503).json({ status: 'not ready', reason: err.message })
  }
})

app.get('/health/startup', (req, res) => {
  // Startup: is initialization complete? (only during startup)
  if (appStarted) {
    res.json({ status: 'started' })
  } else {
    res.status(503).json({ status: 'starting' })
  }
})