深入理解Kubernetes資源限制:CPU
寫在前面
在上一篇關於Kubernetes資源限制的文章我們討論瞭如何透過ResourceRequirements設定Pod中容器記憶體限制,以及容器
執行時是如何利用Linux Cgroups實現這些限制的。也分析了requests是用來通知排程器Pod所需資源需求和limits是在宿主
機遇到記憶體壓力時幫助核心限制資源二者的區別。
在本文中,我會繼續深入探討CPU時間的requests和limits。你是否閱讀過第一篇文章並不會影響本文的學習,但是我建議你
兩篇文章都讀一讀,從而得到工程師或者叢集管理員視角的叢集控制全景。
CPU時間
正如我在第一篇文章中指出,限制CPU時間要比限制記憶體限制更加複雜,好訊息是限制CPU也是根據我們前面所瞭解到的
cgroups機制控制的,與限制記憶體的原理是通用的,我們只需要關注一些細節即可。我們從向前文的例子裡新增CPU時間限
制開始:
resources:
requests:
memory: 50Mi
cpu: 50m
limits:
memory: 100Mi
cpu: 100m
單位字尾m表示“千分之一個核心”,所以這個資源物件定義了容器程式需要50/1000的核心(5%),並且最多使用100/100
0的核心(10%)。類似的,2000m表示2顆完整的核心,當然也可以用2或者2.0來表示。讓我們建立一個只擁有CPU
requests的Pod,然後看看Docker是如何配置cgroups的:
$ kubectl run limit-test --image=busybox --requests “cpu=50m” --command – /bin/sh -c “while true; do sleep
2; done”
deployment.apps “limit-test” created
我們能夠看到Kubernetes已經配置了50m的CPU requests:
$ kubectl get pods limit-test-5b4c495556-p2xkr -o=jsonpath=’{.spec.containers[0].resources}’
[cpu:50m]]
我們也可以看到Docker配置了同樣的limits:
$ docker ps | grep busy | cut -d’ ’ -f1
f2321226620e
$ docker inspect f2321226620e --format ‘{{.HostConfig.CpuShares}}’
51
為什麼是51而不是50?CPU cgroup和Docker都把一個核心劃分為1024份,而Kubernetes則劃分為1000份。
那麼Docker如何把它應用到容器程式上?設定記憶體限制會讓Docker來配置程式的memory cgroup,同樣設定CPU限制會
讓它配置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/3be263e7a8372b12d2f8f8f
9b4251f110b79c2a3bb9e6857b2f1473e640e8e75
ls -l /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pode12b33b1-db07-11e8-b1e1-42010a800070/3be263e
7a8372b12d2f8f8f9b4251f110b79c2a3bb9e6857b2f1473e640e8e75
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
Docker的HostConfig.CpuShares容器屬性對映到了cgroup的cpu.shares上,所以讓我們看看:
$ sudo cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/podb5c03ddf-db10-11e8-b1e1-42010a800070/6
4b5f1b636dafe6635ddd321c5b36854a8add51931c7117025a694281fb11444/cpu.shares
51
你可能會驚奇地發現設定一個CPU請求會把這個值傳送到cgroup去,而上篇文章中設定記憶體卻並非如此。下面這行核心對內
存軟限制的行為對Kubernetes來說沒什麼用處,而設定了cpu.shares則是有用的。我等會會對此做出解釋。那麼當我們設
置cpu限制時發生了什麼?讓我們一起找找看:
$ 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
現在我們回過頭來看看Kubernetes Pod資源物件的限制:
$ kubectl get pods limit-test-5b4fb64549-qpd4n -o=jsonpath=’{.spec.containers[0].resources}’
map[limits:map[cpu:100m] requests:map[cpu:50m]]
在Docker容器配置裡:
$ docker ps | grep busy | cut -d’ ’ -f1
f2321226620e
$ docker inspect 472abbce32a5 --format ‘{{.HostConfig.CpuShares}} {{.HostConfig.CpuQuota}} {{.HostConfig.Cp
uPeriod}}’
51 10000 100000
正如我們所見,CPU請求存放在HostConfig.CpuShares屬性裡。CPU限制,儘管不是那麼明顯,它由
HostConfig.CpuPeriod和HostConfig.CpuQuota兩個值表示,這些Docker容器配置對映為程式的cpu, cpuacct cgroup的
兩個屬性:cpu.cfs_period_us和cpu.cfs_quota_us。讓我們仔細看看:
$ sudo cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod2f1b50b6-db13-11e8-b1e1-42010a800070/f08
45c65c3073e0b7b0b95ce0c1eb27f69d12b1fe2382b50096c4b59e78cdf71/cpu.cfs_period_us
100000
$ sudo cat /sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod2f1b50b6-db13-11e8-b1e1-42010a800070/f084
5c65c3073e0b7b0b95ce0c1eb27f69d12b1fe2382b50096c4b59e78cdf71/cpu.cfs_quota_us
10000
如我們所料這兩個配置會同樣配置到Docker容器配置裡。但是這些值是怎麼從Pod的100m CPU限制裡轉換過來,並且是
怎麼實現的呢?原來CPU requests和CPU limits是由兩套不同的cgroup分別進行控制的。Requests使用CPU分片系統,是
二者中出現較早的一個。Cpu分片是將每個核心劃分為1024份,並且保證每個程式會接收到一定比例的CPU分片。如果只
有1024片而這兩個程式都設定cpu.shares為512,那麼這兩個程式會各自得到一半的CPU時間。CPU分片系統並不能指定
上界,也就是說如果一個程式沒有使用它的這一份,其它程式是可以使用的。
在2010年左右Google和一些公司注意到了這個可能存在的問題。進而合併了一個更加強大的秒級響應的系統:CPU頻寬控
制。頻寬控制系統定義了一個通常是1/10秒的週期,或者100000微秒,以及一個表示週期裡一個程式可以使用的最大分片數
配額。在這個例子裡,我們為我們的Pod申請了100mCPU,它等價於100/1000的核心,或者10000/100000毫秒的CPU時
間。所以我們的CPU requests被翻譯為設定這個程式的cpu,cpuacct的配置為cpu.cfs_period_us=100000並且
c pu.cfs_quota_us=10000。cfs表示完全公平排程,它是Linux預設的CPU排程器。同時還有一個響應quota值的實
時排程器 。
我們為Kubernetes設定CPU requests實際上是設定了cpu.shares cgroup屬性,設定CPU limits配置了另一個子系統的
cpu.cfs_period_us和cpu.cfs_quota_us屬性。就像記憶體requests對排程器的意義一樣,CPU requests會讓排程器選擇至
少擁有那麼多可用CPU分片的節點。不同於記憶體requests,設定CPU requests也會給cgroup設定相應的屬性,幫助核心
實際給程式分配一樣數量的CPU核心分片。Limits的處理也與記憶體不一樣。超出記憶體limits會讓你的容器程式成為oom-kill的
選項,但是你的程式基本上不可能超出設定的cpu配額,並且永遠不會因為試著使用更多CPU而被驅逐。系統在排程器那裡
加強了配額的使用,所以程式在到達limits後只會被限流。
如果你並未為你的容器設定這些屬性,或者給他們設定了不準確的值會怎麼樣?作為記憶體,如果你設定了limits但並未指
定requests,Kubernetes會預設讓request指向limit。如果你對你的應用需要多少CPU時間很清楚的話這沒問題。那麼如果
設定requests而不設定limits呢?在這個場景裡Kubernetes仍然可以精確地排程你的Pod,核心也會保證它能得到需要的最
少資源配額。但是不會限制你的程式只能使用requested數量的資源,它可能會偷取別的程式的分片。不設定requests和
limits是最壞的情況,排程器不知道容器需要多少資源,程式的CPU分片也是無限的,這也許會對節點帶來不利的影響。這引出了我想要說的最後一件事情:為每個namespace設定預設的的資源限制。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69908804/viewspace-2638397/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入理解Kubernetes資源限制:記憶體記憶體
- 如何設定Kubernetes資源限制
- Kubernetes資源請求與限制
- Kubernetes:容器資源需求與限制(約束)
- Kubernetes中如何使用CPU請求和限制? - daniele
- 《深入剖析Kubernetes》資源連結清單
- Kubernetes筆記(四):詳解Namespace與資源限制ResourceQuota,LimitRange筆記namespaceMIT
- 在kubernetes裡使用AppArmor限制容器對資源的訪問APP
- 如何使用 Docker 來限制 CPU、記憶體和 IO等資源?Docker記憶體
- 深入解析 kubernetes 資源管理,容器雲牛人有話說
- Docker的資源限制Docker
- jvm 可以限制cpu嗎JVM
- 利用Kubernetes名稱空間來管理記憶體和CPU資源(二)記憶體
- 利用Kubernetes名稱空間來管理記憶體和CPU資源(一)記憶體
- Flink - 合理利用 cpu 資源
- Kubernetes as Database: 使用kubesql查詢kubernetes資源DatabaseSQL
- 深入理解Prometheus: Kubernetes環境中的監控實踐Prometheus
- Kubernetes CRDs 自定義資源
- setrlimit函式限制程序資源MIT函式
- 容器技術之Docker資源限制Docker
- 帶你深入淺出理解深度學習(附資源打包下載)深度學習
- 效能測試必備知識(7)- 深入理解“CPU 使用率”
- docker筆記34-容器資源需求、資源限制及HeapSterDocker筆記
- kubernetes資源均衡器Descheduler
- kubernetes排程之資源配額
- 如何用 Kubernetes 自定義資源?
- kubernetes之常用核心資源物件物件
- 深入理解 Autolayout 與列表效能 -- 背鍋的 Cassowary 和偷懶的 CPU
- 深入理解redis資料型別Redis資料型別
- 深入理解GlusterFS之資料均衡
- Oracle的過載保護-資料庫資源限制Oracle資料庫
- kubernetes之計算機資源管理計算機
- kubernetes排程之資源配額示例
- Kubernetes 節點的預留資源
- 使用 Elastic GPU 管理 Kubernetes GPU 資源ASTGPU
- 效能測試必備知識(5)- 深入理解“CPU 上下文切換”
- 深入解析Kubernetes admission webhooksWebHook
- LSTM:好理解的資源