這篇文章將為大家詳細(xì)講解有關(guān)如何理解Kubernetes資源限制CPU,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)文水,10余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):13518219792
Requests 和 Limits 之間的區(qū)別,其中 Requests
用于在調(diào)度時(shí)通知調(diào)度器 Pod 需要多少資源才能調(diào)度,而 Limits
用來告訴 Linux 內(nèi)核什么時(shí)候你的進(jìn)程可以為了清理空間而被殺死。我會繼續(xù)仔細(xì)分析 CPU 資源限制。
正如我在上一篇文章中提到的,CPU
資源限制比內(nèi)存資源限制更復(fù)雜,原因?qū)⒃谙挛脑斒?。幸運(yùn)的是 CPU
資源限制和內(nèi)存資源限制一樣都是由 cgroup
控制的,上文中提到的思路和工具在這里同樣適用,我們只需要關(guān)注他們的不同點(diǎn)就行了。首先,讓我們將 CPU 資源限制添加到之前示例中的 yaml:
resources: requests: memory: 50Mi cpu: 50m limits: memory: 100Mi cpu: 100m
Copy
單位后綴 m
表示千分之一核,也就是說 1 Core = 1000m
。因此該資源對象指定容器進(jìn)程需要 50/1000
核(5%)才能被調(diào)度,并且允許最多使用 100/1000
核(10%)。同樣,2000m
表示兩個(gè)完整的 CPU 核心,你也可以寫成 2
或者 2.0
。為了了解 Docker 和 cgroup 如何使用這些值來控制容器,我們首先創(chuàng)建一個(gè)只配置了 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 命令我們可以驗(yàn)證這個(gè) 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
?這是因?yàn)?Linux cgroup 和 Docker 都將 CPU 核心數(shù)分成了 1024
個(gè)時(shí)間片(shares),而 Kubernetes 將它分成了 1000
個(gè) shares。
shares 用來設(shè)置 CPU 的相對值,并且是針對所有的 CPU(內(nèi)核),默認(rèn)值是 1024,假如系統(tǒng)中有兩個(gè) cgroup,分別是 A 和 B,A 的 shares 值是 1024,B 的 shares 值是 512,那么 A 將獲得 1024/(1204+512)=66% 的 CPU 資源,而 B 將獲得 33% 的 CPU 資源。shares 有兩個(gè)特點(diǎn):
如果 A 不忙,沒有使用到 66% 的 CPU 時(shí)間,那么剩余的 CPU 時(shí)間將會被系統(tǒng)分配給 B,即 B 的 CPU 使用率可以超過 33%。
如果添加了一個(gè)新的 cgroup C,且它的 shares 值是 1024,那么 A 的限額變成了 1024/(1204+512+1024)=40%,B 的變成了 20%。
從上面兩個(gè)特點(diǎn)可以看出:
在閑的時(shí)候,shares 基本上不起作用,只有在 CPU 忙的時(shí)候起作用,這是一個(gè)優(yōu)點(diǎn)。
由于 shares 是一個(gè)絕對值,需要和其它 cgroup 的值進(jìn)行比較才能得到自己的相對限額,而在一個(gè)部署很多容器的機(jī)器上,cgroup 的數(shù)量是變化的,所以這個(gè)限額也是變化的,自己設(shè)置了一個(gè)高的值,但別人可能設(shè)置了一個(gè)更高的值,所以這個(gè)功能沒法精確的控制 CPU 使用率。
與配置內(nèi)存資源限制時(shí) Docker 配置容器進(jìn)程的內(nèi)存 cgroup 的方式相同,設(shè)置 CPU 資源限制時(shí) Docker 會配置容器進(jìn)程的 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
屬性,可以驗(yàn)證一下:
$ 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 時(shí)并沒有將值傳播到 cgroup。這是因?yàn)閮?nèi)存的 soft limit
內(nèi)核特性對 Kubernetes 不起作用,而設(shè)置了 cpu.shares
卻對 Kubernetes 很有用。后面我會詳細(xì)討論為什么會這樣?,F(xiàn)在讓我們先看看設(shè)置 CPU limits
時(shí)會發(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 驗(yàn)證我們的資源配置:
$ 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 就不太明顯了,它由兩個(gè)屬性控制:HostConfig.CpuPeriod
和 HostConfig.CpuQuota
。Docker 容器中的這兩個(gè)屬性又會映射到進(jìn)程的 cpu,couacct
cgroup 的另外兩個(gè)屬性: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
如我所說,這些值與容器配置中指定的值相同。但是這兩個(gè)屬性的值是如何從我們在 Pod 中設(shè)置的 100m
cpu limits 得出的呢,他們是如何實(shí)現(xiàn)該 limits 的呢?這是因?yàn)?cpu requests 和 cpu limits 是使用兩個(gè)獨(dú)立的控制系統(tǒng)來實(shí)現(xiàn)的。Requests 使用的是 cpu shares
系統(tǒng),cpu shares 將每個(gè) CPU 核心劃分為 1024
個(gè)時(shí)間片,并保證每個(gè)進(jìn)程將獲得固定比例份額的時(shí)間片。如果總共有 1024 個(gè)時(shí)間片,并且兩個(gè)進(jìn)程中的每一個(gè)都將 cpu.shares
設(shè)置為 512
,那么它們將分別獲得大約一半的 CPU 可用時(shí)間。但 cpu shares 系統(tǒng)無法精確控制 CPU 使用率的上限,如果一個(gè)進(jìn)程沒有設(shè)置 shares,則另一個(gè)進(jìn)程可用自由使用 CPU 資源。
大約在 2010 年左右,谷歌團(tuán)隊(duì)和其他一部分人注意到了這個(gè)問題。為了解決這個(gè)問題,后來在 linux 內(nèi)核中增加了第二個(gè)功能更強(qiáng)大的控制系統(tǒng):CPU 帶寬控制組。帶寬控制組定義了一個(gè) 周期,通常為 1/10
秒(即 100000 微秒)。還定義了一個(gè) 配額,表示允許進(jìn)程在設(shè)置的周期長度內(nèi)所能使用的 CPU 時(shí)間數(shù),兩個(gè)文件配合起來設(shè)置CPU的使用上限。兩個(gè)文件的單位都是微秒(us),cfs_period_us
的取值范圍為 1 毫秒(ms)到 1 秒(s),cfs_quota_us
的取值大于 1ms 即可,如果 cfs_quota_us 的值為 -1
(默認(rèn)值),表示不受 CPU 時(shí)間的限制。
下面是幾個(gè)例子:
# 1.限制只能使用1個(gè)CPU(每250ms能使用250ms的CPU時(shí)間) $ echo 250000 > cpu.cfs_quota_us /* quota = 250ms */ $ echo 250000 > cpu.cfs_period_us /* period = 250ms */ # 2.限制使用2個(gè)CPU(內(nèi)核)(每500ms能使用1000ms的CPU時(shí)間,即使用兩個(gè)內(nèi)核) $ echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */ $ echo 500000 > cpu.cfs_period_us /* period = 500ms */ # 3.限制使用1個(gè)CPU的20%(每50ms能使用10ms的CPU時(shí)間,即使用一個(gè)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
個(gè) CPU 核心,即 100000
微秒的 CPU 時(shí)間周期中的 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)中默認(rèn)的 CPU 調(diào)度算法。還有一個(gè)實(shí)時(shí)調(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)度時(shí)通知調(diào)度器節(jié)點(diǎn)上至少需要多少個(gè) cpu shares 才可以被調(diào)度。
與 內(nèi)存 requests 不同,設(shè)置了 cpu requests 會在 cgroup 中設(shè)置一個(gè)屬性,以確保內(nèi)核會將該數(shù)量的 shares 分配給進(jìn)程。
cpu limits 與 內(nèi)存 limits 也有所不同。如果容器進(jìn)程使用的內(nèi)存資源超過了內(nèi)存使用限制,那么該進(jìn)程將會成為 oom-killing
的候選者。但是容器進(jìn)程基本上永遠(yuǎn)不能超過設(shè)置的 CPU 配額,所以容器永遠(yuǎn)不會因?yàn)閲L試使用比分配的更多的 CPU 時(shí)間而被驅(qū)逐。系統(tǒng)會在調(diào)度程序中強(qiáng)制進(jìn)行 CPU 資源限制,以確保進(jìn)程不會超過這個(gè)限制。
如果你沒有在容器中設(shè)置這些屬性,或?qū)⑺麄冊O(shè)置為不準(zhǔn)確的值,會發(fā)生什么呢?與內(nèi)存一樣,如果只設(shè)置了 limits 而沒有設(shè)置 requests,Kubernetes 會將 CPU 的 requests 設(shè)置為 與 limits 的值一樣。如果你對你的工作負(fù)載所需要的 CPU 時(shí)間了如指掌,那再好不過了。如果只設(shè)置了 CPU requests 卻沒有設(shè)置 CPU limits 會怎么樣呢?這種情況下,Kubernetes 會確保該 Pod 被調(diào)度到合適的節(jié)點(diǎn),并且該節(jié)點(diǎn)的內(nèi)核會確保節(jié)點(diǎn)上的可用 cpu shares 大于 Pod 請求的 cpu shares,但是你的進(jìn)程不會被阻止使用超過所請求的 CPU 數(shù)量。既不設(shè)置 requests 也不設(shè)置 limits 是最糟糕的情況:調(diào)度程序不知道容器需要什么,并且進(jìn)程對 cpu shares 的使用是無限制的,這可能會對 node 產(chǎn)生一些負(fù)面影響。
最后我還想告訴你們的是:為每個(gè) pod 都手動配置這些參數(shù)是挺麻煩的事情,kubernetes 提供了 LimitRange
資源,可以讓我們配置某個(gè) namespace 默認(rèn)的 request 和 limit 值。
通過上文的討論大家已經(jīng)知道了忽略資源限制會對 Pod 產(chǎn)生負(fù)面影響,因此你可能會想,如果能夠配置某個(gè) namespace 默認(rèn)的 request 和 limit 值就好了,這樣每次創(chuàng)建新 Pod 都會默認(rèn)加上這些限制。Kubernetes 允許我們通過 LimitRange 資源對每個(gè)命名空間設(shè)置資源限制。要?jiǎng)?chuàng)建默認(rèn)的資源限制,需要在對應(yīng)的命名空間中創(chuàng)建一個(gè) LimitRange
資源。下面是一個(gè)例子:
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
這里的幾個(gè)字段可能會讓你們有些困惑,我拆開來給你們分析一下。
limits
字段下面的 default
字段表示每個(gè) Pod 的默認(rèn)的 limits
配置,所以任何沒有分配資源的 limits 的 Pod 都會被自動分配 100Mi
limits 的內(nèi)存和 100m
limits 的 CPU。
defaultRequest
字段表示每個(gè) Pod 的默認(rèn) requests
配置,所以任何沒有分配資源的 requests 的 Pod 都會被自動分配 50Mi
requests 的內(nèi)存和 50m
requests 的 CPU。
max
和 min
字段比較特殊,如果設(shè)置了這兩個(gè)字段,那么只要這個(gè)命名空間中的 Pod 設(shè)置的 limits
和 requests
超過了這個(gè)上限和下限,就不會允許這個(gè) Pod 被創(chuàng)建。我暫時(shí)還沒有發(fā)現(xiàn)這兩個(gè)字段的用途,如果你知道,歡迎在留言告訴我。
LimitRange
中設(shè)定的默認(rèn)值最后由 Kubernetes 中的準(zhǔn)入控制器 LimitRanger
插件來實(shí)現(xiàn)。準(zhǔn)入控制器由一系列插件組成,它會在 API 接收對象之后創(chuàng)建 Pod 之前對 Pod 的 Spec
字段進(jìn)行修改。對于 LimitRanger
插件來說,它會檢查每個(gè) Pod 是否設(shè)置了 limits 和 requests,如果沒有設(shè)置,就給它配置 LimitRange
中設(shè)定的默認(rèn)值。通過檢查 Pod 中的 annotations
注釋,你可以看到 LimitRanger
插件已經(jīng)在你的 Pod 中設(shè)置了默認(rèn)值。例如:
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é)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
本文標(biāo)題:如何理解Kubernetes資源限制CPU
新聞來源:http://muchs.cn/article34/gdohpe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站制作、App設(shè)計(jì)、品牌網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站建設(shè)、服務(wù)器托管
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)