Skip to content

Deployment

概述

Deployment是Kubernetes中用于管理无状态应用的核心对象。它提供了Pod和ReplicaSet的声明式更新,支持滚动更新、回滚、扩缩容等功能。

Deployment核心功能

1. 副本管理

  • 确保指定数量的Pod副本运行
  • 自动替换失败的Pod
  • 支持水平扩缩容

2. 滚动更新

  • 零停机更新应用
  • 控制更新速度和顺序
  • 支持暂停和恢复更新

3. 版本回滚

  • 回滚到历史版本
  • 查看更新历史
  • 手动控制回滚

4. 健康检查

  • 集成Pod探针
  • 自动健康检查
  • 失败Pod自动替换

Deployment配置详解

基本Deployment配置

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

完整Deployment配置

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app-deployment
  namespace: production
  annotations:
    deployment.kubernetes.io/revision: "1"
spec:
  replicas: 5
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600
  minReadySeconds: 30
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  selector:
    matchLabels:
      app: web
      tier: frontend
  template:
    metadata:
      labels:
        app: web
        tier: frontend
      annotations:
        sidecar.istio.io/inject: "false"
    spec:
      serviceAccountName: web-service-account
      containers:
      - name: web
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
        env:
        - name: ENVIRONMENT
          value: "production"
        - name: LOG_LEVEL
          value: "INFO"
        envFrom:
        - configMapRef:
            name: web-config
        - secretRef:
            name: web-secrets
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "256Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
        startupProbe:
          httpGet:
            path: /startup
            port: 80
          failureThreshold: 30
          periodSeconds: 10
        volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/conf.d
        - name: logs-volume
          mountPath: /var/log/nginx
      volumes:
      - name: config-volume
        configMap:
          name: nginx-config
      - name: logs-volume
        emptyDir: {}
      nodeSelector:
        disktype: ssd
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "web"
        effect: "NoSchedule"
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web
              topologyKey: kubernetes.io/hostname

更新策略

1. 滚动更新(RollingUpdate)

yaml
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 25%
    maxUnavailable: 25%

参数说明

  • maxSurge: 更新过程中可以超过期望副本数的最大Pod数量(可以是具体数字或百分比)
  • maxUnavailable: 更新过程中不可用的Pod的最大数量(可以是具体数字或百分比)

2. 重建更新(Recreate)

yaml
strategy:
  type: Recreate

特点

  • 先删除所有旧Pod
  • 然后创建新Pod
  • 会有短暂的服务中断

操作命令

创建Deployment

bash
# 从YAML文件创建
kubectl apply -f deployment.yaml

# 直接创建
kubectl create deployment nginx --image=nginx:1.21 --replicas=3

查看Deployment

bash
# 查看所有Deployment
kubectl get deployments
kubectl get deploy

# 查看详细信息
kubectl describe deployment <deployment-name>

# 查看YAML格式
kubectl get deployment <deployment-name> -o yaml

# 查看JSON格式
kubectl get deployment <deployment-name> -o json

扩缩容

bash
# 扩展副本数
kubectl scale deployment nginx --replicas=5

# 自动扩缩容(需要Metrics Server)
kubectl autoscale deployment nginx --min=3 --max=10 --cpu-percent=80

更新Deployment

bash
# 更新镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.22

# 更新环境变量
kubectl set env deployment/nginx-deployment ENVIRONMENT=production

# 更新资源限制
kubectl set resources deployment/nginx-deployment -c nginx --limits=cpu=500m,memory=256Mi

查看更新状态

bash
# 查看更新状态
kubectl rollout status deployment/nginx-deployment

# 查看更新历史
kubectl rollout history deployment/nginx-deployment

# 查看特定版本详情
kubectl rollout history deployment/nginx-deployment --revision=2

回滚操作

bash
# 回滚到上一个版本
kubectl rollout undo deployment/nginx-deployment

# 回滚到指定版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2

暂停和恢复更新

bash
# 暂停更新
kubectl rollout pause deployment/nginx-deployment

# 恢复更新
kubectl rollout resume deployment/nginx-deployment

删除Deployment

bash
# 删除Deployment(保留Pod)
kubectl delete deployment nginx-deployment

# 删除Deployment及其所有Pod
kubectl delete deployment nginx-deployment --cascade=foreground

# 删除Deployment但不删除Pod
kubectl delete deployment nginx-deployment --cascade=orphan

实践示例

示例1:Web应用Deployment

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web
    environment: production
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.21
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "256Mi"
            cpu: "500m"

示例2:API服务Deployment

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-service
  labels:
    app: api
    tier: backend
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: myapi:v1.2.0
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url
        - name: REDIS_HOST
          value: "redis-service"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/ready
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 5
        resources:
          requests:
            memory: "256Mi"
            cpu: "500m"
          limits:
            memory: "512Mi"
            cpu: "1000m"

示例3:Worker服务Deployment

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: worker-service
  labels:
    app: worker
    tier: backend
spec:
  replicas: 2
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: worker
  template:
    metadata:
      labels:
        app: worker
    spec:
      containers:
      - name: worker
        image: worker:v1.0.0
        command: ["python", "worker.py"]
        args: ["--queue", "default"]
        env:
        - name: REDIS_URL
          value: "redis://redis-service:6379"
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url
        resources:
          requests:
            memory: "512Mi"
            cpu: "1000m"
          limits:
            memory: "1Gi"
            cpu: "2000m"
        volumeMounts:
        - name: config
          mountPath: /app/config
      volumes:
      - name: config
        configMap:
          name: worker-config

高级部署策略

1. 金丝雀发布

详细配置

yaml
# canary-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app-canary
  labels:
    app: web
    version: canary
spec:
  replicas: 1  # 小比例的金丝雀实例
  selector:
    matchLabels:
      app: web
      version: canary
  template:
    metadata:
      labels:
        app: web
        version: canary
    spec:
      containers:
      - name: web
        image: web-app:v2.0.0  # 新版本
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "256Mi"
            cpu: "500m"

流量控制

yaml
# canary-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-app

spec:
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer

通过Ingress控制流量

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"  # 10%流量到金丝雀版本
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-app-canary
            port:
              number: 80

2. 蓝绿部署

蓝色版本

yaml
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      version: blue
  template:
    metadata:
      labels:
        app: web
        version: blue
    spec:
      containers:
      - name: web
        image: web-app:v1.0.0  # 旧版本
        ports:
        - containerPort: 80

绿色版本

yaml
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      version: green
  template:
    metadata:
      labels:
        app: web
        version: green
    spec:
      containers:
      - name: web
        image: web-app:v2.0.0  # 新版本
        ports:
        - containerPort: 80

切换流量

bash
# 切换到绿色版本
kubectl patch service web-app -p '{"spec":{"selector":{"app":"web","version":"green"}}}'

# 如果出现问题,回滚到蓝色版本
kubectl patch service web-app -p '{"spec":{"selector":{"app":"web","version":"blue"}}}'

3. A/B测试

基于用户特性的路由

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "X-User-Group"
    nginx.ingress.kubernetes.io/canary-by-header-value: "beta"
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-app-beta
            port:
              number: 80

4. 灰度发布策略

基于百分比的流量分配

yaml
# 使用Istio进行更精细的流量控制
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: web-app

spec:
  hosts:
  - web-app
  http:
  - route:
    - destination:
        host: web-app-v1
      weight: 90  # 90%流量到v1
    - destination:
        host: web-app-v2
      weight: 10  # 10%流量到v2

3. 自动扩缩容(HPA)

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

故障排查

常见问题

1. Deployment无法更新

bash
# 查看Deployment事件
kubectl describe deployment <deployment-name>

# 查看Pod事件
kubectl get pods --selector=app=<app-name>

# 检查镜像拉取
kubectl describe pod <pod-name>

2. Pod无法启动

bash
# 查看Pod日志
kubectl logs <pod-name>

# 查看容器退出码
kubectl describe pod <pod-name>

# 检查资源配额
kubectl describe resourcequota

3. 滚动更新卡住

bash
# 查看更新状态
kubectl rollout status deployment/<deployment-name>

# 查看ReplicaSet
kubectl get replicasets

# 暂停并恢复更新
kubectl rollout pause deployment/<deployment-name>
# 修复问题后
kubectl rollout resume deployment/<deployment-name>

健康检查最佳实践

1. 探针类型和配置

存活探针(Liveness Probe)

  • 目的:检测容器是否需要重启
  • 配置示例
yaml
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 60  # 应用启动时间
  periodSeconds: 10        # 检查间隔
  timeoutSeconds: 5         # 超时时间
  successThreshold: 1       # 成功阈值
  failureThreshold: 3       # 失败阈值

就绪探针(Readiness Probe)

  • 目的:检测容器是否可以接收流量
  • 配置示例
yaml
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 10   # 就绪检查延迟
  periodSeconds: 5          # 检查间隔
  timeoutSeconds: 3         # 超时时间
  successThreshold: 1       # 成功阈值
  failureThreshold: 3       # 失败阈值

启动探针(Startup Probe)

  • 目的:处理启动时间长的应用
  • 配置示例
yaml
startupProbe:
  httpGet:
    path: /startup
    port: 8080
  failureThreshold: 30      # 启动尝试次数
  periodSeconds: 10         # 检查间隔

2. 探针实现方式

HTTP探针

  • 优点:实现简单,直接检查应用状态
  • 适用场景:Web应用、API服务
  • 示例
yaml
livenessProbe:
  httpGet:
    path: /actuator/health
    port: 8080
    httpHeaders:
    - name: Custom-Header
      value: Health-Check

命令探针

  • 优点:灵活性高,可以执行任意命令
  • 适用场景:非HTTP应用、后台服务
  • 示例
yaml
livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy

TCP探针

  • 优点:检查网络连接,适用于任何TCP服务
  • 适用场景:数据库、缓存服务
  • 示例
yaml
livenessProbe:
  tcpSocket:
    port: 3306

3. 健康检查最佳实践

  1. 根据应用特性配置

    • Web应用:使用HTTP探针
    • 数据库:使用TCP探针
    • 后台服务:使用命令探针
  2. 合理设置参数

    • initialDelaySeconds:根据应用启动时间设置
    • periodSeconds:平衡检查频率和系统负载
    • timeoutSeconds:避免检查超时影响应用
    • failureThreshold:允许短暂的故障
  3. 实现健康检查端点

    • 提供专门的健康检查端点
    • 检查应用依赖(数据库、缓存等)
    • 返回合适的HTTP状态码
  4. 监控健康状态

    • 监控探针失败事件
    • 设置告警机制
    • 分析重启原因
  5. 渐进式部署

    • 使用就绪探针控制流量接入
    • 确保新Pod就绪后再移除旧Pod
    • 避免滚动更新过程中的服务中断

4. 常见健康检查问题

问题1:探针过于敏感

症状:Pod频繁重启,影响服务稳定性 解决方案

  • 增加failureThreshold
  • 调整periodSeconds间隔
  • 优化健康检查逻辑

问题2:探针设置不足

症状:不健康的Pod仍在接收流量 解决方案

  • 配置就绪探针
  • 确保探针能检测出真实的健康状态
  • 定期测试探针有效性

问题3:启动时间过长

症状:Pod在启动过程中被重启 解决方案

  • 使用启动探针
  • 增加initialDelaySeconds
  • 优化应用启动时间

部署最佳实践

1. 标签管理

  • 使用有意义的标签:便于资源管理和查询
  • 标准化标签:使用推荐的标签规范
  • 标签一致性:保持标签在整个应用中的一致性
  • 使用标签选择器:精确选择目标资源

2. 资源管理

  • 设置资源请求和限制:根据应用实际需求配置
  • 监控资源使用:定期检查资源使用情况
  • 使用自动扩缩容:根据负载自动调整副本数
  • 资源配额:在命名空间级别限制资源使用

3. 更新策略

  • 生产环境:使用滚动更新,零停机部署
  • 测试环境:可以使用重建更新
  • 合理配置参数:根据应用特性设置maxSurgemaxUnavailable
  • 暂停和恢复:复杂更新时使用暂停功能

4. 版本控制

  • 保留更新历史:设置合理的revisionHistoryLimit
  • 使用有意义的镜像标签:避免使用latest标签
  • 记录更新说明:使用annotations记录更新内容
  • 定期清理历史版本:避免过多的历史记录

5. 安全配置

  • 使用非root用户:以非特权用户运行容器
  • 限制权限:使用最小权限原则
  • 只读文件系统:配置容器使用只读根文件系统
  • 安全上下文:设置适当的安全上下文
  • 镜像安全:使用官方镜像,定期更新

6. 监控和日志

  • 配置日志收集:使用Sidecar容器或日志驱动
  • 暴露指标:实现应用指标的采集
  • 健康检查端点:提供应用健康状态
  • 事件监控:关注Deployment相关事件

7. 故障排查

  • 日志分析:检查容器日志
  • 事件查看:分析Deployment事件
  • 资源监控:检查资源使用情况
  • 网络诊断:测试网络连通性
  • 配置验证:检查Deployment配置是否正确

总结

Deployment是Kubernetes中管理无状态应用的核心对象,通过本章的学习,您已经掌握了:

核心功能

  1. 基本功能

    • 副本管理和自动扩缩容
    • 滚动更新和版本回滚
    • 健康检查和故障自动修复
    • 声明式配置管理
  2. 高级部署策略

    • 金丝雀发布:小比例流量测试新版本
    • 蓝绿部署:无停机切换版本
    • A/B测试:基于用户特性的流量路由
    • 灰度发布:渐进式流量迁移
  3. 健康检查

    • 探针类型:存活探针、就绪探针、启动探针
    • 实现方式:HTTP探针、命令探针、TCP探针
    • 最佳实践:根据应用特性配置合适的探针
    • 常见问题:探针敏感度、启动时间、健康检查逻辑
  4. 部署最佳实践

    • 标签管理和资源配置
    • 更新策略和版本控制
    • 安全配置和监控日志
    • 故障排查和问题解决

Deployment提供了一套完整的无状态应用管理解决方案,支持从开发到生产的全生命周期管理。通过合理配置Deployment,您可以实现零停机部署、自动故障恢复、弹性扩缩容等高级功能,构建更加可靠、高效的容器化应用。

掌握Deployment的使用是Kubernetes学习的重要一步,它为您提供了构建现代化、弹性、高可用应用的基础能力。

下一步学习