扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
本文接k8s之Deployment 。
我们提供的服务有:网站建设、网站制作、微信公众号开发、网站优化、网站认证、泰顺ssl等。为上千余家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的泰顺网站制作公司
假定现在有一个这样的需求,需要收集每个Node的运行状态信息,并进行上报,假设有4个节点,我们可以使用Deployment 来实现吗?好像是可以的,我们只需要将repliacas设置为4不就行了,但是deployment只能保证有4个POD在运行,不能保证4个POD是分布在4个Node上的,即deployment的POD分布和节点是没有关系的,那怎么办呢?能否让deployment具备这种功能,然后在yaml中提供相关的配置参数就行了?行是行,但是这样就违背了单一职责
的原则,使得单一对象功能过于复杂,维护成本高,因此我们就需要另外一个API对象来完成这个功能,k8s提供的这个API对象就是DaemonSet,也是本文的绝对主角。
我本地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 -k
error: 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 -k
error: 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 -k
error: 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-ds
labels:
app: redis-ds
spec:
selector:
matchLabels:
name: redis-ds
template:
metadata:
labels:
name: redis-ds
spec:
containers:
- image: redis:5-alpine
name: redis
ports:
- 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 mongodaddyredis-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 mongodaddyredis-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/master
effect: NoSchedule
operator: Exists
意思就是容忍存在Exists
通过key和effect指定的污点,这里设置的就是master node当前的污点node-role.kubernetes.io/master:NoSchedule
,修改yaml后如下:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: redis-ds
labels:
app: redis-ds
spec:
selector:
matchLabels:
name: redis-ds
template:
metadata:
labels:
name: redis-ds
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
operator: Exists
containers:
- image: redis:5-alpine
name: redis
ports:
- 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:静态PODdaemonset会在每个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还定义了很多其他的污点,可以参考官网 。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流