目录

一、ReplicaSet 控制器

生活类比

1. 建立控制器

核心代码逐行解析(Line-by-Line Breakdown)

⚠️ 坑点(Gotchas)

2. 测试功能

🏭 企业级生产应用(Enterprise Scenario)

🚨 课后防宕机指南(Troubleshooting)

二、Deployment 控制器

生活类比

1. 监控

2. 建立 Deployment 控制器

核心代码逐行解析(Line-by-Line Breakdown)

⚠️ 坑点(Gotchas)

3. 升级和回滚

升级

回滚

🏭 企业级生产应用(Enterprise Scenario)

🚨 课后防宕机指南(Troubleshooting)

三、版本更新管理及优化

1. 查看更新策略信息

2. 设定更新策略

核心代码逐行解析(Line-by-Line Breakdown)

⚠️ 坑点(Gotchas)

3. 更新暂停和恢复

🏭 企业级生产应用(Enterprise Scenario)

🚨 课后防宕机指南(Troubleshooting)

四、DaemonSet

生活类比

核心代码逐行解析(Line-by-Line Breakdown)

⚠️ 坑点(Gotchas)

🏭 企业级生产应用(Enterprise Scenario)

🚨 课后防宕机指南(Troubleshooting)

五、Job 控制器

生活类比

核心代码逐行解析(Line-by-Line Breakdown)

⚠️ 坑点(Gotchas)

🏭 企业级生产应用(Enterprise Scenario)

🚨 课后防宕机指南(Troubleshooting)

六、CronJob 控制器

生活类比

核心代码逐行解析(Line-by-Line Breakdown)

⚠️ 坑点(Gotchas)

🏭 企业级生产应用(Enterprise Scenario)

🚨 课后防宕机指南(Troubleshooting)



一、ReplicaSet 控制器

生活类比

ReplicaSet 就像餐厅的后厨排班经理。你告诉经理 "我需要 2 个厨师同时在岗",经理就会确保永远有 2 个厨师在工作。如果一个厨师请假了,经理立刻再找一个补上;如果厨师多了,经理就安排多余的人下班。它只关心 "数量对不对",不关心 "厨师是谁"。

1. 建立控制器

bash

运行

[root@master controler]# kubectl create deployment webcluster --image myapp:v1 --dry-run=client -o yaml > repset.yml

代码解释:生成一个 Deployment 的 YAML 模板(因为 kubectl 没有直接生成 ReplicaSet 的快捷命令),不实际创建资源,只输出 YAML 到文件。

  • --dry-run=client:客户端模拟执行,不向 API Server 发送请求
  • -o yaml:输出格式为 YAML

bash

运行

[root@master controler]# vim repset.yml

编辑后的完整 YAML

yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  replicas: 2
  selector:
    matchLabels:
      app: webcluster
  # strategy: {}
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp
核心代码逐行解析(Line-by-Line Breakdown)

表格

行号 代码 底层触发动作
1 apiVersion: apps/v1 告诉 Kubernetes API Server 使用apps组的v1版本处理这个资源请求,这是 ReplicaSet 的稳定 API 版本
2 kind: ReplicaSet 声明这是一个 ReplicaSet 类型的资源,API Server 会将请求路由到 ReplicaSet 控制器处理
5-6 labels: app: webcluster 给 ReplicaSet 对象本身打标签,用于后续的资源筛选和管理
7 name: webcluster default命名空间中创建一个名为webcluster的 ReplicaSet 对象,名称在命名空间内必须唯一
10 replicas: 2 设置期望的 Pod 副本数为 2,ReplicaSet 控制器会持续对比实际运行的 Pod 数和这个值
11-13 selector: matchLabels: app: webcluster 最核心的配置!ReplicaSet 通过这个标签选择器来管理所有带有app=webcluster标签的 Pod。底层会在 etcd 中执行标签查询,找到所有匹配的 Pod
15-22 template: 定义 Pod 模板,当需要创建新 Pod 时,ReplicaSet 会完全按照这个模板来生成
17-18 labels: app: webcluster 给生成的 Pod 打标签,必须和上面的 selector 完全匹配,否则 ReplicaSet 会无限创建新 Pod
21 image: myapp:v1 Pod 中的容器使用myapp:v1镜像,kubelet 会从本地或配置的镜像仓库拉取这个镜像
22 name: myapp 给容器命名,在 Pod 内必须唯一
⚠️ 坑点(Gotchas)
  1. 标签不匹配:如果template.metadata.labelsspec.selector.matchLabels不一致,ReplicaSet 会认为没有任何 Pod 属于它,从而无限创建新 Pod,直到耗尽集群资源
  2. 手动创建的 Pod:如果手动创建了带有app=webcluster标签的 Pod,ReplicaSet 会自动接管它,如果数量超过replicas值,会随机删除多余的 Pod
  3. 不能直接更新镜像:ReplicaSet 不支持滚动更新,修改模板中的镜像版本不会影响已运行的 Pod,只有新创建的 Pod 会使用新镜像

bash

运行

[root@master controler]# kubectl apply -f repset.yml

代码解释:将 YAML 文件提交给 Kubernetes API Server,创建 ReplicaSet 资源。

  • 底层:API Server 验证 YAML 语法和权限,将对象写入 etcd,ReplicaSet 控制器监听到新对象,开始创建 Pod

bash

运行

# 打开一个新的shell
[root@master ~]# watch -n 1 kubectl get pods --show-labels

代码解释:每秒执行一次kubectl get pods命令,实时查看 Pod 状态和标签。

  • --show-labels:显示每个 Pod 的所有标签,用于验证标签是否正确

监控输出

plaintext

Every 1.0s: kubectl get pods --show-labels
master: Sat Apr 11 10:08:32 2026

NAME              READY   STATUS    RESTARTS   AGE     LABELS
webcluster-tbxq4  1/1     Running   0          6m49s   app=webcluster
webcluster-jna23  1/1     Running   0          6m49s   app=webcluster

输出解释:ReplicaSet 成功创建了 2 个 Pod,都处于 Running 状态,标签都是app=webcluster

2. 测试功能

bash

运行

[root@master controler]# vim repset.yml

修改内容

yaml

spec:
  replicas: 4

代码解释:将期望的 Pod 副本数从 2 修改为 4

bash

运行

[root@master controler]# kubectl apply -f repset.yml

代码解释:更新 ReplicaSet 资源,ReplicaSet 控制器会立即发现期望副本数变为 4,开始创建 2 个新 Pod

监控输出

plaintext

Every 1.0s: kubectl get pods --show-labels
master: Sat Apr 11 10:11:06 2026

NAME              READY   STATUS    RESTARTS   AGE     LABELS
webcluster-4sxz4  1/1     Running   0          13s     app=webcluster
webcluster-lvtsn  1/1     Running   0          13s     app=webcluster
webcluster-tbxq4  1/1     Running   0          9m23s   app=webcluster
webcluster-tr5qk  1/1     Running   0          13s     app=webcluster

输出解释:ReplicaSet 成功扩容到 4 个 Pod,原有 2 个 Pod 保持不变,新增 2 个 Pod

🏭 企业级生产应用(Enterprise Scenario)

使用场景

  • 无状态服务的基础副本管理(但生产中几乎不直接使用 ReplicaSet,而是使用 Deployment)
  • 需要精确控制 Pod 数量的场景,如批处理任务的 worker 节点
  • 自定义控制器的基础组件

进阶优化

  1. 添加资源限制:为容器设置resources.requestsresources.limits,防止 Pod 耗尽节点资源
  2. 配置亲和性和反亲和性:让 Pod 分布在不同的节点上,提高可用性
  3. 添加存活探针和就绪探针:让 ReplicaSet 能够自动重启故障 Pod,并将未就绪的 Pod 从服务中移除
  4. 使用 HPA 自动扩缩容:根据 CPU、内存使用率或自定义指标自动调整replicas

🚨 课后防宕机指南(Troubleshooting)

错误 1:Pod 无限创建

  • 报错现象:kubectl get pods显示大量 Pending 状态的 Pod,数量持续增加
  • 错误原因:template.metadata.labelsspec.selector.matchLabels不匹配
  • 排查思路:
    1. 执行kubectl describe rs webcluster查看 ReplicaSet 的事件
    2. 检查selector.matchLabelstemplate.metadata.labels是否完全一致
    3. 执行kubectl delete rs webcluster删除错误的 ReplicaSet,重新创建

错误 2:Pod 无法创建

  • 报错现象:Pod 一直处于 Pending 状态
  • 错误原因:节点资源不足,或镜像拉取失败
  • 排查思路:
    1. 执行kubectl describe pod <pod-name>查看 Pod 的事件
    2. 检查节点资源:kubectl describe nodes
    3. 检查镜像是否存在,以及节点是否能够拉取该镜像

二、Deployment 控制器

生活类比

Deployment 就像餐厅的总经理。它不仅管理厨师的数量(通过 ReplicaSet),还负责菜单的更新(滚动升级)、出错时的回滚(回到上一个菜单版本)、以及更新的节奏(一次换几个厨师)。它是 ReplicaSet 的 "上级管理者",提供了更高级的部署策略。

1. 监控

bash

运行

[root@master ~]# watch -n 1 "kubectl get pods --show-labels;echo ====;kubectl get replicasets.apps"

代码解释:同时监控 Pod 和 ReplicaSet 的状态,观察 Deployment 如何通过管理 ReplicaSet 来实现滚动更新。

  • 底层:每秒执行两个命令,分别获取 Pod 列表和 ReplicaSet 列表,用====分隔输出

2. 建立 Deployment 控制器

bash

运行

[root@master controler]# kubectl create deployment webcluster --image myapp:v1 --dry-run=client -o yaml > dep.yml

代码解释:生成一个 Deployment 的 YAML 模板,不实际创建资源,只输出 YAML 到文件。

bash

运行

[root@master controler]# vim dep.yml

编辑后的完整 YAML

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  minReadySeconds: 5
  replicas: 2
  selector:
    matchLabels:
      app: webcluster
  # strategy: {}
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp
      # resources: {}
核心代码逐行解析(Line-by-Line Breakdown)

表格

行号 代码 底层触发动作
2 kind: Deployment 声明这是一个 Deployment 类型的资源,API Server 会将请求路由到 Deployment 控制器处理
8 minReadySeconds: 5 关键配置!Pod 就绪后等待 5 秒,再将其标记为可用,然后继续更新下一个 Pod。底层:kubelet 会在 Pod 就绪后等待指定时间,再向 Deployment 控制器发送就绪信号
9 replicas: 2 设置期望的 Pod 副本数为 2,Deployment 会将这个值传递给它管理的 ReplicaSet
10-12 selector: matchLabels: app: webcluster Deployment 通过这个标签选择器来管理它创建的 ReplicaSet,必须和 Pod 模板的标签完全匹配
14-22 template: 定义 Pod 模板,Deployment 会根据这个模板创建 ReplicaSet,然后由 ReplicaSet 创建 Pod
⚠️ 坑点(Gotchas)
  1. minReadySeconds设置为 0:如果设置为 0,Pod 一就绪就会被标记为可用,可能导致流量被转发到还没完全启动的 Pod,造成请求失败
  2. 直接修改 ReplicaSet:不要直接修改 Deployment 创建的 ReplicaSet,Deployment 会覆盖你的修改
  3. 标签冲突:如果集群中已经存在带有相同标签的 ReplicaSet 或 Pod,Deployment 会接管它们,可能导致意外的 Pod 删除

bash

运行

[root@master controler]# kubectl apply -f dep.yml

代码解释:创建 Deployment 资源。

  • 底层:Deployment 控制器创建一个 ReplicaSet,名称为webcluster-<pod-template-hash>,然后由 ReplicaSet 创建 2 个 Pod

监控输出

plaintext

Every 1.0s: kubectl get pods --show-labels;echo ====;kubectl get replicasets.apps
master: Sat Apr 11 10:43:24 2026

NAME                                 READY   STATUS    RESTARTS   AGE   LABELS
webcluster-77c87d9946-49kh5          1/1     Running   0          45s   app=webcluster,pod-template-hash=77c87d9946
webcluster-77c87d9946-m2x2d          1/1     Running   0          45s   app=webcluster,pod-template-hash=77c87d9946

====
NAME                           DESIRED   CURRENT   READY   AGE
webcluster-77c87d9946          2         2         2       45s

输出解释

  • Deployment 创建了一个名为webcluster-77c87d9946的 ReplicaSet
  • ReplicaSet 创建了 2 个 Pod,每个 Pod 都有一个pod-template-hash标签,这个标签是根据 Pod 模板的内容计算出来的哈希值
  • 当 Pod 模板发生变化时,哈希值会改变,Deployment 会创建一个新的 ReplicaSet

bash

运行

# 发布服务
[root@master controler]# kubectl expose deployment webcluster --port 80 --target-port 80

代码解释:为 Deployment 创建一个 ClusterIP 类型的 Service,将 Service 的 80 端口转发到 Pod 的 80 端口。

  • 底层:创建一个 Service 对象,Service 的 selector 为app=webcluster,会自动将流量转发到所有带有这个标签的 Pod

bash

运行

[root@master controler]# kubectl describe services webcluster

代码解释:查看 Service 的详细信息。

输出

plaintext

Name:              webcluster
Namespace:         default
Labels:            app=webcluster
Annotations:       <none>
Selector:          app=webcluster
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.107.142.60
IPs:               10.107.142.60
Port:              80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.6:80,10.244.1.9:80
Session Affinity:  None
Internal Traffic Policy:  Cluster
Events:            <none>

输出解释

  • Service 的 ClusterIP 为10.107.142.60
  • Endpoints 显示了 2 个 Pod 的 IP 地址和端口,Service 会将流量负载均衡到这 2 个 Pod

bash

运行

# 访问:
[root@master controler]# curl 10.107.142.60
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

代码解释:通过 Service 的 ClusterIP 访问应用,返回 v1 版本的内容。

3. 升级和回滚

升级

bash

运行

[root@master controler]# vim dep.yml

修改内容

yaml

spec:
  containers:
  - image: myapp:v2 # 升级为版本2
    name: myapp

代码解释:将 Pod 模板中的镜像版本从 v1 修改为 v2。

bash

运行

[root@master controler]# kubectl apply -f dep.yml
deployment.apps/webcluster configured

代码解释:更新 Deployment 资源。

  • 底层:Deployment 控制器检测到 Pod 模板发生变化,创建一个新的 ReplicaSet(哈希值改变),然后按照滚动更新策略,逐步将旧 ReplicaSet 的 Pod 数量减少到 0,同时将新 ReplicaSet 的 Pod 数量增加到 2

bash

运行

[root@master controler]# curl 10.107.142.60
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

代码解释:访问应用,现在返回 v2 版本的内容。

回滚

bash

运行

[root@master controler]# vim dep.yml

修改内容

yaml

spec:
  containers:
  - image: myapp:v1 # 回滚为版本1
    name: myapp

代码解释:将 Pod 模板中的镜像版本改回 v1。

bash

运行

[root@master controler]# kubectl apply -f dep.yml

代码解释:更新 Deployment 资源,Deployment 会创建一个新的 ReplicaSet(使用 v1 镜像),然后逐步替换 v2 版本的 Pod。

bash

运行

[root@master controler]# curl 10.107.142.60
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

代码解释:访问应用,现在返回 v1 版本的内容。

🏭 企业级生产应用(Enterprise Scenario)

使用场景

  • 所有无状态服务的部署和更新,这是 Kubernetes 中最常用的控制器
  • 微服务架构中的每个服务都应该使用 Deployment 进行管理
  • 支持蓝绿部署、金丝雀发布等高级部署策略

进阶优化

  1. 配置滚动更新策略:通过maxSurgemaxUnavailable控制更新的速度和可用性
  2. 添加版本历史记录:设置revisionHistoryLimit保留更多的历史版本,方便回滚
  3. 配置就绪探针和存活探针:确保只有完全就绪的 Pod 才会接收流量,故障的 Pod 会被自动重启
  4. 使用 ConfigMap 和 Secret 管理配置:将配置和镜像分离,不需要重新构建镜像就能修改配置
  5. 实现金丝雀发布:通过创建两个 Deployment(一个旧版本,一个新版本),并使用 Service 或 Ingress 控制流量比例

🚨 课后防宕机指南(Troubleshooting)

错误 1:滚动更新卡住

  • 报错现象:kubectl rollout status deployment webcluster显示一直处于更新中
  • 错误原因:新 Pod 无法就绪(镜像拉取失败、健康检查失败、资源不足等)
  • 排查思路:
    1. 执行kubectl describe deployment webcluster查看 Deployment 的事件
    2. 执行kubectl get pods查看新 Pod 的状态
    3. 执行kubectl describe pod <new-pod-name>查看 Pod 的事件
    4. 如果更新失败,执行kubectl rollout undo deployment webcluster回滚到上一个版本

错误 2:回滚失败

  • 报错现象:执行回滚命令后,Pod 没有回到旧版本
  • 错误原因:历史版本已被删除(revisionHistoryLimit设置太小)
  • 排查思路:
    1. 执行kubectl rollout history deployment webcluster查看可用的历史版本
    2. 如果没有可用的历史版本,只能重新应用旧的 YAML 文件
    3. 建议将revisionHistoryLimit设置为 10 以上,保留足够的历史版本

三、版本更新管理及优化

bash

运行

[root@master controler]# vim dep.yml

修改内容

yaml

spec:
  minReadySeconds: 5
  replicas: 6 # 把pod数量设定为6方便观察
  selector:
    matchLabels:
      app: webcluster

代码解释:将 Pod 副本数增加到 6,方便观察滚动更新的过程。

bash

运行

[root@master controler]# kubectl apply -f dep.yml
deployment.apps/webcluster configured

代码解释:更新 Deployment,将 Pod 数量扩容到 6。

1. 查看更新策略信息

bash

运行

[root@master controler]# kubectl describe deployments.apps webcluster

输出关键信息

plaintext

RollingUpdateStrategy: 25% max unavailable, 25% max surge

代码解释:这是 Deployment 的默认滚动更新策略。

  • maxUnavailable: 25%:更新过程中,最多允许 25% 的 Pod 不可用
  • maxSurge: 25%:更新过程中,最多允许比期望副本数多 25% 的 Pod

底层逻辑:对于 6 个 Pod 的情况:

  • 最多不可用:6 × 25% = 1.5 → 向上取整为 2 个
  • 最多超出:6 × 25% = 1.5 → 向上取整为 2 个
  • 更新过程中,最多同时有 6 + 2 = 8 个 Pod 在运行,最少有 6 - 2 = 4 个 Pod 可用

2. 设定更新策略

bash

运行

[root@master controler]# vim dep.yml

修改内容

yaml

spec:
  minReadySeconds: 5
  replicas: 6
  selector:
    matchLabels:
      app: webcluster
  strategy:
    rollingUpdate:
      maxSurge: 1 # 更新时pod数量最多比期望值多一个
      maxUnavailable: 0 # 不能使用pod数量比期望值数量多0
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp
核心代码逐行解析(Line-by-Line Breakdown)

表格

行号 代码 底层触发动作
6 strategy: rollingUpdate: 声明使用滚动更新策略(这是默认策略,也可以设置为Recreate
7 maxSurge: 1 更新过程中,最多允许比期望副本数多 1 个 Pod。底层:Deployment 控制器在创建新 Pod 时,会确保总 Pod 数不超过replicas + maxSurge
8 maxUnavailable: 0 更新过程中,不允许任何 Pod 不可用。底层:Deployment 控制器会先创建一个新 Pod,等它就绪后,再删除一个旧 Pod,依次类推
⚠️ 坑点(Gotchas)
  1. maxUnavailable: 0maxSurge: 0不能同时设置:这样会导致无法进行任何更新
  2. 数值过大导致资源耗尽:如果maxSurge设置过大,更新过程中会创建大量 Pod,可能耗尽集群资源
  3. Recreate策略会导致服务中断:如果设置strategy: type: Recreate,Deployment 会先删除所有旧 Pod,再创建新 Pod,会导致服务完全中断

bash

运行

[root@master controler]# kubectl apply -f dep.yml

代码解释:更新 Deployment 的滚动更新策略。

  • 底层:后续的所有更新都会按照这个新策略执行

3. 更新暂停和恢复

bash

运行

[root@master controler]# kubectl rollout history deployment webcluster

代码解释:查看 Deployment 的更新历史记录。

输出

plaintext

deployment.apps/webcluster
REVISION  CHANGE-CAUSE
7         <none>
8         <none>

输出解释

  • REVISION:版本号,每次更新都会生成一个新的版本号
  • CHANGE-CAUSE:更新的原因,默认是<none>,可以通过--record参数记录

bash

运行

[root@master controler]# kubectl rollout pause deployment webcluster # 暂停更新
deployment.apps/webcluster paused

代码解释:暂停 Deployment 的滚动更新过程。

  • 底层:Deployment 控制器会停止处理任何对 Pod 模板的修改,直到恢复更新

bash

运行

[root@master controler]# vim dep.yml

修改内容

yaml

containers:
- image: myapp:v2
  name: myapp

代码解释:将镜像版本修改为 v2。

bash

运行

[root@master controler]# kubectl apply -f dep.yml # 执行成功。但更新过程在监控中没出现
deployment.apps/webcluster configured

代码解释:虽然 YAML 文件更新成功,但因为 Deployment 处于暂停状态,所以不会开始滚动更新。

bash

运行

[root@master controler]# kubectl rollout history deployment webcluster

输出

plaintext

deployment.apps/webcluster
REVISION  CHANGE-CAUSE
7         <none>
8         <none>

输出解释:因为更新被暂停,所以没有生成新的版本号。

bash

运行

[root@master controler]# kubectl rollout resume deployment webcluster # 开启更新
deployment.apps/webcluster resumed

代码解释:恢复 Deployment 的滚动更新过程。

  • 底层:Deployment 控制器会检测到 Pod 模板的变化,开始按照配置的滚动更新策略进行更新

bash

运行

[root@master controler]# kubectl rollout history deployment webcluster

输出

plaintext

deployment.apps/webcluster
REVISION  CHANGE-CAUSE
8         <none>
9         <none>

输出解释:恢复更新后,生成了一个新的版本号 9。

🏭 企业级生产应用(Enterprise Scenario)

使用场景

  • 高可用服务的更新,要求更新过程中服务不中断
  • 分批发布,先更新一小部分 Pod,观察没有问题后再继续更新
  • 紧急回滚,当新版本出现问题时,快速回滚到上一个稳定版本

进阶优化

  1. 使用--record参数记录更新原因:执行kubectl apply -f dep.yml --record,这样CHANGE-CAUSE会记录执行的命令,方便后续排查
  2. 配置金丝雀发布:通过暂停更新,只更新一小部分 Pod,观察流量和错误率,没有问题后再恢复更新
  3. 设置progressDeadlineSeconds:如果更新在指定时间内没有完成,自动标记为失败并回滚
  4. 使用 Argo CD 或 Flux 进行 GitOps 部署:将 Deployment 的 YAML 文件存储在 Git 仓库中,通过 GitOps 工具自动同步到集群,实现版本控制和审计

🚨 课后防宕机指南(Troubleshooting)

错误 1:更新过程中服务不可用

  • 报错现象:更新过程中,部分请求失败
  • 错误原因:maxUnavailable设置过大,或minReadySeconds设置为 0
  • 排查思路:
    1. 检查滚动更新策略:kubectl describe deployment webcluster | grep RollingUpdateStrategy
    2. 确保maxUnavailable不超过 25%,minReadySeconds至少设置为 5 秒
    3. 配置就绪探针,确保只有完全就绪的 Pod 才会接收流量

错误 2:更新暂停后无法恢复

  • 报错现象:执行kubectl rollout resume后,更新仍然没有开始
  • 错误原因:Deployment 的状态异常,或 Pod 模板没有实际变化
  • 排查思路:
    1. 执行kubectl describe deployment webcluster查看 Deployment 的状态和事件
    2. 检查 Pod 模板是否真的发生了变化
    3. 如果仍然无法恢复,可以执行kubectl rollout restart deployment webcluster重启所有 Pod

四、DaemonSet

生活类比

DaemonSet 就像小区的保安。每个单元楼(节点)都必须有一个保安(Pod),不能多也不能少。当有新的单元楼建成(新节点加入集群),保安公司会立刻派一个保安过去;当单元楼拆除(节点离开集群),保安也会被撤走。

bash

运行

[root@master controler]# kubectl create deployment daemonset --image myapp:v1 --dry-run=client -o yaml > daemonset.yml

代码解释:生成一个 Deployment 的 YAML 模板,然后修改为 DaemonSet。

bash

运行

[root@master controler]# vim daemonset.yml

编辑后的完整 YAML

yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: daemonset
  name: daemonset
spec:
  selector:
    matchLabels:
      app: daemonset
  template:
    metadata:
      labels:
        app: daemonset
    spec:
      containers:
      - image: myapp:v1
        name: myapp
核心代码逐行解析(Line-by-Line Breakdown)

表格

行号 代码 底层触发动作
2 kind: DaemonSet 声明这是一个 DaemonSet 类型的资源,API Server 会将请求路由到 DaemonSet 控制器处理
7-9 selector: matchLabels: app: daemonset DaemonSet 通过这个标签选择器来管理它创建的 Pod,必须和 Pod 模板的标签完全匹配
10-18 template: 定义 Pod 模板,DaemonSet 会在每个符合条件的节点上创建一个这样的 Pod
⚠️ 坑点(Gotchas)
  1. 没有设置节点亲和性:默认情况下,DaemonSet 会在所有节点上创建 Pod,包括 master 节点。如果不想在 master 节点上运行,需要设置节点亲和性或污点容忍
  2. 资源限制:DaemonSet 的 Pod 会占用每个节点的资源,如果没有设置资源限制,可能会影响节点上其他 Pod 的运行
  3. 更新策略:DaemonSet 的默认更新策略是RollingUpdate,会逐个节点更新 Pod。如果设置为OnDelete,只有当旧 Pod 被删除时,才会创建新 Pod

bash

运行

# 另外开启一个主机node3,并设定在初始化集群时的所有设定确保所有服务的开启
# 在master中重新生成集群主机注册时需要的token
[root@master controler]# kubeadm token create --print-join-command

代码解释:生成一个新的节点加入集群的命令。

输出

plaintext

kubeadm join 172.25.254.100:6443 --token lqcz14.6f4krq91w75h58bt --discovery-token-ca-cert-hash sha256:6b5950ef2cdba8d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927

bash

运行

[root@node3 ~]# kubeadm join 172.25.254.100:6443 --token lqcz14.6f4krq91w75h58bt --discovery-token-ca-cert-hash sha256:6b5950ef2cdba8d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927 --cri-socket unix:///var/run/cri-dockerd.sock

代码解释:在 node3 节点上执行加入集群的命令。

  • --cri-socket unix:///var/run/cri-dockerd.sock:指定使用 cri-dockerd 作为容器运行时,这是 Kubernetes 1.24 + 版本使用 Docker 作为容器运行时的必要参数

代码解释:当 node3 成功加入集群后,DaemonSet 控制器会立即在 node3 上创建一个 Pod。

  • 底层:DaemonSet 控制器会持续监听集群中的节点变化,当有新节点加入时,检查该节点是否符合 DaemonSet 的节点选择器,如果符合,就创建一个 Pod

🏭 企业级生产应用(Enterprise Scenario)

使用场景

  • 日志收集:每个节点上运行一个 Fluentd 或 Filebeat Pod,收集节点上所有容器的日志
  • 监控代理:每个节点上运行一个 Prometheus Node Exporter 或 Datadog Agent Pod,收集节点的监控指标
  • 网络插件:Calico、Flannel 等 CNI 网络插件都是以 DaemonSet 的形式运行的
  • 存储插件:Ceph、GlusterFS 等存储插件的客户端也是以 DaemonSet 的形式运行的

进阶优化

  1. 设置节点亲和性:只在特定的节点上运行 DaemonSet 的 Pod
  2. 配置污点容忍:让 DaemonSet 的 Pod 能够在带有污点的节点上运行,如 master 节点
  3. 设置更新策略:配置maxUnavailable控制更新的速度
  4. 使用主机网络:对于需要访问主机网络的 Pod,可以设置hostNetwork: true

🚨 课后防宕机指南(Troubleshooting)

错误 1:DaemonSet 的 Pod 没有在所有节点上运行

  • 报错现象:kubectl get daemonset显示DESIREDCURRENT数量不一致
  • 错误原因:节点带有污点,DaemonSet 没有配置对应的污点容忍;或节点不符合节点选择器的条件
  • 排查思路:
    1. 执行kubectl describe daemonset daemonset查看 DaemonSet 的事件
    2. 执行kubectl describe nodes <node-name>查看节点的污点和标签
    3. 为 DaemonSet 添加对应的污点容忍或修改节点选择器

错误 2:DaemonSet 的 Pod 无法启动

  • 报错现象:Pod 一直处于 Pending 状态
  • 错误原因:节点资源不足,或镜像拉取失败
  • 排查思路:
    1. 执行kubectl describe pod <pod-name>查看 Pod 的事件
    2. 检查节点资源:kubectl describe nodes <node-name>
    3. 检查镜像是否存在,以及节点是否能够拉取该镜像

五、Job 控制器

生活类比

Job 就像公司的临时项目组。你告诉项目经理 "我需要完成 6 个任务,每次最多 2 个人同时做",项目经理就会安排 2 个人开始工作,当一个人完成一个任务后,再安排下一个任务,直到所有 6 个任务都完成。任务完成后,项目组就解散了。

bash

运行

[root@master ~]# docker load -i perl-5.34.tar.gz

代码解释:从本地文件加载 perl 镜像。

bash

运行

[root@master ~]# docker tag perl:5.34.0 reg.timinglee.org/library/perl:5.34.0

代码解释:给镜像打标签,指向私有镜像仓库。

bash

运行

[root@master ~]# docker login reg.timinglee.org -u admin
Password:
Login Succeeded

代码解释:登录私有镜像仓库。

bash

运行

[root@master ~]# docker push reg.timinglee.org/library/perl:5.34.0

代码解释:将镜像推送到私有镜像仓库。

bash

运行

[root@master controler]# kubectl create job job --image perl:5.34.0 --dry-run=client -o yaml > job.yml

代码解释:生成一个 Job 的 YAML 模板。

bash

运行

[root@master controler]# vim job.yml

编辑后的完整 YAML

yaml

apiVersion: batch/v1
kind: Job
metadata:
  name: job
spec:
  completions: 6
  parallelism: 2
  template:
    spec:
      containers:
      - image: perl:5.34.0
        name: job
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4
核心代码逐行解析(Line-by-Line Breakdown)

表格

行号 代码 底层触发动作
2 kind: Job 声明这是一个 Job 类型的资源,API Server 会将请求路由到 Job 控制器处理
6 completions: 6 总共需要成功完成 6 个 Pod。底层:Job 控制器会持续统计成功完成的 Pod 数量,直到达到这个值
7 parallelism: 2 最多同时运行 2 个 Pod。底层:Job 控制器会确保同时运行的 Pod 数量不超过这个值
12 command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] 容器启动后执行的命令,计算圆周率的前 2000 位
13 restartPolicy: Never 如果 Pod 失败,不要重启它,而是创建一个新的 Pod。可选值:NeverOnFailure
14 backoffLimit: 4 最多重试 4 次。如果 Pod 失败次数达到这个值,Job 会被标记为失败
⚠️ 坑点(Gotchas)
  1. restartPolicy设置错误:Job 的restartPolicy只能是NeverOnFailure,不能是Always(这是 Pod 的默认值)
  2. backoffLimit设置过大:如果设置过大,失败的 Pod 会不断重试,浪费集群资源
  3. 没有设置活跃时间:如果 Pod 运行时间过长,可能会一直占用资源。可以设置activeDeadlineSeconds限制 Pod 的最大运行时间

bash

运行

[root@master controler]# kubectl apply -f job.yml
job.batch/job created

代码解释:创建 Job 资源。

  • 底层:Job 控制器会创建 2 个 Pod,开始执行任务。当一个 Pod 成功完成后,再创建一个新的 Pod,直到总共成功完成 6 个 Pod

bash

运行

[root@master controler]# kubectl logs job-4b45g

代码解释:查看成功完成的 Pod 的日志,输出圆周率的前 2000 位。

输出

plaintext

3.141592653589793238462643383279502884197169399375105820974944592307816406286208
99862803482534211706798214808651328230664709384460955058223172535940812848111745
02841027019385211055596446229489549303819644288109756659334461284756482337867831
65271201909145648566923460348610454326648213393607260249141273724587006606315588
17488152092096282925409171536436789259036001133053054882046652138414695194151160
94330572703657595919530921861173819326117931051185480744623799627495673518857527
24891227938183011949129833673362440656643086021394946395224737190702179860943702
77053921717629317675238467481846766940513200056812714526356082778577134275778960
91736371787214684409012249534301465495853710507922796892589235420199561121290219
60864034418159813629774771309960518707211349999998372978049951059731732816096318
59502445945534690830264252230825334468503526193118817101000313783875288658753320
83814206171776691473035982534904287554687311595628638823537875937519577818577805
32171226806613001927876611195909216420198938095257201065485863278865936153381827
96823030195203530185296899577362259941389124972177528347913151557485724245415069
59508295331168617278558890750983817546374649393192550604009277016711390098488240
12858361603563707660104710181942955596198946767837449448255379774726847104047534
64620804668425906949129331367702898915210475216205696602405803815019351125338243
00355876402474964732639141992726042699227967823547816360093417216412199245863150
30286182974555706749838505494588586926995690927210797509302955321165344987202755
96023648066549911988183479775356636980742654252786255181841757467289097777279380
00816470600161452491921732172147723501414419735685481613611573525521334757418494
68438523323907394143334547762416862518983569485562099219222184272550254256887671
79049460165346680498862723279178608578438382796797668145410095388378636095068006
42251252051173929848960841284886269456042419652850222106611863067442786220391949
45047123713786960956364371917287467764657573962413890865832645995813390478027590
1

🏭 企业级生产应用(Enterprise Scenario)

使用场景

  • 批处理任务:数据处理、数据分析、报表生成等
  • 一次性任务:数据库迁移、备份恢复、代码构建等
  • 并行计算:科学计算、机器学习训练等

进阶优化

  1. 设置activeDeadlineSeconds:限制 Job 的最大运行时间,防止任务卡住
  2. 使用ttlSecondsAfterFinished:Job 完成后自动删除,清理集群资源
  3. 配置 Pod 亲和性:将 Job 的 Pod 调度到特定的节点上,如带有 GPU 的节点
  4. 使用 Indexed Job:对于需要按顺序执行的任务,可以使用 Indexed Job,每个 Pod 会有一个唯一的索引

🚨 课后防宕机指南(Troubleshooting)

错误 1:Job 一直失败

  • 报错现象:kubectl get jobs显示COMPLETIONS一直为 0,有大量失败的 Pod
  • 错误原因:容器命令执行失败,或镜像拉取失败
  • 排查思路:
    1. 执行kubectl describe job job查看 Job 的事件
    2. 执行kubectl logs <failed-pod-name>查看失败 Pod 的日志
    3. 检查容器命令是否正确,镜像是否存在

错误 2:Job 没有创建任何 Pod

  • 报错现象:kubectl get jobs显示 Job 已创建,但没有任何 Pod
  • 错误原因:restartPolicy设置为Always,或 Job 的 YAML 语法错误
  • 排查思路:
    1. 执行kubectl describe job job查看 Job 的事件
    2. 检查restartPolicy是否为NeverOnFailure
    3. 检查 YAML 语法是否正确

六、CronJob 控制器

生活类比

CronJob 就像公司的闹钟。你告诉闹钟 "每天早上 9 点提醒我开会",闹钟就会每天准时提醒你。CronJob 会按照你指定的时间计划,定期创建 Job 来执行任务。

bash

运行

[root@master controler]# kubectl create cronjob cronjob --image busybox --schedule "* * * * *" --dry-run=client -o yaml > cronjob.yml

代码解释:生成一个 CronJob 的 YAML 模板,计划为每分钟执行一次。

bash

运行

[root@master controler]# vim cronjob.yml

编辑后的完整 YAML

yaml

apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob
spec:
  jobTemplate:
    metadata:
      name: cronjob
    spec:
      template:
        spec:
          containers:
          - image: busybox
            name: cronjob
            command:
            - /bin/sh
            - -c
            - echo "hello timinglee"
          restartPolicy: OnFailure
  schedule: '* * * * *'
核心代码逐行解析(Line-by-Line Breakdown)

表格

行号 代码 底层触发动作
2 kind: CronJob 声明这是一个 CronJob 类型的资源,API Server 会将请求路由到 CronJob 控制器处理
5-17 jobTemplate: 定义 Job 模板,CronJob 会按照这个模板定期创建 Job
18 schedule: '* * * * *' Cron 表达式,定义任务的执行计划。格式为:分 时 日 月 周* * * * *表示每分钟执行一次
⚠️ 坑点(Gotchas)
  1. Cron 表达式错误:Cron 表达式的格式很容易写错,特别是日和周的部分
  2. 并发执行:如果任务执行时间超过了执行间隔,可能会导致多个 Job 同时运行。可以设置concurrencyPolicy控制并发策略
  3. 时区问题:CronJob 使用的是控制平面的时区,不是节点的时区。如果需要使用特定时区,可以设置timeZone字段(Kubernetes 1.24+)

bash

运行

[root@master controler]# kubectl apply -f cronjob.yml # 整分运行

代码解释:创建 CronJob 资源。

  • 底层:CronJob 控制器会每分钟检查一次计划时间,当时间到达时,创建一个 Job

bash

运行

[root@master controler]# kubectl get cronjobs.batch

代码解释:查看 CronJob 的状态。

输出

plaintext

NAME      SCHEDULE    TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob   * * * * *   <none>     False     0        17s             70s

输出解释

  • LAST SCHEDULE:上次执行任务的时间
  • ACTIVE:当前正在运行的 Job 数量

bash

运行

[root@master controler]# kubectl logs cronjob-29598241-pxggh
hello timinglee

代码解释:查看 CronJob 创建的 Pod 的日志,输出 "hello timinglee"。

🏭 企业级生产应用(Enterprise Scenario)

使用场景

  • 定时任务:每天凌晨备份数据库、每周生成报表、每月清理日志等
  • 定时监控:定期检查服务状态、定期发送监控告警等
  • 定时数据同步:定期从其他系统同步数据等

进阶优化

  1. 设置concurrencyPolicy:控制并发策略,可选值:Allow(允许并发)、Forbid(禁止并发)、Replace(替换旧的 Job)
  2. 设置startingDeadlineSeconds:如果因为某种原因错过了执行时间,最多延迟多久执行
  3. 设置successfulJobsHistoryLimitfailedJobsHistoryLimit:限制保留的成功和失败 Job 的数量
  4. 使用timeZone字段:指定 CronJob 使用的时区

🚨 课后防宕机指南(Troubleshooting)

错误 1:CronJob 没有按时执行

  • 报错现象:到了计划时间,没有创建 Job
  • 错误原因:Cron 表达式错误,或控制平面的时间不正确
  • 排查思路:
    1. 检查 Cron 表达式是否正确
    2. 检查控制平面节点的时间是否正确
    3. 执行kubectl describe cronjob cronjob查看 CronJob 的事件

错误 2:多个 Job 同时运行

  • 报错现象:有多个 Job 同时在运行
  • 错误原因:任务执行时间超过了执行间隔,且concurrencyPolicy设置为Allow
  • 排查思路:
    1. 检查任务的执行时间
    2. concurrencyPolicy设置为ForbidReplace
    3. 调整执行间隔,确保任务能够在间隔时间内完成

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐