K8s 学习笔记(三):工作负载管理

写在前面

本文是 K8s 学习笔记系列的第三篇,介绍 K8s 的工作负载管理:Deployment、StatefulSet、DaemonSet、Job 和 CronJob。前置知识:Pod 与容器管理(第二篇)。


一、Deployment

Deployment 是最常用的工作负载,管理无状态应用(Web 服务、API 等)。

1.1 Deployment 完整示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web-app
spec:
  replicas: 3                       # 副本数
  selector:
    matchLabels:
      app: web-app                  # 匹配 Pod 标签
  strategy:
    type: RollingUpdate             # 滚动更新策略
    rollingUpdate:
      maxSurge: 1                   # 更新时最多多出1个 Pod
      maxUnavailable: 0             # 更新时允许0个不可用
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web-app
        image: my-app:v1.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "256Mi"
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

1.2 滚动更新

Deployment 更新镜像时会自动滚动更新:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 方式1:set image
kubectl set image deployment/web-app web-app=my-app:v2.0

# 方式2:edit 直接编辑
kubectl edit deployment web-app

# 方式3:apply 新的 YAML
kubectl apply -f deployment-v2.yaml

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

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

1.3 回滚

1
2
3
4
5
6
7
8
# 查看历史版本
kubectl rollout history deployment/web-app

# 回滚到上一版本
kubectl rollout undo deployment/web-app

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

1.4 滚动更新策略

1
2
3
4
5
6
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1         # 更新时额外创建的 Pod 数(可以是数字或百分比)
      maxUnavailable: 0    # 更新时允许不可用的 Pod 数
1
2
maxSurge: 1, maxUnavailable: 0  → 先起新 Pod,再删旧 Pod(最安全,需要多余资源)
maxSurge: 0, maxUnavailable: 1  → 先删旧 Pod,再起新 Pod(省资源,有短暂不可用)

1.5 扩缩容

1
2
3
4
5
6
# 手动扩缩容
kubectl scale deployment web-app --replicas=5
kubectl scale deployment web-app --replicas=2

# 基于指标自动扩缩(HPA)
kubectl autoscale deployment web-app --min=2 --max=10 --cpu-percent=70

二、StatefulSet

StatefulSet 用于有状态应用(数据库、消息队列等),提供稳定的标识和持久化存储。

2.1 和 Deployment 的区别

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Deployment:
- Pod 名随机(web-app-7854ff8879-abcde)
- Pod IP 不固定
- 没有稳定的持久化标识
- 适合无状态应用

StatefulSet:
- Pod 名有序(mysql-0, mysql-1, mysql-2)
- 每个 Pod 有稳定的网络标识
- 每个 Pod 有独立的持久化存储
- 适合有状态应用

2.2 StatefulSet 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql              # 关联的 Headless Service
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: root-password
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:           # 每个 Pod 独立的 PVC
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi

2.3 Headless Service

StatefulSet 通常配合 Headless Service 使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  clusterIP: None                # Headless:不分配 ClusterIP
  selector:
    app: mysql
  ports:
  - port: 3306

Headless Service 让每个 Pod 有固定的 DNS 名称:mysql-0.mysql.default.svc.cluster.local


三、DaemonSet

DaemonSet 确保每个节点上运行一个 Pod 副本,常用于日志收集、监控、网络插件。

3.1 DaemonSet 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-collector
  labels:
    app: log-collector
spec:
  selector:
    matchLabels:
      app: log-collector
  template:
    metadata:
      labels:
        app: log-collector
    spec:
      tolerations:                # 容忍 Master 节点的污点
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluentd:latest
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log          # 挂载宿主机日志目录

3.2 常见使用场景

1
2
3
4
日志收集    — Fluentd、Filebeat
监控 Agent — Prometheus Node Exporter
网络插件    — Calico、Flannel
存储插件    — CSI Driver

四、Job

Job 运行一次性任务,完成后退出。

4.1 Job 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: batch/v1
kind: Job
metadata:
  name: data-migration
spec:
  completions: 1                  # 需要1次成功完成
  parallelism: 1                  # 并行数
  backoffLimit: 3                 # 失败重试次数
  activeDeadlineSeconds: 300      # 最长运行时间(秒)
  template:
    spec:
      restartPolicy: Never        # Job 不能用 Always
      containers:
      - name: migrate
        image: my-app:latest
        command: ["python", "migrate.py"]

4.2 批处理 Job

1
2
3
4
# 并行处理多个任务
spec:
  completions: 10                 # 需要成功10次
  parallelism: 3                  # 3个 Pod 并行执行

五、CronJob

CronJob 按时间计划运行 Job。

5.1 CronJob 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup
spec:
  schedule: "0 2 * * *"           # 每天凌晨2点(cron 格式)
  concurrencyPolicy: Forbid       # 禁止并发执行
  successfulJobsHistoryLimit: 3   # 保留3个成功记录
  failedJobsHistoryLimit: 1       # 保留1个失败记录
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: backup
            image: my-app:latest
            command: ["sh", "-c", "pg_dump ... | gzip > /backup/db.sql.gz"]

5.2 Cron 格式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
┌──────── 分钟 (0-59)
│ ┌────── 小时 (0-23)
│ │ ┌──── 日 (1-31)
│ │ │ ┌── 月 (1-12)
│ │ │ │ ┌ 星期 (0-6, 0=周日)
│ │ │ │ │
* * * * *

"*/5 * * * *"     → 每5分钟
"0 * * * *"        → 每小时整点
"0 2 * * *"        → 每天凌晨2点
"0 0 * * 1"        → 每周一零点
"0 0 1 * *"        → 每月1号零点

5.3 手动触发 CronJob

1
kubectl create job --from=cronjob/backup backup-manual

六、工作负载选型

1
2
3
4
5
Web 服务 / API        → Deployment
数据库 / 消息队列      → StatefulSet
日志 / 监控 Agent     → DaemonSet
数据迁移 / 批处理      → Job
定时备份 / 报表        → CronJob

七、小结

本文学习了 K8s 的工作负载管理:

  • Deployment:无状态应用、滚动更新、回滚
  • StatefulSet:有状态应用、稳定的网络标识和存储
  • DaemonSet:每个节点运行一个 Pod
  • Job:一次性任务
  • CronJob:定时任务
  • 工作负载选型

下一篇将学习服务发现与网络:Service、Ingress 和 DNS。