本文接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元起,快前往官網查看詳情吧