Kubernetes Qos之Requests和Limits的注意項及記錄

使用Kubernetes去創建Deployment, StatefulSetDaemonSetcontroller,或直接創建pod時,可設置內部容器的RequestsLimits,這裏有不少地方需要注意,以下作記錄和總結。

  • Requests用於pod的調度, kube scheduller在一系列條件篩選後(taintsaffinity等),當然也有predicate預選和priority等過濾過程, 最後使用round robin算法將pod調度到滿足Requests資源要求的Node上。

  • Limits 用於限制pod的資源使用量。

  • pod包含多個container,則該pod的調度和資源限制分別由podcontainerRequests總量和Limits總量來決定。

  • Limits的值不能低於Requests的值,否則apiserver會報錯。

  • Limits中,CPUMemory某一項超過kubernetes集羣內最大節點配置,則該pod將永遠不會被調度到Node上。除非一些雲服務商會配置vm伸縮策略去實時增加vmkubernetes集羣上,如GKE

  • 除非部署的app使用多線程模型,能利用多cpu核操作,否則建議使用1核或以下配置,並配合多實例使用。

  • 當某container對CPU的使用量超過Limits時,由於CPU是可壓縮資源,kubernetes會限制該containerCPU使用量, 導致container的性能下降, 但contianer不會退出或停止。可使用liveness health checkcontainer進行健康檢查。

  • 當某containerMemory的使用量超過Limits時, kubernetes不能限制Memory的使用,但是會讓container停止,若該container對應的pod是由deployment來控制的話,則會使得pod不斷地重啓。系統傾向於在其原所在的機器上重啓該container

  • 當某節點內所有的containersLimits總量超過該節點的可用資源capacity時,這時候kubernetes進入overcommitted 狀態:

    • 節點的Memory使用量用滿時,kubernetes會啓動算法去刪除超出Request申請量的container。若存在多個這樣的container, 則根據priorityRequest的超出量來決定。
    • 按照Qos的規範,刪除的順序爲Best-Effort pods -> Burstable pods -> Guaranteed pods。源碼kubernetes\pkg\kubelet\qos\policy.go
    • 節點的cpu使用量用滿時,kubernetes壓縮各containercpu使用量,同時會確保各container能使用其在Requests指定的使用量。
  • DaemonSet不適合創建BestEffort 類型的Pods,而通常應該爲Guaranteed類型Pods更爲恰當。因爲當節點資源緊張時,BestEffort類型的Pods會被優先驅散,但是由於DaemonSet 的特性, Pod在驅散後仍會在原節點啓動。

  • 可以通過設置ResourceQuotas對象來限制命名空間下的所有containerRequestsLimits的總量。

  • 可以通過設置LimitRanges來限制(或提供默認值)每一個containerRequestsLimits

  • 關於kube scheduller的調度原理及其源碼分析,參見此文章足矣。

  • 關於RequestsLimits的底層實現機制:
    在這裏插入圖片描述

  • pod被刪除的過程,過程分爲若干階段:

    1. pod 首先進入默認的30s grace period,可通過podterminationGracePeriodSeconds調整grace period的大小。
    2. pod.state = Terminating, service對應的endpoint會被清理,pod 不再接收訪問流量。此過程是滾動式的,保證服務的可用性。此時pod內的container運行不會受影響。
    3. kubernetes 同時執行preStop Hook 指定的指令。若app中已有邏輯捕獲SIGTERM信號(在golang開發的web service的場景中,程序中利用signal庫實現SIGTERM信號的捕獲並實施一些列的回收釋放操作(數據庫連接池回收,日誌服務回收等,同時調用net/http中的Shutdown方法,使得web service同樣能夠gracefully shut down),則可不指定preStop Hook
    4. SIGTERM 信號同時傳輸到pod內的containerpid1的進程。
    5. 若在terminationGracePeriodSeconds未執行完preStop Hookapp捕獲SIGTERM信號後的清理邏輯,SIGKILL則會發送到container。同時kubernetes會清理所有container所涉及到的Object。此後不能從apiserver查詢到該pod
  • 對於Golang編寫的app而言, 當其用容器環境部署的時候,會默認設置PGOMAXPROCS)的個數爲CPU核數,而一般docker容器內沒有屏蔽cpu信息, 會導致GOMAXPROCS數量大於實際可用值, 這時可依賴第三方包從cgroup中獲取正確的cpu份額信息, 如https://godoc.org/go.uber.org/automaxprocs。 否則會導致app性能下降, 過多的P導致過多的上下文切換context switch

Reference:

https://cloud.google.com/blog/products/gcp
https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
https://medium.com/@betz.mark/understanding-resource-limits-in-kubernetes-cpu-time-9eff74d3161b
https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/

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