在k8s上,可由容器或pod請求或消費的計算資源時指cpu和內存,這也是目前僅有的受支持的兩種類型。相比較來說,cpu屬於可壓縮資源,即資源額度可按需收縮,而內存則是不可壓縮型資源,對其執行收縮操作可能會導致某種程度的問題。
目前來說,資源隔離尚且屬於容器級別,cpu和內存資源的配置需要在pod中的容器上運行,每種資源均可由request屬性定義其請求的確保可用值,即容器運行可能用不到這些額度的資源,但用到的時候必須要確保有如此多的資源可用,而limits屬性則用於吸納子資源可用的最大值,即硬限制。通常把資源配置稱作pod資源的請求和限制,只不過它是pod內所有容器上某種類型資源的請求和限制的總和。
在k8s系統上,1個單位的cpu相當於虛擬機上的1顆cpu(vcpu)或物理機上的一個超線程或邏輯cpu,它支持分數計量方式,一個核心相當於1000個微核心,因此500m相當於是0.5個核心,內存的計量方式與日常使用方式相同,默認單位是字節,也可以使用E、P、T、G、M和K作為單位后綴。
一、資源需求
自主式pod要求為stress容器確保128M的內存及五分之一個cpu核心資源可用,它運行stress-ng鏡像啟動一個進程進行內存性能壓力測試,滿載測試時它也會盡可能多地占用cpu資源,另外再啟動一個專用的cpu壓力測試進程。stress-ng是一個多功能系統壓力測試工具,master/worker模型,master為主進程,負責生成和控制子進程,worker是負責執行各類特定測試的子進程。
集群中的每個節點都擁有定量的cpu和內存資源,調度pod時,僅那些被請求資源的余量可容納當前調度的pod的請求量的節點才可作為目標節點。也就是說,k8s的調度器會根據容器的requests屬性中定義的資源需求量來判定僅哪些節點可接受運行相關的pod資源,而對於一個節點的資源來說,每運行一個pod對象,其requestes中定義的請求量都要被預留,直到被所有pod對象瓜分完畢為止。
二、資源限制
容器的資源需求僅能達到為其保證可用的最少資源量的目的,它並不會限制容器的可用資源上限,因此對因應用程序自身存在bug等多種原因而導致的系統資源被長期占用的情況則無計可施,這就需要通過limits屬性定義資源的最大可用量。資源分配時,可壓縮型資源cpu的控制閾可自由調節,容器進程無法獲得超出其cpu配額的可用時間。不過,如果進程申請分配超出其limits屬性定義的硬限制的內存資源時,它將被OOM killer殺死。不過,隨后可能會被其控制進程所重啟。例如,容器進程的pod對象會被殺死並重啟(重啟策略為always或onfailure時),或者是容器進程的子進程被其父進程所重啟。
與requests不同的是,limits並不會影響pod的調度結果,也就是說,一個節點上的說有pod對象的limits數量之和可以大於節點所擁有的資源量,即支持資源的過載使用。不過,這么一來一旦資源耗盡,尤其是內存資源耗盡,則必然會有容器因OOMKilled而終止。另外,k8s僅會確保pod能夠獲得他們請求的cpu時間額度,他們能否獲得額外的cpu時間,則取決於其他正在運行的作業對cpu資源的占用情況。例如,對於總數為1000m的cpu來說,容器a請求使用200m,容器b請求使用500m,在不超出它們各自的最大限額的前提下,余下的300m在雙方都需要時會以2:5的方式進行配置。
三、容器的可見資源
於容器中運行top等命令觀察資源可用量信息時,即便定義了requests和limits屬性,雖然其可用資源受限於此兩個屬性的定義,但容器中可見的資源量依然是節點級別的可用總量。
四、pod的服務質量類別
k8s允許節點資源對limits的過載使用,這意味着節點無法同時滿足其上的所有pod對象以資源滿載的方式運行。於是,在內存資源緊缺時,應該以何種次序先后終止哪些pod對象?k8s無法自行對此做出決策,它需要借助於pod對象的優先級完成判定。根據pod對象的requests和limits屬性,k8s將pod對象歸類到BestEffort、Burstable和Guaranteed三個服務質量類別下,具體如下:
Guaranteed:每個容器都為cpu資源設置了具有相同值的requests和limits屬性,以及每個容器都為內存資源設置了具有相同值的requests和limits屬性的pod資源會自動歸屬於此類別,這類pod資源具有最高優先級.
Burstable:至少有一個容器設置了cpu或內存資源的requests屬性,但不滿足Guaranteed類別要求的pod資源將自動歸屬此類別,它們具有中等優先級。
BestEffort:未為任何一個容器設置requests和limits屬性的pod資源將自動歸屬於此類別,它們的優先級為最低級別。
內存資源緊缺時,BestEfford類別的容器將首當其沖地終止,因為系統不為其提供任何級別的資源保證,但換來的好處是,它們能夠在可用時做到盡可能多地占用資源。若已然不存在BestEfford類別的容器,則接下來是有着中等優先級的Burstable類別的pod被終止。Guaranteed類別的容器擁有最高優先級,它們不會被殺死,除非其內存資源需求超限,或者OOM時沒有其他更低優先級的pod資源存在。
每個運行狀態的容器都有其OOM得分,得分越高越會被優先殺死。OOM得分主要根據兩個維度進行計算:由QoS類別繼承而來的默認分值和容器的可用內存資源比例。同等類別的pod資源的默認分值相同。同等級別優先級的pod資源在OOM時,與自身requests屬性相比,其內存占用比例最大的pod對象將被首先殺死。需要特別說明的是,OOM是內存耗盡時的處理機制,它們與可壓縮型資源cpu無關,因此cpu資源的需求無法得到保證時,pod僅僅是暫時獲取不到相應的資源而已。