写在前面
本文是 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。