kubernetes(K8s)学习笔记(第六期):控制器管理
本笔记为 Kubernetes 系列第六期,聚焦 Kubernetes 控制器体系。涵盖:ReplicaSet、Deployment、DaemonSet、Job、CronJob 五种核心控制器的原理、使用方法和最佳实践。所有命令和 YAML 示例均来自课堂笔记,经过整理和注释。全文约 5300 字 ,包含 25 个 YAML 示例 、70+ 命令示例 和 14 张对比表格,是 Kubernetes 工作负载管理的必备指南。
--- Compiled and Authored by Whisky --- June 27th, 2026
目录
- Controllers 概述
- ReplicaSet
- Deployment
- DaemonSet
- Job
- CronJob
- 总结与知识点一览表
一、Controllers 概述
1.1 什么是 Controller?
Controller(控制器) 是 Kubernetes 控制平面的核心组件之一,其主要作用是确保所管理的资源处于用户期望的状态。控制器通过不断地监控资源的状态,并根据实际状态与期望状态之间的差异执行相应的动作,来实现资源的自愈、自动扩展等功能。
通俗理解 :控制器就像"监工",你告诉它"我需要 3 个 Pod 一直运行",它就负责确保始终有 3 个 Pod 在运行。如果某个 Pod 挂了,它会立即启动一个新的来替代。这种模式被称为声明式管理------你只需声明"期望状态",控制器负责"实现并维持"这个状态。
1.2 容器的分类
在了解控制器之前,先回顾一下容器的分类:
| 类型 | 特点 | 示例 |
|---|---|---|
| 服务类容器 | 持续运行,长期提供服务 | Web 服务器、API 服务 |
| 工作类容器 | 一次性任务,完成后退出 | 批处理程序、数据迁移 |
Kubernetes 控制器分类:
| 控制器 | 管理的容器类型 | 核心功能 |
|---|---|---|
| ReplicaSet | 服务类 | 确保指定数量的 Pod 副本运行 |
| Deployment | 服务类 | 声明式更新、回滚、扩缩容 |
| DaemonSet | 服务类 | 每个节点运行一个 Pod |
| Job | 工作类 | 运行一次性任务 |
| CronJob | 工作类 | 周期性地运行 Job |
1.3 环境准备
bash
root@master30:~# kubectl create ns controllers
root@master30:~# kubectl config set-context --current --namespace controllers
二、ReplicaSet
2.1 ReplicaSet 介绍
ReplicaSet(RS) 是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。它通常用来保证给定数量的、完全相同的 Pod 的可用性。
注意 :ReplicaSet 主要被 Deployment 用来作为一种编排 Pod 创建、删除及更新的机制。在生产环境中,建议使用 Deployment 管理 ReplicaSet,而非直接操作 ReplicaSet。ReplicaSet 本质上是 Deployment 的"实现细节"------Deployment 通过创建和管理 ReplicaSet 来实现滚动更新、版本回滚等功能。
2.2 ReplicaSet 工作原理
ReplicaSet 包含三个核心字段:
| 字段 | 作用 |
|---|---|
| selector | 识别可获得的 Pod 集合的选择算符 |
| replicas | 应该维护的副本个数 |
| template | 创建新 Pod 时使用的 Pod 模板 |
工作逻辑:
- 如果 Pod 数量 > 指定数量 → 终止多余的 Pod
- 如果 Pod 数量 < 指定数量 → 创建新的 Pod
选择算符(selector)的两种类型:
| 类型 | 示例 | 特点 |
|---|---|---|
| 基于等值 | app: nginx |
匹配 app=nginx 的 Pod |
| 基于集合 | app in (nginx, web) |
匹配 app 为 nginx 或 web 的 Pod |
2.3 ReplicaSet 创建
YAML 文件:
yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
bash
root@master30:~# kubectl apply -f rs.yaml
root@master30:~# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx 3 3 3 8m45s
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-95pth 1/1 Running 0 8m48s
nginx-9jg4f 1/1 Running 0 8m48s
nginx-tjtp2 1/1 Running 0 8m48s
Pod 的 OwnerReference:
bash
root@master30:~# kubectl describe pod nginx-9jg4f | grep Controlled
Controlled By: ReplicaSet/nginx
Pod 的 metadata.ownerReferences 字段记录了所属主资源(ReplicaSet),正是通过这一连接,ReplicaSet 知道它所维护的 Pod 集合的状态。这种"父子关系"是 Kubernetes 垃圾回收机制的基础------删除父资源时,子资源会被自动清理。
2.4 ReplicaSet 健壮性测试
测试 1:删除单个 Pod,验证自动重建
bash
root@master30:~# kubectl delete pod nginx-95pth --force
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-4qw2z 1/1 Running 0 2s # 新创建的 Pod
nginx-9jg4f 1/1 Running 0 9m20s
nginx-tjtp2 1/1 Running 0 9m20s
测试 2:创建具有相同标签的 Pod,验证 ReplicaSet 的"收养"行为
bash
root@master30:~# kubectl run nginx --image=nginx -l app=nginx
pod/nginx created
# 但刚创建出来就被 Terminating------因为 ReplicaSet 发现 Pod 数量超过期望值,立即终止了多余的 Pod
如果一个 Pod 没有 OwnerReference 且匹配到某 ReplicaSet 的选择算符,该 Pod 会被此 ReplicaSet 自动"收养"------这是 Kubernetes 控制器模式的一个重要特性:控制器通过标签选择器来"认领"资源。
2.5 ReplicaSet 删除
默认删除(会删除所管理的 Pod):
bash
root@master30:~# kubectl delete rs nginx
保留 Pod (--cascade=orphan 选项):
bash
root@master30:~# kubectl delete rs nginx --cascade=orphan
root@master30:~# kubectl get pods # Pod 仍然存在
三、Deployment
3.1 Deployment 介绍
Deployment(部署) 为 Pod 和 ReplicaSet 提供声明式的更新能力。
Deployment vs ReplicaSet:
| 特性 | ReplicaSet | Deployment |
|---|---|---|
| 确保副本数 | ✅ | ✅(通过管理 ReplicaSet) |
| 滚动更新 | ❌ | ✅ |
| 版本回滚 | ❌ | ✅ |
| 暂停/恢复更新 | ❌ | ✅ |
| 扩缩容 | ✅ | ✅(更高级) |
建议 :使用 Deployment 管理 ReplicaSet,除非你需要自定义更新编排。这意味着你可能永远不需要直接操作 ReplicaSet 对象。Deployment 是 Kubernetes 中最常用的工作负载控制器。
3.2 Deployment 创建
方式一:命令行创建
bash
root@master30:~# kubectl create deployment web \
--image=nginx:1.27 \
--replicas=2
deployment.apps/web created
查看创建的资源:
bash
root@master30:~# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/web-b78cbd74b-6fjxs 1/1 Running 0 3s
pod/web-b78cbd74b-mh6fh 1/1 Running 0 3s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 2/2 2 2 3s
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-b78cbd74b 2 2 2 3s
查看 Deployment 详细信息:
bash
root@master30:~# kubectl describe deployments.apps web
Name: web
Namespace: controllers
Selector: app=web
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
RollingUpdateStrategy: 25% max unavailable, 25% max surge
...
方式二:YAML 文件创建
生成 YAML 模板:
bash
root@master30:~# kubectl create deployment web \
--image=nginx:1.27 \
--replicas=2 \
--dry-run=client -o yaml > deployment-web.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx:1.27
name: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
bash
root@master30:~# kubectl apply -f deployment-web.yaml
创建方式对比:
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 命令行 | 简单、直观、快捷 | 不易重复部署 | 临时测试或实验 |
| YAML 文件 | 描述期望状态、可重复部署、可版本管理 | 需要熟悉语法 | 正式、跨环境、规模化部署 |
3.3 查看 Deployment 状态
bash
# 查看 Deployment 列表
root@master30:~# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
web 3/3 3 3 26m
# 查看 Deployment 的 YAML 定义
root@master30:~# kubectl get deployments.apps web -o yaml
# 查看关联的 ReplicaSet
root@master30:~# kubectl describe replicaset.apps web-b78cbd74b | grep Controlled
Controlled By: Deployment/web
3.4 水平伸缩(Scale)
bash
# 方法1:使用 scale 命令
root@master30:~# kubectl scale deployment web --replicas=3
# 方法2:编辑 Deployment
root@master30:~# kubectl edit deployments.apps web
# 修改 spec.replicas 的值
# 方法3:修改 YAML 文件并 apply
root@master30:~# kubectl get deployments.apps web -o yaml > web.yaml
root@master30:~# vim web.yaml # 修改 replicas
root@master30:~# kubectl apply -f web.yaml
3.5 健壮性测试(节点宕机与 Pod 驱逐)
测试场景:关闭 Worker 节点,观察 Pod 如何在其他节点重建。
完整流程:
| 阶段 | 时间 | 行为 |
|---|---|---|
| 心跳上报 | 每 10 秒 | kubelet 向 API Server 上报节点状态 |
| 节点健康检查 | 每 5 秒 | controller-manager 检查节点心跳 |
| 标记 NotReady | 连续 40 秒无心跳 | 节点标记为 NotReady |
| Pod 驱逐 | NotReady 持续 5 分钟 | controller-manager 开始驱逐 Pod |
相关参数(属于 kube-controller-manager):
| 参数 | 默认值 | 作用 |
|---|---|---|
--node-monitor-period |
5s | 检查节点心跳的周期 |
--node-monitor-grace-period |
40s | 无心跳后标记 NotReady 的宽限期 |
--pod-eviction-timeout |
5m | NotReady 后驱逐 Pod 的超时时间 |
修改方法 :编辑 /etc/kubernetes/manifests/kube-controller-manager.yaml,找到 command 段,添加或修改参数,保存后触发静态 Pod 重启。
3.6 更新镜像
bash
# 1. 查看当前镜像
root@master30:~# kubectl get deployments.apps web -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
web 3/3 3 3 26m nginx nginx:1.27 app=web
# 2. 更新镜像
root@master30:~# kubectl set image deployment/web nginx=nginx:1.28 --record
# 3. 观察更新过程
root@master30:~# kubectl get pods -w
web-5899d78c9-cckln 1/1 Running 0 9m28s
web-6c57bdf5f4-p8pk4 1/1 Running 0 43s
web-6c57bdf5f4-phntq 1/1 Running 0 43s
web-5899d78c9-phntq 1/1 Terminating 0 9m28s
更新后:会创建一个新的 ReplicaSet(web-6c57bdf5f4),旧 ReplicaSet 的副本数逐渐缩减到 0。
3.7 版本控制与回滚
查看更新历史:
bash
root@master30:~# kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deployment/web nginx=nginx:1.28 --record=true
3 kubectl set image deployment/web nginx=nginx:1.29 --record=true
--record的作用:记录触发变更的命令,方便追溯。在生产环境中强烈建议使用此选项。
回滚到指定版本:
bash
# 回滚到版本 1
root@master30:~# kubectl rollout undo deployment web --to-revision=1
deployment.apps/web rolled back
# 回滚到上一个版本
root@master30:~# kubectl rollout undo deployment web
常用 rollout 命令:
bash
kubectl rollout history deployment/<name> # 查看历史
kubectl rollout undo deployment/<name> # 回滚
kubectl rollout status deployment/<name> # 查看状态
kubectl rollout pause deployment/<name> # 暂停更新
kubectl rollout resume deployment/<name> # 恢复更新
kubectl rollout restart deployment/<name> # 重启(触发滚动更新)
3.8 滚动更新机制
Kubernetes 提供了两个关键参数来控制滚动更新的速度:
| 参数 | 含义 | 默认值 |
|---|---|---|
| maxSurge | 滚动更新过程中超过期望副本数的最大数量 | 25% |
| maxUnavailable | 滚动更新过程中不可用副本数占期望值的最大比例 | 25% |
示例:期望副本数为 10,maxSurge=25%,maxUnavailable=25%
- 最大副本数 = 10 + ceil(10 × 25%) = 13
- 最小可用副本数 = 10 - floor(10 × 25%) = 8
配置建议:
| 场景 | maxSurge | maxUnavailable | 理由 |
|---|---|---|---|
| 快速部署 | 50% | 50% | 速度快,但资源消耗大 |
| 生产环境(推荐) | 25% | 25% | 平衡速度与资源 |
| 保守更新 | 10% | 10% | 速度慢,但更安全 |
更新策略对比:
| 策略 | 行为 | 适用场景 |
|---|---|---|
| RollingUpdate(默认) | 逐步替换 Pod,确保服务不中断 | 生产环境 |
| Recreate | 先删除所有旧 Pod,再创建新 Pod | 开发/测试环境,可接受短暂中断 |
Recreate 配置示例:
yaml
spec:
strategy:
type: Recreate
监控滚动更新过程的脚本:
bash
#!/bin/bash
# monitor_pod_numbers.sh
while true
do
echo '==================='
kubectl get pods --no-headers | awk '{print $3}' | sort | uniq -c | sed -r 's/^ +//'
sleep 0.5
done
典型输出:
text
===================
10 Running
===================
5 ContainerCreating
8 Running
2 Terminating
===================
5 ContainerCreating
8 Running
===================
3 ContainerCreating
1 Pending
9 Running
4 Terminating
===================
10 Running
四、DaemonSet
4.1 DaemonSet 介绍
DaemonSet(DS) 确保全部(或者某些)节点上运行一个 Pod 的副本。当有新节点加入集群时,也会在新节点上新增一个 Pod;当有节点从集群移除时,节点上的 Pod 也会被回收。
典型用例:
| 场景 | 示例 |
|---|---|
| 集群守护进程 | glusterd、ceph |
| 日志收集 | Fluentd、Logstash |
| 监控守护进程 | Prometheus Node Exporter、collectd |
| 网络插件 | Calico Node、kube-proxy |
4.2 DaemonSet 创建
YAML 文件:
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: busybox
spec:
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
imagePullPolicy: IfNotPresent
command:
- sleep
- "36000"
bash
root@master30:~# kubectl apply -f daemonset.yaml
root@master30:~# kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
busybox 2 2 2 2 2 <none> 118s
root@master30:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
busybox-5hfv6 1/1 Running 0 102s 10.224.41.132 worker31
busybox-jdnsv 1/1 Running 0 102s 10.224.193.66 worker32
4.3 DaemonSet 调度机制(Taint 与 Toleration)
Master 节点默认不可调度(有 Taint):
bash
root@master30:~# kubectl describe node master | grep Taints
Taints: node-role.kubernetes.io/control-plane:NoSchedule
Taint(污点) 是节点上的标记,用于排斥 Pod 调度。Toleration(容忍) 是 Pod 上的标记,允许 Pod 调度到有对应 Taint 的节点上。
临时允许 Master 节点调度:
bash
# 移除 Taint
root@master30:~# kubectl taint node master node-role.kubernetes.io/control-plane-
root@master30:~# kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE
busybox 3 3 3 3 3
# 恢复 Taint
root@master30:~# kubectl taint node master node-role.kubernetes.io/control-plane:NoSchedule
4.4 DaemonSet 健壮性测试
bash
# 删除一个 Pod
root@master30:~# kubectl delete pod busybox-5hfv6
# 自动创建新 Pod
root@master30:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
busybox-jdnsv 1/1 Running 0 7m 10.224.193.66 worker32
busybox-wlqqv 1/1 Running 0 8s 10.224.41.133 worker31
4.5 K8s 集群中的 DaemonSet 实例
bash
root@master30:~# kubectl get daemonsets -n kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR
calico-node 3 3 3 3 3 kubernetes.io/os=linux
kube-proxy 3 3 3 3 3 kubernetes.io/os=linux
calico-node DaemonSet 核心配置:
yaml
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: calico-node
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: calico-node
template:
metadata:
labels:
k8s-app: calico-node
spec:
nodeSelector:
kubernetes.io/os: linux
hostNetwork: true
containers:
- name: calico-node
image: calico/node:v3.28.0
关键点 :
hostNetwork: true使 Pod 直接使用宿主机网络,这对于网络插件来说是必需的。
4.6 生产级示例
Fluent Bit 日志采集 DaemonSet:
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit-ds
namespace: kube-system
spec:
selector:
matchLabels:
app: fluent-bit
template:
metadata:
labels:
app: fluent-bit
spec:
containers:
- name: fluent-bit
image: cr.fluentbit.io/fluent/fluent-bit:latest
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
思考 :为什么 Fluent Bit 使用 hostPath 挂载宿主机的
/var/log和/var/lib/docker/containers?因为它需要读取节点上所有容器的日志文件,而 DaemonSet 确保每个节点都有一个 Fluent Bit Pod 在运行。
五、Job
5.1 Job 介绍
Job 用于运行一次性任务:
- 如果 Pod 运行失败,会创建新的 Pod 继续运行
- 直到任务成功完成(Pod 中任务退出代码为 0)
- 删除 Job 会清除所创建的全部 Pod
典型用例:
- 执行数据库清理
- 备份 Kubernetes 集群数据
- 数据迁移
- 批量计算
5.2 Job 创建
方式一:命令行创建
bash
root@master30:~# kubectl create job myjob --image=busybox -- echo "hello k8s job!"
job.batch/myjob created
root@master30:~# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/myjob-pdrwv 0/1 Completed 0 11m
NAME COMPLETIONS DURATION AGE
job.batch/myjob 1/1 20s 11m
root@master30:~# kubectl logs myjob-pdrwv
hello k8s job!
方式二:YAML 文件创建
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
template:
metadata:
name: myjob
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command: ["echo", "hello k8s job!"]
restartPolicy: Never
bash
root@master30:~# kubectl apply -f job.yaml
5.3 经典示例:计算 π
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
imagePullPolicy: IfNotPresent
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(200)"]
restartPolicy: Never
backoffLimit: 4
bash
root@master30:~# kubectl apply -f job-pi.yaml
root@master30:~# kubectl logs pi-qzxv4
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303820
5.4 restartPolicy 对 Job 的影响
Job 的 restartPolicy 只能是 Never 或 OnFailure:
| 策略 | 行为 | Pod 数量 |
|---|---|---|
| Never | 任务失败时创建新的 Pod | 可能产生多个 Pod |
| OnFailure | 任务失败时重启 Pod | 始终只有 1 个 Pod |
实验:错误命令 + Never:
yaml
command: ["echoxxx", "hello k8s job!"] # 错误的命令
restartPolicy: Never
bash
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod/myjob-6hp5t 0/1 StartError 0 33s
pod/myjob-gczbz 0/1 StartError 0 2s
pod/myjob-n4bpv 0/1 StartError 0 22s
因为 Job 期望 1 个成功完成的 Pod,但永远达不到,所以会不断创建新的 Pod。
5.5 backoffLimit:失败重试次数
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
backoffLimit: 2 # 最多重试 2 次
template:
spec:
containers:
- name: hello
image: busybox
command: ["echoxx", "hello"]
restartPolicy: Never
最多创建 2 个新 Pod。
5.6 completions:完成次数
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
completions: 2 # 需要 2 个 Pod 成功完成
template:
spec:
containers:
- name: hello
image: busybox
command: ["echo", "hello"]
restartPolicy: Never
bash
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod/myjob-72zgz 0/1 Completed 0 4s
pod/myjob-8brdq 0/1 Completed 0 8s
NAME COMPLETIONS DURATION AGE
job.batch/myjob 2/2 12s 12s
5.7 parallelism:并行度
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
completions: 6 # 总共需要 6 个
parallelism: 2 # 每次并行运行 2 个
template:
spec:
containers:
- name: hello
image: busybox
command: ["echo", "hello"]
restartPolicy: Never
效果:每次运行 2 个 Pod,直到总共有 6 个 Pod 成功完成。
5.8 activeDeadlineSeconds:超时控制
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi-with-timeout
spec:
backoffLimit: 5
activeDeadlineSeconds: 10 # 最多运行 10 秒
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
优先级 :
activeDeadlineSeconds的优先级高于backoffLimit。即使重试次数未达到限制,超时后也会终止 Job。
5.9 suspend:挂起 Job
从 Kubernetes 1.21 开始,Job 支持 .spec.suspend 字段:
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
suspend: true # 挂起 Job,不会创建 Pod
template:
spec:
containers:
- name: hello
image: busybox
command: ["echo", "hello"]
restartPolicy: Never
作用:创建 Job 但不立即执行,待恢复后才开始。这在需要"按需启动"任务的场景中非常有用。
5.10 ttlSecondsAfterFinished:自动清理
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi-with-ttl
spec:
ttlSecondsAfterFinished: 100 # 完成后 100 秒自动删除
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(200)"]
restartPolicy: Never
六、CronJob
6.1 CronJob 介绍
CronJob 用于周期性地执行 Job,类似于 Linux 的 cron 程序。
典型用例:
- 定期备份数据库
- 定时生成报表
- 周期性的数据清理
- 定时同步数据
命名限制:CronJob 名称不能超过 52 个字符(控制器会自动在名称后附加 11 个字符,Job 名称最大长度为 63 个字符)。
6.2 CronJob 创建
方式一:命令行创建
bash
root@master30:~# kubectl create cronjob mycronjob \
--image=busybox \
--schedule='*/2 * * * *' \
-- echo "hello k8s job!"
# 等待一段时间,观察 Job 自动创建
root@master30:~# kubectl get all
pod/mycronjob-28301160-gvm2v 0/1 Completed 0 5m18s
pod/mycronjob-28301162-25jll 0/1 Completed 0 3m18s
pod/mycronjob-28301164-h7mf7 0/1 Completed 0 78s
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/mycronjob */2 * * * * False 0 78s 36m
方式二:YAML 文件创建
yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: mycronjob
spec:
schedule: "*/2 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
command: ["echo", "hello k8s job!"]
restartPolicy: Never
6.3 Cron 时间表语法
text
# ┌───────────── 分钟 (0 - 59)
# │ ┌───────────── 小时 (0 - 23)
# │ │ ┌───────────── 月的某天 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日=0)
# │ │ │ │ │
# * * * * *
常用示例:
| 表达式 | 含义 |
|---|---|
*/2 * * * * |
每 2 分钟 |
0 * * * * |
每小时整点 |
0 2 * * * |
每天凌晨 2 点 |
0 0 * * 0 |
每周日午夜 |
0 0 1 * * |
每月 1 日午夜 |
0 2 * * 1-5 |
工作日(周一至周五)凌晨 2 点 |
6.4 关键参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| startingDeadlineSeconds | 无 | 错过了调度时间后,开始任务的截止时间(秒) |
| concurrencyPolicy | Allow | 并发策略:Allow / Forbid / Replace |
| successfulJobsHistoryLimit | 3 | 保留的成功任务数量 |
| failedJobsHistoryLimit | 1 | 保留的失败任务数量 |
concurrencyPolicy 详解:
| 策略 | 行为 |
|---|---|
Allow |
允许并发执行 |
Forbid |
禁止并发,新任务跳过(如果旧任务还在运行) |
Replace |
替换当前运行的任务 |
时区处理(Kubernetes 1.27+):
从 Kubernetes 1.27 开始,CronJob 支持在 schedule 字段中指定时区:
yaml
spec:
schedule: "CRON_TZ=Asia/Shanghai 0 2 * * *"
如果未指定时区,默认使用 UTC 时间。
6.5 综合案例
案例 1:定期清理主机目录
yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: clean
spec:
schedule: '* * * * *' # 每分钟执行
jobTemplate:
spec:
template:
spec:
nodeName: worker31.whisky.cloud
containers:
- command:
- sh
- -c
- sleep 3 && rm -fr /var/data/*
image: busybox
name: clean
volumeMounts:
- mountPath: /var/data
name: data
volumes:
- name: data
hostPath:
path: /var/data
restartPolicy: OnFailure
案例 2:通过 CronJob 操作 K8s 集群
bash
# 1. 创建包含 kubectl 配置的 ConfigMap
[root@master controller]# kubectl create cm kubeconfig \
--from-file=config=/root/.kube/config
yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: clean-pods
spec:
schedule: '* * * * *'
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- image: bitnami/kubectl
imagePullPolicy: IfNotPresent
name: kubectl
args:
- delete
- pods
- -l
- app=hello
- --force
- -n
- controllers
volumeMounts:
- name: kubeconfig
mountPath: "/.kube"
volumes:
- name: kubeconfig
configMap:
name: kubeconfig
七、总结与知识点一览表
7.1 五种控制器对比
| 控制器 | 类型 | 核心功能 | 适用场景 |
|---|---|---|---|
| ReplicaSet | 服务类 | 确保指定数量的 Pod 副本 | 被 Deployment 间接使用 |
| Deployment | 服务类 | 声明式更新、回滚、扩缩容 | 生产环境首选,无状态应用 |
| DaemonSet | 服务类 | 每个节点一个 Pod | 日志收集、监控、网络插件 |
| Job | 工作类 | 运行一次性任务 | 数据迁移、批处理 |
| CronJob | 工作类 | 周期性地运行 Job | 定时备份、报表生成 |
7.2 控制器选择决策树
text
你的应用需要什么?
│
├── 需要每个节点都运行一个实例?
│ └── 使用 DaemonSet(日志采集、监控、网络)
│
├── 需要定期执行或一次性执行?
│ ├── 周期性执行 → 使用 CronJob
│ └── 一次性执行 → 使用 Job
│
├── 需要滚动更新、版本回滚、扩缩容?
│ └── 使用 Deployment(生产环境首选)
│
└── 只是简单维持 Pod 数量?
└── 使用 ReplicaSet(但不推荐直接使用)
7.3 常用命令速查
| 操作 | Deployment | DaemonSet | Job | CronJob |
|---|---|---|---|---|
| 创建 | kubectl create deployment |
YAML 文件 | kubectl create job |
kubectl create cronjob |
| 查看 | kubectl get deploy |
kubectl get ds |
kubectl get jobs |
kubectl get cj |
| 查看详情 | kubectl describe deploy |
kubectl describe ds |
kubectl describe job |
kubectl describe cj |
| 扩容 | kubectl scale deploy |
--- | --- | --- |
| 更新镜像 | kubectl set image deploy |
--- | --- | --- |
| 回滚 | kubectl rollout undo deploy |
--- | --- | --- |
| 删除 | kubectl delete deploy |
kubectl delete ds |
kubectl delete job |
kubectl delete cj |
7.4 常见错误排查
| 错误 | 原因 | 解决方法 |
|---|---|---|
FailedScheduling |
节点资源不足或 Taint | 检查节点资源,添加容忍 |
CrashLoopBackOff |
容器反复崩溃 | 查看 Pod 日志,检查命令是否正确 |
ImagePullBackOff |
镜像拉取失败 | 检查镜像名称和仓库认证 |
| Deployment 更新卡住 | maxUnavailable 设置过小 | 调整滚动更新参数 |
| 节点宕机后 Pod 不迁移 | pod-eviction-timeout 未到 | 等待 5 分钟或修改参数 |
failed to create containerd task: exec: "xxx": executable file not found |
命令不存在 | 检查 command 拼写 |
7.5 生产环境最佳实践
| 实践 | 说明 |
|---|---|
| 使用 Deployment 而非 ReplicaSet | Deployment 提供了更丰富的功能 |
| 设置资源请求和限制 | 避免 Pod 资源争抢 |
| 使用滚动更新策略 | 确保服务不中断 |
| 配置 PodDisruptionBudget | 保护应用不被同时驱逐 |
| 添加健康检查 | livenessProbe 和 readinessProbe |
使用 --record 记录变更 |
便于追溯和回滚 |
| 合理设置历史限制 | 避免 ReplicaSet 无限堆积 |
下一期预告:Kubernetes Service 与服务发现------ClusterIP、NodePort、LoadBalancer 三种 Service 类型,Endpoints 机制,以及 kube-proxy 的工作原理。
--- Compiled and Authored by Whisky --- June 27th, 2026