k8s筆記--驅逐與重調度,以及deschueduler的一次實驗

    在Kubernetes中,調度是指將Pod放置到合適的Node上,然後對應的Node上的Kubelet才能夠運行這些pod。調度器通過Kubernetes的監測機制來發現集羣中新創建且尚未被調度的Node上的Pod。K8s中默認的調度器是kube-scheduler, 當然,也可以自行實現一個自定義的調度器。

   在開始之前,先來看幾個相關的概念:

驅逐:

    kubelet監控集羣節點的CPU, 內存,磁盤空間和文件系統的inode等資源。當這些資源中的一個或多個達到特定的消耗水平,kubelet可以通過主動地使節點上一個或多個Pod失效,以回收資源防止資源不足。(當然,kubelet在終止最終用戶Pod之前會嘗試回收節點級資源。例如,它會在磁盤資源不足時刪除未使用的容器鏡像。當然這不在我們的考慮範圍內。) 驅逐實質上是kubelet主動終止Pod以回收節點上資源的過程。

    由kubelet發起的驅逐稱爲節點壓力驅逐,這種方式下,如果使用了 軟驅逐條件 kubelet會考慮配置的 eviction-max-pod-grace-period (驅逐寬限期), 如果使用了 硬驅逐條件 它會立即驅逐pod。

    當然也可以通過API發起驅逐,API發起的驅逐通過Eviction API創建驅逐對象,由它來體面地中止Pod。API發起的驅逐將尊村你的PodDisruptionBudgets (干擾預算,即PDB) 和 terminationGracePeriodSeconds (pod生命週期)配置。

重調度:

    將pod調度到指定的Node上運行是一個比較複雜的過程,有幾個概念需要介紹一下:

  • nodeSelector 通過在PodSpec中定義它,選擇node標籤中包含每個鍵值對的對應的節點
  • 親和性與反親和性(affinity/antiaffinity) 相比之下,這個規則更想是 軟需求 或是 偏好,因此如果調度器無法滿足該要求,仍然調度該pod
    • 可以使用node裏的pod的標籤來約束,而不是使用node本身的標籤。這可以實現允許哪些pod應當放到一起,或者不應當放到一起。
  • 污點和容忍度(taints/tolerations) 上面的親和性與反親和性,nodeSelector都是Pod的一種屬性。而污點則是Node上屬性,它能使節點排斥一類特定的Pod
    • 想像一下pod都是有潔癖的,一旦node上有污點並且pod不能容忍這個污點,那麼這個pod就不會被分配在這個node上
    • 同樣,pod如果可以容忍污點,還是可以正常的分配。
    • 一個node上可以有0個或多個污點
  • PDB: PodDisruptionBudget能夠針對自發的驅逐(即上面提到的通過API發起驅逐)提供保護
    • 例如將minAvailable設置爲10,那麼即使是在干擾期間,也必須保證始終有10個Pod可用
    • PDB不能完全保證指定數量/指定百分比的Pod一直處於運行狀態,如當Pod集合的規模處於預算指定的最小值時,恰好某個pod又發生了故障,就會導致pod數量低於預期值。

    污點的effect值NoExecute會影響已經在節點上運行的Pod,此時

    • 如果pod不能忍受effect值爲NoExecute的污點,那麼Pod將被馬上驅逐
    • 如果Pod能忍受這個污點,但在容忍度tolerationSeconds上沒有定義,則Pod還會一直在節點上運行
    • 如果Pod能夠忍受這個污點,並且指定了tolerationSeconds,那麼pod還會在這個節點上運行指定的時間長度

 

------------------------------------------------分割線-------------------------------------------------------------------------------------------------

 

下面是筆者關於descheduler的一次實驗

    先簡單介紹一下,descheduler是由社區提供,用於支持多種策略的調度器,可以根據不同策略對pod進行二次調度,使得node的使用率更加均衡一些。descheduler本身也支持許多不同的調度策略。

 

準備工作:

deschueduler部署:

    社區提供了基於Helm, Kustomize等多種部署方式,這次實驗採用的是手動部署的方式

  1. git clone 源代碼
  2. make image 生成鏡像文件
  3. docker tag / docker push 準備好鏡像文件
  4. 修改descheduler/kubernetes/base下的configMap文件,禁用其他策略,僅保留RemoveDuplicates,用於驅逐在同一個node上部署的多個相同pod的副本
  5. kubectl create -f kubernetes/base/rbac.yaml 爲descheduler授權
  6. kubectl create -f kubernetes/base/configmap.yaml 初始化配置相關文件


其他準備:

    針對要測試用的pod

    1. 修改pod spec, 添加nodeSelector
    2. 爲集羣下105,106,108node添加對應的labels
    3. 部署pod有一定概率在108機器上同時部署兩個相同的pod (此處基於kube-scheduler的默認調度策略,未查看具體原因)

實驗記錄:

    1. 通過kubectl get pods -n 你的namespace -o wide 查看pod,確認確實有兩個相同的pod都部署到了108節點上

 

 

    2. 通過kubectl apply -f descheduler/kubernetes/cronjob/cronjob.yaml 開啓descheduler的cronjob (cronjob 根據cron表達式指定的週期定期執行job,具體針對k8s來說,cronjob controller會定期創建對應的job pod)

 

 

此時的descheduler的配置爲:

 

 

僅開啓了RemoveDuplicates策略

    3. 一段時間後再次通過kubectl get pods -n cloudadvisor-qa -o wide 查看pod,顯示結果如下,發現原有pod已被驅逐並在105節點上重建

 

 

    4. 通過 kubectl get jobs -n kube-system 找到當前cronjob創建的descheduler job,  然後再通過kubectl get pods -n kube-system -l job-name='jobname' 查看當前job所在的pod  注意-l 根據label選擇的使用

 

 

    5. 查看這個pod對應的日誌,並搜索與我們要觀察的oversold相關的部分(這裏爲了後續查看,已經導出爲文件了)

 

 

    這裏可以看到descheduler先是發現了 duplicate的node節點,然後進行Adjusting feasible調整,並且可以看到驅逐的節點hkcl8正是剛剛我們在108創建的重複pod之一

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章