本文接k8s之Deployment 。
我們提供的服務(wù)有:網(wǎng)站建設(shè)、網(wǎng)站制作、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、泰順ssl等。為上千余家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的泰順網(wǎng)站制作公司
假定現(xiàn)在有一個這樣的需求,需要收集每個Node的運(yùn)行狀態(tài)信息,并進(jìn)行上報,假設(shè)有4個節(jié)點(diǎn),我們可以使用Deployment 來實(shí)現(xiàn)嗎?好像是可以的,我們只需要將repliacas設(shè)置為4不就行了,但是deployment只能保證有4個POD在運(yùn)行,不能保證4個POD是分布在4個Node上的,即deployment的POD分布和節(jié)點(diǎn)是沒有關(guān)系的,那怎么辦呢?能否讓deployment具備這種功能,然后在yaml中提供相關(guān)的配置參數(shù)就行了?行是行,但是這樣就違背了單一職責(zé)
的原則,使得單一對象功能過于復(fù)雜,維護(hù)成本高,因此我們就需要另外一個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
都是一樣的錯誤,其實(shí)就是因?yàn)閗8s不支持生成ds的yaml模板文件,我想可能是k8s漏掉了吧!故意不支持實(shí)在是沒有任何道理。這個時候我們該怎么辦呢?可以抄啊! 可以在kubenetes的官網(wǎng) 找到一份這樣的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
其實(shí)daemonset的yaml和deployment的yaml相比就少了replicas這個指定API對象實(shí)例個數(shù)的屬性,這也很好理解,因?yàn)閐aemonset的API對象的個數(shù)是和節(jié)點(diǎn)數(shù)一樣的,且一個Node一個API對象實(shí)例,通過下圖對比會更加明顯:
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對象的個數(shù)只有1個,不是應(yīng)該和節(jié)點(diǎn)的個數(shù)一樣嗎?出現(xiàn)這個現(xiàn)象的原因是k8s默認(rèn)是不向master node部署API對象實(shí)例的,這又是怎么實(shí)現(xiàn)的呢?要想解釋清楚這個問題,我們就得先來看下k8s中的另外兩個概念污點(diǎn) taint
和容忍度 toleration
。污點(diǎn)是k8s集群的Node一個標(biāo)簽,其實(shí)就是一個字符串,但污點(diǎn)Node可以配置也可以不配置,通過命令kubectl describe node nodename/hostname
可以查看Node配置的污點(diǎn)信息,如下:
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的主機(jī)名,mongomummy是我本地worker node的主機(jī)名,需要根據(jù)自己的來修改,否則會報找不到節(jié)點(diǎn)錯誤。
可以看到master node配置了污點(diǎn)node-role.kubernetes.io/master:NoSchedule
,而worker node沒有配置任何污點(diǎn),是一個非常純潔的Node
。什么是容忍度呢?容忍度是POD上的概念,即允許Node上有哪些污點(diǎn)自己才會在其上創(chuàng)建,默認(rèn)POD是非常挑剔的
,不允許Node有任何的污點(diǎn),這是為什么DaemonSet的Pod沒有在master node上部署的原因,知道了這個,我們只需要讓master node沒有污點(diǎn),是不是非常挑剔的POD
就會向已經(jīng)變得純潔的master node
部署pod了呢,我們試一下,要想去除master node的污點(diǎn),我們需要使用命令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創(chuàng)建了:
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
可以看到確實(shí)創(chuàng)建了,也可以看下是不是在master node上創(chuàng)建的,如下:
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的污點(diǎn),會直接影響到其它所有的API對象,因此我們最好還是不要這樣搞,所以,還是把master node的污點(diǎn)恢復(fù)比較好,而恢復(fù)污點(diǎn)使用命令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
這個時候污點(diǎn)已經(jīng)加回去了,那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
的結(jié)果已經(jīng)變成了1,但pod還依然在,不知道這算不算是k8s的一個bug,為什么pod沒有被刪除,不過也沒有關(guān)系,我們就手動先把master node上的刪除吧:
dongyunqi@mongodaddy:~/k8s$ kubectl delete pod redis-ds-6ldlr
pod "redis-ds-6ldlr" deleted
我們繼續(xù)往后看,既然修改master node讓其變的純潔
影響太大,那么我們能不能只修改POD呢?讓它不那么挑剔
,這就需要修改其容忍度了,如下:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
operator: Exists
意思就是容忍存在Exists
通過key和effect指定的污點(diǎn),這里設(shè)置的就是master node當(dāng)前的污點(diǎn)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:靜態(tài)PODdaemonset會在每個NODE上都部署一個POD,k8s中還有一種方式能夠在指定的Node上部署POD,這種方式是靜態(tài)POD,想要生成靜態(tài)POD的話只需要在/etc/kubernetes/manifests
目錄下創(chuàng)建需要的yaml就行了,系統(tǒng)會自動檢測并生成POD,如下是當(dāng)前的:
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的主要組件都是通過這種方式來運(yùn)行的,但這種POD游離于集群之外,不容易管控,所以最好還是不要使用。
寫在后面 總結(jié)本文分析了daemonset API對象,介紹了其在每個Node部署一個POD的特點(diǎn),并引入了POD選擇Node時相關(guān)的誤點(diǎn)taint和容忍度toleration概念,并給出了具體的例子,最后作為對比引出了靜態(tài)POD的概念,知道了master node的apiserver,etcd,controller manager,scheduler組件都是以這種方式運(yùn)行的。最后,希望這篇文章能夠幫助到你。
多知道一點(diǎn)污點(diǎn)的格式是key:NoSchedule
,如node-role.kubernetes.io/master:NoSchedule
,k8s還定義了很多其他的污點(diǎn),可以參考官網(wǎng) 。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧