k8s之DaemonSet
创始人
2024-05-10 07:56:35
0

写在前面

本文接k8s之Deployment 。

假定现在有一个这样的需求,需要收集每个Node的运行状态信息,并进行上报,假设有4个节点,我们可以使用Deployment 来实现吗?好像是可以的,我们只需要将repliacas设置为4不就行了,但是deployment只能保证有4个POD在运行,不能保证4个POD是分布在4个Node上的,即deployment的POD分布和节点是没有关系的,那怎么办呢?能否让deployment具备这种功能,然后在yaml中提供相关的配置参数就行了?行是行,但是这样就违背了单一职责的原则,使得单一对象功能过于复杂,维护成本高,因此我们就需要另外一个API对象来完成这个功能,k8s提供的这个API对象就是DaemonSet,也是本文的绝对主角。

1:k8s集群说明

我本地k8s集群一共有2个Node,一个Maser Node,一个Worker Node,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get node
NAME         STATUS   ROLES                  AGE   VERSION
mongodaddy   Ready    control-plane,master   43h   v1.23.3
mongomummy   Ready                     29h   v1.23.3

2:apply

先看下DaemonSet的API定义:

dongyunqi@mongodaddy:~/k8s$ kubectl api-resources | egrep "DaemonSet|KIND"
NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
daemonsets                        ds           apps/v1                                true         DaemonSet

还是老套路来生成API模板:

dongyunqi@mongodaddy:~/k8s$ export out="--dry-run=client -o yaml" && kubectl create ds info $out
Error: must specify one of -f and -kerror: unknown command "ds info"
See 'kubectl create -h' for help and examples

竟然提示error: unknown command "ds info",难道是不支持缩写,用全称试下:

dongyunqi@mongodaddy:~/k8s$ export out="--dry-run=client -o yaml" && kubectl create DaemonSet info $out
Error: must specify one of -f and -kerror: unknown command "DaemonSet info"
See 'kubectl create -h' for help and examples
dongyunqi@mongodaddy:~/k8s$ export out="--dry-run=client -o yaml" && kubectl create daemonsets info $out
Error: must specify one of -f and -kerror: unknown command "daemonsets info"
See 'kubectl create -h' for help and examples

都是一样的错误,其实就是因为k8s不支持生成ds的yaml模板文件,我想可能是k8s漏掉了吧!故意不支持实在是没有任何道理。这个时候我们该怎么办呢?可以抄啊! 可以在kubenetes的官网 找到一份这样的yaml然后我们再稍作修改就可以了,最终如下:

apiVersion: apps/v1
kind: DaemonSet
metadata:name: redis-dslabels:app: redis-dsspec:selector:matchLabels:name: redis-dstemplate:metadata:labels:name: redis-dsspec:containers:- image: redis:5-alpinename: redisports:- containerPort: 6379

其实daemonset的yaml和deployment的yaml相比就少了replicas这个指定API对象实例个数的属性,这也很好理解,因为daemonset的API对象的个数是和节点数一样的,且一个Node一个API对象实例,通过下图对比会更加明显:

在这里插入图片描述

yaml编写完毕后我们就可以apply了,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f daemon.yml 
daemonset.apps/redis-ds created
dongyunqi@mongodaddy:~/k8s$ kubectl get ds
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   1         1         0       1            0                     13s
稍等一会就READY了:
dongyunqi@mongodaddy:~/k8s$ kubectl get daemonset
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   1         1         1       1            1                     3m22s

但是我们注意到ds API对象的个数只有1个,不是应该和节点的个数一样吗?出现这个现象的原因是k8s默认是不向master node部署API对象实例的,这又是怎么实现的呢?要想解释清楚这个问题,我们就得先来看下k8s中的另外两个概念污点 taint容忍度 toleration。污点是k8s集群的Node一个标签,其实就是一个字符串,但污点Node可以配置也可以不配置,通过命令kubectl describe node nodename/hostname可以查看Node配置的污点信息,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl describe node mongodaddy | grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule
dongyunqi@mongodaddy:~/k8s$ kubectl describe node mongomummy | grep Taints
Taints:             

mongodaddy是我本地master node的主机名,mongomummy是我本地worker node的主机名,需要根据自己的来修改,否则会报找不到节点错误。

可以看到master node配置了污点node-role.kubernetes.io/master:NoSchedule,而worker node没有配置任何污点,是一个非常纯洁的Node。什么是容忍度呢?容忍度是POD上的概念,即允许Node上有哪些污点自己才会在其上创建,默认POD是非常挑剔的,不允许Node有任何的污点,这是为什么DaemonSet的Pod没有在master node上部署的原因,知道了这个,我们只需要让master node没有污点,是不是非常挑剔的POD就会向已经变得纯洁的master node部署pod了呢,我们试一下,要想去除master node的污点,我们需要使用命令 kubectl taint node nodename/hostname node-role.kubernetes.io/master:NoSchedule-,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl taint node mongodaddy node-role.kubernetes.io/master:NoSchedule-
node/mongodaddy untainted

此时我们再查看POD是否在master node创建了:

dongyunqi@mongodaddy:~/k8s$ kubectl get daemonset
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   2         2         2       2            2                     43m

可以看到确实创建了,也可以看下是不是在master node上创建的,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod -o wide -l 'app!=ngx-dep'
NAME             READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
redis-ds-6ldlr   1/1     Running   0          18m   10.10.0.4    mongodaddy              
redis-ds-w5bmk   1/1     Running   0          44m   10.10.1.10   mongomummy              

但是这种方式影响太大了,改变了master node的污点,会直接影响到其它所有的API对象,因此我们最好还是不要这样搞,所以,还是把master node的污点恢复比较好,而恢复污点使用命令kubectl taint node nodename/hostname node-role.kubernetes.io/master:NoSchedule,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl taint node mongodaddy node-role.kubernetes.io/master:NoSchedule
node/mongodaddy tainted

这个时候污点已经加回去了,那daemonset在master node部署的POD是不是就该被剔除了呢,看下:

dongyunqi@mongodaddy:~/k8s$ kubectl get daemonset
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   1         1         1       1            1                     51m
dongyunqi@mongodaddy:~/k8s$ kubectl get pod -o wide -l 'app!=ngx-dep'
NAME             READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
redis-ds-6ldlr   1/1     Running   0          30m   10.10.0.4    mongodaddy              
redis-ds-w5bmk   1/1     Running   0          56m   10.10.1.10   mongomummy              

可以看到kubectl get daemonset的结果已经变成了1,但pod还依然在,不知道这算不算是k8s的一个bug,为什么pod没有被删除,不过也没有关系,我们就手动先把master node上的删除吧:

dongyunqi@mongodaddy:~/k8s$ kubectl delete pod redis-ds-6ldlr
pod "redis-ds-6ldlr" deleted

我们继续往后看,既然修改master node让其变的纯洁影响太大,那么我们能不能只修改POD呢?让它不那么挑剔,这就需要修改其容忍度了,如下:

tolerations:
- key: node-role.kubernetes.io/mastereffect: NoScheduleoperator: Exists

意思就是容忍存在Exists通过key和effect指定的污点,这里设置的就是master node当前的污点node-role.kubernetes.io/master:NoSchedule,修改yaml后如下:

apiVersion: apps/v1
kind: DaemonSet
metadata:name: redis-dslabels:app: redis-dsspec:selector:matchLabels:name: redis-dstemplate:metadata:labels:name: redis-dsspec:tolerations:- key: node-role.kubernetes.io/mastereffect: NoScheduleoperator: Existscontainers:- image: redis:5-alpinename: redisports:- containerPort: 6379

重新apply,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f daemon.yml 
daemonset.apps/redis-ds configured
dongyunqi@mongodaddy:~/k8s$ kubectl get daemonset
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   2         2         1       2            1                     80m
dongyunqi@mongodaddy:~/k8s$ kubectl get daemonset
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
redis-ds   2         2         2       2            2                     81m

可以看到成功了。

3:静态POD

daemonset会在每个NODE上都部署一个POD,k8s中还有一种方式能够在指定的Node上部署POD,这种方式是静态POD,想要生成静态POD的话只需要在/etc/kubernetes/manifests目录下创建需要的yaml就行了,系统会自动检测并生成POD,如下是当前的:

dongyunqi@mongodaddy:~/k8s$ ll /etc/kubernetes/manifests
total 24
drwxr-xr-x 2 root root 4096  1月  8 21:45 ./
drwxr-xr-x 4 root root 4096  1月  8 21:45 ../
-rw------- 1 root root 2229  1月  8 21:45 etcd.yaml
-rw------- 1 root root 4014  1月  8 21:45 kube-apiserver.yaml
-rw------- 1 root root 3514  1月  8 21:45 kube-controller-manager.yaml
-rw------- 1 root root 1435  1月  8 21:45 kube-scheduler.yaml

可以看到master node的主要组件都是通过这种方式来运行的,但这种POD游离于集群之外,不容易管控,所以最好还是不要使用。

写在后面

总结

本文分析了daemonset API对象,介绍了其在每个Node部署一个POD的特点,并引入了POD选择Node时相关的误点taint和容忍度toleration概念,并给出了具体的例子,最后作为对比引出了静态POD的概念,知道了master node的apiserver,etcd,controller manager,scheduler组件都是以这种方式运行的。最后,希望这篇文章能够帮助到你。

多知道一点

污点的格式是key:NoSchedule,如node-role.kubernetes.io/master:NoSchedule,k8s还定义了很多其他的污点,可以参考官网 。

参考文章列表

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...