cordon、drain和delete三個命令都會使node停止被調度,后期創建的pod不會繼續被調度到該節點上,但操作的暴力程度卻不一樣。
一、cordon 停止調度
(不可調度,臨時從K8S集群隔離)
- 影響最小,只會將node標識為SchedulingDisabled不可調度狀態。
- 之后K8S再創建的pod資源,不會被調度到該節點。
- 舊有的pod不會受到影響,仍正常對外提供服務。
- 禁止調度命令"kubectl cordon node_name"。
- 恢復調度命令"kubectl uncordon node_name"。(恢復到K8S集群中,變回可調度狀態)
二、drain 驅逐節點
(先不可調度,然后排干)
- 首先,驅逐Node上的pod資源到其他節點重新創建。
- 接着,將節點調為SchedulingDisabled不可調度狀態。
- 禁止調度命令"kubectl drain node_name --force --ignore-daemonsets --delete-local-data"
- 恢復調度命令"kubectl uncordon node_name"。(恢復到K8S集群中,變回可調度狀態)
- drain方式是安全驅逐pod,會等到pod容器應用程序優雅停止后再刪除該pod。
- drain驅逐流程:先在Node節點刪除pod,然后再在其他Node節點創建該pod。所以為了確保drain驅逐pod過程中不中斷服務(即做到"無感知"地平滑驅逐),必須保證要驅逐的pod副本數大於1,並且采用了"反親和策略"將這些pod調度到不同的Node節點上了!也就是說,在"多個pod副本+反親和策略"的場景下,drain驅逐過程對容器服務是沒有影響的。
需要注意:
- 對節點執行維護操作之前(例如:內核升級,硬件維護等),您可以使用 kubectl drain 安全驅逐節點上面所有的 pod。
- drain安全驅逐方式將會允許 pod 里面的容器遵循指定的 PodDisruptionBudgets 執行優雅中止。也就是說,drain安全驅逐可以做到:優雅地終止pod里的容器進程。
- kubectl drain 返回成功表明所有的 pod (除了排除的那些)已經被安全驅逐(遵循期望優雅的中止期,並且沒有違反任何應用程序級別的中斷預算)。
- 然后,通過對物理機斷電或者在雲平台上刪除節點所在的虛擬機,都能安全的將節點移除。
一般線上K8S的PDB(PodDisruptionBudgets)配置的也是符合Pod驅逐的理想情況的,即maxUnavailable設置為0,maxSurge設置為1:
replicas: 3 strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type: RollingUpdate
默認情況下,kubectl drain 會忽略那些不能殺死的系統類型的 pod。drain命令中需要添加三個參數:--force、--ignore-daemonsets、--delete-local-data
- --force 當一些pod不是經 ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet 管理的時候就需要用--force來強制執行 (例如:kube-proxy)
- --ignore-daemonsets 無視DaemonSet管理下的Pod。即--ignore-daemonsets往往需要指定的,這是因為deamonset會忽略unschedulable標簽(使用kubectl drain時會自動給節點打上不可調度標簽),因此deamonset控制器控制的pod被刪除后可能馬上又在此節點上啟動起來,這樣就會成為死循環.因此這里忽略daemonset。
- --delete-local-data 如果有mount local volumn的pod,會強制殺掉該pod。
drain禁止調度的操作步驟:
確定要排空的節點的名稱 # kubectl get nodes 查看pod # kubectl get po 命令node節點開始釋放所有pod,並且不接收新的pod進程 # kubectl drain [node-name] --force --ignore-daemonsets --delete-local-data 此時可以對該node節點進行平滑維護,后續需要恢復到k8s集群中: # kubectl uncordon [node-name]
三、delete 刪除節點
- 首先,驅逐Node節點上的pod資源到其他節點重新創建。
- 驅逐流程:先在Node節點刪除pod,然后再在其他Node節點上創建這些pod。
- node節點刪除,master失去對其控制,該節點從k8s集群摘除。
- delete是一種暴力刪除node的方式。在驅逐pod時是強制干掉容器進程,做不到優雅終止Pod。相比較而言,顯然drain更安全。
恢復調度(即重新加入到K8S集群中)
- delete刪除后,后續如果需重新加入K8S集群。則需要重啟node節點的kubelet服務,重啟后,基於node的自注冊功能,該節點才能重新加入到K8S集群,並且恢復使用(即恢復可調度的身份)。
- 另外:如果kubelet服務重啟后,node節點系統時間跟其他節點不一致,則導致該節點證書會失效!kubelet注冊后,還需要手動approve簽發TLS認證操作了。如下示例:
k8s-vm02節點重啟后,系統時間變了,跟其他node節點系統時間不一致,導致該節點的集群證書失效! [root@k8s-vm01 ingress]# kubectl exec -ti test-finhub-app-56df548879-ghlb2 -n wiseco -- /bin/bash Error from server: error dialing backend: x509: certificate is valid for k8s-vm01, not k8s-vm02 [root@k8s-vm01 ingress]# kubectl get csr NAME AGE REQUESTOR CONDITION csr-7zt2w 50m system:node:k8s-vm02 Pending csr-8sw6k 36m system:node:k8s-vm02 Pending csr-9jv7z 21m system:node:k8s-vm02 Pending 需要手動approve簽發TLS認證 [root@k8s-vm01 ingress]# kubectl certificate approve csr-7zt2w [root@k8s-vm01 ingress]# kubectl certificate approve csr-8sw6k [root@k8s-vm01 ingress]# kubectl certificate approve csr-9jv7z
四、Node節點平滑維護
通常情況下,如果要對K8S集群中的一台Node節點進行平滑維護,如升級或調整配置。正確的操作:
- cordon臨時從K8S集群隔離出來,標識為SchedulingDisabled不可調度狀態。
- drain排干該節點上的pod資源到其他node節點上。
- 對該節點展開平滑維護操作,如升級或調整配置。
- uncordon恢復,重新回到K8S集群,變回可調度狀態。
同時注意:為了確保drain驅逐pod的時候,容器應用服務不中斷,必須滿足:
- 要驅逐的pod副本數量必須大於1
- 要配置"反親和策略",確保被驅逐的pod被調度到不同的Node節點上
- deployment采用滾動更新,設置maxUnavailable為0,maxSurge為1