一、控制器概述
1. 概述
在 Kubernetes 中运行了一系列控制器来确保集群的当前状态与期望状态保持一致,它们就是 Kubernetes 集群内部的管理控制中心或者说是”中心大脑”。例如,ReplicaSet 控制器负责维护集群中运行的 Pod 数量;Node 控制器负责监控节点的状态,并在节点出现故障时,执行自动化修复流程,确保集群始终处于预期的工作状态。
控制器-控制循环
2. 控制器分类
Pod控制器有如下几类:
- ReplicationController 和 ReplicaSet
- 功能:确保指定数量的 Pod 副本始终运行。
- ReplicationController(旧版):通过标签选择器管理 Pod 副本数,但功能较基础。
- ReplicaSet(推荐):新一代控制器,支持更灵活的集合型标签选择器(如
matchLabels
和matchExpressions
),通常被 Deployment 间接使用。
- 典型场景:无状态应用的副本维护(如 Web 服务)。
- 功能:确保指定数量的 Pod 副本始终运行。
- Deployment
- 功能:管理 ReplicaSet 并提供声明式更新(如滚动升级、回滚)。
- 通过控制 ReplicaSet 实现 Pod 的副本管理。
- 支持版本控制和更新策略(如
RollingUpdate
或Recreate
)。
- 典型场景:需要滚动更新或回滚的无状态应用(如微服务)。
- 功能:管理 ReplicaSet 并提供声明式更新(如滚动升级、回滚)。
- DaemonSet
- 功能:确保每个节点(或指定节点)运行一个指定的 Pod。
- Pod 通常与节点绑定(如日志收集、网络插件)。
- 节点加入集群时自动创建 Pod,节点移除时删除。
- 典型场景:集群级守护进程(如
kube-proxy
、fluentd
)。
- 功能:确保每个节点(或指定节点)运行一个指定的 Pod。
- StateFulSet
- 功能:管理有状态应用的 Pod,提供稳定的标识和持久化存储。
- 每个 Pod 有唯一名称(如
web-0
、web-1
)和持久化存储(PVC)。 - 支持有序部署/扩展(按序号顺序操作)。
- 每个 Pod 有唯一名称(如
- 典型场景:数据库、分布式存储(如 MySQL、ZooKeeper)。
- 功能:管理有状态应用的 Pod,提供稳定的标识和持久化存储。
- Job/CronJob
- Job:
- 创建一次性 Pod 并确保其成功完成。
- 支持并行执行和重试机制。
- 场景:批处理任务(如数据处理)。
- CronJob:
- 基于时间表(Cron 表达式)周期性运行 Job。
- 场景:定时任务(如每日备份)。
- Job:
- Horizontal Pod Autoscaling
- 功能:根据 CPU 使用率或其他自定义指标自动调整 Pod 副本数。
- 与 ReplicaSet/Deployment 配合使用。
- 支持动态扩缩容(如流量高峰时扩容)。
- 典型场景:应对负载波动的服务(如电商大促)。
- 功能:根据 CPU 使用率或其他自定义指标自动调整 Pod 副本数。
二、ReplicationController 和 ReplicaSet
ReplicationController(RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收;
在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 。ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector;
1. 案例:ReplicationController
001-replication-controller.yaml
apiVersion: v1
kind: ReplicationController # 资源类型为 ReplicationController(旧版副本控制器)
metadata:
name: rc-demo # RC 的名称,在命名空间中唯一
namespace: default
spec:
replicas: 3 # 确保始终有 3 个 Pod 副本在运行
selector:
app: rc-demo # 选择标签为 `app: rc-demo` 的 Pod 进行管理
template: # Pod 模板
metadata:
labels:
app: rc-demo # 给 Pod 打上标签,与 selector 对应
spec:
containers:
- name: rc-demo-container # 容器名称
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
env: # 定义环境变量
- name: GET_HOSTS_FROM # 环境变量1 key
value: dns
- name: zhangsan # 环境变量2 key
value: "123"
ports:
- containerPort: 80 # 容器暴露的端口
运行 ReplicationController
kubectl apply -f 001-replication-controller.yaml
查看Pod的运行情况
kubectl get pod -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rc-demo-47nqt 1/1 Running 0 36s 172.16.85.199 k8s-node01 <none> <none>
rc-demo-74hbx 1/1 Running 0 36s 172.16.58.198 k8s-node02 <none> <none>
rc-demo-zp8ck 1/1 Running 0 36s 172.16.85.200 k8s-node01 <none> <none>
在两个node子节点上,运行了三个 Pod
测试Pod自动恢复
新起一个shell终端,杀死一个pod
kubectl delete pod rc-demo-74hbx
观察Pod运行情况
kubectl get pod -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rc-demo-47nqt 1/1 Running 0 36s 172.16.85.199 k8s-node01 <none> <none>
rc-demo-74hbx 1/1 Running 0 36s 172.16.58.198 k8s-node02 <none> <none>
rc-demo-zp8ck 1/1 Running 0 36s 172.16.85.200 k8s-node01 <none> <none>
rc-demo-74hbx 1/1 Terminating 0 63s 172.16.58.198 k8s-node02 <none> <none>
rc-demo-fgfmr 0/1 Pending 0 1s <none> <none> <none> <none>
rc-demo-fgfmr 0/1 Pending 0 1s <none> k8s-node02 <none> <none>
rc-demo-fgfmr 0/1 ContainerCreating 0 2s <none> k8s-node02 <none> <none>
rc-demo-74hbx 1/1 Terminating 0 65s 172.16.58.198 k8s-node02 <none> <none>
rc-demo-74hbx 0/1 Terminating 0 71s 172.16.58.198 k8s-node02 <none> <none>
rc-demo-74hbx 0/1 Terminating 0 75s <none> k8s-node02 <none> <none>
rc-demo-74hbx 0/1 Terminating 0 75s <none> k8s-node02 <none> <none>
rc-demo-74hbx 0/1 Terminating 0 75s <none> k8s-node02 <none> <none>
rc-demo-fgfmr 0/1 ContainerCreating 0 13s <none> k8s-node02 <none> <none>
rc-demo-fgfmr 1/1 Running 0 20s 172.16.58.199 k8s-node02 <none> <none>
杀死了 Pod rc-demo-74hbx
, k8s又自动创建了Pod rc-demo-fgfmr
。
2. 案例:ReplicaSet
2.1 RS yaml 文件
002-ReplicaSet.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replica-set-demo # rs的名字,全局唯一,生成的Pod的名字:replica-set-demo-xxxx
namespace: default
spec:
replicas: 3
selector:
matchLabels: # 基于标签匹配
app: rs-ml-demo # ReplicaSet 将管理带有标签 app=rs-ml-demo 的 Pod
template:
metadata:
namespace: default
labels: # 为 Pod 设置标签
app: rs-ml-demo # 给 Pod 打上标签 app=rs-ml-demo,与 selector 中的 matchLabels 对应
spec:
containers:
- name: rs-ml-container
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
env: # 定义容器的环境变量
- name: GET_HOSTS_FROM
value: dns
- name: George
value: "30"
ports:
- containerPort: 80
2.2 启动RS
kubectl apply -f 002-ReplicaSet.yaml
2.3 查看RS启动详情
kubectl describe replicaset replica-set-demo
Name: replica-set-demo
Namespace: default
Selector: app=rs-ml-demo
Labels: <none>
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=rs-ml-demo
Containers:
rs-ml-container:
Image: wangyanglinux/myapp:v1.0
Port: 80/TCP
Host Port: 0/TCP
Environment:
GET_HOSTS_FROM: dns
George: 30
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 67s replicaset-controller Created pod: replica-set-demo-p4tpb
Normal SuccessfulCreate 67s replicaset-controller Created pod: replica-set-demo-hnddq
Normal SuccessfulCreate 67s replicaset-controller Created pod: replica-set-demo-89pz7
RS 创建了3个 Pod 副本,均已启动成功。
2.4 查看 RS 启动的 Pod
根据 Pod 的标签过滤
kubectl get pods -l app=rs-ml-demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
replica-set-demo-89pz7 1/1 Running 0 2m58s 172.16.58.203 k8s-node02 <none> <none>
replica-set-demo-hnddq 1/1 Running 0 2m58s 172.16.85.202 k8s-node01 <none> <none>
replica-set-demo-p4tpb 1/1 Running 0 2m58s 172.16.58.202 k8s-node02 <none> <none>
2.5 查看Pod的日志
查看最近1000行日志
kubectl logs -f --tail=1000 replica-set-demo-89pz7
查看最近1小时的日志
kubectl logs -f --tail=1000 replica-set-demo-89pz7 --since=1h
2.6 验证Pod设置的环境变量是否有效
进入Pod容器
kubectl exec -it replica-set-demo-89pz7 /bin/bash
打印环境变量
replica-set-demo-89pz7:/# echo $GET_HOSTS_FROM
dns
replica-set-demo-89pz7:/# echo $George
30
2.7 验证RS对于Pod副本数量的自动恢复
在一个shell中监控RS
kubectl get replicaset replica-set-demo -o wide -w
在另一个shell中,杀死这个RS管理的其中一个Pod
kubectl delete pod replica-set-demo-89pz7
可以看到RS管理的Pod从最开始3个,变成2个,又迅速恢复成3个
kubectl get replicaset replica-set-demo -o wide -w
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replica-set-demo 3 3 3 10m rs-ml-container wangyanglinux/myapp:v1.0 app=rs-ml-demo
replica-set-demo 3 2 2 11m rs-ml-container wangyanglinux/myapp:v1.0 app=rs-ml-demo
replica-set-demo 3 3 2 11m rs-ml-container wangyanglinux/myapp:v1.0 app=rs-ml-demo
replica-set-demo 3 3 3 11m rs-ml-container wangyanglinux/myapp:v1.0 app=rs-ml-demo
2.8 验证 yaml 文件中定义的Pod的标签与RS标签选择器不一致时,是否可以启动
yaml文件如下:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replica-set-demo # rs命名,全局唯一
namespace: default
spec:
replicas: 3
selector:
matchLabels: # 基于标签匹配
app: rs-ml-demo # ReplicaSet 将管理带有标签 app=rs-ml-demo 的 Pod
template:
metadata:
namespace: default
labels: # 为 Pod 设置标签
app: rs-ml-demo-123 # 给 Pod 打上标签 app=rs-ml-demo,与 selector 中的 matchLabels 对应
spec:
containers:
- name: rs-ml-container
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
env:
- name: GET_HOSTS_FROM
value: dns
- name: George
value: "30"
ports:
- containerPort: 80
RS 标签选择器管理的标签是 rs-ml-demo , 而 Pod模板定义的标签是 rs-ml-demo-123 ,这样 RS 将无法管理此 Pod。
启动RS
kubectl apply -f 002-ReplicaSet.yaml
The ReplicaSet "replica-set-demo" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{"app":"rs-ml-demo-123"}: `selector` does not match template `labels`
启动报错,K8S不允许定义定Pod标签与RS标签选择器无法匹配的情况。
3. 标签选择器
在 Kubernetes 的 ReplicaSet(或其他资源如 Deployment、Service 等)中,matchLabels 是 selector 的一部分,用于指定如何选择要管理的 Pod。它基于标签(labels)进行匹配。matchLabels 本身只支持一种匹配模式:精确匹配(exact match),即键值对必须完全相等。但 Kubernetes 提供了更灵活的标签选择器机制,比如 matchExpressions,可以实现更复杂的匹配模式。
3.1 matchLabels 的匹配模式
定义:matchLabels 是一个键值对映射,要求被选中的 Pod 的标签与 matchLabels 中定义的键值对完全一致。
模式:仅支持精确匹配。
语法:
selector: matchLabels: key1: value1 key2: value2
行为:Pod 必须同时具备所有指定的标签键值对才能被选中。(Pod定的标签可以比 matchLabels 定义的标签多,但是不能比 matchLabels 定义的标签少,否则无法被 RS 管理)
示例: 在你的 ReplicaSet 配置中:
selector: matchLabels: app: rs-ml-demo key2: value2
- 这表示 ReplicaSet 只管理带有标签
app=rs-ml-demo
和key2=value2
的 Pod。 - Pod 的标签必须完全匹配
app: rs-ml-demo
和key2: value2
,多余的标签不会影响匹配,但缺少这个标签的 Pod 不会被选中。
- 这表示 ReplicaSet 只管理带有标签
3.2 matchExpressions 的匹配模式
Kubernetes 的 selector 还支持 matchExpressions,它提供了更丰富的匹配模式。matchExpressions 是一个可选字段,与 matchLabels 可以一起使用,允许基于逻辑运算进行标签选择。
它提供了更丰富的匹配模式。matchExpressions 是一个可选字段,与 matchLabels 可以一起使用,允许基于逻辑运算进行标签选择。
语法:
selector: matchLabels: app: rs-ml-demo matchExpressions: - {key: environment, operator: In, values: [prod, staging]}
支持的运算符(Operator):
- In:
- 标签的值必须在指定值列表中。
- 示例:environment 的值必须是 prod 或 staging。
- NotIn:
- 标签的值不能在指定值列表中。
- 示例:environment 的值不能是 dev 或 test。
- Exists:
- 标签键必须存在,值无要求。
- 示例:Pod 必须有 environment 标签,具体值不限。
- DoesNotExist:
- 标签键不能存在。
- 示例:Pod 不能有 environment 标签。
- In:
示例:
selector: matchExpressions: - {key: tier, operator: In, values: [frontend, backend]} - {key: deprecated, operator: DoesNotExist}
- 匹配条件:Pod 必须有 tier=frontend 或 tier=backend,且不能有 deprecated 标签。
3.3 matchLabels 和 matchExpressions 的关系
matchLabels 是简化的写法:它会被 Kubernetes 内部转换为等价的 matchExpressions,每个键值对对应一个 In 运算符。
例如:
matchLabels: app: rs-ml-demo
等价于:
matchExpressions: - {key: app, operator: In, values: [rs-ml-demo]}
组合使用:如果同时指定 matchLabels 和 matchExpressions,Pod 必须满足两者的条件(逻辑“与”关系)。
3.4 注意事项
- 一致性:selector.matchLabels(或 matchExpressions)必须与 template.metadata.labels 中的标签匹配,否则 ReplicaSet 无法正确管理 Pod。
- 大小写敏感:标签键和值是大小写敏感的,例如 app: Rs-ml-demo 和 app: rs-ml-demo 不匹配。
- Service 的选择器:虽然问题聚焦于 ReplicaSet,但值得一提的是 Service 的 selector 只支持 matchLabels 风格的精确匹配,不支持 matchExpressions。
3.5 实际案例
003-matchExpressions.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-me-exists-demo
spec:
replicas: 3
selector:
matchExpressions:
- key: app # Pod 必须有 app 标签
operator: Exists
- key: version # Pod 必须有 version=v1 或 version=v2
operator: In
values:
- v1
- v2
- key: souce # Pod不能有 souce 标签
operator: DoesNotExist
template:
metadata:
namespace: default
labels: # 为 Pod 设置标签
app: rs-ml-demo # 给 Pod 打上标签 app=rs-ml-demo,与 selector 中的 matchLabels 对应
version: v1
spec:
containers:
- name: rs-ml-container
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
env: # 定义容器的环境变量
- name: GET_HOSTS_FROM
value: dns
- name: George
value: "30"
ports:
- containerPort: 80
3.6 总结
- matchLabels:只支持精确匹配,键值对必须完全相等。
- matchExpressions(扩展功能):支持 In、NotIn、Exists、DoesNotExist 四种模式,提供更灵活的匹配。
三、Deployment 控制器
1. Deployment - 基本概念
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义 ( declarative ) 方法,用来替代以前的 ReplicationController 来方便的管理应用。典型的应用场景包括:
- 定义 Deployment 来创建 Pod 和 ReplicaSet
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续 Deployment
2. Deployment - 与 RS 的关联
Deployment 是通过创建 ReplicaSet 来间接的管理 Pod。
3. Deployment - 常用命令
根据资源清单创建 deployment
--record 参数可以记录命令,我们可以很方便的查看每次 revision 的变化
kubectl create -f deployment.yaml --record
修改 Deployment 类型的 Pod 的数量
kubectl scale deployment nginx-deployment --replicas 10
设置 Pod 自动扩缩容,最大15个,最小 10个,扩缩依据:CPU利用率是否超过 80%
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
更新 deployment 类型的Pod nginx-deployment 下的容器 nginx-deployment-container 的镜像为:wangyanglinux/myapp:v2.0
kubectl set image deployment/nginx-deployment nginx-deployment-container=wangyanglinux/myapp:v2.0
回滚Pod变更 (只能回滚到前一次变更操作,如:1 -> 2 -> 3, 第一次回滚回到2,第二次回滚则回到3,无法回滚到)
kubectl rollout undo deployment/nginx-deployment
4. apply 、create、replace 区别
kubectl create -f deployment.yaml
和 kubectl apply -f deployment.yaml
都是用于创建或更新 Kubernetes 资源的命令,但它们在行为上有关键区别,主要涉及 声明式管理 和 命令式管理 的不同逻辑。
4.1 命令式命令
kubectl create -f deployment.yaml
- 作用:严格创建新资源。
- 行为:
- 如果资源(如 Deployment)已存在,会报错并拒绝执行(报
AlreadyExists
错误)。 - 仅适用于首次创建,不能用于更新。
- 如果资源(如 Deployment)已存在,会报错并拒绝执行(报
- 适用场景:
- 你明确知道资源不存在,且只需要一次性创建。
- 脚本中需要严格避免覆盖现有配置时。
示例输出(资源已存在时):
Error from server (AlreadyExists): deployments.apps "deployment-demo-1" already exists
4.2 声明式命令
- 作用:创建或更新资源,智能合并变更。
- 行为:
- 如果资源不存在,则创建它(等同于
create
)。 - 如果资源已存在,则对比当前配置和 YAML 文件的差异,增量更新(保留未修改的字段)。
- 依赖
metadata.annotations
中的kubectl.kubernetes.io/last-applied-configuration
记录上次配置,用于计算变更。
- 如果资源不存在,则创建它(等同于
- 适用场景:
- 日常维护(例如更新镜像版本、调整副本数)。
- GitOps 或 CI/CD 流程中(推荐使用
apply
而非create
)。
示例输出(更新时):
deployment.apps/deployment-demo-1 configured
4.3 关键区别总结
特性 | kubectl create |
kubectl apply |
---|---|---|
资源已存在 | 报错,拒绝执行 | 合并更新 |
资源不存在 | 创建资源 | 创建资源 |
管理方式 | 命令式(直接执行) | 声明式(对比差异后更新) |
记录变更 | 无 | 记录到 last-applied-configuration |
适用场景 | 一次性创建 | 持续维护(创建 + 更新) |
4.4 kubectl replace -f
- 类似
create
,但会强制替换现有资源(需资源已存在)。 - 与
apply
不同:不合并字段,直接覆盖整个配置(可能丢失未指定的字段)。 - 慎用,通常仅在需要完全重置配置时使用。
建议:
- **优先使用
apply
**(声明式操作更符合 Kubernetes 设计理念)。 - 仅在需要严格控制创建时使用
create
。 - 自动化流程:推荐始终使用
apply
(避免因资源存在导致失败)。
5. Deployment - 案例实操
5.1 编写资源清单
004-deployment-demo.yaml
apiVersion: apps/v1 # 版本号
kind: Deployment # 控制器类型为:Deployment
metadata:
labels:
app: deployment-demo # 控制器标签
name: deployment-demo-1 # 控制器名称
spec:
replicas: 1 # 初始Pod副本数
selector:
matchLabels:
app: deployment-demo # Pod标签选择器,管理 标签为 app: deployment-demo 的Pod
template:
metadata:
labels:
app: deployment-demo # Pod的标签,与 selector 标签选择器对应
spec:
containers:
- image: wangyanglinux/myapp:v1.0 # 容器使用的镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略
name: deployment-demo-container # 镜像
5.2 创建 Deployment
根据资源清单创建 Deployment 和对应的 Pod
kubectl apply -f 004-deployment-demo.yaml
5.3 查看 Deployment 和 Pod
查看 Deployment 信息
kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment-demo-1 1/1 1 1 2m21s deployment-demo-container wangyanglinux/myapp:v1.0 app=deployment-demo
可以看到创建一个 Deployment 类型的控制器,名称为:deployment-demo-1, 标签为:app=deployment-demo,控制器内 Pod的副本数为 1。
查看 Deployment 详细信息
kubectl get deployment deployment-demo-1 -o yaml
内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1" # 当前修订版本号(用于回滚)
kubectl.kubernetes.io/last-applied-configuration: | # 上次 kubectl apply 使用的完整配置(用于对比变更)
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"deployment-demo"},"name":"deployment-demo-1","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"deployment-demo"}},"template":{"metadata":{"labels":{"app":"deployment-demo"}},"spec":{"containers":[{"image":"wangyanglinux/myapp:v1.0","imagePullPolicy":"IfNotPresent","name":"deployment-demo-container"}]}}}}
creationTimestamp: "2025-04-09T01:59:05Z"
generation: 1
labels:
app: deployment-demo
name: deployment-demo-1
namespace: default
resourceVersion: "1484447"
uid: 8cec6671-c1e9-4292-921c-dbe8bae8c357
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10 # 保留最近 10 个历史版本(用于回滚),超出部分会被自动清理
selector:
matchLabels:
app: deployment-demo
strategy:
rollingUpdate: # 滚动更新策略 (strategy)
maxSurge: 25% # 允许临时超出期望副本数的比例(例如 1.25 个 Pod)
maxUnavailable: 25% # 更新时允许不可用的 Pod 比例(例如最多 0.75 个 Pod 不可用)
type: RollingUpdate # 更新策略类型: 滚动更新,逐步替换旧 Pod,确保服务不中断。
template:
metadata:
creationTimestamp: null
labels:
app: deployment-demo
spec:
containers:
- image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
name: deployment-demo-container
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30 # 终止前等待 30 秒(优雅退出)
status:
availableReplicas: 1 # 当前可用的 Pod 数量
conditions:
- lastTransitionTime: "2025-04-09T01:59:07Z"
lastUpdateTime: "2025-04-09T01:59:07Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2025-04-09T01:59:05Z"
lastUpdateTime: "2025-04-09T01:59:07Z"
message: ReplicaSet "deployment-demo-1-6995c75668" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1 # 已就绪的 Pod 数量
replicas: 1 # 实际运行的 Pod 数量
updatedReplicas: 1 # 已更新到最新版本的 Pod 数量
查看Pod
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-demo-1-6995c75668-klh7h 1/1 Running 0 33m 172.16.58.208 k8s-node02 <none> <none>
注意看 Pod 的名字是 deployment-demo-1-6995c75668-klh7h
,这是由 Deployment 创建时,自动创建了 对应的 ReplicaSet 的名字(deployment-demo-1-6995c75668
) 再拼接上 随机字符串:klh7h
生成的,可以查看是否有 ReplicaSet 验证:
kubectl get rs
NAME DESIRED CURRENT READY AGE
deployment-demo-1-6995c75668 1 1 1 33m
5.4 Pod 副本扩缩容
查看当前Pod副本数
kubectl get pods
NAME READY STATUS RESTARTS AGE
deployment-demo-1-6995c75668-klh7h 1/1 Running 0 29h
扩展 Pod 数量
kubectl scale deployment deployment-demo-1 --replicas 10
再次查看 Pod 数量
kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-demo-1-6995c75668-44fnz 1/1 Running 0 10s
deployment-demo-1-6995c75668-64zdm 1/1 Running 0 10s
deployment-demo-1-6995c75668-9xxbc 1/1 Running 0 10s
deployment-demo-1-6995c75668-klh7h 1/1 Running 0 29h
deployment-demo-1-6995c75668-kqqhj 1/1 Running 0 10s
deployment-demo-1-6995c75668-mmdrx 1/1 Running 0 10s
deployment-demo-1-6995c75668-twr24 1/1 Running 0 10s
deployment-demo-1-6995c75668-vq67h 1/1 Running 0 10s
deployment-demo-1-6995c75668-wpq6x 1/1 Running 0 10s
deployment-demo-1-6995c75668-zxvwc 1/1 Running 0 10s
缩小 Pod 副本数
kubectl scale deployment deployment-demo-1 --replicas 1
再次查看Pod
kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-demo-1-6995c75668-klh7h 1/1 Running 0 29h
5.5 动态更新 Deployment 的 Pod 容器镜像
当前资源清单中使用的镜像是:wangyanglinux/myapp:v1.0
,现在测试在不停止Pod运行的情况下,将镜像升级到 wangyanglinux/myapp:v2.0
查看当前运行中的Pod
创建 Pod
kubectl create -f 004-deployment-demo.yaml --record
查看Pod
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-demo-1-6995c75668-4rljk 1/1 Running 0 28m 172.16.58.213 k8s-node02 <none> <none>
访问Pod,确认当前版本是 1.0
curl 172.16.58.213
www.xinxianghf.com | hello MyAPP | version v1.0
命令后面添加 --record
目的是为了让 kubectl 记住Pod操作历史,以便于后期回滚操作。
升级容器镜像版本
kubectl set image deployment/deployment-demo-1 deployment-demo-container=wangyanglinux/myapp:v2.0 --record
查看Pod
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-demo-1-6465d4c5c9-b5dsn 1/1 Running 0 89s 172.16.58.214 k8s-node02 <none> <none>
访问Pod,镜像版本已更新到 2.0
curl 172.16.58.214
www.xinxianghf.com | hello MyAPP | version v2.0
查看Pod更新的历史记录
kubectl rollout history deployment/deployment-demo-1
deployment.apps/deployment-demo-1
REVISION CHANGE-CAUSE
1 kubectl apply --filename=004-deployment-demo.yaml --record=true
2 kubectl set image deployment/deployment-demo-1 deployment-demo-container=wangyanglinux/myapp:v2.0 --record=true
6. Deployment 滚动升级
在 Kubernetes 中,Deployment 是管理 Pod 副本和实现无缝升级的核心资源。滚动升级(Rolling Update) 是默认的更新策略,它允许逐步替换旧版本的 Pod,确保应用在升级过程中不中断服务。
6.1 滚动升级的核心机制
(1)更新流程
- 创建新版本的 ReplicaSet
- 当修改 Deployment 的 Pod 模板(如镜像版本)时,Kubernetes 会创建一个新的 ReplicaSet。
- 新 ReplicaSet 逐步启动新 Pod,旧 ReplicaSet 逐步缩减旧 Pod。
- 逐步替换 Pod
- 通过
maxSurge
和maxUnavailable
控制替换速度:- **
maxSurge
**:允许临时超出replicas
的 Pod 数量(默认 25%)。 - **
maxUnavailable
**:升级过程中允许不可用的 Pod 比例(默认 25%)。
- **
- 通过
- 完成升级
- 所有旧 Pod 被替换后,旧 ReplicaSet 保留(便于回滚),但 Pod 数为 0。
(2)关键配置参数
在 Deployment 的 spec.strategy
中定义:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 允许临时多启动 25% 的 Pod(例如 replicas=4 时,最多 5 个 Pod)
maxUnavailable: 25% # 允许最多 25% 的 Pod 不可用(例如 replicas=4 时,至少 3 个 Pod 可用)
6.2 触发滚动升级的方式
(1)直接修改 YAML 并应用
kubectl apply -f deployment.yaml
适用于通过版本控制的 YAML 文件管理部署。
(2)命令式更新镜像版本
kubectl set image deployment/<deployment-name> <container-name>=<new-image>:<tag>
例如:
kubectl set image deployment/deployment-demo-1 deployment-demo-container=wangyanglinux/myapp:v2.0
(3)其他可触发升级的操作
- 修改环境变量、资源限制(CPU/内存)、标签等 Pod 模板内容。
- 调整副本数(
kubectl scale
)不会触发滚动升级。
6.3 查看升级状态
(1)检查升级进度
kubectl rollout status deployment/<deployment-name>
输出示例:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
(2)查看历史版本
kubectl rollout history deployment/<deployment-name>
输出示例:
REVISION CHANGE-CAUSE
1 kubectl apply --filename=deployment.yaml
2 kubectl set image deployment/deployment-demo-1 deployment-demo-container=myapp:v2.0
(3)查看具体版本的配置
kubectl rollout history deployment/<deployment-name> --revision=<revision-number>
例如:
kubectl rollout history deployment/deployment-demo-1 --revision=2
6.4 回滚升级
如果新版本出现问题,可快速回滚到之前的版本:
(1)回滚到上一个版本
kubectl rollout undo deployment/<deployment-name>
(2)回滚到指定版本
kubectl rollout undo deployment/<deployment-name> --to-revision=<revision-number>
例如:
kubectl rollout undo deployment/deployment-demo-1 --to-revision=1
6.5 高级控制技巧
(1)暂停/恢复升级
暂停升级(手动分阶段发布):
kubectl rollout pause deployment/<deployment-name>
恢复升级:
kubectl rollout resume deployment/<deployment-name>
(2)强制重建 Pod(非滚动更新)
删除所有 Pod 触发重建(慎用):
kubectl delete pods -l app=<deployment-label>
(3)修改默认滚动策略
默认滚动策略如下:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 允许临时多启动 25% 的 Pod(例如 replicas=4 时,最多 5 个 Pod)
maxUnavailable: 25% # 允许最多 25% 的 Pod 不可用(例如 replicas=4 时,至少 3 个 Pod 可用)
查看当前 Deployment 滚动策略:
$kubectl get deployment my-deployment-demo -o jsonpath='{.spec.strategy}'
{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"}
修改滚动策略,
$kubectl edit deployment my-deployment-demo --record
修改完成后保存,会自动生效。
6.6 故障排查
(1)升级卡住怎么办?
检查事件:
kubectl describe deployment/<deployment-name>
查看 Pod 状态:
kubectl get pods
(2)常见原因
- 镜像拉取失败:检查镜像名称或权限。
- 资源不足:节点 CPU/内存不足。
- 就绪探针失败:新版本 Pod 未通过健康检查。
7. 滚动升级案例实操
演示一个 Deployment 下有多个 Pod 副本(10个),升级镜像版本,以及回退版本相关操作。
7.1 资源清单
005-deployment-demo.yaml
apiVersion: apps/v1 # 版本号
kind: Deployment # 控制器类型为:Deployment
metadata:
labels:
app: deployment-demo # 控制器标签
name: my-deployment-demo # 控制器名称
spec:
replicas: 1 # 初始Pod副本数
selector:
matchLabels:
app: deployment-demo # Pod标签选择器,管理 标签为 app: deployment-demo 的Pod
template:
metadata:
labels:
app: deployment-demo # Pod的标签,与 selector 标签选择器对应
spec:
containers:
- name: deployment-demo-container # 容器名称
image: wangyanglinux/myapp:v1.0 # 容器使用的镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略
7.2 创建 Service
创建Service的目的是为了通过访问 service,查看 Pod 滚动升级的过程。
创建 Service
kubectl create svc clusterip deployment-demo --tcp=80:80
查看 Service
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deployment-demo ClusterIP 10.103.97.136 <none> 80/TCP 5m53s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
while 命令循环访问 service
while true; do curl 10.103.97.136; done
7.3 创建Deloyment
# 创建 Deployment ,添加了 --record 会记录操作的命令详情
$ kubectl create -f 005-deployment-demo.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/my-deployment-demo created
# 查看 Deployment
$ kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-deployment-demo 1/1 1 1 3s deployment-demo-container wangyanglinux/myapp:v1.0 app=deployment-demo
7.4 Pod副本扩容
# 将当前Pod数量从1个,扩容到10个
$ kubectl scale deployment my-deployment-demo --replicas 10
deployment.apps/my-deployment-demo scaled
# 查看Deployment
$ kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-deployment-demo 10/10 10 10 2m49s deployment-demo-container wangyanglinux/myapp:v1.0 app=deployment-demo
# 查看Pod
$ kubectl get pod -l app=deployment-demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-deployment-demo-6995c75668-5fxrj 1/1 Running 0 2m31s 172.16.85.211 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-977kq 1/1 Running 0 2m31s 172.16.58.223 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-lq4kj 1/1 Running 0 2m31s 172.16.58.221 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-mvdsm 1/1 Running 0 2m31s 172.16.58.220 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-rt2wp 1/1 Running 0 2m31s 172.16.85.208 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-ssx86 1/1 Running 0 2m31s 172.16.58.222 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-v69wv 1/1 Running 0 2m31s 172.16.85.210 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-vvjg2 1/1 Running 0 2m31s 172.16.85.212 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-whc7z 1/1 Running 0 5m3s 172.16.58.219 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-zsgg9 1/1 Running 0 2m31s 172.16.85.209 k8s-node01 <none> <none>
7.5 查看当前Pod的镜像版本
$ while true; do curl 10.103.97.136; done
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
当前访问的所有Pod 镜像版本都是 1.0
7.6 升级 Pod 镜像版本
新开一个shell终端,执行命令升级镜像版本,前一个shell终端循环访问pod,打印Pod镜像版本信息
# 升级镜像版本,并打印当前pod详细信息
$ kubectl set image deployment/my-deployment-demo deployment-demo-container=wangyanglinux/myapp:v2.0 --record && kubectl get pod -l app=deployment-demo -o wide
deployment.apps/my-deployment-demo image updated
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-deployment-demo-6465d4c5c9-crrcz 0/1 Pending 0 0s <none> k8s-node02 <none> <none>
my-deployment-demo-6465d4c5c9-fckht 0/1 ContainerCreating 0 0s <none> k8s-node02 <none> <none>
my-deployment-demo-6465d4c5c9-tkjst 0/1 ContainerCreating 0 0s <none> k8s-node01 <none> <none>
my-deployment-demo-6995c75668-2fg6c 1/1 Running 0 12m 172.16.58.229 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-bhs4q 1/1 Running 0 11m 172.16.85.221 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-fj7hf 1/1 Running 0 11m 172.16.85.220 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-p7bhr 1/1 Running 0 11m 172.16.85.218 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-qbdmg 1/1 Running 0 11m 172.16.58.230 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-qprl6 1/1 Running 0 11m 172.16.85.222 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-qtdbb 1/1 Terminating 0 11m 172.16.58.232 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-r2xvv 1/1 Running 0 11m 172.16.85.219 k8s-node01 <none> <none>
my-deployment-demo-6995c75668-sg7vt 1/1 Terminating 0 11m 172.16.58.233 k8s-node02 <none> <none>
my-deployment-demo-6995c75668-wbqn2 1/1 Running 0 11m 172.16.58.231 k8s-node02 <none> <none>
此时Pod正在升级滚动升级中,当前看到共有13个Pod,这是因为Pod在滚动升级的过程中,默认允许新增不超过原设定副本数 25% 副本数量(maxSurge: 25%
)。(上面的打印结果有2个Pod的状态是 Terminating,运行中和加载中的Pod数没有超过原设备Pod数的 125%)
查看前一个shell终端的打印结果如下:
w.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v2.0
www.xinxianghf.com | hello MyAPP | version v2.0
www.xinxianghf.com | hello MyAPP | version v2.0
www.xinxianghf.com | hello MyAPP | version v1.0
curl: (7) Failed to connect to 10.103.97.136 port 80: Connection refused
www.xinxianghf.com | hello MyAPP | version v1.0
curl: (7) Failed to connect to 10.103.97.136 port 80: Connection refused
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v2.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v2.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
curl: (7) Failed to connect to 10.103.97.136 port 80: Connection refused
curl: (7) Failed to connect to 10.103.97.136 port 80: Connection refused
www.xinxianghf.com | hello MyAPP | version v2.0
curl: (7) Failed to connect to 10.103.97.136 port 80: Connection refused
www.xinxianghf.com | hello MyAPP | version v1.0
curl: (7) Failed to connect to 10.103.97.136 port 80: Connection refused
www.xinxianghf.com | hello MyAPP | version v1.0
www.xinxianghf.com | hello MyAPP | version v1.0
可以得出如下结论:
- 通过访问 Service 会轮询访问 lable 名称与 Service 名称一样的 Pod
- Pod 正处于滚动升级的过程中,打印的镜像版本有的是 1.0,有的是 2.0,有的处于 Terminating 状态,不可访问
8. Deloyment 回滚案例实操
8.1 资源清单
006-deployment-demo.yaml
apiVersion: apps/v1 # 版本号
kind: Deployment # 控制器类型为:Deployment
metadata:
labels:
app: deployment-demo # 控制器标签
name: my-deployment-demo # 控制器名称
spec:
replicas: 1 # 初始Pod副本数
selector:
matchLabels:
app: deployment-demo # Pod标签选择器,管理 标签为 app: deployment-demo 的Pod
template:
metadata:
labels:
app: deployment-demo # Pod的标签,与 selector 标签选择器对应
spec:
containers:
- name: deployment-demo-container # 容器名称
image: wangyanglinux/myapp:v1.0 # 容器使用的镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略
8.2 创建Deployment
# 1.创建 Service
$ kubectl create svc clusterip deployment-demo --tcp=80:80
# 查看 Service
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deployment-demo ClusterIP 10.103.97.136 <none> 80/TCP 5m53s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
# 2.创建 Deployment ,添加了 --record 会记录操作的命令详情
$ kubectl create -f 006-deployment-demo.yaml --record
# 3. 将当前Pod数量从1个,扩容到10个
$ kubectl scale deployment my-deployment-demo --replicas 10
# 查看Deployment
$ kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-deployment-demo 10/10 10 10 2m49s deployment-demo-container wangyanglinux/myapp:v1.0 app=deployment-demo
# 查看当前 Pod 镜像版本
$ curl 10.103.97.136
www.xinxianghf.com | hello MyAPP | version v1.0
8.3 升级镜像
# 1. 将镜像版本升级到 2.0
$ kubectl set image deployment/my-deployment-demo deployment-demo-container=wangyanglinux/myapp:v2.0 --record
# 测试访问镜像
$ curl 10.103.97.136
www.xinxianghf.com | hello MyAPP | version v2.0
# 2. 将镜像版本升级到 3.0
$ kubectl set image deployment/my-deployment-demo deployment-demo-container=wangyanglinux/myapp:v3.0 --record
# 测试访问镜像
$ curl 10.103.97.136
www.xinxianghf.com | hello MyAPP | version v3.0
# 3. 查看 Deployment 历史版本(创建Deployment、升级镜像命令都添加了 --record 参数,所以CHANGE-CAUSE才有操作记录)
$ kubectl rollout history deployment/my-deployment-demo
deployment.apps/my-deployment-demo
REVISION CHANGE-CAUSE
1 kubectl apply --filename=006-deployment-demo.yaml --record=true
2 kubectl set image deployment/my-deployment-demo deployment-demo-container=wangyanglinux/myapp:v2.0 --record=true
3 kubectl set image deployment/my-deployment-demo deployment-demo-container=wangyanglinux/myapp:v3.0 --record=true
8.4 回滚镜像版本
6.4.1 回滚到上一个版本
# 1.回滚到上一个版本(从3.0 -> 2.0)
$ kubectl rollout undo deployment/my-deployment-demo
# 测试访问镜像(此时已回滚到 2.0版本)
$ curl 10.103.97.136
www.xinxianghf.com | hello MyAPP | version v2.0
# 2.再次执行版本回滚
$ kubectl rollout undo deployment/my-deployment-demo
# 测试访问镜像(此时又回滚到 3.0版本)
$ curl 10.103.97.136
www.xinxianghf.com | hello MyAPP | version v3.0
kubectl rollout undo deployment/<deployment-demo>
命令只能回滚到前一次操作,但无法回滚到前前上操作,例如升级操作如下:
v1 -> v2 -> v3
升级到v3版本后开始回滚:v1 -> v2 -> v3 -> v2 -> v3 -> v2 -> v3 ,
这样无法从 v3 -> v1
8.4.2 回滚到指定版本
前面的每次升级操作命令,都携带了参数 --record
,此参数会让 kubectl 记录操作命令,通过查看 deployment 历史版本,方便版本回滚。
# 1.查看 Deployment 历史版本(REVISION 就是每次操作后的版本号)
$ kubectl rollout history deployment/my-deployment-demo
deployment.apps/my-deployment-demo
REVISION CHANGE-CAUSE
1 kubectl apply --filename=006-deployment-demo.yaml --record=true
4 kubectl set image deployment/my-deployment-demo deployment-demo-container=wangyanglinux/myapp:v2.0 --record=true
5 kubectl set image deployment/my-deployment-demo deployment-demo-container=wangyanglinux/myapp:v3.0 --record=true
# 2.回滚到 v1.0 版本(通过指定版本号)
$ kubectl rollout undo deployment my-deployment-demo --to-revision=1
# 测试访问镜像(此时回滚到 1.0版本)
$ curl 10.103.97.136
www.xinxianghf.com | hello MyAPP | version v1.0
9. Deployment 清理策略
过设置 .spec.revisionHistoryLimit
项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment 就不允许回退了
四、DaemonSet 控制器
1. 基本概念
在 Kubernetes 中,DaemonSet 控制器用于确保集群中的每个节点(或指定节点子集)都运行一个 Pod 副本。通常用于部署系统级别的服务,例如日志收集代理(如 Fluentd、Logstash)、监控代理(如 Prometheus Node Exporter)或网络代理(如 kube-proxy)。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod
使用 DaemonSet 的一些典型用法:
- 运行集群存储 daemon,例如在每个 Node 上运行
glusterd
、ceph
- 在每个 Node 上运行日志收集 daemon,例如
fluentd
、logstash
- 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、
collectd
、Datadog 代理、New Relic 代理,或 Gangliagmond
2. DaemonSet 的核心特性
- 自动调度:DaemonSet 确保每个符合条件的节点上运行一个 Pod。如果节点被添加或移除,DaemonSet 会自动调整。
- Pod 一致性:所有 Pod 通常使用相同的 Pod 模板运行。
- 节点选择:可以通过 nodeSelector 或 taints/tolerations 控制 DaemonSet 在哪些节点上运行。
- 更新策略:支持 RollingUpdate 和 OnDelete 两种更新策略,默认是 RollingUpdate。
3. 案例演示
3.1 资源清单
007-DaemonSet-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: my-daemonset-demo # DaemonSet 控制器的名字
namespace: default # 命名空间
labels:
app: daemonset-demo # DaemonSet 控制的标签
spec:
selector:
matchLabels:
name: daemonset-demo # 匹配标签为 name: daemonset-demo 的Pod
template:
metadata:
labels: # Pod模板标签,与 spec.selector.matchLabels 对应
name: daemonset-demo
spec:
containers: # 主容器
- name: daemonset-demo-container
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
3.1 创建 DaemonSet
# 创建 DaemonSet 控制器
$ kubectl apply -f 007-DaemonSet-demo.yaml
3.2 查看 DeamonSet
# 查看 DaemonSet (指定了 名称空间、标签)
$ kubectl get ds -n default -l app=daemonset-demo -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
my-daemonset-demo 2 2 2 2 2 <none> 4m5s daemonset-demo-container wangyanglinux/myapp:v1.0 name=daemonset-demo
3.3 查看 Pod
$ kubectl get pod -n default -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-daemonset-demo-kltsf 1/1 Running 0 36s 172.16.58.215 k8s-node02 <none> <none>
my-daemonset-demo-tn554 1/1 Running 0 36s 172.16.85.211 k8s-node01 <none> <none>
DanmonSet 控制器自动创建了两个 Pod,分别运行到两个子节点上(k8s-node01、k8s-node02),而没有运行到 master 节点,这是为什么呢?
3.4 为什么 DeamonSet 没有运行在主节点上
在 Kubernetes 中,DaemonSet 创建的 Pod 默认不会运行到主节点(master 或 control-plane 节点),主要是因为主节点通常被配置了污点(Taints),而 DaemonSet 创建的 Pod 没有默认的容忍(Tolerations)来匹配这些污点。以下是详细原因及机制:
3.4.1 主节点的污点(Taints)
Kubernetes 主节点通常被配置了一个或多个污点,以防止普通的工作负载(包括 DaemonSet 的 Pod)调度到这些节点上。常见的污点是:
- node-role.kubernetes.io/master:NoSchedule(Kubernetes 1.24 及更早版本)
- node-role.kubernetes.io/control-plane:NoSchedule(Kubernetes 1.25 及更新版本)
这些污点的效果是 NoSchedule,表示除非 Pod 明确声明可以容忍该污点,否则不会被调度到主节点。
查看主节点污点:
kubectl describe node <master-node-name> | grep -i taint
示例输出:
Taints: node-role.kubernetes.io/control-plane:NoSchedule
3.4.2 DaemonSet Pod 的容忍(Tolerations)
DaemonSet 的 Pod 模板(spec.template.spec)默认不包含任何 tolerations。这意味着它们无法绕过主节点的 NoSchedule 污点,因此不会被调度到主节点。
例如资源清单 007-DaemonSet-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: my-daemonset-demo # DaemonSet 控制器的名字
namespace: default # 命名空间
labels:
app: daemonset-demo # DaemonSet 控制的标签
spec:
selector:
matchLabels:
name: daemonset-demo # 匹配标签为 name: daemonset-demo 的Pod
template:
metadata:
labels: # Pod模板标签,与 spec.selector.matchLabels 对应
name: daemonset-demo
spec:
containers: # 主容器
- name: daemonset-demo-container
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
在这个配置中,spec.template.spec 没有定义 tolerations,因此 Pod 不会调度到带有 NoSchedule 污点的主节点。
3.4.3 为什么主节点需要污点?
主节点运行控制平面组件(如 kube-apiserver、kube-scheduler、kube-controller-manager),这些组件对集群的稳定性至关重要。允许普通工作负载(如 DaemonSet 的 Pod)运行在主节点可能会导致以下问题:
- 资源竞争:DaemonSet Pod 可能消耗 CPU、内存等资源,影响控制平面组件的性能。
- 稳定性风险:某些 DaemonSet Pod(例如日志收集或监控代理)可能出现异常,干扰主节点的运行。
- 安全隔离:主节点通常需要更高的隔离级别,避免不受信任的工作负载运行。
因此,Kubernetes 默认通过污点机制保护主节点,只允许特定的、必要的 Pod(如控制平面组件或特定的系统 DaemonSet)运行。
3.4.4 例外情况:系统 DaemonSet
某些系统级的 DaemonSet(如 kube-proxy、CNI 插件)确实需要运行在所有节点上,包括主节点。这些 DaemonSet 的 YAML 通常会显式配置 tolerations 来容忍主节点的污点。例如:
spec:
template:
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
这种配置允许 Pod 忽略主节点的污点,从而调度到主节点。
3.4.5 如何让 DaemonSet Pod 运行在主节点?
如果你希望 DaemonSet 的 Pod 运行在主节点上,可以在 DaemonSet 的 Pod 模板中添加相应的 tolerations。
查看节点列表
$ kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-node01 Ready <none> 14d v1.29.15 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux
k8s-node02 Ready <none> 14d v1.29.15 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux
node Ready control-plane 14d v1.29.15 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
可以看到有三个节点,其中 name为 node 的就是 master 节点,因为该节点的标签中包含:node-role.kubernetes.io/control-plane
查看 master 节点详情
$ kubectl describe nodes node
Name: node
Roles: control-plane
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=node
kubernetes.io/os=linux
node-role.kubernetes.io/control-plane=
node.kubernetes.io/exclude-from-external-load-balancers=
Annotations: kubeadm.alpha.kubernetes.io/cri-socket: unix:///var/run/cri-dockerd.sock
node.alpha.kubernetes.io/ttl: 0
projectcalico.org/IPv4Address: 192.168.6.139/24
projectcalico.org/IPv4IPIPTunnelAddr: 172.16.167.128
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Fri, 28 Mar 2025 17:24:27 +0800
# Node自身设置的污点,key为node-role.kubernetes.io/control-plane,影响效果::NoSchedule(不是key的值)
Taints: node-role.kubernetes.io/control-plane:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: node
AcquireTime: <unset>
RenewTime: Sat, 12 Apr 2025 14:07:56 +0800
...
资源清单内容如下:008-DaemonSet-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: my-daemonset-demo # DaemonSet 控制器的名字
namespace: default # 命名空间
labels:
app: daemonset-demo # DaemonSet 控制的标签
spec:
selector:
matchLabels:
name: daemonset-demo # 匹配标签为 name: daemonset-demo 的Pod
template:
metadata:
labels: # Pod模板标签,与 spec.selector.matchLabels 对应
name: daemonset-demo
spec:
tolerations: # 定义了 Pod 的容忍度,允许 Pod 被调度到带有特定污点的节点上
- key: node-role.kubernetes.io/control-plane # 这里允许 Pod 被调度到控制平面节点(通常有 node-role.kubernetes.io/control-plane:NoSchedule 污点)
operator: Exists # 表示只要存在指定的 key 就容忍(Exists:只要节点上有这个键的污点就匹配(不需要检查值), 如果是Equal:要求键和值都匹配(此时需要指定 value 字段))
effect: NoSchedule # 指定要容忍污点的影响效果
containers: # 主容器
- name: daemonset-demo-container
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
创建 DaemonSet
# 创建DS
$ kubectl apply -f 008-DaemonSet-demo.yaml --record
# 查看DS,可以看到DS运行了三个 Pod
$ kubectl get ds -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
my-daemonset-demo 3 3 3 3 3 <none> 2m33s daemonset-demo-container wangyanglinux/myapp:v1.0 name=daemonset-demo
# 查看Pod(master节点也运行了一个Pod)
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-daemonset-demo-gsjlk 1/1 Running 0 11s 192.168.167.141 node <none> <none>
my-daemonset-demo-j5nls 1/1 Running 0 11s 192.168.58.200 k8s-node02 <none> <none>
my-daemonset-demo-vv9cf 1/1 Running 0 11s 192.168.85.204 k8s-node01 <none> <none>
查看Pod
# 查看 DaemonSet,此时 DeamonSet 控制器有了三个Pod
$ kubectl get ds -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
my-daemonset-demo 3 3 3 3 3 <none> 135m daemonset-demo-container wangyanglinux/myapp:v1.0 name=daemonset-demo
# 查看 Pod
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-daemonset-demo-gsjlk 1/1 Running 1 (129m ago) 137m 192.168.167.142 node <none> <none>
my-daemonset-demo-j5nls 1/1 Running 1 (129m ago) 137m 192.168.58.201 k8s-node02 <none> <none>
my-daemonset-demo-vv9cf 1/1 Running 1 (129m ago) 137m 192.168.85.205 k8s-node01 <none> <none>
master 节点上也运行了一个 Pod,资源清单配置生效。
五、Job 控制器
1. Job 控制器特性
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束
特殊说明
- spec.template 格式同 Pod
- RestartPolicy 仅支持 Never 或 OnFailure
- 单个 Pod 时,默认 Pod 成功运行后 Job 即结束
.spec.completions
标志 Job 结束需要成功运行的 Pod 个数,默认为 1.spec.parallelism
标志并行运行的 Pod 的个数,默认为 1spec.activeDeadlineSeconds
设置了 Job 的最长活动时间(单位:秒)。这个计时器从 Job 被创建时开始计时:- 超时强制终止:如果 Job 运行时间超过 10 秒(包括 Pod 创建、执行、重试等所有时间),整个 Job 会被 Kubernetes 强制终止。
- 状态标记:超时后 Job 的状态会变为
Failed
,并显示原因Reason: DeadlineExceeded
。
2. 案例演示
求 π 值,算法:马青公式
这个公式由英国天文学教授 约翰·马青 于 1706 年发现。他利用这个公式计算到了 100 位的圆周率。马青公式每计算一项可以得到 1.4 位的 十进制精度。因为它的计算过程中被乘数和被除数都不大于长整数,所以可以很容易地在计算机上编程实现
2.1 Python代码
main.py
# -*- coding: utf-8 -*-
from __future__ import division
# 导入时间模块
import time
# 计算当前时间
time1=time.time()
# 算法根据马青公式计算圆周率 #
number = 1000
# 多计算10位,防止尾数取舍的影响
number1 = number+10
# 算到小数点后number1位
b = 10**number1
# 求含4/5的首项
x1 = b*4//5
# 求含1/239的首项
x2 = b // -239
# 求第一大项
he = x1+x2
#设置下面循环的终点,即共计算n项
number *= 2
#循环初值=3,末值2n,步长=2
for i in xrange(3,number,2):
# 求每个含1/5的项及符号
x1 //= -25
# 求每个含1/239的项及符号
x2 //= -57121
# 求两项之和
x = (x1+x2) // i
# 求总和
he += x
# 求出π
pai = he*4
#舍掉后十位
pai //= 10**10
# 输出圆周率π的值
paistring=str(pai)
result=paistring[0]+str('.')+paistring[1:len(paistring)]
print result
time2=time.time()
print u'Total time:' + str(time2 - time1) + 's'
2.2 Dockerfile
FROM python:2.7
ADD ./main.py /root
CMD /usr/bin/python /root/main.py
2.3 构建镜像
# 将 main.py 放到 Dockerfile 同级目录下,并在此目录执行下面的命令构建镜像
docker build -t tools:maqingpythonv1 .
2.4 资源清单
009-job-demo.yaml
apiVersion: batch/v1
kind: Job # Job控制器资源类型
metadata:
name: job-demo
namespace: default
labels:
app: my-job
spec:
template:
metadata:
name: my-job-pod
labels:
app: my-job
spec:
containers:
- name: job-demo-container
image: wangyanglinux/tools:maqingpythonv1
restartPolicy: Never # 对于 Job 控制器,容器重启策略仅支持 Never 和 OnFailure
查看日志,可以显示出打印的 2000 位 π 值
2.5 运行Pod,查看日志
运行Pod
# 运行job控制器
$ kubectl apply -f 009-job-demo.yaml
查看Job运行状态
# 查看job列表
$ kubectl get job
NAME COMPLETIONS DURATION AGE
job-demo 1/1 3s 6m48s
# 查看Job详情
$ kubectl describe job job-demo
Name: job-demo
Namespace: default
Selector: batch.kubernetes.io/controller-uid=ea1dec0d-b8d4-4942-8b72-2d3ac0abde91
Labels: app=my-job
Annotations: <none>
Parallelism: 1
Completions: 1
Completion Mode: NonIndexed
Start Time: Thu, 17 Apr 2025 21:32:13 +0800
Completed At: Thu, 17 Apr 2025 21:32:16 +0800
Duration: 3s
Pods Statuses: 0 Active (0 Ready) / 1 Succeeded / 0 Failed
Pod Template:
Labels: app=my-job
batch.kubernetes.io/controller-uid=ea1dec0d-b8d4-4942-8b72-2d3ac0abde91
batch.kubernetes.io/job-name=job-demo
controller-uid=ea1dec0d-b8d4-4942-8b72-2d3ac0abde91
job-name=job-demo
Containers:
job-demo-container:
Image: wangyanglinux/tools:maqingpythonv1
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 6m25s job-controller Created pod: job-demo-6q4sh
Normal Completed 6m22s job-controller Job completed
通过查看Job详情,观察到 Job 已运行完成
查看Pod列表
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
job-demo-6q4sh 0/1 Completed 0 7m58s 172.16.58.217 k8s-node02 <none> <none>
查看Pod运行日志
$ kubectl logs job-demo-6q4sh -f --tail=1000
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198
打印出了圆周率!!!
3. Job - 正常退出完成
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束
3.1 案例一:让容器返回码为1
目的:指定容器退出的返回码为1,验证当返回码不为0时,Job会异常退出。
010-job-rand-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: rand
namespace: default
spec:
completions: 1 # 标志Job结束需要成功运行的 Pod 个数,默认为1
parallelism: 5 # 标志并行运行的Pod的个数,默认为1
# activeDeadlineSeconds: 10 # 标志失败Pod 的重试最大时间,由于Pod重启策略为Never,因此超过 10秒,整个Pod强制中止
template:
metadata:
name: rand
spec:
containers:
- name: rand
image: wangyanglinux/tools:randexitv1
imagePullPolicy: IfNotPresent
# 指定退出码
args: ["--exitcode=1"]
restartPolicy: Never
运行Pod,查看结果
$ kubectl apply -f 010-job-rand-demo.yaml
监控Pod运行结果
$ kubectl get pod -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rand-4ftcj 0/1 Error 0 27s 172.16.58.225 k8s-node02 <none> <none>
rand-76fkv 1/1 Running 0 2s 172.16.58.224 k8s-node02 <none> <none>
rand-zd9bp 0/1 Error 0 42s 172.16.58.228 k8s-node02 <none> <none>
rand-76fkv 0/1 Error 0 6s 172.16.58.224 k8s-node02 <none> <none>
rand-76fkv 0/1 Error 0 7s 172.16.58.224 k8s-node02 <none> <none>
上面的Pod监控列表,一个Pod处于运行中,两个返回都是失败(运行中的Pod也会返回失败,因为在资源清单中制定了返回码为 1)。
由于在资源清单中指定了容器退出返回码为1,所以此清单创建的所有Pod都会返回失败。
查看Pod日志
$ kubectl logs rand-4ftcj -f --tail=100
休眠 4 秒,返回码为 1!
$ kubectl logs rand-76fkv -f --tail=100
休眠 4 秒,返回码为 1!
结论:只有当Pod容器返回码不为0为,Pod异常退出。
3.2 案例二:随机生成返回码
目的:当Pod容器返回码为1是,Pod成功退出。
011-job-rand-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: rand
namespace: default
spec:
completions: 3 # 标志Job结束需要成功运行的 Pod 个数,默认为1
parallelism: 5 # 标志并行运行的Pod的个数,默认为1
template:
metadata:
name: rand
spec:
containers:
- name: rand
image: wangyanglinux/tools:randexitv1
imagePullPolicy: IfNotPresent
restartPolicy: Never
运行Pod,查看结果
# 运行Pod
$ kubectl apply -f 011-job-rand-demo.yaml
查看Pod运行列表
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
rand-4jcmh 1/1 Running 0 5s
rand-dfnf9 1/1 Running 0 5s
rand-sh9vp 1/1 Running 0 5s
有3个Pod 并行运行,符合资源清单设置内容 spec.parallelism: 5
等待Job运行结束后,再次查看Pod列表
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rand-4jcmh 0/1 Error 0 4m43s 172.16.58.238 k8s-node02 <none> <none>
rand-8kwhc 0/1 Completed 0 4m25s 172.16.58.242 k8s-node02 <none> <none>
rand-dfnf9 0/1 Completed 0 4m43s 172.16.58.229 k8s-node02 <none> <none>
rand-hk9lw 0/1 Completed 0 4m25s 172.16.58.239 k8s-node02 <none> <none>
rand-sh9vp 0/1 Error 0 4m43s 172.16.85.215 k8s-node01 <none> <none>
一共运行了5个Pod,其中3个运行完成,2个返回失败
查看Job
$ kubectl get job -o wide
NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR
rand 3/3 26s 48s rand wangyanglinux/tools:randexitv1 batch.kubernetes.io/controller-uid=76957688-7f47-4694-a451-9adfb4f9c9cd
Job 有3个Pod 运行完成,成功退出,满足资源清单设置要求:spec.completions: 3
六、CronJob 控制器
1. CronJob 控制器特性
Cron Job 管理基于时间的 Job,即:
在给定时间点只运行一次
周期性地在给定时间点运行
使用条件:当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)
典型的用法如下所示:
- 在给定的时间点调度 Job 运行
- 创建周期性运行的 Job,例如:数据库备份、发送邮件
2. CroneJob 资源清单
.spec.schedule
:调度,必需字段,指定任务运行周期,格式同 Cron.spec.jobTemplate
:Job 模板,必需字段,指定需要运行的任务,格式同 Job.spec.startingDeadlineSeconds
:启动 Job 的期限(秒级别),该字段是可选的。如果因为任何原因而错过了被调度的时间,那么错过执行时间的 Job 将被认为是失败的。如果没有指定,则没有期限.spec.concurrencyPolicy
:并发策略,该字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种:Allow
(默认):允许并发运行 JobForbid
:禁止并发运行,如果前一个还没有完成,则直接跳过下一个Replace
:取消当前正在运行的 Job,用一个新的来替换- 注意,当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job, 它们创建的 Job 之间总是允许并发运行。
.spec.suspend
:挂起,该字段也是可选的。如果设置为true
,后续所有执行都会被挂起。它对已经开始执行的 Job 不起作用。默认值为false
.spec.successfulJobsHistoryLimit
和.spec.failedJobsHistoryLimit
:历史限制,是可选的字段。它们指定了可以保留多少完成和失败的 Job。默认情况下,它们分别设置为3
和1
。设置限制的值为0
,相关类型的 Job 完成后将不会被保留
3. 案例演示
3.1 资源清单
012-cronjob-demo.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: cronjob-demo
namespace: default
spec:
# 调度,必需字段,指定任务运行周期,格式同 Cron
schedule: "*/1 * * * *" # 每分钟执行一次
startingDeadlineSeconds: 30 # 启动 Job 的期限(秒级别),该字段是可选的。如果因为任何原因而错过了被调度的时间,那么错过执行时间的 Job 将被认为是失败的。如果没有指定,则没有期限
concurrencyPolicy: Allow # 并发策略,该字段也是可选的。(默认)允许并发运行 Job
successfulJobsHistoryLimit: 10 # 保留运行成功的job数,默认:3
failedJobsHistoryLimit: 3 #保留云心告失败的Job数,默认:1
# Job 模板,必需字段,指定需要运行的任务,格式同 Job
jobTemplate:
spec:
completions: 3 # 标志Job结束需要成功运行的 Pod 个数,默认为1
parallelism: 3 # 标志并行运行的Pod的个数,默认为1
template:
spec:
containers:
- name: cronjob-demo-container
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure # 重启策略:失败重启
启动 CronJob
$ kubectl apply -f 012-cronjob-demo.yaml
查看结果
# 查看Pod运行列表,完成了3个Pod
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cronjob-demo-29082370-8zl5f 0/1 Completed 0 15s 172.16.58.244 k8s-node02 <none> <none>
cronjob-demo-29082370-ht2mk 0/1 Completed 0 15s 172.16.85.217 k8s-node01 <none> <none>
cronjob-demo-29082370-mm7kc 0/1 Completed 0 15s 172.16.58.247 k8s-node02 <none> <none>
# 查看 cronjob 控制器(cronjob 每分钟都会执行一次)
$ kubectl get cronjob -o wide
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE CONTAINERS IMAGES SELECTOR
cronjob-demo */1 * * * * False 0 52s 2m14s cronjob-demo-container busybox <none>
# 过一会再次查看Pod列表,又多了三个Pod,因为 cronjob 设置每次完成需要 3个pod,spec.completions: 3
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cronjob-demo-29082370-8zl5f 0/1 Completed 0 114s 172.16.58.244 k8s-node02 <none> <none>
cronjob-demo-29082370-ht2mk 0/1 Completed 0 114s 172.16.85.217 k8s-node01 <none> <none>
cronjob-demo-29082370-mm7kc 0/1 Completed 0 114s 172.16.58.247 k8s-node02 <none> <none>
cronjob-demo-29082371-68kdz 0/1 Completed 0 54s 172.16.58.243 k8s-node02 <none> <none>
cronjob-demo-29082371-9b5j6 0/1 Completed 0 54s 172.16.58.251 k8s-node02 <none> <none>
cronjob-demo-29082371-cf2dg 0/1 Completed 0 54s 172.16.85.216 k8s-node01 <none> <none>
4. CronJob - 限制
创建 Job 操作应该是幂等的
七、StatefulSet 控制器
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 george_95@126.com