如何理解Kubernetes資源限制CPU

這篇文章將為大家詳細(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 資源限制。

1. 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 值。

2. 默認(rèn)限制


通過上文的討論大家已經(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)

成都app開發(fā)公司