控制器(Controller)是 Kubernetes 控制面的灵魂。整个集群之所以能在节点宕机、Pod 漂移、版本劣化的情况下依然稳定对外服务,靠的不是人工干预,而是控制器永不停歇的调谐循环(Reconcile Loop)。本文以实操为主线,逐一拆解 ReplicaSet、Deployment、DaemonSet 的设计哲学、边界与工程实践。
文章目录
-
- 一、Controllers:期望状态的守护者
-
- [1. 核心职责](#1. 核心职责)
- [2. 两类容器,两条治理路径](#2. 两类容器,两条治理路径)
- [3. 环境准备](#3. 环境准备)
- 二、ReplicaSet:副本数量的守门人
-
- [1. 定义与定位](#1. 定义与定位)
- [2. 工作原理](#2. 工作原理)
- [3. 创建与验证](#3. 创建与验证)
- [4. 健壮性实测](#4. 健壮性实测)
-
- 测试一:删除单个副本,观察自愈
- [测试二:手动创建相同标签的 Pod](#测试二:手动创建相同标签的 Pod)
- [5. 删除行为与孤儿保留](#5. 删除行为与孤儿保留)
- 三、ReplicationController:已被取代的前辈
- 四、Deployment:声明式更新的编排者
-
- [1. 定位与层级关系](#1. 定位与层级关系)
- [2. 典型用例](#2. 典型用例)
- [3. 创建:两种范式](#3. 创建:两种范式)
-
- 方式一:命令行(快捷起手)
- [方式二:YAML 清单(生产首选)](#方式二:YAML 清单(生产首选))
- 两种方式如何选
- [4. 编辑](#4. 编辑)
- [5. 删除](#5. 删除)
- [6. 水平伸缩](#6. 水平伸缩)
- [7. 健壮性实测:节点宕机后的自愈](#7. 健壮性实测:节点宕机后的自愈)
- [8. 更新镜像](#8. 更新镜像)
- [9. 版本控制与回滚](#9. 版本控制与回滚)
- [10. 滚动更新:两个参数决定一切](#10. 滚动更新:两个参数决定一切)
- 五、DaemonSet:节点级守护进程
-
- [1. 定义](#1. 定义)
- [2. 典型用例](#2. 典型用例)
- [3. 用法层次](#3. 用法层次)
- [4. 创建与查看](#4. 创建与查看)
- [5. 调度:污点决定 Pod 落点](#5. 调度:污点决定 Pod 落点)
- [6. 健壮性与删除](#6. 健壮性与删除)
- [7. K8s 集群中的 DaemonSet](#7. K8s 集群中的 DaemonSet)
- 总结
一、Controllers:期望状态的守护者
1. 核心职责
Controller 的唯一使命,是让被管理资源的实际状态 不断逼近用户声明的期望状态 。它持续监控集群对象,一旦发现实际与期望存在偏差,就立即执行补偿动作------这正是 Kubernetes 自愈能力 与自动弹性伸缩的能力来源。
2. 两类容器,两条治理路径
从运行形态看,容器可分为两类,Kubernetes 也据此给出了两套控制器体系:
| 容器类型 | 行为特征 | 典型场景 | 对应控制器 |
|---|---|---|---|
| 服务类容器 | 常驻运行,持续对外提供服务 | Nginx、API 服务、数据库 | ReplicaSet、Deployment、DaemonSet |
| 工作类容器 | 一次性任务,执行完毕后容器退出 | 批处理、数据清洗、定时报表 | Job、CronJob |
3. 环境准备
为隔离实验资源,先建立独立命名空间并切换上下文:
bash
root@master30:~# kubectl create ns controllers
root@master30:~# kubectl config set-context --current --namespace controllers
二、ReplicaSet:副本数量的守门人
1. 定义与定位
ReplicaSet(简称 RS)负责维护一组在任意时刻都处于运行状态的 Pod 副本集合,其价值在于保证指定数量的、完全相同的 Pod 始终可用。
需要清醒认识到它的定位:RS 主要被 Deployment 用作 Pod 创建、删除与更新的底层编排机制。日常生产中,几乎没有人直接操作 ReplicaSet。
2. 工作原理
ReplicaSet 由三个核心字段驱动:
- selector ------ 用于识别归属 Pod 集合的选择算符;
- replicas ------ 应当维持的副本数量;
- template ------ 创建新 Pod 时使用 Pod 模板。
RS 依据模板创建出指定数量的 Pod,并通过持续的差值比对实现自身价值:
- 实际数量 多于 期望数量 → RS 主动终止多余的 Pod;
- 实际数量 少于 期望数量 → RS 立即补齐 Pod(例如宿主机内核升级后,在其他节点上重建新 Pod)。
3. 创建与验证
bash
root@master30:~# vim rs.yaml
bash
# rs.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: hub.laoma.cloud/library/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 的属主关系
root@master30:~# kubectl describe pod nginx-9jg4f | grep Controlled
Controlled By: ReplicaSet/nginx
4. 健壮性实测
测试一:删除单个副本,观察自愈
bash
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
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
nginx-9jg4f 1/1 Running 0 9m20s
nginx-tjtp2 1/1 Running 0 9m20s
nginx-95pth 消失 2 秒后,nginx-4qw2z 被立即补建,副本数重回 3。
机制要点 :Pod 的
metadata.ownerReferences字段记录了所属的主资源。正是通过这条引用链,ReplicaSet 才能掌握自己维护的 Pod 集合状态,并据此规划操作行为。更值得注意的是认领规则 :RS 通过 selector 获取 Pod 集合。若某个 Pod 没有 OwnerReference,或其 OwnerReference 并非控制器,同时又能匹配到某个 ReplicaSet 的选择算符,那么该 Pod 会立即被这个 ReplicaSet 认领。
测试二:手动创建相同标签的 Pod
bash
# 创建一个带 app=nginx 标签的裸 Pod
root@master30:~# kubectl run nginx --image=hub.laoma.cloud/library/nginx:latest -l app=nginx; kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 Terminating 0 0s
nginx-4qw2z 1/1 Running 0 3m40s
nginx-9jg4f 1/1 Running 0 12m
nginx-tjtp2 1/1 Running 0 12m
# 结果:刚创建出来就立刻被 Terminating
裸 Pod 被 RS 认领后,因超出 replicas: 3 的期望值,随即被回收------认领即治理。
5. 删除行为与孤儿保留
默认删除 RS 控制器时,其管理的全部 Pod 会被级联删除:
bash
root@master30:~# kubectl delete rs nginx
root@master30:~# kubectl get pods
使用 --cascade=orphan 可只删除 RS、保留 Pod( Pod 变为无主孤儿):
bash
root@master30:~# kubectl apply -f rs.yaml
root@master30:~# kubectl delete rs nginx --cascade=orphan
root@master30:~# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod/nginx-27vzb 1/1 Running 0 73s
pod/nginx-7lc95 1/1 Running 0 73s
pod/nginx-mmrhk 1/1 Running 0 73s
# 清理残留 Pod
root@master30:~# kubectl delete all -l app=nginx
三、ReplicationController:已被取代的前辈
ReplicationController(简称 RC)与 ReplicaSet 功能相近,是早期版本中的副本管理机制。ReplicaSet 是 RC 的升级版 ,关键差异在于 RS 支持新的基于集合的标签选择算符 (matchExpressions)。
由于 RC 已退出主流实践,本文不再展开。新项目一律使用 ReplicaSet 或 Deployment。
四、Deployment:声明式更新的编排者
1. 定位与层级关系
Deployment(简称 deploy)为 Pod 与 ReplicaSet 提供声明式的更新能力。
三者的层级清晰可见:
bash
# 资源层级:上层控制器逐层托管下层资源
Deployment → ReplicaSet → Pod
- ReplicaSet 只解决"跑够 N 个副本";
- Deployment 管理 ReplicaSet,并在此之上提供滚动更新、版本回滚、暂停恢复、伸缩等编排能力。
因此官方建议:用 Deployment 管理 ReplicaSet,除非你需要自定义更新编排。这意味着你可能永远不需要直接操作 ReplicaSet 对象。
2. 典型用例
| 场景 | 具体动作 |
|---|---|
| 上线发布 | 创建 Deployment 将 ReplicaSet 上线,并检查其是否成功 |
| 渐进更新 | 更新 PodTemplateSpec 声明 Pod 新状态,新 ReplicaSet 被创建,Pod 以受控速率从旧 RS 迁移至新 RS,每轮都推进修订版本 |
| 故障回滚 | 当前状态不稳定时回滚至较早版本,每次回滚同样更新修订版本 |
| 容量扩展 | 扩大 Deployment 规模以承载更高负载 |
| 批量变更 | 暂停上线以应用多项 PodTemplateSpec 修改,再恢复执行启动新版本 |
| 停滞判定 | 使用 Deployment Status 判断上线过程是否卡住 |
| 资源清理 | 清理较旧的、不再需要的 ReplicaSet |
3. 创建:两种范式
方式一:命令行(快捷起手)
bash
root@master30:~# kubectl create deployment web --image=hub.laoma.cloud/library/nginx:1.27 --replicas=2
# 查看 Deployment 连带创建的所有资源
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
逐层验证属主关系:
bash
# Deployment 详细信息
root@master30:~# kubectl describe deployments.apps web
Name: web
Namespace: laoma
CreationTimestamp: Sat, 21 Oct 2023 13:17:06 +0000
Labels: app=web
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=web
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=web
Containers:
nginx:
Image: nginx:1.27
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: web-b78cbd74b (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 21s deployment-controller Scaled up replica set web-b78cbd74b to 2
# ReplicaSet 与 Deployment 的关系
root@master30:~# kubectl describe replicaset.apps web-b78cbd74b | grep Controlled
Controlled By: Deployment/web
# 指明 ReplicaSet 由 Deployment/web 创建
# Pod 与 ReplicaSet 的关系
root@master30:~# kubectl describe pod web-b78cbd74b-6fjxs | grep Controlled
Controlled By: ReplicaSet/web-b78cbd74b
# 指明 Pod 由 ReplicaSet/web-b78cbd74b 创建
方式二:YAML 清单(生产首选)
先用 dry-run 导出清单,再纳入版本管理:
bash
# 导出 Deployment 的 yaml 文件
root@master30:~# kubectl create deployment web --image=hub.laoma.cloud/library/nginx:1.27 --replicas=2 --dry-run=client -o yaml > deployment-web.yaml
root@master30:~# cat deployment-web.yaml
# deployment-web.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: hub.laoma.cloud/library/nginx:1.27
name: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
root@master30:~# kubectl apply -f deployment-web.yaml
关键字段语义
| 字段 | 含义 |
|---|---|
apiVersion |
当前配置格式的版本 |
kind |
要创建的资源类型,此处为 Deployment |
metadata |
资源元数据,name 为必需项 |
spec |
该 Deployment 的规格说明 |
spec.replicas |
副本数量,默认为 1 |
spec.template |
Pod 模板,配置文件的核心部分 |
spec.template.metadata |
Pod 元数据,至少定义一个 label,key/value 可任意指定 |
spec.template.spec |
Pod 规格,定义容器属性,name 与 image 为必需 |
两种方式如何选
| 维度 | 命令行方式 | 配置文件方式 |
|---|---|---|
| 上手成本 | 简单、直观、快捷 | 需熟悉清单语法,有一定门槛 |
| 表达内容 | 描述 How(怎么做) | 描述 What(最终要达到的状态) |
| 可复用性 | 一次性 | 提供资源模板,可重复部署 |
| 适用场景 | 临时测试、实验验证 | 正式、跨环境、规模化部署 |
附带一句实用价值:
kubectl apply不仅能创建资源,同样能更新资源,一个命令贯穿建与改。
4. 编辑
bash
# 方法一:命令行直接修改
root@master30:~# kubectl edit deployments.apps web
# 方法二:编辑资源文件后 apply 应用
# 方法三:命令行定向修改,例如调整副本数
root@master30:~# kubectl scale deployment web --replicas=4
5. 删除
删除 Deployment 时,默认连带删除其管理的子资源:
bash
root@master30:~# kubectl delete deployments.apps web
deployment.apps "web" deleted
使用 --cascade=orphan 可保留子资源:
bash
root@master30:~# kubectl apply -f deployment-web.yaml
root@master30:~# kubectl delete deployments.apps web --cascade=orphan
# 先确认待删除对象
root@master30:~# kubectl get all -l app=web
# 确认无误后再删除
root@master30:~# kubectl delete all -l app=web
root@master30:~# kubectl get all -l app=web
6. 水平伸缩
bash
# 创建 Deployment
root@master30:~# kubectl create deployment web --image=hub.laoma.cloud/library/nginx:1.27 --replicas=2
# 一键扩容
root@master30:~# kubectl scale deployment web --replicas=3
# 或者交互式编辑
root@master30:~# kubectl edit deployments.apps web
# 或者导出清单、修改后 apply
root@master30:~# kubectl get deployments.apps web -o yaml > web.yaml
root@master30:~# vim web.yaml
root@master30:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-5899d78c9-cckln 1/1 Running 0 9m28s
web-5899d78c9-p8pk4 1/1 Running 0 43s
web-5899d78c9-phntq 1/1 Running 0 9m28s
7. 健壮性实测:节点宕机后的自愈
关闭 worker 节点,观察 Pod 重建行为:
bash
root@master30:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-5899d78c9-cckln 1/1 Running 0 14m 10.224.51.134 worker31.laoma.cloud <none> <none>
web-5899d78c9-p8pk4 1/1 Running 0 6m12s 10.224.51.135 worker31.laoma.cloud <none> <none>
web-5899d78c9-phntq 1/1 Running 0 14m 10.224.225.69 worker32.laoma.cloud <none> <none>
# 关闭 worker32
root@worker32:~# init 0
# 等待约 5 分钟:Kubernetes 判定 worker32 不可用,将其上的 Pod 标记为 Unknown,
# 并在 worker31 上重建 Pod,维持总副本数为 3
# 当 worker32 恢复后,Unknown 的 Pod 会被删除;
# 已在其他节点运行的 Pod 不会重新调度回 worker32
Kubernetes 判定节点宕机,需经历三个阶段:
| 阶段 | 机制 | 关键参数 | 归属组件 |
|---|---|---|---|
| ① 心跳上报 | Node 上 kubelet 默认每 10s 向 apiserver 上报自身状态(kubelet → kube-apiserver) | --- | kubelet |
| ② 健康判定 | Master 上 controller-manager 每 5s 检查一次心跳,连续 40s 未收到即判定 Node 不健康并标记为 NotReady | node-monitor-period=5s node-monitor-grace-period=40s |
kube-controller-manager |
| ③ 驱逐 Pod | 节点 NotReady 持续满 5 分钟,开始将 Pod 驱逐到其他节点 | pod-eviction-timeout=300s |
kube-controller-manager |
参数修改方式(该组件以静态 Pod 形式运行在 master 节点):
bash
# 配置路径
/etc/kubernetes/manifests/kube-controller-manager.yaml
# 编辑静态 Pod 配置文件,找到 command 段,
# 在其下面添加或修改上述参数行,保存文件即可触发静态 Pod 重启
8. 更新镜像
将 Deployment 的镜像从 nginx:1.27 升级至 nginx:1.28:
bash
# 获取容器名称
root@master30:~# kubectl get deployments.apps -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
web 3/3 3 3 139m nginx hub.laoma.cloud/library/nginx:1.27 app=web
# 或者
root@master30:~# kubectl describe deployments.apps web | grep Container -i -A2
Containers:
nginx:
Image: hub.laoma.cloud/library/nginx:1.27
# 更新镜像
root@master30:~# kubectl set image deployment/web nginx=hub.laoma.cloud/library/nginx:1.28 --record
# 或者直接编辑 Deployment 设置镜像
root@master30:~# kubectl edit deployments.apps web
# 可以看到新增了一个 ReplicaSet,用于创建新的 Pod
root@master30:~# kubectl get rs
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-5899d78c9 0 0 0 26m
replicaset.apps/web-6c57bdf5f4 3 3 3 9s
# 校验镜像版本
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 hub.laoma.cloud/library/nginx:1.28 app=web
旧 ReplicaSet 被缩容至 0 但并未删除------这正是回滚能力的物质基础。
9. 版本控制与回滚
kubectl rollout 是 Deployment 版本控制的统一入口:
bash
root@master30:~# kubectl rollout -h
Manage the rollout of one or many resources.
Valid resource types include:
* deployments
* daemonsets
* statefulsets
Examples:
# Rollback to the previous deployment
kubectl rollout undo deployment/abc
# Check the rollout status of a daemonset
kubectl rollout status daemonset/foo
# Restart a deployment
kubectl rollout restart deployment/abc
# Restart deployments with the 'app=nginx' label
kubectl rollout restart deployment --selector=app=nginx
Available Commands:
history View rollout history
pause Mark the provided resource as paused
restart Restart a resource
resume Resume a paused resource
status Show the status of the rollout
undo Undo a previous rollout
Usage:
kubectl rollout SUBCOMMAND [options]
Use "kubectl rollout <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).
实操示例:
bash
# 再次更新镜像至 nginx:1.29
root@master30:~# kubectl set image deployment/web nginx=hub.laoma.cloud/library/nginx:1.29 --record
# 查看更新记录(--record 会把变更原因写入 CHANGE-CAUSE)
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
# 回滚到版本 1
root@master30:~# kubectl rollout undo deployment web --to-revision=1
deployment.apps/web rolled back
root@master30:~# kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
2 kubectl set image deployment/web *=nginx:1.28 --record=true
3 kubectl set image deployment/web *=nginx:1.29 --record=true
4 <none>
注意回滚后修订版本号的走向:回滚本身会生成 REVISION 4 ,而不是把编号倒退回 1。Kubernetes 的版本序列是单调递增的,回滚只是复用旧模板的一次新上线。
10. 滚动更新:两个参数决定一切
Kubernetes 用 maxSurge 与 maxUnavailable 精细控制 Pod 替换节奏:
| 参数 | 作用 | 取值形式 | 默认 | 示例(DESIRED=10) |
|---|---|---|---|---|
maxSurge |
滚动更新过程中,副本总数允许超过期望值的上限 | 整数(如 3)或百分比,向上取整 | 25% | 副本总数最大为 roundUp(10 + 10 × 25%) = 13,因此 CURRENT 可见 13 |
maxUnavailable |
滚动更新过程中,不可用副本占期望值的最大比例 | 整数(如 3)或百分比,向下取整 | 25% | 可用副本至少为 roundDown(10 - 10 × 25%) = 8,因此 AVAILABLE 可见 8 |
两条直觉结论:
maxSurge越大 → 初始创建的新副本越多;maxUnavailable越大 → 初始销毁的旧副本越多,更新初期造成的不可用副本也越多。
理想情况下,本案例的滚动更新过程应当如此演进:
- 创建 3 个新副本,此时 Running 副本数为 10,叠加
maxSurge后副本总数达到 13; - 销毁 2 个旧副本,同时再创建 2 个新副本,此时 Running 副本数为 8。若先前创建的 3 个副本尚未转为 Running,则
ContainerCreating副本数为 5,maxSurge总数仍为 13; - 新副本状态转为 Running------例如先前创建的 5 个新副本在同一时刻变为 Running(这是一种理想化情形);
- 此时 Running 状态副本为 13 个,那么可以一次性销毁 5 个旧副本,同时一次性创建 5 个新副本,使 Running 副本数回到 8;
- 该过程持续循环,直到所有旧副本被新副本替换,滚动更新完成。
实践验证:更新 Deployment 镜像,并用以下脚本持续监控 Pod 状态分布:
bash
root@master30:~# vim monitor_pod_numbers
bash
#!/bin/bash
while true
do
echo '===================' >> output.log
kubectl get pods --no-headers |awk '{print $3}' |sort | uniq -c |sed -r 's/^ +//' >> output.log
sleep 0.5
done
采集到的日志形态如下(可清晰看到状态从 Running 向 ContainerCreating / Terminating 扩散、再收敛回全量 Running 的完整曲线):
bash
# output.log
===================
10 Running
===================
5 ContainerCreating
8 Running
2 Terminating
===================
5 ContainerCreating
8 Running
2 Terminating
===================
5 ContainerCreating
8 Running
===================
5 ContainerCreating
8 Running
===================
3 ContainerCreating
1 Pending
9 Running
4 Terminating
===================
5 ContainerCreating
8 Running
5 Terminating
===================
5 ContainerCreating
8 Running
5 Terminating
===================
5 ContainerCreating
8 Running
3 Terminating
===================
10 Running
4 Terminating
===================
10 Running
2 Terminating
===================
10 Running
===================
10 Running
===================
10 Running
五、DaemonSet:节点级守护进程
1. 定义
DaemonSet(简称 DS)确保全部或指定节点上各运行一个 Pod 副本。集群规模变化时,DS 自动跟随:
- 新节点加入集群 → 在该节点上新建一个 Pod;
- 节点从集群移除 → 该节点上的 Pod 同步回收。
一句话概括其语义:"每台机器都要有一个"。
2. 典型用例
DS 天然适合承载节点级守护进程:
| 类别 | 代表组件 |
|---|---|
| 集群守护进程 | 存储守护进程 glusterd、ceph |
| 日志收集 | fluentd、logstash |
| 监控采集 | Prometheus Node Exporter、collectd |
3. 用法层次
- 简单用法:为每种守护进程,在所有节点上各启动一个 DaemonSet;
- 复杂用法:为同一种守护进程部署多个 DaemonSet,各自携带不同标志,并对不同硬件类型施加不同的内存与 CPU 要求(配合节点亲和性实现差异化部署)。
4. 创建与查看
bash
root@master30:~# vim daemonset.yaml
bash
# daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: busybox
spec:
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: hub.laoma.cloud/library/busybox
imagePullPolicy: IfNotPresent
command:
- sleep
- "36000"
root@master30:~# kubectl apply -f daemonset.yaml
root@master30:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-5hfv6 1/1 Running 0 102s 10.224.41.132 worker31.laoma.cloud <none> <none>
busybox-jdnsv 1/1 Running 0 102s 10.224.193.66 worker32.laoma.cloud <none> <none>
root@master30:~# kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
busybox 2 2 2 2 2 <none> 118s
5. 调度:污点决定 Pod 落点
master 节点默认携带 NoSchedule 污点,因此不可调度:
bash
# master 节点默认是不可调度节点
root@master30:~# kubectl describe node master.laoma.cloud | grep Taints
Taints: node-role.kubernetes.io/control-plane:NoSchedule
# 移除污点,设置 master 节点可调度
root@master30:~# kubectl taint node master.laoma.cloud node-role.kubernetes.io/control-plane-
root@master30:~# kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
busybox 3 3 3 3 3 <none> 7m43s
# 重新加回污点,设置 master 节点不可调度
root@master30:~# kubectl taint node master.laoma.cloud node-role.kubernetes.io/control-plane:NoSchedule
root@master30:~# kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
busybox 2 2 2 2 2 <none> 8m37s
# Pod 数量为 2,但 master 节点上已有的 busybox Pod 不会自动删除,
# 也不再计入这里的统计
值得记住的细节:污点回收的是调度资格 ,不是既有负载。已容忍污点运行的 Pod 不会被驱逐,DS 的计数也只会把它排除在外。
6. 健壮性与删除
bash
# 删除其中一个 Pod
root@master30:~# kubectl delete pod busybox-5hfv6
# 自动在原节点重建新 Pod
root@master30:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-jdnsv 1/1 Running 0 7m6s 10.224.193.66 worker32.laoma.cloud <none> <none>
busybox-wlqqv 1/1 Running 0 8s 10.224.41.133 worker31.laoma.cloud <none> <none>
删除行为与 Deployment 一致:默认级联删除其创建的所有 Pod;使用 --cascade=orphan 可保留 Pod。
bash
[root@master master]# kubectl delete daemonsets.apps busybox
daemonset.apps "busybox" deleted
7. K8s 集群中的 DaemonSet
Kubernetes 自身的系统组件正是由 DS 承载的------kube-proxy、calico-node 都是 DaemonSet:
bash
root@master30:~# kubectl get daemonsets.apps --namespace kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
calico-node 3 3 3 3 3 kubernetes.io/os=linux 4h12m
kube-proxy 3 3 3 3 3 kubernetes.io/os=linux 4h56m
分析 calico-node 的清单(可见其通过 nodeSelector 排除 Windows 节点,并用 RollingUpdate + maxUnavailable: 1 保证网络插件逐节点安全升级):
bash
# kubectl get ds calico-node -n kube-system -o yaml(节选)
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: calico-node
namespace: kube-system
labels:
k8s-app: calico-node
spec:
selector:
matchLabels:
k8s-app: calico-node
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
k8s-app: calico-node
总结
控制器的本质,是把运维经验固化为一套持续运转的自动调谐机制。ReplicaSet 用最朴素的差值比对守住副本数量,让"死一个补一个"成为集群本能;Deployment 在其之上编排多套 ReplicaSet,用 maxSurge 与 maxUnavailable 精确权衡发布速度与业务可用性,把升级风险压进可控区间;DaemonSet 则换以节点为单位,让日志、监控、网络插件天然覆盖每台机器。实践需牢记三条边界:标签与 selector 一旦重叠,裸 Pod 会被立即认领;污点回收的是调度资格,不是既有负载;--cascade=orphan 是保留现场的安全阀。