Kubernetes 控制器与工作负载策略

本文最后更新于 2025年8月14日 上午

工作负载概述

Pod对象不具备自动故障恢复能力,而且对需要水平扩容的多副本管理也非常复杂。kubernetes通过定义管理Pod的工作负载资源来完成对于Pod的创建,调度,水平扩/缩容,故障恢复等生命周期管理的工作

RC控制器

RC独立于所控制的Pod并通过标签的松耦合关系控制目标Pod实例的创建和销毁。

ReplicaSet

ReplicaSet在RC的基础上,提供了更灵活的标签选择模式。RS可以一次性选择多个标签,并且选择多个不同的版本进行部署,如

1
2
3
4
5
selector:
matchLabels:
tier: frontend
matchExpression:
- {key: tier , operator: In , values: [frontend]}
1
2
3
4
5
selector:
matchLabels:
version: v2
matchExpression:
- {key: version , operator: In , values: [v1,v2]}

特殊需求

  1. 不同Pod之间的亲和性, 比如MySQL数据库与Redis中间件不能被调度到同一个目标Node上,或者两个需要紧密连接的微服务Pod必须调度到同一个Node上,以实现本地文件共享或本地网络通信等需求。
  2. 有状态集群的调度。对于ZooKeeper,Elasticsearch,MongoDB,Kafka等有状态集群,虽然集群中的每个Node看起来都是相同的,但每个Node都必须有明确的不变的唯一身份标识
  3. 在每个Node上调度并且仅仅创建一个Pod副本,这种调度通常用于系统监控相关的Pod
  4. 批处理作业,需要创建多个Pod副本来协同工作,当这些Pod副本都完成自己的任务时,整个批处理作业就结束了。
  5. 控制器与Pod间是松绑定关系,如果控制Pod与控制器间的控制逻辑

Deployment

面向无状态应用的Pod副本集管理

Deployment是一种面向无状态应用的多个Pod副本进行自动化管理的工作负载控制器。无状态应用通常要求每个Pod副本的工作机制相同,提供的服务也相同。Deployment在部署Pod之后会持续监控副本的运行状况和数量,始终保证用户指定的副本数量的Pod正常运行。

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

创建deployment

1
2
# kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deployment created

查看deployment状态

1
2
3
# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 16s

NAME: Deployment的名称

READY: 处于Ready状态的Pod副本数量,“/” 右侧为期望的Pod副本数量,即spec.replicas字段的设置值

UP-TO-DATE: 更新到最新Pod模板的Pod副本数量

AVAILABLE: 可供用户使用的Pod副本数量

AGE: Deployment的运行时间

1
2
3
# kubectl get replicasets
NAME DESIRED CURRENT READY AGE
nginx-deployment-4087004483 3 3 3 53s

NAME : ReplicaSet的名称

DESIRED: 期望的副本数量

CURRENT: 当前处于运行状态的Pod副本数量

READY: 处于Ready状态的Pod副本数量

AGE: Deployment的运行时间

查看pod运行状态

1
2
3
4
5
# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-4087004473-9jqqs 1/1 Running 0 1m
nginx-deployment-4087004473-cq0cf 1/1 Running 0 1m
nginx-deployment-4087004473-vxn56 1/1 Running 0 1m

配置信息

  • selector : 标签选择器,用于关联具有指定标签的Pod列表
  • template : Pod模板,其中的配置项就是Pod的定义,作为Deployment资源的一部分存在,无须在设置apiVersion 和 kind这两个元素
  • replicas : 期望的Pod副本数量,默认值为1。通过kubectl scale命令调整后的副本数量将会覆盖初始设置的值。如果使用自动扩缩容来自动调整Pod副本数量,则不需要设置这个值
  • strategy : 更新策略,可选项包括Recreate和RollingUpdate
  • minReadySeconds : Pod最短就绪时间,达到这个时间,系统才会设置Pod为Ready状态
  • progressDeadlineSeconds : 设置未能处于部署完成状态的超时时间,默认值为600s。达到这个时间之后,系统将设置Progressing的状态为False,并将Reason设置为ProgressDeadlineExceeded
  • revisionHistoryLimit: 修订历史最大数量,每个修订版本都有一个对应的ReplicaSet资源,保存地过多将消耗更多资源
  • paused : 设置为true来表示部署过程处于暂停状态,设置为false表示处于正常部署过程。
  • matchLabels: 设置一个或多个标签的值,以key:value 格式表示,如果设置了多个标签,需要满足全部条件才能与Pod关联成功
1
2
3
4
selector:
matchLabels:
- app: nginx
- version: v1
  • matchExpressions: 设置一个或多个标签取值表达式,以(key,operation,values)三元组格式进行设置,其中values 可以设置多个值。
1
2
3
4
5
6
7
8
9
10
11
selector:
matchExpressions:
- key: role
operator: In
values:
- manager
- key: env
operator: NotIn
values:
- test
- prod

Deployment的更新

配置更新过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# nginx-deployment.yaml
apiVersion: app/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

查询已运行的Pod

1
2
3
4
5
# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-4087004473-9jqqs 1/1 Running 0 1m
nginx-deployment-4087004473-cq0cf 1/1 Running 0 1m
nginx-deployment-4087004473-vxn56 1/1 Running 0 1m

更新nginx的镜像版本

  1. 通过命令好修改
1
2
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment.apps/nginx-deployment image updated
  1. 使用kubectl edit 编辑deployment配置文件
1
2
kubectl edit deployment/nginx-deployment
deployment.apps/nginx-deployment edited

Deployment 通过创建一个新的ReplicaSet ,先扩展创建新版本的Pod ,如何将旧版本的Pod进行对应缩减,同时维持替换过程中,至少有期望副本数量-1的Pod 是可用的。

更新策略

  1. Recreate: 设置spec.strategy.type=Recreate表示 在更新时需要先杀死所有旧Pod在创建更新
  2. RollingUpdate: 设置spec.strategy.type=RollingUpdate表示 以滚动更新的方式逐个更新Pod

Deployment的回滚

回滚过程

查询回滚历史

1
2
3
4
5
kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 ...
2 ...

查询之前的版本

1
kubectl rollout history deployment/nginx-deployment --revision=3

回滚

1
2
3
kubectl rollout undo deployment/nginx-deployment

kubectl roolout undo deployment/nginx-deployment --to-revision=2

Deployment的暂停与恢复

通过kubectl rollout pause 暂停Deployment的更新操作

1
2
kubectl rollout pause deployment/nginx-deployment
deployment.apps/nginx-deployment paused

使用kubectl rollout resume deploy nginx-deployment恢复更新

1
2
kubectl rollout resume deploy nginx-deployment
deployment.apps/nginx-deloyment resume

期间可以对deployment进行修改而不会触发deployment的更新

Deployment的生命周期

Progressing

  • 正在创建新的ReplicaSet
  • 正在创建最新的ReplicaSet
  • 正在为旧的RelicaSet进行水平缩容
  • 新的Pod处于Ready或者Available状态

Complete

  • 最新版本的ReplicaSet已部署完成
  • Pod副本数量达到期望副本数量,并且都处于可用状态
  • 没有旧的Pod副本还在运行

Failed

  • 容器镜像下载失败
  • Pod所需的资源配额一直不足
  • 启动Pod所需的权限不足
  • 资源限制范围LimitRange配置不正确
  • Pod的服务就绪探针一直失败
  • 容器应用启动一直失败

DeamonSet

DeamonSet用于管理集群中的每个Node上仅运行一个Pod副本,当新增Node或删除Node时 会自动增删Node上的副本

场景

  • 在每个Node上都运行一个共享存储驱动的守护进程
  • 在每个Node上都运行一个日志采集程序,采集Node上全部容器的日志
  • 在每个Node上都运行一个性能监控程序,采集Node上容器和操作系统的运行性能数据
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
apiVersion: apps/v1
kind: DeamonSet
metadata:
name: fluentd
namespace: kube-system
labels:
k8s-app: fluentd
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
namespace: kube-system
labels:
app: fluentd
spec:
containers:
- name: fluentd
image: fluentd
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log

创建DeamonSet

1
2
# kubectl create -f fluentd.yaml
daemonset.apps/fluentd created

配置信息

  • selector: 标签选择器,用于关联具有指定标签的Pod列表
  • template: Pod模板,配置项就是Pod的定义
  • updateStratgy: 更新策略,可选项包括OnDelete和RollingUpdate
  • minReadySecond: Pod最短就绪时间
  • revisionHistoryLimit: 修订历史最大数量

更新策略

  • OnDelete : 旧版本需要用户手动删除才能触发新的创建
  • RollingUpdate : 旧版本自动被杀掉,然后创建新版本的Pod

回滚

与Deploy类似

StatefulSet

面向有状态应用的Pod副本管理

由StatefulSet管理的Pod 意味着每个Pod副本都应该具有唯一不变的身份标识,例如ID或者服务名称;多个Pod副本不是对等无差别的,而是相互之间可能需要通信来实现某种功能。以及需要独立的持久化存储,以及多个Pod可能需要按固定的顺序逐个启动扽业务需求

StatefulSet 提供了以下功能

  • 每个Pod 都具有唯一且不变的身份标识,包括ID和网络访问地址
  • 为每个Pod都配置稳定的持久化存储
  • 对多个Pod提供有序的,优雅的部署和扩缩容等管理功能
  • 对多个Pod提供有序的,优雅的滚动更新等管理功能

限制:

  • 为每个Pod配置的持久化存储必须是PVC类型的共享存储
  • 删除Pod时不会删除关联的后端存储,主要考虑的是容器应用的数据通常都具有业务价值
  • 必须创建一个Headless Service,用于创建每个Pod的网络访问地址
  • 删除StatefulSet资源时,系统不保证Pod终止
  • 使用OrderedReady 策略滚动更新时,如果某个Pod一直无法Ready可能需要人工干预

配置信息

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
46
47
48
49
50
# nginx-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
servicename: "nginx"
replicas: 3
minReadySeconds: 10
template:
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: nginx
porsts:
- name: web
containerPort: 80
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
storageClassName: "nginx-storage-class"
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- port: 80
name: web
clusterIP: None
  • selector: 标签选择器,用于关联具有指定标签的Pod列表
  • template: Pod模板,配置项就是Pod的定义
  • updateStratgy: 更新策略,可选项包括OnDelete和RollingUpdate
  • minReadySeconds: Pod最短就绪时间
  • podManagementPolicy: Pod管理策略
    • OrderedReady 按顺序创建
    • Parallel 并行创建
  • volumeClaimTemplates: 后端存储的PVC模板
  • serviceName : 关联的无头服务名称
  • replicas : Pod副本数量
  • persistentVolumeClaimRetentionPolicy: PVC存储的保留策略
  • ordinals.start: Pod名称的起始序号

创建Pod唯一稳定的网络访问地址

查看Headless Service信息,可以看到服务后端Endpoints列表中包含了每个Pod的IP地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# kubectl get service nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 20m

# kubectl describe service nginx
Name: nginx
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: web 80/TCP
TargetPort: 80/TCP
Endpoints: 10.1.95.26:80,10.1.95.28:80,10.1.95.39:80
Session Affinity: None
Events: <none>

StatefulSet会将 无头服务名与Pod名组合成服务访问地址,以DNS域名的格式进行表示

结构类似为 <pod-name>.<service-name>.<namespace>.svc.<clusterDomain>

后端存储

StatefulSet会为每个Pod 创建一个PVC,当发生故障时,之重新创建Pod,再将之前的PVC挂载给新的Pod

删除机制

默认情况下 StatefulSet控制器管理的Pod 会全部删除,而使用非级联模式,可以不影响Pod的情况下进行删除 kubectl delete statefulset web —cascade=orphan=true

水平 扩容/缩容

  1. 扩容
1
kubectl scale statefulset web --replicas=5
  1. 缩容
1
kubectl scale statefulset web --replicas=3

更新策略

  • 策略为OnDelete时, 需要用户手动触发删除后,自动触发创建
  • 策略为RollingUpdate时,删除所有创建的Pod对象,再依次创建新的对象
  • 通过设置spec.update.Strategy.rollingUpdate.partition ,可以进行分区更新,只对大于partition的Pods进行更新

Pod管理策略

  • OrderedReady: 扩容时按照顺序管理Pod的创建和扩/缩容操作
  • Parallel: 表示可以并行创建或删除所有Pod

PVC保存策略

  • whenDeleted: 设置删除Statefulset时的存储保留策略
  • whenScaled: 设置缩容时的保留策略

子策略

  • Retain: 保留数据,不执行自动删除操作
  • Delete: 自动删除Pod关联的PVC
1
2
3
4
5
6
7
8
apiVersion: apps/v1
kind: StatefulSet
...
spec:
presistentVolumeClaimRetentionPolicy:
whenDeleted: Retain
whenScaled: Delete
...

Job批处理任务

配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# job.yaml
apiVersion: v1
kind: Job
metadata:
name: hello
spec:
template:
spec:
containers:
- name: hello
image: busybox
command: ["echo","Hello World!"]
restartPolicy: Never
backoffLimit: 4
  • template: Pod模板,其中的配置项是Pod的定义
  • selector: 默认情况下,不需要特别设置标签选择器
  • restartPolicy: Pod重启策略,可选项保活Never和OnFailure,不能被设置为Always
  • parallelism: 可以并行运行的任务数量
  • completions和completionMode: 用于设置成功完成的Pod数量,默认为1
  • backoffLimit: 设置失败任务的重试上限
  • podFailurePolicy: 失效特性
  • podReplacementPolicy: 替换策略

Job处理机制

单个一次性任务

通常一个Job只启动一个Pod,除非Pod异常,才会重启该Pod

有指定数量的并行任务

同时控制多个Job来执行任务

带工作队列的并行任务

一个Pod处理一个工作队列

这种情况,需要Job从外部拉取任务队列中的工作项,将每个工作项打包定义为Worker Pod,Worker Pod的逻辑是从队列中拉去一个工作项并处理,完成后结束

Pod数量可变的队列

这种情况,Job不确定队列中工作项的具体数目,由多个Pod对任务项进行处理,当所有工作项处理完成后,Job结束

静态任务分派且带索引的Job

Pod之间需要通信的Job

Job模板扩展

CronJob 定时任务

配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes Cluster
restartPolicy: OnFailure
  • metadata.name:CronJob 名称,必须在命名空间内唯一。
  • schedule:Cron 表达式,定义任务运行的时间,这里是 “*/1 * * * *” 表示每分钟执行一次。
  • jobTemplate:任务模板,定义每次调度时要运行的 Job 规范。
  • startingDeadlineSeconds:可选,单位秒。表示如果某次任务错过了调度时间(例如因集群不可用),在调度时间之后的这段时间内仍然允许启动任务。超过这个时间则放弃本次任务。
  • concurrencyPolicy:可选,定义同一 CronJob 多个任务实例的并发策略。可选值有:
    • Allow(默认):允许并发运行多个任务实例。
    • Forbid:禁止并发运行,如果上一个任务还在运行,则跳过新任务。
    • Replace:如果上一个任务还在运行,则先终止它,再启动新的任务。
  • suspend:可选,布尔值。设置为 true 时暂停 CronJob 的调度,不会创建新的 Job;已有的 Job 不受影响。
  • successfulJobsHistoryLimit:可选,整数。保留的已成功完成的 Job 数量,超过这个数量的旧 Job 会被自动清理。
  • failedJobsHistoryLimit:可选,整数。保留的已失败的 Job 数量,超过这个数量的旧 Job 会被自动清理。
  • timeZone:可选,指定 Cron 表达式解析使用的时区。例如 “Asia/Shanghai”。如果不指定,默认使用 kube-controller-manager 的时区(通常是 UTC)。

Kubernetes 控制器与工作负载策略
http://gadoid.io/2025/08/08/Kubernetes-控制器与工作负载策略/
作者
Codfish
发布于
2025年8月8日
许可协议