云原生学习03-工作负载资源

Deployment

Deployment 是 Kubernetes 中最常用的控制器,它可以保证 Pod 副本数始终保持在期望的数量,并可以根据策略自动更新 Pod。

ReplicaSet 是 Deployment 的子控制器,它负责管理 Pod 副本数。

1
2
3
4
5
6
7
8
9
10
11
12
graph TD
D[Deployment] -->|管理| RS[ReplicaSet]
RS -->|创建/管理| P1[Pod 1]
RS -->|创建/管理| P2[Pod 2]
RS -->|创建/管理| P3[Pod N]

P1 --> C11[Container 1]
P1 --> C12[Container 2]
P2 --> C21[Container 1]
P2 --> C22[Container 2]
P3 --> C31[Container 1]
P3 --> C32[Container 2]
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
$ kubectl explain deploy #简写
GROUP: apps
KIND: Deployment
VERSION: v1

DESCRIPTION:
Deployment enables declarative updates for Pods and ReplicaSets.

FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

metadata <ObjectMeta>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

spec <DeploymentSpec> -required-
Specification of the desired behavior of the Deployment.

status <DeploymentStatus>
Most recently observed status of the 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
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # 指定期望的 Pod 副本数
selector:
matchLabels:
app: nginx # 选择器,用于匹配和管理哪些 Pod 属于这个 Deployment
strategy:
type: RollingUpdate # 默认策略
rollingUpdate:
maxUnavailable: 1 # 在更新过程中,最多有多少个 Pod 不可用
maxSurge: 1 # 在更新过程中,最多可以创建多少个超出期望副本数的 Pod
template: # Pod 模板,定义了每个 Pod 长什么样
metadata:
labels:
app: nginx # 给 Pod 打上标签,必须与上面的 selector.matchLabels 一致
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
1
kubectl apply -f deploy.yaml

关于Pod命名

1
kubectl get po

NAME READY STATUS RESTARTS AGE
nginx-deployment-d8b657495-kgrlj 1/1 Running 0 43s
nginx-deployment-d8b657495-rbg6k 1/1 Running 0 43s
nginx-deployment-d8b657495-v7hm6 1/1 Running 0 43s

可以看到NAME的组成十分奇怪,他是由三部分拼成的,每一段都有明确的来源

1
2
3
4
5
nginx-deployment  -  d8b657495  -  kgrlj
│ │ │
│ │ └─ Pod 随机后缀(5 位)
│ └────────────── ReplicaSet 的 hash 后缀(Pod 模板哈希)
└───────────────────────────────── Deployment 名字

关于字段更新

可改:

  • spec.replicas(扩缩容,不产生新 RS)
  • spec.template.*(触发滚动更新,产生新 RS)
  • spec.strategy
  • metadata.labels / annotations

不可改:

  • spec.selector —— 报 field is immutable,只能删除重建

好习惯:kubectl diff -f x.yaml 先看变更再 apply。

关于scale调整pod副本数

1
2
3
4
5
# 扩容/缩容到指定数量
kubectl scale deployment/nginx-deployment --replicas=5

# 缩容到 0(暂停工作负载但保留 Deployment 和 RS)
kubectl scale deployment/nginx-deployment --replicas=0

关于set image更新容器镜像

作用:修改 Pod 模板中的容器镜像,触发滚动更新。

1
2
# 格式:资源类型/名称 容器名=新镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.25

关于rollout undo版本回滚

作用:把 Deployment 恢复到之前某个 revision(对应某个旧 ReplicaSet)。

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

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

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

statefulset

StatefulSet 是 Kubernetes 中用于管理有状态应用的工作负载资源。它和 Deployment 最根本的区别在于:Deployment 的 Pod 是可互换的、无身份的;而 StatefulSet 的每个 Pod 都有稳定且唯一的身份(序号、网络标识、存储),即使 Pod 被重建,这个身份也不会变。

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
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: nginx
podManagementPolicy: Parallel
updateStrategy:
type: RollingUpdate # 或 OnDelete
rollingUpdate:
partition: 1 # 用于金丝雀发布
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.18
ports:
- containerPort: 80
name: web

关于sts的命名规则

1
<StatefulSet名称>-<序号>

序号从 0 开始,连续递增到 N-1(N = replicas)。

示例:名为 web、replicas: 3 的 StatefulSet:

1
2
3
web-0
web-1
web-2

image-20261017193611066

关于spec.pod.amagementPolicy.type

这个属性控制的是sts的生成规则,默认是单个轮流生成

image-20261017193346461

如果选择Parallel模式就是可以并发同时生成

image-20261017193423605

关于spec.updateStrategy.type

维度 RollingUpdate(默认) OnDelete
触发方式 apply 修改模板后,控制器自动逐个更新 Pod apply 后不自动更新,必须手动删除旧 Pod,控制器才会用新模板重建它
更新顺序 按序号从大到小(N-1 → 0)逐个更新,前一个 Ready 才更新下一个 无固定顺序,你删哪个就重建哪个
是否受 partition 控制 是,只更新序号 ≥ partition 的 Pod 否,partition 字段无效
更新节奏 控制器自动推进,可用 rollout status 观察 完全由人工控制,想何时更新就何时删 Pod
适合场景 常规升级、金丝雀发布(配合 partition) 需要人工逐台确认的敏感场景(如数据库主节点升级)、需要精确控制更新时机的场景
回滚方式 kubectl rollout undo 或改模板再 apply 同样靠改模板 + 手动删 Pod,无自动回滚

StatefulSet 的 Pod 序号是 0、1、2、…、N-1。滚动更新默认从序号最大的 Pod 开始,倒序更新。

滚动更新:

1
kubectl set image statefulsets web nginx=nginx:1.19

image-20261017201308599

注意到这里仅web-2与web-1被滚动更新了,这里涉及到另外一项配置

1
2
3
4
spec:
updateStrategy:
rollingUpdate:
partition: 1 # 用于金丝雀发布

partition 的含义是:

只更新序号 ≥ partition 的 Pod,序号 < partition 的保持旧版本不动。

DaemonSet

DaemonSet 是 Kubernetes 中用来确保集群里每个(或指定的)节点上都运行一个 Pod 副本的工作负载资源。它和 Deployment、StatefulSet 的核心区别在于:Pod 数量不由你指定,而是由节点数量决定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ssd-monitor
spec:
selector:
matchLabels:
name: ssd-monitor
template:
metadata:
labels:
name: ssd-monitor
spec:
containers:
- name: monitor
image: nginx
imagePullPolicy: IfNotPresent

这种类型的pod通常与监控与网络调度相关,比如minikube的网络系统pod

image-20261017202956678

这种类型的资源调度与节点数量有关,会随着节点数的改变而改变

image-20261017203318558

可以看到每一个节点中都有一个,后续删除或创建节点时也会跟着增加或减少

image-20261017203627930

image-20261017203634647

关于pod.spec.containers.imagePullPolicy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ kubectl explain pod.spec.containers.imagePullPolicy
KIND: Pod
VERSION: v1

FIELD: imagePullPolicy <string>
ENUM:
Always
IfNotPresent
Never

DESCRIPTION:
Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if
:latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More
info: https://kubernetes.io/docs/concepts/containers/images#updating-images

Possible enum values:
- `"Always"` means that kubelet always attempts to pull the latest image.
Container will fail If the pull fails.
- `"IfNotPresent"` means that kubelet pulls if the image isn't present on
disk. Container will fail if the image isn't present and the pull fails.
- `"Never"` means that kubelet never pulls an image, but only uses a local
image. Container will fail if the image isn't present

imagePullPolicy(镜像拉取策略)有三个可选值:

值 含义 简单理解
Always kubelet 总是尝试拉取最新镜像,拉取失败则容器启动失败 每次都去仓库拉,不管本地有没有
IfNotPresent 本地磁盘没有该镜像时才拉取,拉取失败则容器失败 本地有就用本地,没有才去拉
Never 从不拉取,只用本地已有镜像;本地没有则容器失败 只用本地,绝不联网拉

默认值:如果镜像 tag 是 latest,默认为 Always;否则默认为 IfNotPresent。

Job

Job 是 Kubernetes 中的一种工作负载资源,用于运行一次性任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
completionMode: Indexed
completions: 1
parallelism: 3 #并行度,允许多个pod一起跑
ttlSecondsAfterFinished: 5 #删除时间,效果为完成5秒后删除
successPolicy:
rules:
- succeededCount: 1
succeededIndexes: "0,1"
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never # 对于 Job,此策略推荐设置为 Never 或 OnFailure
backoffLimit: 4 # 设定失败重试次数

completions: 1
期望成功完成的 Pod 总数。在 Indexed 模式下,这意味着 Pod 索引只有 0。这与下方 succeededIndexes: "0,1" 直接矛盾:索引 1 不存在,该成功策略规则在逻辑上无法被满足。

successPolicy
定义 Job 的提前成功条件。仅适用于 Indexed 模式的 Job。

  • rules:成功规则列表,满足任意一条即标记 Job 成功。
  • succeededCount: 2:要求成功索引的数量至少为 2。
  • succeededIndexes: "0,1":将计数范围限定在索引 0 和 1 内。结合 succeededCount: 2,意味着索引 0 和 1 必须同时成功,Job 才会提前成功。

restartPolicy: Never
Pod 失败后不重启。这是配合 successPolicy 使用的推荐策略,也是某些 Job 特性的前提条件之一。

CronJob

CronJob 是 Kubernetes 中的一种工作负载资源,用于定时执行任务。

1
2
3
4
5
6
7
8
9
10
11
12
# 每分钟执行
"*/1 * * * *"
# 每小时执行
"0 * * * *"
# 每天凌晨2点执行
"0 2 * * *"
# 每周一上午9点执行
"0 9 * * 1"
# 每月1号凌晨3点执行
"0 3 1 * *"
# 工作日每天下午5点执行
"0 17 * * 1-5"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: batch/v1
kind: CronJob
metadata:
name: cron-pi
spec:
schedule: "0 2 * * *" # 每天凌晨2点执行
timeZone: "Asia/Shanghai" # 使用上海时区
concurrencyPolicy: Forbid # 禁止并发,确保任务不重叠
startingDeadlineSeconds: 600 # 10分钟内必须启动,否则跳过
successfulJobsHistoryLimit: 5 # 保留5个成功备份记录;默认3个
failedJobsHistoryLimit: 3 # 保留3个失败记录用于排查;默认1个
jobTemplate:
spec:
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]

Contents