這篇文章將為大家詳細講解有關(guān)如何理解Kubernetes資源限制CPU,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站設(shè)計、成都做網(wǎng)站、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)文水,10余年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):13518219792
Requests 和 Limits 之間的區(qū)別,其中 Requests
用于在調(diào)度時通知調(diào)度器 Pod 需要多少資源才能調(diào)度,而 Limits
用來告訴 Linux 內(nèi)核什么時候你的進程可以為了清理空間而被殺死。我會繼續(xù)仔細分析 CPU 資源限制。
正如我在上一篇文章中提到的,CPU
資源限制比內(nèi)存資源限制更復(fù)雜,原因?qū)⒃谙挛脑斒?。幸運的是 CPU
資源限制和內(nèi)存資源限制一樣都是由 cgroup
控制的,上文中提到的思路和工具在這里同樣適用,我們只需要關(guān)注他們的不同點就行了。首先,讓我們將 CPU 資源限制添加到之前示例中的 yaml:
resources: requests: memory: 50Mi cpu: 50m limits: memory: 100Mi cpu: 100m
Copy
單位后綴 m
表示千分之一核,也就是說 1 Core = 1000m
。因此該資源對象指定容器進程需要 50/1000
核(5%)才能被調(diào)度,并且允許最多使用 100/1000
核(10%)。同樣,2000m
表示兩個完整的 CPU 核心,你也可以寫成 2
或者 2.0
。為了了解 Docker 和 cgroup 如何使用這些值來控制容器,我們首先創(chuàng)建一個只配置了 CPU requests
的 Pod:
$ kubectl run limit-test --image=busybox --requests "cpu=50m" --command -- /bin/sh -c "while true; do sleep 2; done" deployment.apps "limit-test" created
Copy
通過 kubectl 命令我們可以驗證這個 Pod 配置了 50m
的 CPU requests:
$ kubectl get pods limit-test-5b4c495556-p2xkr -o=jsonpath='{.spec.containers[0].resources}' map[requests:map[cpu:50m]]
Copy
我們還可以看到 Docker 為容器配置了相同的資源限制:
$ docker ps | grep busy | cut -d' ' -f1 f2321226620e $ docker inspect f2321226620e --format '{{.HostConfig.CpuShares}}' 51
Copy
這里顯示的為什么是 51
,而不是 50
?這是因為 Linux cgroup 和 Docker 都將 CPU 核心數(shù)分成了 1024
個時間片(shares),而 Kubernetes 將它分成了 1000
個 shares。
shares 用來設(shè)置 CPU 的相對值,并且是針對所有的 CPU(內(nèi)核),默認值是 1024,假如系統(tǒng)中有兩個 cgroup,分別是 A 和 B,A 的 shares 值是 1024,B 的 shares 值是 512,那么 A 將獲得 1024/(1204+512)=66% 的 CPU 資源,而 B 將獲得 33% 的 CPU 資源。shares 有兩個特點:
如果 A 不忙,沒有使用到 66% 的 CPU 時間,那么剩余的 CPU 時間將會被系統(tǒng)分配給 B,即 B 的 CPU 使用率可以超過 33%。
如果添加了一個新的 cgroup C,且它的 shares 值是 1024,那么 A 的限額變成了 1024/(1204+512+1024)=40%,B 的變成了 20%。
從上面兩個特點可以看出:
在閑的時候,shares 基本上不起作用,只有在 CPU 忙的時候起作用,這是一個優(yōu)點。
由于 shares 是一個絕對值,需要和其它 cgroup 的值進行比較才能得到自己的相對限額,而在一個部署很多容器的機器上,cgroup 的數(shù)量是變化的,所以這個限額也是變化的,自己設(shè)置了一個高的值,但別人可能設(shè)置了一個更高的值,所以這個功能沒法精確的控制 CPU 使用率。
與配置內(nèi)存資源限制時 Docker 配置容器進程的內(nèi)存 cgroup 的方式相同,設(shè)置 CPU 資源限制時 Docker 會配置容器進程的 cpu,cpuacct
cgroup:
$ ps ax | grep /bin/sh 60554 ? Ss 0:00 /bin/sh -c while true; do sleep 2; done $ sudo cat /proc/60554/cgroup ... 4:cpu,cpuacct:/kubepods/burstable/pode12b33b1-db07-11e8-b1e1-42010a800070/3be263e7a8372b12d2f8f8f9b4251f110b79c2a3bb9e6857b2f1473e640e8e75 $ ls -l /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pode12b33b1-db07-11e8-b1e1-42010a800070/3be263e7a8372b12d2f8f8f9b4251f110b79c2a3bb9e6857b2f1473e640e8e75 total 0 drwxr-xr-x 2 root root 0 Oct 28 23:19 . drwxr-xr-x 4 root root 0 Oct 28 23:19 .. ... -rw-r--r-- 1 root root 0 Oct 28 23:19 cpu.shares
Copy
Docker 容器的 HostConfig.CpuShares
屬性映射到 cgroup 的 cpu.shares
屬性,可以驗證一下:
$ sudo cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/podb5c03ddf-db10-11e8-b1e1-42010a800070/64b5f1b636dafe6635ddd321c5b36854a8add51931c7117025a694281fb11444/cpu.shares 51
Copy
你可能會很驚訝,設(shè)置了 CPU requests 竟然會把值傳播到 cgroup
,而在上一篇文章中我們設(shè)置內(nèi)存 requests 時并沒有將值傳播到 cgroup。這是因為內(nèi)存的 soft limit
內(nèi)核特性對 Kubernetes 不起作用,而設(shè)置了 cpu.shares
卻對 Kubernetes 很有用。后面我會詳細討論為什么會這樣。現(xiàn)在讓我們先看看設(shè)置 CPU limits
時會發(fā)生什么:
$ kubectl run limit-test --image=busybox --requests "cpu=50m" --limits "cpu=100m" --command -- /bin/sh -c "while true; do sleep 2; done" deployment.apps "limit-test" created
Copy
再一次使用 kubectl 驗證我們的資源配置:
$ kubectl get pods limit-test-5b4fb64549-qpd4n -o=jsonpath='{.spec.containers[0].resources}' map[limits:map[cpu:100m] requests:map[cpu:50m]]
Copy
查看對應(yīng)的 Docker 容器的配置:
$ docker ps | grep busy | cut -d' ' -f1 f2321226620e $ docker inspect 472abbce32a5 --format '{{.HostConfig.CpuShares}} {{.HostConfig.CpuQuota}} {{.HostConfig.CpuPeriod}}' 51 10000 100000
Copy
可以明顯看出,CPU requests 對應(yīng)于 Docker 容器的 HostConfig.CpuShares
屬性。而 CPU limits 就不太明顯了,它由兩個屬性控制:HostConfig.CpuPeriod
和 HostConfig.CpuQuota
。Docker 容器中的這兩個屬性又會映射到進程的 cpu,couacct
cgroup 的另外兩個屬性:cpu.cfs_period_us
和 cpu.cfs_quota_us
。我們來看一下:
$ sudo cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod2f1b50b6-db13-11e8-b1e1-42010a800070/f0845c65c3073e0b7b0b95ce0c1eb27f69d12b1fe2382b50096c4b59e78cdf71/cpu.cfs_period_us 100000 $ sudo cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod2f1b50b6-db13-11e8-b1e1-42010a800070/f0845c65c3073e0b7b0b95ce0c1eb27f69d12b1fe2382b50096c4b59e78cdf71/cpu.cfs_quota_us 10000
Copy
如我所說,這些值與容器配置中指定的值相同。但是這兩個屬性的值是如何從我們在 Pod 中設(shè)置的 100m
cpu limits 得出的呢,他們是如何實現(xiàn)該 limits 的呢?這是因為 cpu requests 和 cpu limits 是使用兩個獨立的控制系統(tǒng)來實現(xiàn)的。Requests 使用的是 cpu shares
系統(tǒng),cpu shares 將每個 CPU 核心劃分為 1024
個時間片,并保證每個進程將獲得固定比例份額的時間片。如果總共有 1024 個時間片,并且兩個進程中的每一個都將 cpu.shares
設(shè)置為 512
,那么它們將分別獲得大約一半的 CPU 可用時間。但 cpu shares 系統(tǒng)無法精確控制 CPU 使用率的上限,如果一個進程沒有設(shè)置 shares,則另一個進程可用自由使用 CPU 資源。
大約在 2010 年左右,谷歌團隊和其他一部分人注意到了這個問題。為了解決這個問題,后來在 linux 內(nèi)核中增加了第二個功能更強大的控制系統(tǒng):CPU 帶寬控制組。帶寬控制組定義了一個 周期,通常為 1/10
秒(即 100000 微秒)。還定義了一個 配額,表示允許進程在設(shè)置的周期長度內(nèi)所能使用的 CPU 時間數(shù),兩個文件配合起來設(shè)置CPU的使用上限。兩個文件的單位都是微秒(us),cfs_period_us
的取值范圍為 1 毫秒(ms)到 1 秒(s),cfs_quota_us
的取值大于 1ms 即可,如果 cfs_quota_us 的值為 -1
(默認值),表示不受 CPU 時間的限制。
下面是幾個例子:
# 1.限制只能使用1個CPU(每250ms能使用250ms的CPU時間) $ echo 250000 > cpu.cfs_quota_us /* quota = 250ms */ $ echo 250000 > cpu.cfs_period_us /* period = 250ms */ # 2.限制使用2個CPU(內(nèi)核)(每500ms能使用1000ms的CPU時間,即使用兩個內(nèi)核) $ echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */ $ echo 500000 > cpu.cfs_period_us /* period = 500ms */ # 3.限制使用1個CPU的20%(每50ms能使用10ms的CPU時間,即使用一個CPU核心的20%) $ echo 10000 > cpu.cfs_quota_us /* quota = 10ms */ $ echo 50000 > cpu.cfs_period_us /* period = 50ms */
Copy
在本例中我們將 Pod 的 cpu limits 設(shè)置為 100m
,這表示 100/1000
個 CPU 核心,即 100000
微秒的 CPU 時間周期中的 10000
。所以該 limits 翻譯到 cpu,cpuacct
cgroup 中被設(shè)置為 cpu.cfs_period_us=100000
和 cpu.cfs_quota_us=10000
。順便說一下,其中的 cfs 代表 Completely Fair Scheduler
(絕對公平調(diào)度),這是 Linux 系統(tǒng)中默認的 CPU 調(diào)度算法。還有一個實時調(diào)度算法,它也有自己相應(yīng)的配額值。
現(xiàn)在讓我們來總結(jié)一下:
在 Kubernetes 中設(shè)置的 cpu requests 最終會被 cgroup 設(shè)置為 cpu.shares
屬性的值, cpu limits 會被帶寬控制組設(shè)置為 cpu.cfs_period_us
和 cpu.cfs_quota_us
屬性的值。與內(nèi)存一樣,cpu requests 主要用于在調(diào)度時通知調(diào)度器節(jié)點上至少需要多少個 cpu shares 才可以被調(diào)度。
與 內(nèi)存 requests 不同,設(shè)置了 cpu requests 會在 cgroup 中設(shè)置一個屬性,以確保內(nèi)核會將該數(shù)量的 shares 分配給進程。
cpu limits 與 內(nèi)存 limits 也有所不同。如果容器進程使用的內(nèi)存資源超過了內(nèi)存使用限制,那么該進程將會成為 oom-killing
的候選者。但是容器進程基本上永遠不能超過設(shè)置的 CPU 配額,所以容器永遠不會因為嘗試使用比分配的更多的 CPU 時間而被驅(qū)逐。系統(tǒng)會在調(diào)度程序中強制進行 CPU 資源限制,以確保進程不會超過這個限制。
如果你沒有在容器中設(shè)置這些屬性,或?qū)⑺麄冊O(shè)置為不準確的值,會發(fā)生什么呢?與內(nèi)存一樣,如果只設(shè)置了 limits 而沒有設(shè)置 requests,Kubernetes 會將 CPU 的 requests 設(shè)置為 與 limits 的值一樣。如果你對你的工作負載所需要的 CPU 時間了如指掌,那再好不過了。如果只設(shè)置了 CPU requests 卻沒有設(shè)置 CPU limits 會怎么樣呢?這種情況下,Kubernetes 會確保該 Pod 被調(diào)度到合適的節(jié)點,并且該節(jié)點的內(nèi)核會確保節(jié)點上的可用 cpu shares 大于 Pod 請求的 cpu shares,但是你的進程不會被阻止使用超過所請求的 CPU 數(shù)量。既不設(shè)置 requests 也不設(shè)置 limits 是最糟糕的情況:調(diào)度程序不知道容器需要什么,并且進程對 cpu shares 的使用是無限制的,這可能會對 node 產(chǎn)生一些負面影響。
最后我還想告訴你們的是:為每個 pod 都手動配置這些參數(shù)是挺麻煩的事情,kubernetes 提供了 LimitRange
資源,可以讓我們配置某個 namespace 默認的 request 和 limit 值。
通過上文的討論大家已經(jīng)知道了忽略資源限制會對 Pod 產(chǎn)生負面影響,因此你可能會想,如果能夠配置某個 namespace 默認的 request 和 limit 值就好了,這樣每次創(chuàng)建新 Pod 都會默認加上這些限制。Kubernetes 允許我們通過 LimitRange 資源對每個命名空間設(shè)置資源限制。要創(chuàng)建默認的資源限制,需要在對應(yīng)的命名空間中創(chuàng)建一個 LimitRange
資源。下面是一個例子:
apiVersion: v1 kind: LimitRange metadata: name: default-limit spec: limits: - default: memory: 100Mi cpu: 100m defaultRequest: memory: 50Mi cpu: 50m - max: memory: 512Mi cpu: 500m - min: memory: 50Mi cpu: 50m type: Container
Copy
這里的幾個字段可能會讓你們有些困惑,我拆開來給你們分析一下。
limits
字段下面的 default
字段表示每個 Pod 的默認的 limits
配置,所以任何沒有分配資源的 limits 的 Pod 都會被自動分配 100Mi
limits 的內(nèi)存和 100m
limits 的 CPU。
defaultRequest
字段表示每個 Pod 的默認 requests
配置,所以任何沒有分配資源的 requests 的 Pod 都會被自動分配 50Mi
requests 的內(nèi)存和 50m
requests 的 CPU。
max
和 min
字段比較特殊,如果設(shè)置了這兩個字段,那么只要這個命名空間中的 Pod 設(shè)置的 limits
和 requests
超過了這個上限和下限,就不會允許這個 Pod 被創(chuàng)建。我暫時還沒有發(fā)現(xiàn)這兩個字段的用途,如果你知道,歡迎在留言告訴我。
LimitRange
中設(shè)定的默認值最后由 Kubernetes 中的準入控制器 LimitRanger
插件來實現(xiàn)。準入控制器由一系列插件組成,它會在 API 接收對象之后創(chuàng)建 Pod 之前對 Pod 的 Spec
字段進行修改。對于 LimitRanger
插件來說,它會檢查每個 Pod 是否設(shè)置了 limits 和 requests,如果沒有設(shè)置,就給它配置 LimitRange
中設(shè)定的默認值。通過檢查 Pod 中的 annotations
注釋,你可以看到 LimitRanger
插件已經(jīng)在你的 Pod 中設(shè)置了默認值。例如:
apiVersion: v1 kind: Pod metadata: annotations: kubernetes.io/limit-ranger: 'LimitRanger plugin set: cpu request for container limit-test' name: limit-test-859d78bc65-g6657 namespace: default spec: containers: - args: - /bin/sh - -c - while true; do sleep 2; done image: busybox imagePullPolicy: Always name: limit-test resources: requests: cpu: 100m
關(guān)于如何理解Kubernetes資源限制CPU就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
本文標題:如何理解Kubernetes資源限制CPU
新聞來源:http://www.rwnh.cn/article34/gdohpe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站制作、App設(shè)計、品牌網(wǎng)站設(shè)計、品牌網(wǎng)站建設(shè)、服務(wù)器托管
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)