Contents
DaemonSet控制器¶
DaemonSet控制器是一种特殊的Pod控制器,会在集群中的各个节点上运行单一的Pod副本。
它非常适合部署那些为节点本身提供服务或执行维护的Pod。
例如,对于日志收集和转发、监控以及运行以增加节点本身功能为目的的服务,这些都使用DaemonSet控制器。
因为DaemonSet控制器通常用于提供基本服务,并且每个节点都需要它,所以它可以绕过调度限制而直接部署到主机上。
比如,原本Master服务器会不可用于常规的Pod调度,但因为DaemonSet控制器独特的职责,它可以越过基于Pod的限制,以确保基础服务的运行。
DaemonSet控制器的一些典型用法包括但不限于以下几种。
运行集群存储Daemon控制器,如在每个Node上运行glusterd、ceph。
在每个Node上运行日志收集Daemon控制器,如Fluentd、logstash。
在每个Node上运行监控Daemon控制器,如Prometheus Node Exporter、collectd、Datadog代理、New Relic 代理或Ganglia gmond。
当把Node加入集群时,也会自动为它新增一个Pod。当从集群中移除Node时,对应的Pod也会被回收。
删除DaemonSet控制器将会删除它创建的所有Pod。
1. DaemonSet yaml模板¶
DaemonSet除了不用设置replicas,其他的与Deployment一致
apiVersion: apps/v1 #必填,版本号
kind: DaemonSet #必填,资源类型
metadata: #必填,元数据
name: <name>-ds #必填,资源名称
namespace: <namespace> #Pod所属的命名空间
labels: #自定义标签
- name: string #自定义标签名字<key: value>
spec: #必填,部署的详细定义
selector: #必填,标签选择
matchLabels: #必填,标签匹配
name: <name> #必填,通过此标签匹配对应pod<key: value>
template: #必填,应用容器模版定义
metadata:
labels:
name: <name> #必填,与上面matchLabels的标签相同
spec:
containers: #此处参考pod的containers
yaml示例:监控组件node-exporter部署示例
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: node-exporter-ds
name: node-exporter-ds
namespace: test
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
containers:
- args:
- --web.listen-address=127.0.0.1:9100
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
- --path.rootfs=/host/root
- --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/)
- --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$
image: prometheus/node-exporter:v0.18.1
name: node-exporter
resources:
limits:
cpu: 250m
memory: 180Mi
requests:
cpu: 102m
memory: 180Mi
volumeMounts:
- mountPath: /host/proc
name: proc
readOnly: false
- mountPath: /host/sys
name: sys
readOnly: false
- mountPath: /host/root
mountPropagation: HostToContainer
name: root
readOnly: true
- args:
- --logtostderr
- --secure-listen-address=$(IP):9100
- --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- --upstream=http://127.0.0.1:9100/
env:
- name: IP
valueFrom:
fieldRef:
fieldPath: status.podIP
image: 172.16.140.21/prometheus/kube-rbac-proxy:v0.4.1
name: kube-rbac-proxy
ports:
- containerPort: 9100
hostPort: 9100
name: https
resources:
limits:
cpu: 20m
memory: 60Mi
requests:
cpu: 10m
memory: 20Mi
hostNetwork: true
hostPID: true
nodeSelector:
kubernetes.io/os: linux
securityContext:
runAsNonRoot: true
runAsUser: 65534
serviceAccountName: node-exporter
tolerations:
- operator: Exists
volumes:
- hostPath:
path: /proc
name: proc
- hostPath:
path: /sys
name: sys
- hostPath:
path: /
name: root
2.DaemonSet控制器的基本操作¶
exampleDaemonset.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: exampledaemonset
spec:
selector:
matchLabels:
example: deploymentforhttpd
template:
metadata:
labels:
example: deploymentforhttpd
spec:
containers:
- name: httpd
image: httpd:2.2
ports:
- containerPort: 80
hostPort: 8082
protocol: TCP
该模板的含义如下。
apiVersion表示使用的API版本,apps/v1表示使用Kubernetes API的稳定版本。
kind表示要创建的资源对象,这里使用关键字DaemonSet。
metadata表示该资源对象的元数据。一个资源对象可拥有多个元数据,其中一项是name,这表示当前资源的命名。
spec表示该资源对象的具体设置。
selector/matchLabels:用于定义一个或多个自定义标签(label),其形式为键值对,这对Pod起筛选作用,会选 择与标签定义相匹配的Pod。这在后续章节会详细解说,因为它是必填字段,所以这里填写了一个示例值。
template:Pod模板,具体的模板。httpd镜像中默认定义的对外提供服务的端口为80。通过 containerPort属性,我们将80端口暴露出来,再通过hostPort属性映射到宿主机的端口8082上,以便通过“主 机IP:端口”形式访问容器所提供的服务。
运行以下命令,通过模板创建DaemonSet控制器。
$ kubectl apply -f exampleDaemonset.yml
部署完成后,可以通过以下命令查看当前DaemonSet控制器的状态。
$ kubectl get daemonset
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
exampledaemonset 28 28 2 28 2 <none> 23s
DESIRED表示预期的Pod数(因为有28个Node,所以为28),CURRENT表示当前的Pod数。
同样,也可以通过$ kubectl get pods -o wide命令查看Pod的状态。可以看到我们并没有指定需要多少个Pod副本,DaemonSet 控制器会为每台Node分配一个Pod。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
exampledaemonset-5h2jj 1/1 Running 0 2m1s 10.0.12.216 gitee-k8s-w23 <none> <none>
exampledaemonset-6frgf 1/1 Running 0 2m1s 10.0.16.156 gitee-k8s-w11 <none> <none>
exampledaemonset-7wtz9 1/1 Running 0 2m1s 10.0.23.119 gitee-k8s-w28 <none> <none>
exampledaemonset-8qlgj 1/1 Running 0 2m1s 10.0.9.39 gitee-k8s-w16 <none> <none>
exampledaemonset-96pfr 1/1 Running 0 2m1s 10.0.36.190 gitee-k8s-w08 <none> <none>
exampledaemonset-9vph6 1/1 Running 0 2m1s 10.0.7.93 gitee-k8s-w19 <none> <none>
通过浏览器进入“NodeIP:8082”,就可以访问对应节点的Daemon进程。
[root@ci-base daemonset]# curl 192.168.1.35:8082
<html><body><h1>It works!</h1></body></html>[root@ci-base daemonset]#
如果此时有新的Node加入集群中,Kubernetes也会自动为新节点增加一个exampleDaemonset Pod。
除了我们自己创建的DeamonSet控制器以外,Kubernetes本身的一些组件也是使用DeamonSet控制器来管理的。使用以下命令,可以查看Kubernetes系统的DaemonSet控制器。
# Kubernetes系统的DaemonSet控制器
$ kubectl get daemonset --namespace=kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
cilium 33 33 33 33 33 <none> 167d
要了解一个正在运行的Pod的配置,可以通过以下命令来获取。
$ kubectl get daemonset {daemonset名称} -o yaml
如果是Kubernetes系统级的DaemonSet控制器,则还需要在命令中加上–namespace= kube-system,例如,下面的命令。
$ kubectl get daemonset cilium --namespace=kube-system -o yaml
查看DaemonSet控制器配置得到的执行结果
$ kubectl get daemonset cilium --namespace=kube-system -o yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
annotations:
deprecated.daemonset.template.generation: "1"
meta.helm.sh/release-name: cilium
meta.helm.sh/release-namespace: kube-system
creationTimestamp: "2021-10-26T12:08:24Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
k8s-app: cilium
name: cilium
namespace: kube-system
resourceVersion: "75428394"
selfLink: /apis/apps/v1/namespaces/kube-system/daemonsets/cilium
uid: 6bf95d76-fb85-41b0-8def-3cf8bc78ab3e
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: cilium
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
creationTimestamp: null
labels:
k8s-app: cilium
.....
3.DaemonSet控制器的更新¶
DaemonSet控制器有两种更新方式。
RollingUpdate:当使用RollingUpdate方式时,在更新DaemonSet 控制器模板后,旧的DaemonSet Pod将被终止,并且将以受控方式自动创建新的DaemonSet Pod。
OnDelete:这是向后兼容的默认更新方式。当使用OnDelete更新方式时,在更新DaemonSet控制器模板后,只有手动删除旧的DaemonSet控制器Pod后,才会创建新的DaemonSet控制器Pod。这与Kubernetes 1.5或更早版本中DaemonSet控制器的行为相同。
3.1 RollingUpdate¶
对于RollingUpdate,与之前Deployment控制器不一样的地方在于,
DaemonSet控制器中的RollingUpdate只支持maxUnavailable属性。
因为DaemonSet控制器是在每个Node主机上启动的唯一Pod,不能启动多余的节点,所以无法使用maxSurge属性。
RollingUpdate与deployment的类似,这里就不再介绍了。
3.2 OnDelete¶
OnDelete更新方式。 为了修改之前的yml文件,将其从httpd 2.2版本升级到2.4版本, 首先,运行如下命令。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: exampledaemonset
spec:
selector:
matchLabels:
example: deploymentforhttpd
template:
metadata:
labels:
example: deploymentforhttpd
spec:
containers:
- name: httpd
image: httpd:2.4
ports:
- containerPort: 80
hostPort: 8082
protocol: TCP
updateStrategy:
type: OnDelete
接下来,运行以下命令,通过模板创建DaemonSet控制器。
$ kubectl get daemonset
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
exampledaemonset 28 28 28 28 28 <none> 14s
$ kubectl apply -f exampleDaemonset.yml
daemonset.apps/exampledaemonset configured
$ kubectl get daemonset
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
exampledaemonset 28 28 28 0 28 <none> 2m19s
此时通过$ kubectl get daemonset命令查看状态,可以发现UP-TO-DATE变为0,表示DaemonSet控制器现在都是旧版本,
接下来,执行$ kubectl get pods -o wide命令,现在所有的Pod都是旧版本
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
exampledaemonset-4dghq 1/1 Running 0 99s 10.0.37.173 gitee-k8s-w09 <none> <none>
exampledaemonset-4rcmq 1/1 Running 0 98s 10.0.18.230 gitee-k8s-w25 <none> <none>
exampledaemonset-4s5cc 1/1 Running 0 99s 10.0.6.200 gitee-k8s-w27 <none> <none>
exampledaemonset-6dlbh 1/1 Running 0 99s 10.0.32.85 gitee-k8s-w05 <none> <none>
exampledaemonset-6r52w 1/1 Running 0 99s 10.0.25.143 gitee-k8s-w17 <none> <none>
....
接下来,删除第一个Pod以触发更新,在本例中为exampledaemonset-4dghq,这个Pod所在的机器为gitee-k8s-w09。执行如下 命令。
$ kubectl delete pod exampledaemonset-4dghq
接下来,执行$ kubectl get pods -o wide命令,可以看到原来旧版本的
exampledaemonset-4dghq已经被删除,取而代之的是一个新版本Pod。
最后,通过$ kubectl get daemonset命令查看状态,可以发现UP-TO-DATE变为1,这表示已经有1台机器上的DaemonSet控制器是
新版本了。
$ kubectl get daemonset
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
exampledaemonset 28 28 28 1 28 <none> 5m25s