Deployment - 应用部署

Deployment - 应用部署

为什么需要 Deployment

在上一章我们学习了 Pod,但实际生产中很少直接创建 Pod,而是使用 Deployment

Pod 的问题

直接创建 Pod 存在这些问题:

  • Pod 删除后不会自动重建
  • 无法方便地扩缩容
  • 更新应用需要手动操作
  • 无法实现滚动更新和回滚

Deployment 的优势

Deployment 提供了声明式的更新机制:

  • 自动恢复:Pod 失败自动重建
  • 扩缩容:轻松调整副本数量
  • 滚动更新:零停机更新应用
  • 版本回滚:出问题立即回退
  • 暂停/恢复:分批更新控制

创建 Deployment

基础示例

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

应用配置:

kubectl apply -f deployment.yaml

# 查看 Deployment
kubectl get deployments

# 查看 Pod
kubectl get pods

字段说明

replicas:期望的 Pod 副本数

selector:选择器,用于匹配 Pod

template:Pod 模板,定义 Pod 的配置

管理 Deployment

查看状态

# 查看 Deployment
kubectl get deployment nginx-deployment

# 输出
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           2m

# 详细信息
kubectl describe deployment nginx-deployment

# 查看事件
kubectl get events --sort-by=.metadata.creationTimestamp

字段含义:

  • READY:就绪的 Pod 数量 / 期望数量
  • UP-TO-DATE:已更新到最新版本的 Pod 数量
  • AVAILABLE:可用的 Pod 数量

扩缩容

# 扩容到 5 个副本
kubectl scale deployment nginx-deployment --replicas=5

# 缩容到 2 个副本
kubectl scale deployment nginx-deployment --replicas=2

# 查看效果
kubectl get pods -w

也可以修改 YAML 文件的 replicas 字段后重新 apply。

更新应用

方法一:修改镜像

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

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

# 输出
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out

方法二:修改 YAML

spec:
  containers:
  - name: nginx
    image: nginx:1.22  # 修改版本
kubectl apply -f deployment.yaml

滚动更新策略

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2        # 最多可以超出期望数量的 Pod 数
      maxUnavailable: 1  # 最多不可用的 Pod 数
  template:
    # ...

更新过程:

  1. 创建新版本 Pod(不超过 maxSurge)
  2. 等待新 Pod 就绪
  3. 删除旧版本 Pod(不超过 maxUnavailable)
  4. 重复 1-3 直到所有 Pod 更新完成

回滚

# 查看历史版本
kubectl rollout history deployment/nginx-deployment

# 输出
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployment/nginx-deployment nginx=nginx:1.22
3         kubectl set image deployment/nginx-deployment nginx=nginx:1.23

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

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

# 查看回滚状态
kubectl rollout status deployment/nginx-deployment

暂停和恢复

暂停更新可以避免频繁更新触发多次滚动更新。

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

# 进行多次修改
kubectl set image deployment/nginx-deployment nginx=nginx:1.22
kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi

# 恢复更新(一次性滚动更新)
kubectl rollout resume deployment/nginx-deployment

资源配置

CPU 和内存限制

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: app
        image: myapp:v1
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "256Mi"
            cpu: "500m"
  • requests:Pod 调度时保证的资源
  • limits:Pod 运行时的最大资源

环境变量

spec:
  containers:
  - name: app
    image: myapp:v1
    env:
    - name: DATABASE_HOST
      value: "mysql.example.com"
    - name: DATABASE_PORT
      value: "3306"
    - name: APP_ENV
      value: "production"

健康检查

spec:
  containers:
  - name: app
    image: myapp:v1
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 5
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 3

ReplicaSet

Deployment 内部使用 ReplicaSet 来管理 Pod。

# 查看 ReplicaSet
kubectl get replicaset

# 输出
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5d59d67564   3         3         3       5m

关系链:

Deployment → ReplicaSet → Pod

每次更新会创建新的 ReplicaSet,旧的 ReplicaSet 会保留(副本数为 0),用于回滚。

完整示例

部署一个 Web 应用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: webapp
        version: v1
    spec:
      containers:
      - name: webapp
        image: nginx:1.21
        ports:
        - containerPort: 80
          name: http
        env:
        - name: APP_ENV
          value: "production"
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5

操作流程

# 1. 部署应用
kubectl apply -f webapp-deployment.yaml

# 2. 查看状态
kubectl get deployment webapp
kubectl get pods -l app=webapp

# 3. 扩容
kubectl scale deployment webapp --replicas=5

# 4. 更新版本
kubectl set image deployment/webapp webapp=nginx:1.22

# 5. 监控更新过程
kubectl rollout status deployment/webapp

# 6. 查看历史
kubectl rollout history deployment/webapp

# 7. 回滚(如果需要)
kubectl rollout undo deployment/webapp

常用命令总结

# 创建
kubectl create deployment nginx --image=nginx
kubectl apply -f deployment.yaml

# 查看
kubectl get deployments
kubectl describe deployment <name>
kubectl get pods -l app=<label>

# 扩缩容
kubectl scale deployment <name> --replicas=<count>

# 更新
kubectl set image deployment/<name> <container>=<image>
kubectl apply -f deployment.yaml

# 回滚
kubectl rollout history deployment/<name>
kubectl rollout undo deployment/<name>
kubectl rollout undo deployment/<name> --to-revision=<n>

# 滚动更新控制
kubectl rollout status deployment/<name>
kubectl rollout pause deployment/<name>
kubectl rollout resume deployment/<name>

# 删除
kubectl delete deployment <name>

最佳实践

1. 始终声明资源限制

resources:
  requests:
    memory: "128Mi"
    cpu: "100m"
  limits:
    memory: "256Mi"
    cpu: "200m"

2. 配置健康检查

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
readinessProbe:
  httpGet:
    path: /ready
    port: 8080

3. 使用标签管理

metadata:
  labels:
    app: myapp
    env: prod
    version: v1.2.3

4. 记录更新原因

kubectl apply -f deployment.yaml --record

5. 合理设置副本数

  • 开发环境:1-2 个
  • 测试环境:2-3 个
  • 生产环境:3+ 个(根据负载调整)

小结

Deployment 是 Kubernetes 中最常用的工作负载资源:

  • 声明式:描述期望状态,系统自动实现
  • 自动恢复:Pod 失败自动重建
  • 扩缩容:轻松调整副本数量
  • 滚动更新:零停机更新应用
  • 版本管理:支持回滚到任意版本

下一章我们将学习如何通过 Service 暴露应用。