kubernetes(K8s)学习笔记(第六期):控制器管理

kubernetes(K8s)学习笔记(第六期):控制器管理

本笔记为 Kubernetes 系列第六期,聚焦 Kubernetes 控制器体系。涵盖:ReplicaSet、Deployment、DaemonSet、Job、CronJob 五种核心控制器的原理、使用方法和最佳实践。所有命令和 YAML 示例均来自课堂笔记,经过整理和注释。全文约 5300 字 ,包含 25 个 YAML 示例70+ 命令示例14 张对比表格,是 Kubernetes 工作负载管理的必备指南。
--- Compiled and Authored by Whisky --- June 27th, 2026

目录

  1. Controllers 概述
  2. ReplicaSet
  3. Deployment
  4. DaemonSet
  5. Job
  6. CronJob
  7. 总结与知识点一览表

一、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) 匹配 appnginxweb 的 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 只能是 NeverOnFailure

策略 行为 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