目录
一、DaemonSet 控制器:概念、原理解读
1.1 DaemonSet 概述
1.2 DaemonSet 工作原理:如何管理 Pod ?
1.3 Daemonset 典型的应用场景
1.4 DaemonSet 与 Deployment 的区别
二、DaemonSet 资源清单文件编写技巧
三、DaemonSet 使用案例:部署日志收集组件 fluentd
四、Daemonset 管理 pod:滚动更新
4.1 查看 daemonset 的滚动更新策略:
4.2 创建带有 RollingUpdate 更新策略的 DaemonSet
一、DaemonSet 控制器:概念、原理解读
1.1DaemonSet 概述
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
1.2 DaemonSet 工作原理:如何管理 Pod ?
daemonset 的控制器会监听 kuberntes 的 daemonset 对象、pod 对象、node 对象,这些被监听的对象之变动,就会触发 syncLoop 循环让 kubernetes 集群朝着 daemonset 对象描述的状态进行演进。
1.3 Daemonset 典型的应用场景
- 在每个节点上运行集群守护进程,比如:glusterd 或 cep。
- 在每个节点上运行日志收集守护进程,比如:flunentd 、 logstash、filebeat 等。
- 在每个节点上运行监控守护进程,比如:Prometheus、 Node Exporter 、collectd 等。
一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。
1.4 DaemonSet与 Deployment 的区别
- Deployment 部署的副本 Pod 会分布在各个 Node 上,每个 Node 都可能运行好几个副本。
- DaemonSet 的不同之处在于:每个 Node 上最多只能运行一个副本。
DaemonSet 与 Deployment 非常类似, 它们都能创建 Pod,并且 Pod 中的进程都不希望被终止(例如,Web 服务器、存储服务器)。
建议为无状态的服务使用 Deployment,比如前端服务。 对这些服务而言,对副本的数量进行扩缩容、平滑升级,比精确控制 Pod 运行在某个主机上要重要得多。 当需要 Pod 副本总是运行在全部或特定主机上,并且当该 DaemonSet 提供了节点级别的功能(允许其他 Pod 在该特定节点上正确运行)时, 应该使用 DaemonSet。
例如,网络插件通常包含一个以 DaemonSet 运行的组件。 这个 DaemonSet 组件确保它所在的节点的集群网络正常工作。
二、DaemonSet 资源清单文件编写技巧
# 查看定义 Daemonset 资源需要的字段有哪些
[root@k8s-master01 ~]# kubectl explain daemonset
KIND: DaemonSet
VERSION: apps/v1
DESCRIPTION:
DaemonSet represents the configuration of a daemon set.
FIELDS:
apiVersion <string> # 当前资源使用的 api 版本,跟 VERSION: apps/v1 保持
kind <string> # 资源类型,跟 KIND: DaemonSet 保持一致
metadata <Object> # 元数据,定义 DaemonSet 名字的
spec <Object> # 定义容器的
status <Object> # 状态信息,不能修改
# 查看 DaemonSet 的 spec 字段如何定义
[root@k8s-master01 ~]# kubectl explain daemonset.spec
KIND: DaemonSet
VERSION: apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
The desired behavior of this daemon set. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
DaemonSetSpec is the specification of a daemon set.
FIELDS:
minReadySeconds <integer> # 当新的 pod 启动几秒种后,再 kill 掉旧的 pod
revisionHistoryLimit <integer> # 历史版本
The number of old history to retain to allow rollback. This is a pointer to
distinguish between explicit zero and not specified. Defaults to 10.
selector <Object> -required- # 用于匹配 pod 的标签选择器
template <Object> -required- # 定义 Pod 的模板,基于这个模板定义的所有 pod 是一样的
updateStrategy <Object> # daemonset 的升级策略
# 查看 DaemonSet 的 spec.template 字段如何定义?
# 对于 template 而言,其内部定义的就是 pod,pod 模板是一个独立的对象
[root@k8s-master01 ~]# kubectl explain daemonset.spec.template
KIND: DaemonSet
VERSION: apps/v1
RESOURCE: template <Object>
DESCRIPTION:
An object that describes the pod that will be created. The DaemonSet will
create exactly one copy of this pod on every node that matches the
template's node selector (or on every node if no node selector is
specified). More info:
https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template
PodTemplateSpec describes the data a pod should have when created from a
template
FIELDS:
metadata <Object>
spec <Object>
······
三、DaemonSet 使用案例:部署日志收集组件 fluentd
下面的 daemonset.yaml 文件描述了一个运行 fluentd-elasticsearch Docker 镜像的 DaemonSet:
# 根据帮助命令编写
[root@k8s-master01 ~]# kubectl explain ds
[root@k8s-master01 ~]# kubectl explain ds.metadata
[root@k8s-master01 ~]# kubectl explain ds.spec
[root@k8s-master01 ~]# kubectl explain ds.spec.template
[root@k8s-master01 ~]# kubectl explain ds.spec.template.metadata
[root@k8s-master01 ~]# kubectl explain ds.spec.template.spec
[root@k8s-master01 ~]# kubectl explain ds.spec.selector
[root@k8s-master01 ~]# kubectl explain ds.spec.selector.matchLabels
[root@k8s-master01 ~]# kubectl explain ds.spec.template.spec.containers
[root@k8s-master01 ~]# kubectl explain ds.spec.template.spec.containers.resources
[root@k8s-master01 ~]# kubectl explain ds.spec.template.spec.containers.resources.requests
[root@k8s-master01 ~]# kubectl explain ds.spec.template.spec.tolerations
[root@k8s-master01 ~]# kubectl explain ds.spec.template.spec.volumes
# 查看控制节点的污点
[root@k8s-master01 ~]# kubectl describe nodes k8s-master01 | grep Taints
Taints: node-role.kubernetes.io/control-plane:NoSchedule
# 创建 DaemonSet
[root@k8s-master01 ~]# mkdir daemonset
[root@k8s-master01 ~]# cd daemonset/
[root@k8s-master01 daemonset]# vim daemonset.yaml
apiVersion: apps/v1 # DaemonSet 使用的 api 版本
kind: DaemonSet # 资源类型
metadata:
name: fluentd-elasticsearch # 资源的名字
namespace: kube-system # 资源所在的名称空间
labels:
k8s-app: fluentd-logging # 资源具有的标签
spec:
selector: # 标签选择器
matchLabels:
name: fluentd-elasticsearch # 需与模板中的 pod 标签一致
template:
metadata:
labels: # 基于这次模板定义的 pod 具有的标签
name: fluentd-elasticsearch
spec:
tolerations: # 定义容忍度,根据实际情况填写。为了让 pod 在控制节点运行
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers: # 定义容器
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
imagePullPolicy: IfNotPresent
resources: # 资源配额
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log # 容器内的挂载目录
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers # 容器内的挂载目录
readOnly: true # 挂载目录是只读权限
terminationGracePeriodSeconds: 30 # 优雅的关闭服务
volumes:
- name: varlog
hostPath:
path: /var/log # 基于本地目录创建一个卷
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers # 基于本地目录创建一个卷
# 更新资源清单文件
[root@k8s-master01 daemonset]# kubectl apply -f daemonset.yaml
# 查看 daemonset 是否创建成功
[root@k8s-master01 daemonset]# kubectl get ds -n kube-system -l k8s-app=fluentd-logging
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fluentd-elasticsearch 3 3 3 3 3 <none> 6m56s
# 查看 pod
[root@k8s-master01 daemonset]# kubectl get pods -n kube-system -o wide -l name=fluentd-elasticsearch
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fluentd-elasticsearch-97td6 1/1 Running 0 2m13s 10.244.36.89 k8s-node1 <none> <none>
fluentd-elasticsearch-nsw8s 1/1 Running 0 2m13s 10.244.32.132 k8s-master01 <none> <none>
fluentd-elasticsearch-trggq 1/1 Running 0 2m13s 10.244.169.185 k8s-node2 <none> <none>
通过上面可以看到在 k8s 的三个节点均创建了 fluentd 这个 pod,而且 pod 的名字是由 <控制器的名字-随机数> 组成的。
编写 DaemonSet Spec 官方参考文档:DaemonSet | Kubernetes
四、Daemonset 管理 pod:滚动更新
4.1 查看 daemonset 的滚动更新策略:
[root@k8s-master01 ~]# kubectl explain ds.spec.updateStrategy
KIND: DaemonSet
VERSION: apps/v1
RESOURCE: updateStrategy <Object>
DESCRIPTION:
An update strategy to replace existing DaemonSet pods with new pods.
DaemonSetUpdateStrategy is a struct used to control the update strategy for
a DaemonSet.
FIELDS:
rollingUpdate <Object>
Rolling update config params. Present only if type = "RollingUpdate".
type <string>
Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is
RollingUpdate.
Possible enum values:
- `"OnDelete"` Replace the old daemons only when it's killed
- `"RollingUpdate"` Replace the old daemons by new ones using rolling
update i.e replace them on each node one after the other.
[root@k8s-master01 ~]# kubectl explain ds.spec.updateStrategy.rollingUpdate
DaemonSet 有两种更新策略:
-
OnDelete
: 使用OnDelete
更新策略时,在更新 DaemonSet 模板后,只有当你手动删除老的 DaemonSet pods 之后,新的 DaemonSet Pod 才会被自动创建。跟 Kubernetes 1.6 以前的版本类似。 -
RollingUpdate
: 这是默认的更新策略。使用RollingUpdate
更新策略时,在更新 DaemonSet 模板后, 老的 DaemonSet Pod 将被终止,并且将以受控方式自动创建新的 DaemonSet Pod。 更新期间,最多只能有 DaemonSet 的一个 Pod 运行于每个节点上。
4.2 创建带有 RollingUpdate
更新策略的 DaemonSet
下面的 YAML 包含一个 DaemonSet,其更新策略为 'RollingUpdate':
# 将原来的 yaml 简单修改下
[root@k8s-master01 daemonset]# vim daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
updateStrategy: # 增加滚动更新内容
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
name: fluentd-elasticsearch
······
containers:
- name: fluentd-elasticsearch
image: billygoo/tomcat8-jdk8 # 修改镜像
imagePullPolicy: IfNotPresent
······
[root@k8s-master01 daemonset]# kubectl apply -f daemonset.yaml
daemonset.apps/fluentd-elasticsearch configured
[root@k8s-master01 daemonset]# kubectl get pods -n kube-system -o wide -l name=fluentd-elasticsearch
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fluentd-elasticsearch-g
# 最后,观察 DaemonSet 最新滚动更新的进度
[root@k8s-master01 ~]# kubectl rollout status daemonset fluentd-elasticsearch -n kube-system
当滚动更新完成时,输出结果如下: