03(下)Kubernetes 核心控制器实验手册
目录
核心代码逐行解析(Line-by-Line Breakdown)
🏭 企业级生产应用(Enterprise Scenario)
核心代码逐行解析(Line-by-Line Breakdown)
🏭 企业级生产应用(Enterprise Scenario)
核心代码逐行解析(Line-by-Line Breakdown)
🏭 企业级生产应用(Enterprise Scenario)
核心代码逐行解析(Line-by-Line Breakdown)
🏭 企业级生产应用(Enterprise Scenario)
核心代码逐行解析(Line-by-Line Breakdown)
🏭 企业级生产应用(Enterprise Scenario)
核心代码逐行解析(Line-by-Line Breakdown)
🏭 企业级生产应用(Enterprise Scenario)
一、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)
- 标签不匹配:如果
template.metadata.labels和spec.selector.matchLabels不一致,ReplicaSet 会认为没有任何 Pod 属于它,从而无限创建新 Pod,直到耗尽集群资源 - 手动创建的 Pod:如果手动创建了带有
app=webcluster标签的 Pod,ReplicaSet 会自动接管它,如果数量超过replicas值,会随机删除多余的 Pod - 不能直接更新镜像: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 节点
- 自定义控制器的基础组件
进阶优化:
- 添加资源限制:为容器设置
resources.requests和resources.limits,防止 Pod 耗尽节点资源 - 配置亲和性和反亲和性:让 Pod 分布在不同的节点上,提高可用性
- 添加存活探针和就绪探针:让 ReplicaSet 能够自动重启故障 Pod,并将未就绪的 Pod 从服务中移除
- 使用 HPA 自动扩缩容:根据 CPU、内存使用率或自定义指标自动调整
replicas值
🚨 课后防宕机指南(Troubleshooting)
错误 1:Pod 无限创建
- 报错现象:
kubectl get pods显示大量 Pending 状态的 Pod,数量持续增加 - 错误原因:
template.metadata.labels和spec.selector.matchLabels不匹配 - 排查思路:
- 执行
kubectl describe rs webcluster查看 ReplicaSet 的事件 - 检查
selector.matchLabels和template.metadata.labels是否完全一致 - 执行
kubectl delete rs webcluster删除错误的 ReplicaSet,重新创建
- 执行
错误 2:Pod 无法创建
- 报错现象:Pod 一直处于 Pending 状态
- 错误原因:节点资源不足,或镜像拉取失败
- 排查思路:
- 执行
kubectl describe pod <pod-name>查看 Pod 的事件 - 检查节点资源:
kubectl describe nodes - 检查镜像是否存在,以及节点是否能够拉取该镜像
- 执行
二、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)
minReadySeconds设置为 0:如果设置为 0,Pod 一就绪就会被标记为可用,可能导致流量被转发到还没完全启动的 Pod,造成请求失败- 直接修改 ReplicaSet:不要直接修改 Deployment 创建的 ReplicaSet,Deployment 会覆盖你的修改
- 标签冲突:如果集群中已经存在带有相同标签的 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 进行管理
- 支持蓝绿部署、金丝雀发布等高级部署策略
进阶优化:
- 配置滚动更新策略:通过
maxSurge和maxUnavailable控制更新的速度和可用性 - 添加版本历史记录:设置
revisionHistoryLimit保留更多的历史版本,方便回滚 - 配置就绪探针和存活探针:确保只有完全就绪的 Pod 才会接收流量,故障的 Pod 会被自动重启
- 使用 ConfigMap 和 Secret 管理配置:将配置和镜像分离,不需要重新构建镜像就能修改配置
- 实现金丝雀发布:通过创建两个 Deployment(一个旧版本,一个新版本),并使用 Service 或 Ingress 控制流量比例
🚨 课后防宕机指南(Troubleshooting)
错误 1:滚动更新卡住
- 报错现象:
kubectl rollout status deployment webcluster显示一直处于更新中 - 错误原因:新 Pod 无法就绪(镜像拉取失败、健康检查失败、资源不足等)
- 排查思路:
- 执行
kubectl describe deployment webcluster查看 Deployment 的事件 - 执行
kubectl get pods查看新 Pod 的状态 - 执行
kubectl describe pod <new-pod-name>查看 Pod 的事件 - 如果更新失败,执行
kubectl rollout undo deployment webcluster回滚到上一个版本
- 执行
错误 2:回滚失败
- 报错现象:执行回滚命令后,Pod 没有回到旧版本
- 错误原因:历史版本已被删除(
revisionHistoryLimit设置太小) - 排查思路:
- 执行
kubectl rollout history deployment webcluster查看可用的历史版本 - 如果没有可用的历史版本,只能重新应用旧的 YAML 文件
- 建议将
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)
maxUnavailable: 0和maxSurge: 0不能同时设置:这样会导致无法进行任何更新- 数值过大导致资源耗尽:如果
maxSurge设置过大,更新过程中会创建大量 Pod,可能耗尽集群资源 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,观察没有问题后再继续更新
- 紧急回滚,当新版本出现问题时,快速回滚到上一个稳定版本
进阶优化:
- 使用
--record参数记录更新原因:执行kubectl apply -f dep.yml --record,这样CHANGE-CAUSE会记录执行的命令,方便后续排查 - 配置金丝雀发布:通过暂停更新,只更新一小部分 Pod,观察流量和错误率,没有问题后再恢复更新
- 设置
progressDeadlineSeconds:如果更新在指定时间内没有完成,自动标记为失败并回滚 - 使用 Argo CD 或 Flux 进行 GitOps 部署:将 Deployment 的 YAML 文件存储在 Git 仓库中,通过 GitOps 工具自动同步到集群,实现版本控制和审计
🚨 课后防宕机指南(Troubleshooting)
错误 1:更新过程中服务不可用
- 报错现象:更新过程中,部分请求失败
- 错误原因:
maxUnavailable设置过大,或minReadySeconds设置为 0 - 排查思路:
- 检查滚动更新策略:
kubectl describe deployment webcluster | grep RollingUpdateStrategy - 确保
maxUnavailable不超过 25%,minReadySeconds至少设置为 5 秒 - 配置就绪探针,确保只有完全就绪的 Pod 才会接收流量
- 检查滚动更新策略:
错误 2:更新暂停后无法恢复
- 报错现象:执行
kubectl rollout resume后,更新仍然没有开始 - 错误原因:Deployment 的状态异常,或 Pod 模板没有实际变化
- 排查思路:
- 执行
kubectl describe deployment webcluster查看 Deployment 的状态和事件 - 检查 Pod 模板是否真的发生了变化
- 如果仍然无法恢复,可以执行
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)
- 没有设置节点亲和性:默认情况下,DaemonSet 会在所有节点上创建 Pod,包括 master 节点。如果不想在 master 节点上运行,需要设置节点亲和性或污点容忍
- 资源限制:DaemonSet 的 Pod 会占用每个节点的资源,如果没有设置资源限制,可能会影响节点上其他 Pod 的运行
- 更新策略: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 的形式运行的
进阶优化:
- 设置节点亲和性:只在特定的节点上运行 DaemonSet 的 Pod
- 配置污点容忍:让 DaemonSet 的 Pod 能够在带有污点的节点上运行,如 master 节点
- 设置更新策略:配置
maxUnavailable控制更新的速度 - 使用主机网络:对于需要访问主机网络的 Pod,可以设置
hostNetwork: true
🚨 课后防宕机指南(Troubleshooting)
错误 1:DaemonSet 的 Pod 没有在所有节点上运行
- 报错现象:
kubectl get daemonset显示DESIRED和CURRENT数量不一致 - 错误原因:节点带有污点,DaemonSet 没有配置对应的污点容忍;或节点不符合节点选择器的条件
- 排查思路:
- 执行
kubectl describe daemonset daemonset查看 DaemonSet 的事件 - 执行
kubectl describe nodes <node-name>查看节点的污点和标签 - 为 DaemonSet 添加对应的污点容忍或修改节点选择器
- 执行
错误 2:DaemonSet 的 Pod 无法启动
- 报错现象:Pod 一直处于 Pending 状态
- 错误原因:节点资源不足,或镜像拉取失败
- 排查思路:
- 执行
kubectl describe pod <pod-name>查看 Pod 的事件 - 检查节点资源:
kubectl describe nodes <node-name> - 检查镜像是否存在,以及节点是否能够拉取该镜像
- 执行
五、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。可选值:Never、OnFailure |
| 14 | backoffLimit: 4 |
最多重试 4 次。如果 Pod 失败次数达到这个值,Job 会被标记为失败 |
⚠️ 坑点(Gotchas)
restartPolicy设置错误:Job 的restartPolicy只能是Never或OnFailure,不能是Always(这是 Pod 的默认值)backoffLimit设置过大:如果设置过大,失败的 Pod 会不断重试,浪费集群资源- 没有设置活跃时间:如果 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)
使用场景:
- 批处理任务:数据处理、数据分析、报表生成等
- 一次性任务:数据库迁移、备份恢复、代码构建等
- 并行计算:科学计算、机器学习训练等
进阶优化:
- 设置
activeDeadlineSeconds:限制 Job 的最大运行时间,防止任务卡住 - 使用
ttlSecondsAfterFinished:Job 完成后自动删除,清理集群资源 - 配置 Pod 亲和性:将 Job 的 Pod 调度到特定的节点上,如带有 GPU 的节点
- 使用 Indexed Job:对于需要按顺序执行的任务,可以使用 Indexed Job,每个 Pod 会有一个唯一的索引
🚨 课后防宕机指南(Troubleshooting)
错误 1:Job 一直失败
- 报错现象:
kubectl get jobs显示COMPLETIONS一直为 0,有大量失败的 Pod - 错误原因:容器命令执行失败,或镜像拉取失败
- 排查思路:
- 执行
kubectl describe job job查看 Job 的事件 - 执行
kubectl logs <failed-pod-name>查看失败 Pod 的日志 - 检查容器命令是否正确,镜像是否存在
- 执行
错误 2:Job 没有创建任何 Pod
- 报错现象:
kubectl get jobs显示 Job 已创建,但没有任何 Pod - 错误原因:
restartPolicy设置为Always,或 Job 的 YAML 语法错误 - 排查思路:
- 执行
kubectl describe job job查看 Job 的事件 - 检查
restartPolicy是否为Never或OnFailure - 检查 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)
- Cron 表达式错误:Cron 表达式的格式很容易写错,特别是日和周的部分
- 并发执行:如果任务执行时间超过了执行间隔,可能会导致多个 Job 同时运行。可以设置
concurrencyPolicy控制并发策略 - 时区问题: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)
使用场景:
- 定时任务:每天凌晨备份数据库、每周生成报表、每月清理日志等
- 定时监控:定期检查服务状态、定期发送监控告警等
- 定时数据同步:定期从其他系统同步数据等
进阶优化:
- 设置
concurrencyPolicy:控制并发策略,可选值:Allow(允许并发)、Forbid(禁止并发)、Replace(替换旧的 Job) - 设置
startingDeadlineSeconds:如果因为某种原因错过了执行时间,最多延迟多久执行 - 设置
successfulJobsHistoryLimit和failedJobsHistoryLimit:限制保留的成功和失败 Job 的数量 - 使用
timeZone字段:指定 CronJob 使用的时区
🚨 课后防宕机指南(Troubleshooting)
错误 1:CronJob 没有按时执行
- 报错现象:到了计划时间,没有创建 Job
- 错误原因:Cron 表达式错误,或控制平面的时间不正确
- 排查思路:
- 检查 Cron 表达式是否正确
- 检查控制平面节点的时间是否正确
- 执行
kubectl describe cronjob cronjob查看 CronJob 的事件
错误 2:多个 Job 同时运行
- 报错现象:有多个 Job 同时在运行
- 错误原因:任务执行时间超过了执行间隔,且
concurrencyPolicy设置为Allow - 排查思路:
- 检查任务的执行时间
- 将
concurrencyPolicy设置为Forbid或Replace - 调整执行间隔,确保任务能够在间隔时间内完成
更多推荐


所有评论(0)