containerManager 負責 node 節點上運行的容器的配置信息,如cgroup、cpu、device;
pod的創建流程參考:
http://www.tianfeiyu.com/?p=2825
一構成
1.QOSContainerManager維護pod對應的Qos,用於調度、驅逐、設置各資源的cgroup等模塊
2.cgroupManager根據pod的Qos設置不同級別的cgroup參數,並不斷根據pod的變化維護這些cgroup參數
3.devicemanager管理節點上的device,主要包含分配、回收、本地記錄存儲;
4.cpumanager管理節點上的cpu,主要包含分配、回收、本地記錄存儲
5.devicemanager通過topologymanager爲container選擇最優的device組合
6.cpumanager通過topologymanager爲container選擇最優cpuset
調用流程:
1.kubeRuntimeManager.SyncPod創建完container後,通過cpumanager設置container的啓動參數;
2.kubeRuntimeManager.SyncPod.startContainer啓動container時會調用containerManager獲取container跑在device上的參數,最終回調用到devicemanager
3.Kubelet.SyncPod設置cgroup參數階段-->podContainerManager-->cgroupManager(依賴QOSContainerManager設置QOS)-->runc.libcontainer.cgroupfs將設置的參數apply到container
二、Kubelet.syncPod vs kubeRuntimeManager.SyncPod:調用關係:
Kubelet.syncPod:
1.如果pod需要被刪除,調用containerRuntime.KillPod殺掉pod
2.爲第一次創建的pod記錄創建時間,當pod狀態變化時也記錄當前時間
3.通過一系列admit判斷pod是否能在當前node上運行,如安全相關的appArmorValidator、containerRuntime是否允許root Privilege等
4.設置pod的cgroup參數
5.爲static pod創建mirror pod
6.創建相應的工作目錄,如pod的工作目錄、存儲目錄、插件plugins目錄
7,等待volume掛載到pod的存儲目錄下
8.拉取下載container image的secret
9.調用kubeRuntimeManager.SyncPod爲pod創建container
10.statusManager更新pod的狀態
kubeRuntimeManager.SyncPod:
// 1. Compute sandbox and container changes. // 2. Kill pod sandbox if necessary. // 3. Kill any containers that should not be running. // 4. Create sandbox if necessary. // 5. Create ephemeral containers. // 6. Create init containers. // 7. Create normal containers.
這部分的修改不會導致pod重建
二cgroupmanager
cgroupmanager負責 node 節點上運行的容器的 cgroup 配置信息,kubelet 啓動參數如果指定 --cgroups-per-qos
的時候,kubelet 會啓動 goroutine 來週期性的更新 pod 的 cgroup 信息,維護其正確性,該參數默認爲 true
,實現了 pod 的Guaranteed/BestEffort/Burstable 三種級別的 Qos。
目前 kubernetes 僅支持 cpu、memory、pids 、hugetlb 四個 cgroup 子系統
runtime 有兩種 cgroup 驅動:一種是 systemd
,另外一種是 cgroupfs
:
-
cgroupfs
比較好理解,比如說要限制內存是多少、要用 CPU share 爲多少,其實直接把 pid 寫入到對應cgroup task 文件中,然後把對應需要限制的資源也寫入相應的 memory cgroup 文件和 CPU 的 cgroup 文件就可以了; -
另外一個是
systemd
的 cgroup 驅動,這個驅動是因爲systemd
本身可以提供一個 cgroup 管理方式。所以如果用systemd
做 cgroup 驅動的話,所有的寫 cgroup 操作都必須通過 systemd 的接口來完成,不能手動更改 cgroup 的文件;
Kubelet cgroup level:
/sys/fs/cgroup/cpu/kubepods – kubepods cgroup
/sys/fs/cgroup/cpu/kubepods/burstable – Qos level cgroup
/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID> – pod level cgroup
/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID>/container<UID> – container level cgroup
1.cgroupmanager 會把本機的 allocatable 資源寫入到 kubepods
下對應的 cgroup 文件中,比如 kubepods/cpu.share
2.
Qos level cgroup
有兩個
cgroup
:
burstable
和
besteffort
,分別作爲
burstable
級別
pod
和
besteffort
級別
pod
的父
cgroup
;而
Guaranteed Qos
對應的
pod
會直接在
kubepods
同級的
cgroup
中創建
pod cgroup,
原因:
guaranteed
級別的
pod
有明確的資源申請量
(request)
和資源限制量
(limit)
,不需要
qos
級別的
cgroup
來管理和限制資源
3.pod level cgroup
包含
pod
對應的
container level cgroup
4.
創建流程
kubepods>qos>pod>container
,設置流程
container->pod->qos->kubepods
,即設置好
container level cgroup
中各文件的限制,再層層往外更新其它
level
的限制
5.從級別和目錄可以看出:burstable 的 cgroup 需要爲比他等級高的 guaranteed 級別的 pod 的內存資源做預留,而 besteffort 需要爲 burstable 和 guaranteed 都要預留內存資源。
例:
/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID>/container<UID>/cpu.shares=2
/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID>/cpu.shares=204
/sys/fs/cgroup/cpu/kubepods/burstable/cpu.shares=1126
/sys/fs/cgroup/cpu/kubepods/cpu.shares=49512
對於每一個 pod 設定的 requests 和 limits,kubernetes 都會轉換爲 cgroup 中的計算方式,CPU 的轉換方式如下所示:
-
cpu.shares = (cpu in millicores * 1024) / 1000
-
cpu.cfs_period_us = 100000 (i.e. 100ms)
-
cpu.cfs_quota_us = quota = (cpu in millicores * 100000) / 1000
-
memory.limit_in_bytes
CPU 最終都會轉換爲以微秒爲單位,memory 會轉換爲以 bytes 爲單位
如果 pod 指定了 requests 和 limits,kubelet 會按以上的計算方式爲 pod 設置資源限制,如果沒有指定 limit 的話,那麼 cpu.cfs_quota_us
將會被設置爲 -1,即沒有限制。而如果 limit 和 request 都沒有指定的話,cpu.shares
將會被指定爲 2,這個是 cpu.shares
允許指定的最小數值了,可見針對這種 pod,kubernetes 只會給它分配最少的 cpu 資源。而對於內存來說,如果沒有 limit 的指定的話,memory.limit_in_bytes
將會被指定爲一個非常大的值,一般是 2^64 ,可見含義就是不對內存做出限制。
參考:https://www.jianshu.com/p/924e3c48cb9b
三QOSContainerManager
QoS(Quality of Service) 即服務質量,QoS 是一種控制機制,它提供了針對不同用戶或者不同數據流採用相應不同的優先級,或者是根據應用程序的要求,保證數據流的性能達到一定的水準。kubernetes 中有三種 Qos,分別爲:
-
1、
Guaranteed
:pod 的 requests 與 limits 設定的值相等; -
2、
Burstable
:pod requests 小於 limits 的值且不爲 0; -
3、
BestEffort
:pod 的 requests 與 limits 均爲 0;
三者的優先級如下所示,依次遞增,OOM_SCORE_ADJ遞減:
BestEffort -> Burstable -> Guaranteed
。
三種 Qos 在調度和底層表現上都不一樣:
-
1、在調度時調度器只會根據 request 值進行調度;
-
2、二是當系統 OOM上時對於處理不同 OOMScore 的進程表現不同,OOMScore 是針對 memory 的,當宿主上 memory 不足時系統會優先 kill 掉 OOMScore 值低的進程,可以使用
$ cat /proc/$PID/oom_score
查看進程的 OOMScore。OOMScore 的取值範圍爲 [-1000, 1000],Guaranteed
pod 的默認值爲 -998,Burstable
pod 的值爲 2~999,BestEffort
pod 的值爲 1000,也就是說當系統 OOM 時,首先會 kill 掉BestEffort
pod 的進程,若系統依然處於 OOM 狀態,然後纔會 kill 掉Burstable
pod,最後是Guaranteed
pod; -
3、三是 cgroup 的配置不同,kubelet 爲會三種 Qos 分別創建對應的 QoS level cgroups,
Guaranteed
Pod Qos 的 cgroup level 會直接創建在RootCgroup/kubepods
下,Burstable
Pod Qos 的創建在RootCgroup/kubepods/burstable
下,BestEffort
Pod Qos 的創建在RootCgroup/kubepods/BestEffort
下,上文已經說了 root cgroup 可以通過$ mount | grep cgroup
看到,在 cgroup 的每個子系統下都會創建 Qos level cgroups, 此外在對應的 QoS level cgroups 還會爲 pod 創建 Pod level cgroups;
qos的計算方式:
memoryRequest := container.Resources.Requests.Memory().Value()
oomScoreAdjust := 1000 - (1000*memoryRequest)/memoryCapacity
// A guaranteed pod using 100% of memory can have an OOM score of 10. Ensure
// that burstable pods have a higher OOM score adjustment.
if int(oomScoreAdjust) < (1000 + guaranteedOOMScoreAdj) {
return (1000 + guaranteedOOMScoreAdj)
}
// Give burstable pods a higher chance of survival over besteffort pods.
if int(oomScoreAdjust) == besteffortOOMScoreAdj {
return int(oomScoreAdjust - 1)
}
return int(oomScoreAdjust)
可見:pod的container使用memory越多,它的 OOMScore越小,越不容易被驅逐。
三 device manager
四topology manager
白話:爲container的resource選擇最優組合,如同組的cpuset,container所需的device來自同一個NUMA Node.
topology manager不是單獨起作用的,當前k8s 1.17.3中,它和CPU manager,device manager共同爲pod分配資源,優化資源訪問。
topology manager從Hint Providers中以bitmask的形式接受NUMA拓撲信息(Topology Hint),包括當前可用的NUMA節點和傾向的資源分配指示。Topology manager策略對提供的hint進行一系列操作以後將所有的hint決定匯聚起來,得出一個最佳的hint(bestHint)。通過配置的策略(policy),主機節點可以選擇接受或者拒絕pod。
topology manager當前所支持的策略有四個:None,BestEffort,Restricted和SingleNumaNode。
None是默認的策略,這個策略不會做任何的NUMA感知的資源對齊。
BestEffort對於pod裏面的每一個container都會調用它們的hint provider來發現它們的資源可用性。topology manager計算存儲這些container的NUMA親和度的信息,如果親和度不能被滿足的話,manager也會存儲親和度信息同時也會允許pod加入這個主機節點。
Restricted同樣也會對pod裏面的每一個container計算NUMA親和度。不同的是,如果親和度不能被滿足的話,主機節點會拒絕這個pod的加入。這樣會導致pod處於Terminated的狀態。如果pod被接受了,那麼親和度信息將會被用於container的資源分配。
SingleNumaNode策略用來判斷單個NUMA節點的親和度是否滿足,如果滿足的話hint provider即可利用親和度信息進行資源分配;如果不滿足的話主機節點會拒絕pod的加入,這樣也會導致pod處於Terminated的狀態。
參考:https://blog.csdn.net/qjm1993/article/details/103237944
五cpu manager
白話:根據NUMA爲container選擇最優的cpuset,讓container從cpu方向得到更高的性能
目前CPU Manager支持兩種Policy,分別爲none和static,通過kubelet --cpu-manager-policy
設置,未來會增加dynamic policy做Container生命週期內的cpuset動態調整。
-
-
none: 爲cpu manager的默認值,相當於沒有啓用cpuset的能力。cpu request對應到cpu share,cpu limit對應到cpu quota。
-
static: 目前,請設置
--cpu-manager-policy=static
來啓用,kubelet將在Container啓動前分配綁定的cpu set,分配時還會考慮cpu topology來提升cpu affinity,後面會提到。
-
-
確保kubelet爲
--kube-reserved
和--system-reserved
都配置了值,可以不是整數個cpu,最終會計算reserved cpus時會向上取整。這樣做的目的是爲了防止CPU Manager把Node上所有的cpu cores分配出去了,導致kubelet及系統進程都沒有可用的cpu了。
注意CPU Manager還有一個配置項--cpu-manager-reconcile-period
,用來配置CPU Manager Reconcile Kubelet內存中CPU分配情況到cpuset cgroups的修復週期。如果沒有配置該項,那麼將使用--node-status-update-frequency
(
default 10s
)
配置的值。
使用CPU Manager的Pod、Container具備以下兩個條件:
-
Pod QoS爲Guaranteed;
-
Pod中該Container的Cpu request必須爲整數CPUs;
工作流程:
-
Kuberuntime調用容器運行時去create該Container。
-
創建完後,調用PreStartContainer將該Container交給CPU Manager處理。
-
創建業務container時,先把init container佔用的cpu釋放
-
CPU Manager爲Container按照static policy邏輯進行處理。
-
CPU Manager從當前Shared Pool中挑選“最佳”Set拓撲結構的CPU,對於不滿足Static Policy的Contianer,則返回Shared Pool中所有CPUS組成的Set。
-
挑選方式:根據Node上的NUMA CPU Topology劃分cpu組,當container需要多個cpu時,讓這幾個cpu儘量來自同一個組(簡單理解爲一個插槽),這樣同組訪問能加快速度提高性能。
-
CPU Manager將對該Container的CPUs分配情況記錄到Checkpoint State中,並且從Shared Pool中刪除剛分配的CPUs。
-
CPU Manager再從state中讀取該Container的CPU分配信息,然後通過UpdateContainerResources cRI接口將其更新到Cpuset Cgroups中,包括對於非Static Policy Container。
-
Kuberuntime調用容器運行時Start該容器。
Checkpoint文件內容就是CPUManagerCheckpoint結構體的json格式,其中Entries的key是ContainerID,value爲該Container對應的Assigned CPU Set信息。
當這些通過CPU Manager分配CPUs的Container要Delete時,CPU Manager工作流大致如下:
-
Kuberuntime會調用CPU Manager去按照static policy中定義邏輯處理。
-
CPU Manager將該Container分配的Cpu Set重新歸還到Shared Pool中。
-
Kuberuntime調用容器運行時Remove該容器。
-
CPU Manager會異步地進行Reconcile Loop,爲使用Shared Pool中的Cpus的Containers更新CPU集合。
CPU Manager Reconcile按照--cpu-manager-reconcile-period
配置的週期進行Loop,Reconcile注意進行如下處理:
-
遍歷所有activePods中的所有Containers,注意包括InitContainers,對每個Container繼續進行下面處理。
-
檢查該ContainerID是否在CPU Manager維護的Memory State assignments中,
-
如果不在Memory State assignments中:
-
再檢查對應的Pod.Status.Phase是否爲Running且DeletionTimestamp爲nil,如果是,則調用CPU Manager的AddContainer對該Container/Pod進行QoS和cpu request檢查,如果滿足static policy的條件,則調用takeByTopology爲該Container分配“最佳”CPU Set,並寫入到Memory State和Checkpoint文件(
cpu_manager_sate
)中,並繼續後面流程。 -
如果對應的Pod.Status.Phase是否爲Running且DeletionTimestamp爲nil爲false,則跳過該Container,該Container處理結束。不滿足static policy的Containers因爲不在Memory State assignments中,所以對它們的處理流程也到此結束。
-
-
如果ContainerID在CPU Manager assignments維護的Memory State中,繼續後面流程。
-
-
然後從Memory State中獲取該ContainerID對應的CPU Set。
-
最後調用CRI UpdateContainerCPUSet更新到cpuset cgroups中。
cpumanager調用State進行validate處理:
-
當Memory State中Shared(Default) CPU Set爲空時,CPU Assginments也必須爲空,然後對Memory State中的Shared Pool進行初始化,並寫入到Checkpoint文件中(初始化Checkpoint)。
-
只要我們沒有手動去刪Checkpoint文件,那麼在前面提到的state.NewCheckpointState中會根據Checkpoint文件restore到Memory State中,因此之前Assgned CPU Set、Default CPU Set都還在。
-
當檢測到Memory State已經成功初始化(根據Checkpoint restore),則檢查這次啓動時reserved cpu set是否都在Default CPU Set中,如果不是(比如kube/system reserved cpus增加了),則報錯返回,因爲這意味着reserved cpu set中有些cpus被Assigned到了某些Container中了,這可能會導致這些容器啓動失敗,此時需要用戶自己手動的去修正Checkpoint文件。
-
檢測reserved cpu set通過後,再檢測Default CPU Set和Assigned CPU Set是否有交集,如果有交集,說明Checkpoint文件restore到Memory State的數據有錯,報錯返回。
-
最後檢查這次啓動時從cAdvisor中獲取到的CPU Topology中的所有CPUs是否與Memory State(從Checkpoint中restore)中記錄的所有CPUs(Default CPU Set + Assigned CPU Set)相同,如果不同,則報錯返回。可能因爲上次CPU Manager停止到這次啓動這個時間內,Node上的可用CPUs發生變化。
參考:https://blog.csdn.net/weixin_34050389/article/details/92574505