文章目录
- 1. DaemonSet 基础
- 1.1 什么是 DS
- 1.2 DS 的典型用法
- 1.3 如何编写 DS 资源
- 1.4 DS 示例文件
- 1.5 DS Pod 是如何被调度的
- 1.6 更新 DS
- 1.7 DS 替代方案
- 1.8 DS 工作负载字段描述
- 2. DaemonSet 的使用
- 2.1 每个节点运行一个
- 2.2 DS 更新策略
- 2.3 滚动更新
- 2.4 OnDelete 更新
- 2.6 更新回滚
- 2.5 故障排查
1. DaemonSet 基础
1.1 什么是 DS
DaemonSet
工作负载,确保了全部(某一些)节点运行一个 Pod
副本
-
如果有节点加入集群,自动为该节点新增一个
Pod
-
如果有节点从集群中移除,该节点上的
Pod
就会被回收 -
删除工作负载
DaemonSet
就会删除它创建的所有节点的Pod
1.2 DS 的典型用法
- 在每个节点上运行集群守护进程
- 在每个节点上运行日志收集守护进程
- 在每个节点上运行监控守护进程
1.3 如何编写 DS 资源
还是老规矩:kubectl explain ds
apiVersion <string>
kind <string>
metadata <Object>
spec <Object>
kubectl explain ds.spec
必须字段
apiVersion
、kind
和metadata
.spec
- Pod 模块:
.spec.template
- Pod 选择算符:
.spec.selector
- Pod 模块:
特定节点运行
如果指定了 .spec.template.spec.nodeSelector
,DaemonSet 控制器将在能够与 Node 选择算符匹配的节点上创建 Pod。 类似这种情况,可以指定 .spec.template.spec.affinity
,之后 DaemonSet 控制器 将在能够与节点亲和性 匹配的节点上创建 Pod。 如果根本就没有指定,则 DaemonSet Controller 将在所有节点上创建 Pod
1.4 DS 示例文件
###ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
运行查看一下结果
- 没有像以前设置 Pod 的副本数多少,因为
DS
资源会在每一个节点只运行一个,控制节点除外,好像要特殊设置才行,遇到了我再看看
1.5 DS Pod 是如何被调度的
- DaemonSet 控制器为每个符合条件的节点创建一个 Pod,并添加 Pod 的
spec.affinity.nodeAffinity
字段以匹配目标主机:kubectl get ds fluentd-elasticsearch
- Pod 创建以后,默认的调度程序通常通过设置 Pod 的
.spec.nodeName
字段来接管 Pod 并将 Pod 绑定到目标主机,如果新的 Pod 无法放在节点上,默认的调度程序可能会根据新 Pod 的优先级抢占某些现存的 Pod
用户通过设置 DaemonSet 的
.spec.template.spec.schedulerName
字段,可以为 DamonSet 的 Pod 指定不同的调度程序。不设置就是default-scheduler
关于亲和性、污点、容忍度后续进行一个补充
1.6 更新 DS
-
如果节点的标签被修改,DaemonSet 将立刻向新匹配上的节点添加 Pod, 同时删除不匹配的节点上的 Pod
-
你可以修改 DaemonSet 创建的 Pod。不过并非 Pod 的所有字段都可更新。 下次当某节点(即使具有相同的名称)被创建时,DaemonSet 控制器还会使用最初的模板
-
你可以删除一个 DaemonSet。如果使用
kubectl
并指定--cascade=orphan
选项, 则 Pod 将被保留在节点上。接下来如果创建使用相同选择算符的新 DaemonSet, 新的 DaemonSet 会收养已有的 Pod。 如果有 Pod 需要被替换,DaemonSet 会根据其updateStrategy
来替换 -
可以对 DaemonSet 执行滚动更新操作
1.7 DS 替代方案
参考官网地址:
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/#required-fields
- init 脚本
- 裸 Pod
- 静态 Pod
- Deploy
1.8 DS 工作负载字段描述
参考官网地址:
https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/
-
apiVersion: apps/v1
-
kind: DaemonSet
-
metadata
标准的对象元数据
-
spec
此守护进程集的预期行为
-
selector 必需
对由守护进程集管理的 Pod 的标签查询。Pod 必须匹配此查询才能被此 DaemonSet 控制。 查询条件必须与 Pod 模板的标签匹配
-
template 必需
描述将要创建的 Pod 的对象。DaemonSet 将在与模板的节点选择器匹配的每个节点上 (如果未指定节点选择器,则在每个节点上)准确创建此 Pod 的副本
-
minReadySeconds (int32)
新建的 DaemonSet Pod 应该在没有任何容器崩溃的情况下处于就绪状态的最小秒数,这样它才会被认为是可用的。 默认为 0(Pod 准备就绪后将被视为可用)
-
updateStrategy (DaemonSetUpdateStrategy)
用新 Pod 替换现有 DaemonSet Pod 的更新策略
-
revisionHistoryLimit (int32)
用来允许回滚而保留的旧历史记录的数量。此字段是个指针,用来区分明确的零值和未指定的指针。默认值是 10
-
2. DaemonSet 的使用
2.1 每个节点运行一个
我打算每个节点都运行一个基于 nginx 的 Pod
示例文件
###ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ds-demo
labels:
k8s-app: nginx
spec:
selector:
matchLabels:
name: app
template:
metadata:
labels:
name: app
spec:
tolerations:
#这些容忍度设置是为了让该守护进程集在控制平面节点上运行
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: nginx
image: nginx:1.23
imagePullPolicy: Never ##这个镜像拉取我是真的难受 直接弄本地来吧
运行查看一下
- 控制节点也是可以运行的,因为我加了一个东西
- 每个节点都只运行一个 Pod
尝试删除一个 Pod
##尝试删除一下 k8s-02上面的pod,跟着一下状态
kubectl delete pod ds-demo-dlzh4
- 可以看到最终还是会再该节点启动一个 Pod
2.2 DS 更新策略
DaemonSet 有两种更新策略:
OnDelete
: 使用OnDelete
更新策略时,在更新 DaemonSet 模板后,只有当你手动删除老的 DaemonSet pods 之后,新的 DaemonSet Pod 才会被自动创建。跟 Kubernetes 1.6 以前的版本类似。RollingUpdate
: 这是默认的更新策略。使用RollingUpdate
更新策略时,在更新 DaemonSet 模板后, 老的 DaemonSet Pod 将被终止,并且将以受控方式自动创建新的 DaemonSet Pod。 更新期间,最多只能有 DaemonSet 的一个 Pod 运行于每个节点上
kubectl explain ds.spec.updateStrategy
2.3 滚动更新
我要对上面的资源更新一个镜像,修改一下 yaml 文件
###ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ds-demo
labels:
k8s-app: nginx
spec:
selector:
matchLabels:
name: app
updateStrategy: ## 更新
type: RollingUpdate ## 更新策略
rollingUpdate: ##更新参数,仅在 type 值为 "RollingUpdate" 时出现
maxUnavailable: 1 ##更新期间不可用的 DaemonSet Pod 的最大数量
template:
metadata:
labels:
name: app
spec:
tolerations:
#这些容忍度设置是为了让该守护进程集在控制平面节点上运行
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: nginx
image: nginx:1.23.3
imagePullPolicy: Never ##这个镜像拉取我是真的难受 直接弄本地来吧
更新一下,并跟踪状态
- 停一个,更新一个;停一个,更新一个;停一个;更新一个
查看更新状态
[root@k8s-01 k8s-yaml]# kubectl rollout status ds ds-demo
daemon set "ds-demo" successfully rolled out
[root@k8s-01 k8s-yaml]#
2.4 OnDelete 更新
我们再更新一次,换一种方式
###ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ds-demo
labels:
k8s-app: nginx
spec:
selector:
matchLabels:
name: app
updateStrategy: ## 更新
type: OnDelete ## 更新策略
template:
metadata:
labels:
name: app
spec:
tolerations:
#这些容忍度设置是为了让该守护进程集在控制平面节点上运行
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: nginx
image: nginx:1.23
imagePullPolicy: Never ##这个镜像拉取我是真的难受 直接弄本地来吧
更新运行看状态:kubectl apply -f ds.yaml
- 可以看到更新方式改变了,所以这次更新没反应
杀死一个 Pod 试试
[root@k8s-01 k8s-yaml]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ds-demo-6fxtx 1/1 Running 0 6m44s 192.168.0.135 k8s-02 <none> <none>
ds-demo-8zlpb 1/1 Running 0 6m29s 192.168.0.74 k8s-01 <none> <none>
ds-demo-9r7hv 1/1 Running 0 6m18s 192.168.0.7 k8s-03 <none> <none>
[root@k8s-01 k8s-yaml]# kubectl delete pod ds-demo-8zlpb
pod "ds-demo-8zlpb" deleted
[root@k8s-01 k8s-yaml]#
看一下是否更新完成:镜像是否改变 kubectl describe pod ds-demo-qgd49
- 可以看到镜像已经更新了
- 这种类型的更新细节就是:只有当你手动删除老的 DaemonSet pods 之后,新的 DaemonSet Pod 才会被自动创建。
2.6 更新回滚
DS 修订版本
kubectl explain ds.spec
中的 [revisionHistoryLimit] 确认了版本保留的数量,默认就是10
查看 DS 的所有版本
kubectl rollout history ds ds-demo
查看指定版本的详细信息
kubectl rollout history ds ds-demo --revision=2
回滚到指定版本
kubectl rollout undo ds ds-demo --to-revision=2
查看更新结果
因为我之前改过更新策略,我必须杀死 Pod 后,才能回退成功
查看回滚进度
kubectl rollout status ds ds-demo
- 看提示是因为我的更新策略不适用这种查询方式
[root@k8s-01 k8s-yaml]# kubectl rollout status ds ds-demo
error: rollout status is only available for RollingUpdate strategy type
[root@k8s-01 k8s-yaml]#
2.5 故障排查
如果 DS 更新卡住的话,可能有以下一些原因:
- 节点可用资源耗尽
- 不完整的滚动更新
- 时钟偏差:如果在 DaemonSet 中指定了
.spec.minReadySeconds
,主控节点和工作节点之间的时钟偏差会使 DaemonSet 无法检测到正确的滚动更新进度