Kubernetes 為 Pod 和容器管理資源

2022-05-21 14:57 更新

為 Pod 和容器管理資源

當(dāng)你定義 Pod 時(shí)可以選擇性地為每個(gè) 容器設(shè)定所需要的資源數(shù)量。 最常見的可設(shè)定資源是 CPU 和內(nèi)存(RAM)大??;此外還有其他類型的資源。

當(dāng)你為 Pod 中的 Container 指定了資源 請(qǐng)求 時(shí), kube-scheduler 就利用該信息決定將 Pod 調(diào)度到哪個(gè)節(jié)點(diǎn)上。 當(dāng)你還為 Container 指定了資源 約束 時(shí),kubelet 就可以確保運(yùn)行的容器不會(huì)使用超出所設(shè)約束的資源。 kubelet 還會(huì)為容器預(yù)留所 請(qǐng)求 數(shù)量的系統(tǒng)資源,供其使用。

請(qǐng)求和約束 

如果 Pod 運(yùn)行所在的節(jié)點(diǎn)具有足夠的可用資源,容器可能(且可以)使用超出對(duì)應(yīng)資源 ?request? 屬性所設(shè)置的資源量。不過,容器不可以使用超出其資源 ?limit ?屬性所設(shè)置的資源量。

例如,如果你將容器的 ?memory ?的請(qǐng)求量設(shè)置為 256 MiB,而該容器所處的 Pod 被調(diào)度到一個(gè)具有 8 GiB 內(nèi)存的節(jié)點(diǎn)上,并且該節(jié)點(diǎn)上沒有其他 Pods 運(yùn)行,那么該容器就可以嘗試使用更多的內(nèi)存。

如果你將某容器的 ?memory ?約束設(shè)置為 4 GiB,kubelet (和 容器運(yùn)行時(shí)) 就會(huì)確保該約束生效。 容器運(yùn)行時(shí)會(huì)禁止容器使用超出所設(shè)置資源約束的資源。 例如:當(dāng)容器中進(jìn)程嘗試使用超出所允許內(nèi)存量的資源時(shí),系統(tǒng)內(nèi)核會(huì)將嘗試申請(qǐng)內(nèi)存的進(jìn)程終止, 并引發(fā)內(nèi)存不足(OOM)錯(cuò)誤。

約束值可以以被動(dòng)方式來實(shí)現(xiàn)(系統(tǒng)會(huì)在發(fā)現(xiàn)違例時(shí)進(jìn)行干預(yù)),或者通過強(qiáng)制生效的方式實(shí)現(xiàn) (系統(tǒng)會(huì)避免容器用量超出約束值)。不同的容器運(yùn)行時(shí)采用不同方式來實(shí)現(xiàn)相同的限制。

Note:
如果你為某個(gè)資源指定了限制,但不指定請(qǐng)求, 并且沒有應(yīng)用準(zhǔn)入時(shí)機(jī)制為該資源設(shè)置默認(rèn)請(qǐng)求, 然后 Kubernetes 復(fù)制你所指定的限制值,將其用作資源的請(qǐng)求值。

資源類型 

CPU 和 內(nèi)存 都是 資源類型。每種資源類型具有其基本單位。 CPU 表達(dá)的是計(jì)算處理能力,其單位是 Kubernetes CPUs。 內(nèi)存的單位是字節(jié)。 對(duì)于 Linux 負(fù)載,則可以指定巨頁(yè)(Huge Page)資源。 巨頁(yè)是 Linux 特有的功能,節(jié)點(diǎn)內(nèi)核在其中分配的內(nèi)存塊比默認(rèn)頁(yè)大小大得多。

例如,在默認(rèn)頁(yè)面大小為 4KiB 的系統(tǒng)上,你可以指定約束 ?hugepages-2Mi: 80Mi?。 如果容器嘗試分配 40 個(gè) 2MiB 大小的巨頁(yè)(總共 80 MiB ),則分配請(qǐng)求會(huì)失敗。

Note:
你不能過量使用 ?hugepages- *? 資源。 這與 ?memory ?和 ?cpu ?資源不同。

CPU 和內(nèi)存統(tǒng)稱為“計(jì)算資源”,或簡(jiǎn)稱為“資源”。 計(jì)算資源的數(shù)量是可測(cè)量的,可以被請(qǐng)求、被分配、被消耗。 它們與 API 資源 不同。 API 資源(如 Pod 和 Service)是可通過 Kubernetes API 服務(wù)器讀取和修改的對(duì)象。

Pod 和 容器的資源請(qǐng)求和約束 

針對(duì)每個(gè)容器,你都可以指定其資源約束和請(qǐng)求,包括如下選項(xiàng):

  • ?spec.containers[].resources.limits.cpu ?
  • ?spec.containers[].resources.limits.memory ?
  • ?spec.containers[].resources.limits.hugepages-<size> ?
  • ?spec.containers[].resources.requests.cpu ?
  • ?spec.containers[].resources.requests.memory ?
  • ?spec.containers[].resources.requests.hugepages-<size>?

盡管你只能逐個(gè)容器地指定請(qǐng)求和限制值,考慮 Pod 的總體資源請(qǐng)求和約束也是有用的。 對(duì)特定資源而言,Pod 的資源請(qǐng)求/約束值是 Pod 中各容器對(duì)該類型資源的請(qǐng)求/約束值的總和。

Kubernetes 中的資源單位 

CPU 資源單位 

CPU 資源的約束和請(qǐng)求以 “cpu” 為單位。 在 Kubernetes 中,一個(gè) CPU 等于1 個(gè)物理 CPU 核 或者 一個(gè)虛擬核, 取決于節(jié)點(diǎn)是一臺(tái)物理主機(jī)還是運(yùn)行在某物理主機(jī)上的虛擬機(jī)。

你也可以表達(dá)帶小數(shù) CPU 的請(qǐng)求。 當(dāng)你定義一個(gè)容器,將其 ?spec.containers[].resources.requests.cpu? 設(shè)置為 0.5 時(shí), 你所請(qǐng)求的 CPU 是你請(qǐng)求 ?1.0? CPU 時(shí)的一半。 對(duì)于 CPU 資源單位,數(shù)量 表達(dá)式 ?0.1? 等價(jià)于表達(dá)式 ?100m?,可以看作 “100 millicpu”。 有些人說成是“一百毫核”,其實(shí)說的是同樣的事情。

CPU 資源總是設(shè)置為資源的絕對(duì)數(shù)量而非相對(duì)數(shù)量值。 例如,無論容器運(yùn)行在單核、雙核或者 48-核的機(jī)器上,?500m? CPU 表示的是大約相同的計(jì)算能力。

Note:
Kubernetes 不允許設(shè)置精度小于 ?1m? 的 CPU 資源。 因此,當(dāng) CPU 單位小于 ?1? 或 ?1000m? 時(shí),使用毫核的形式是有用的; 例如 ?5m? 而不是 ?0.005?。

內(nèi)存資源單位 

?memory ?的約束和請(qǐng)求以字節(jié)為單位。 你可以使用普通的證書,或者帶有以下 數(shù)量后綴 的定點(diǎn)數(shù)字來表示內(nèi)存:E、P、T、G、M、k。 你也可以使用對(duì)應(yīng)的 2 的冪數(shù):Ei、Pi、Ti、Gi、Mi、Ki。 例如,以下表達(dá)式所代表的是大致相同的值:

128974848、129e6、129M、128974848000m、123Mi

請(qǐng)注意后綴的大小寫。如果你請(qǐng)求 ?400m? 內(nèi)存,實(shí)際上請(qǐng)求的是 0.4 字節(jié)。 如果有人這樣設(shè)定資源請(qǐng)求或限制,可能他的實(shí)際想法是申請(qǐng) 400 兆字節(jié)(?400Mi?) 或者 400M 字節(jié)。

容器資源示例 

以下 Pod 有兩個(gè)容器。每個(gè)容器的請(qǐng)求為 0.25 CPU 和 64MiB(226 字節(jié))內(nèi)存, 每個(gè)容器的資源約束為 0.5 CPU 和 128MiB 內(nèi)存。 你可以認(rèn)為該 Pod 的資源請(qǐng)求為 0.5 CPU 和 128 MiB 內(nèi)存,資源限制為 1 CPU 和 256MiB 內(nèi)存。

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

    

帶資源請(qǐng)求的 Pod 如何調(diào)度 

當(dāng)你創(chuàng)建一個(gè) Pod 時(shí),Kubernetes 調(diào)度程序?qū)?nbsp;Pod 選擇一個(gè)節(jié)點(diǎn)。 每個(gè)節(jié)點(diǎn)對(duì)每種資源類型都有一個(gè)容量上限:可為 Pod 提供的 CPU 和內(nèi)存量。 調(diào)度程序確保對(duì)于每種資源類型,所調(diào)度的容器的資源請(qǐng)求的總和小于節(jié)點(diǎn)的容量。 請(qǐng)注意,盡管節(jié)點(diǎn)上的實(shí)際內(nèi)存或 CPU 資源使用量非常低,如果容量檢查失敗, 調(diào)度程序仍會(huì)拒絕在該節(jié)點(diǎn)上放置 Pod。 當(dāng)稍后節(jié)點(diǎn)上資源用量增加,例如到達(dá)請(qǐng)求率的每日峰值區(qū)間時(shí),節(jié)點(diǎn)上也不會(huì)出現(xiàn)資源不足的問題。

Kubernetes 應(yīng)用資源請(qǐng)求與約束的方式

當(dāng) kubelet 啟動(dòng) Pod 中的容器時(shí),它會(huì)將容器的 CPU 和內(nèi)存請(qǐng)求與約束信息傳遞給容器運(yùn)行時(shí)。

在 Linux 系統(tǒng)上,容器運(yùn)行時(shí)通常會(huì)配置內(nèi)核 CGroups,負(fù)責(zé)應(yīng)用并實(shí)施所定義的請(qǐng)求。

  • CPU 約束值定義的是容器可使用的 CPU 時(shí)間的硬性上限。 在每個(gè)調(diào)度周期(時(shí)間片)期間,Linux 內(nèi)核檢查是否已經(jīng)超出該約束值; 內(nèi)核會(huì)在允許該 cgroup 恢復(fù)執(zhí)行之前會(huì)等待。
  • CPU 請(qǐng)求值定義的是一個(gè)權(quán)重值。如果若干不同的容器(CGroups)需要在一個(gè)共享的系統(tǒng)上競(jìng)爭(zhēng)運(yùn)行, CPU 請(qǐng)求值大的負(fù)載會(huì)獲得比請(qǐng)求值小的負(fù)載更多的 CPU 時(shí)間。
  • 內(nèi)存請(qǐng)求值主要用于(Kubernetes)Pod 調(diào)度期間。在一個(gè)啟用了 CGroup v2 的節(jié)點(diǎn)上, 容器運(yùn)行時(shí)可能會(huì)使用內(nèi)存請(qǐng)求值作為設(shè)置 ?memory.min? 和 ?memory.low? 的提示值。
  • 內(nèi)存約束值定義的是 CGroup 的內(nèi)存約束。如果容器嘗試分配的內(nèi)存量超出約束值, 則 Linux 內(nèi)核的內(nèi)存不足處理子系統(tǒng)會(huì)被激活,并停止嘗試分配內(nèi)存的容器中的某個(gè)進(jìn)程。 如果該進(jìn)程在容器中 PID 為 1,而容器被標(biāo)記為可重新啟動(dòng),則 Kubernetes 會(huì)重新啟動(dòng)該容器。
  • Pod 或容器的內(nèi)存約束值也適用于通過內(nèi)存供應(yīng)的卷,例如 ?emptyDir ?卷。 kubelet 會(huì)跟蹤 ?tmpfs ?形式的 emptyDir 卷用量,將其作為容器的內(nèi)存用量, 而不是臨時(shí)存儲(chǔ)用量。

如果某容器內(nèi)存用量超過其內(nèi)存請(qǐng)求值并且所在節(jié)點(diǎn)內(nèi)存不足時(shí),容器所處的 Pod 可能被逐出.

每個(gè)容器可能被允許也可能不被允許使用超過其 CPU 約束的處理時(shí)間。 但是,容器運(yùn)行時(shí)不會(huì)由于 CPU 使用率過高而殺死 Pod 或容器。

監(jiān)控計(jì)算和內(nèi)存資源用量

kubelet 會(huì)將 Pod 的資源使用情況作為 Pod ?status ?的一部分來報(bào)告的。

如果為集群配置了可選的監(jiān)控工具, 則可以直接從指標(biāo) API 或者監(jiān)控工具獲得 Pod 的資源使用情況。

本地臨時(shí)存儲(chǔ) 

FEATURE STATE: Kubernetes v1.10 [beta]

節(jié)點(diǎn)通常還可以具有本地的臨時(shí)性存儲(chǔ),由本地掛接的可寫入設(shè)備或者有時(shí)也用 RAM 來提供支持。 “臨時(shí)(Ephemeral)”意味著對(duì)所存儲(chǔ)的數(shù)據(jù)不提供長(zhǎng)期可用性的保證。

Pods 通??梢允褂门R時(shí)性本地存儲(chǔ)來實(shí)現(xiàn)緩沖區(qū)、保存日志等功能。 kubelet 可以為使用本地臨時(shí)存儲(chǔ)的 Pods 提供這種存儲(chǔ)空間,允許后者使用 ?emptyDir ?類型的 卷將其掛載到容器中。

kubelet 也使用此類存儲(chǔ)來保存 節(jié)點(diǎn)層面的容器日志, 容器鏡像文件、以及運(yùn)行中容器的可寫入層。

Caution: 如果節(jié)點(diǎn)失效,存儲(chǔ)在臨時(shí)性存儲(chǔ)中的數(shù)據(jù)會(huì)丟失。 你的應(yīng)用不能對(duì)本地臨時(shí)性存儲(chǔ)的性能 SLA(例如磁盤 IOPS)作任何假定。

作為一種 beta 階段功能特性,Kubernetes 允許你跟蹤、預(yù)留和限制 Pod 可消耗的臨時(shí)性本地存儲(chǔ)數(shù)量。

本地臨時(shí)性存儲(chǔ)的配置

Kubernetes 有兩種方式支持節(jié)點(diǎn)上配置本地臨時(shí)性存儲(chǔ):

  • 單一文件系統(tǒng)
  • 采用這種配置時(shí),你會(huì)把所有類型的臨時(shí)性本地?cái)?shù)據(jù)(包括 ?emptyDir ?卷、可寫入容器層、容器鏡像、日志等)放到同一個(gè)文件系統(tǒng)中。 作為最有效的 kubelet 配置方式,這意味著該文件系統(tǒng)是專門提供給 Kubernetes (kubelet)來保存數(shù)據(jù)的。

    kubelet 也會(huì)生成 節(jié)點(diǎn)層面的容器日志, 并按臨時(shí)性本地存儲(chǔ)的方式對(duì)待之。

    kubelet 會(huì)將日志寫入到所配置的日志目錄(默認(rèn)為 ?/var/log?)下的文件中; 還會(huì)針對(duì)其他本地存儲(chǔ)的數(shù)據(jù)使用同一個(gè)基礎(chǔ)目錄(默認(rèn)為 ?/var/lib/kubelet?)。

    通常,?/var/lib/kubelet? 和 ?/var/log? 都是在系統(tǒng)的根文件系統(tǒng)中。kubelet 的設(shè)計(jì)也考慮到這一點(diǎn)。

    你的集群節(jié)點(diǎn)當(dāng)然可以包含其他的、并非用于 Kubernetes 的很多文件系統(tǒng)。

  • 雙文件系統(tǒng)
  • 你使用節(jié)點(diǎn)上的某個(gè)文件系統(tǒng)來保存運(yùn)行 Pods 時(shí)產(chǎn)生的臨時(shí)性數(shù)據(jù):日志和 ?emptyDir ?卷等。你可以使用這個(gè)文件系統(tǒng)來保存其他數(shù)據(jù)(例如:與 Kubernetes 無關(guān)的其他系統(tǒng)日志);這個(gè)文件系統(tǒng)還可以是根文件系統(tǒng)。

    kubelet 也將 節(jié)點(diǎn)層面的容器日志 寫入到第一個(gè)文件系統(tǒng)中,并按臨時(shí)性本地存儲(chǔ)的方式對(duì)待之。

    同時(shí)你使用另一個(gè)由不同邏輯存儲(chǔ)設(shè)備支持的文件系統(tǒng)。在這種配置下,你會(huì)告訴 kubelet 將容器鏡像層和可寫層保存到這第二個(gè)文件系統(tǒng)上的某個(gè)目錄中。

    第一個(gè)文件系統(tǒng)中不包含任何鏡像層和可寫層數(shù)據(jù)。

    當(dāng)然,你的集群節(jié)點(diǎn)上還可以有很多其他與 Kubernetes 沒有關(guān)聯(lián)的文件系統(tǒng)。

kubelet 能夠度量其本地存儲(chǔ)的用量。實(shí)現(xiàn)度量機(jī)制的前提是:

  • ?LocalStorageCapacityIsolation ?特性門控 被啟用(默認(rèn)狀態(tài)),并且
  • 你已經(jīng)對(duì)節(jié)點(diǎn)進(jìn)行了配置,使之使用所支持的本地臨時(shí)性儲(chǔ)存配置方式之一

如果你的節(jié)點(diǎn)配置不同于以上預(yù)期,kubelet 就無法對(duì)臨時(shí)性本地存儲(chǔ)的資源約束實(shí)施限制。

Note: kubelet 會(huì)將 ?tmpfs ?emptyDir 卷的用量當(dāng)作容器內(nèi)存用量,而不是本地臨時(shí)性存儲(chǔ)來統(tǒng)計(jì)。

為本地臨時(shí)性存儲(chǔ)設(shè)置請(qǐng)求和約束值

你可以使用 ?ephemeral-storage? 來管理本地臨時(shí)性存儲(chǔ)。 Pod 中的每個(gè)容器可以設(shè)置以下屬性:

  • ?spec.containers[].resources.limits.ephemeral-storage ?
  • ?spec.containers[].resources.requests.ephemeral-storage ?

?ephemeral-storage? 的請(qǐng)求和約束值是按量綱計(jì)量的。你可以使用一般整數(shù)或者定點(diǎn)數(shù)字 加上下面的后綴來表達(dá)存儲(chǔ)量:E、P、T、G、M、K。 你也可以使用對(duì)應(yīng)的 2 的冪級(jí)數(shù)來表達(dá):Ei、Pi、Ti、Gi、Mi、Ki。 例如,下面的表達(dá)式所表達(dá)的大致是同一個(gè)值:

  • ?128974848 ?
  • ?129e6 ?
  • ?129M ?
  • ?123Mi?

在下面的例子中,Pod 包含兩個(gè)容器。每個(gè)容器請(qǐng)求 2 GiB 大小的本地臨時(shí)性存儲(chǔ)。 每個(gè)容器都設(shè)置了 4 GiB 作為其本地臨時(shí)性存儲(chǔ)的約束值。 因此,整個(gè) Pod 的本地臨時(shí)性存儲(chǔ)請(qǐng)求是 4 GiB,且其本地臨時(shí)性存儲(chǔ)的約束為 8 GiB。

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
    volumeMounts:
    - name: ephemeral
      mountPath: "/tmp"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
    volumeMounts:
    - name: ephemeral
      mountPath: "/tmp"
  volumes:
    - name: ephemeral
      emptyDir: {}

帶臨時(shí)性存儲(chǔ)的 Pods 的調(diào)度行為

當(dāng)你創(chuàng)建一個(gè) Pod 時(shí),Kubernetes 調(diào)度器會(huì)為 Pod 選擇一個(gè)節(jié)點(diǎn)來運(yùn)行之。 每個(gè)節(jié)點(diǎn)都有一個(gè)本地臨時(shí)性存儲(chǔ)的上限,是其可提供給 Pods 使用的總量。

調(diào)度器會(huì)確保所調(diào)度的容器的資源請(qǐng)求總和不會(huì)超出節(jié)點(diǎn)的資源容量。

臨時(shí)性存儲(chǔ)消耗的管理

如果 kubelet 將本地臨時(shí)性存儲(chǔ)作為資源來管理,則 kubelet 會(huì)度量以下各處的存儲(chǔ)用量:

  • ?emptyDir ?卷,除了 tmpfs ?emptyDir ?卷
  • 保存節(jié)點(diǎn)層面日志的目錄
  • 可寫入的容器鏡像層

如果某 Pod 的臨時(shí)存儲(chǔ)用量超出了你所允許的范圍,kubelet 會(huì)向其發(fā)出逐出(eviction)信號(hào),觸發(fā)該 Pod 被逐出所在節(jié)點(diǎn)。

就容器層面的隔離而言,如果某容器的可寫入鏡像層和日志用量超出其存儲(chǔ)約束, kubelet 也會(huì)將所在的 Pod 標(biāo)記為逐出候選。

就 Pod 層面的隔離而言,kubelet 會(huì)將 Pod 中所有容器的約束值相加,得到 Pod 存儲(chǔ)約束的總值。如果所有容器的本地臨時(shí)性存儲(chǔ)用量總和加上 Pod 的 ?emptyDir ?卷的用量超出 Pod 存儲(chǔ)約束值,kubelet 也會(huì)將該 Pod 標(biāo)記為逐出候選。

Caution:
如果 kubelet 沒有度量本地臨時(shí)性存儲(chǔ)的用量,即使 Pod 的本地存儲(chǔ)用量超出其約束值也不會(huì)被逐出。
不過,如果用于可寫入容器鏡像層、節(jié)點(diǎn)層面日志或者 ?emptyDir ?卷的文件系統(tǒng)中可用空間太少, 節(jié)點(diǎn)會(huì)為自身設(shè)置本地存儲(chǔ)不足的污點(diǎn) 標(biāo)簽。 這一污點(diǎn)會(huì)觸發(fā)對(duì)那些無法容忍該污點(diǎn)的 Pods 的逐出操作。

kubelet 支持使用不同方式來度量 Pod 的存儲(chǔ)用量:

  • 周期性掃描
  • kubelet 按預(yù)定周期執(zhí)行掃描操作,檢查 ?emptyDir ?卷、容器日志目錄以及可寫入容器鏡像層。

    這一掃描會(huì)度量存儲(chǔ)空間用量。

    Note:
    在這種模式下,kubelet 并不檢查已刪除文件所對(duì)應(yīng)的、仍處于打開狀態(tài)的文件描述符。
    如果你(或者容器)在 ?emptyDir ?卷中創(chuàng)建了一個(gè)文件,寫入一些內(nèi)容之后再次打開 該文件并執(zhí)行了刪除操作,所刪除文件對(duì)應(yīng)的 inode 仍然存在,直到你關(guān)閉該文件為止。 kubelet 不會(huì)將該文件所占用的空間視為已使用空間。
  • 文件系統(tǒng)項(xiàng)目配額
  • FEATURE STATE: Kubernetes v1.15 [alpha]

    項(xiàng)目配額(Project Quota)是一個(gè)操作系統(tǒng)層的功能特性,用來管理文件系統(tǒng)中的存儲(chǔ)用量。 在 Kubernetes 中,你可以啟用項(xiàng)目配額以監(jiān)視存儲(chǔ)用量。 你需要確保節(jié)點(diǎn)上為 ?emptyDir ?提供存儲(chǔ)的文件系統(tǒng)支持項(xiàng)目配額。 例如,XFS 和 ext4fs 文件系統(tǒng)都支持項(xiàng)目配額。

    Note: 項(xiàng)目配額可以幫你監(jiān)視存儲(chǔ)用量,但無法對(duì)存儲(chǔ)約束執(zhí)行限制。

    Kubernetes 所使用的項(xiàng)目 ID 始于 ?1048576?。 所使用的 IDs 會(huì)注冊(cè)在 ?/etc/projects? 和 ?/etc/projid? 文件中。 如果該范圍中的項(xiàng)目 ID 已經(jīng)在系統(tǒng)中被用于其他目的,則已占用的項(xiàng)目 IDs 也必須注冊(cè)到 ?/etc/projects? 和 ?/etc/projid? 中,這樣 Kubernetes 才不會(huì)使用它們。

    配額方式與目錄掃描方式相比速度更快,結(jié)果更精確。當(dāng)某個(gè)目錄被分配給某個(gè)項(xiàng)目時(shí), 該目錄下所創(chuàng)建的所有文件都屬于該項(xiàng)目,內(nèi)核只需要跟蹤該項(xiàng)目中的文件所使用的存儲(chǔ)塊個(gè)數(shù)。 如果某文件被創(chuàng)建后又被刪除,但對(duì)應(yīng)文件描述符仍處于打開狀態(tài), 該文件會(huì)繼續(xù)耗用存儲(chǔ)空間。配額跟蹤技術(shù)能夠精確第記錄對(duì)應(yīng)存儲(chǔ)空間的狀態(tài), 而目錄掃描方式會(huì)忽略被刪除文件所占用的空間。

    如果你希望使用項(xiàng)目配額,你需要:

    • 在 kubelet 配置中使用 ?featureGates ?字段 或者使用 ?--feature-gates? 命令行參數(shù) 啟用 ?LocalStorageCapacityIsolationFSQuotaMonitoring=true? 特性門控 。
    • 確保根文件系統(tǒng)(或者可選的運(yùn)行時(shí)文件系統(tǒng))啟用了項(xiàng)目配額。所有 XFS 文件系統(tǒng)都支持項(xiàng)目配額。 對(duì) extf 文件系統(tǒng)而言,你需要在文件系統(tǒng)尚未被掛載時(shí)啟用項(xiàng)目配額跟蹤特性:
    • # 對(duì) ext4 而言,在 /dev/block-device 尚未被掛載時(shí)執(zhí)行下面操作
      sudo tune2fs -O project -Q prjquota /dev/block-device
    • 確保根文件系統(tǒng)(或者可選的運(yùn)行時(shí)文件系統(tǒng))在掛載時(shí)項(xiàng)目配額特性是被啟用了的。 對(duì)于 XFS 和 ext4fs 而言,對(duì)應(yīng)的掛載選項(xiàng)稱作 ?prjquota?。

擴(kuò)展資源(Extended Resources) 

擴(kuò)展資源是 ?kubernetes.io? 域名之外的標(biāo)準(zhǔn)資源名稱。 它們使得集群管理員能夠頒布非 Kubernetes 內(nèi)置資源,而用戶可以使用他們。

使用擴(kuò)展資源需要兩個(gè)步驟。首先,集群管理員必須頒布擴(kuò)展資源。 其次,用戶必須在 Pod 中請(qǐng)求擴(kuò)展資源。

管理擴(kuò)展資源 

節(jié)點(diǎn)級(jí)擴(kuò)展資源 

節(jié)點(diǎn)級(jí)擴(kuò)展資源綁定到節(jié)點(diǎn)。

其他資源 

為了頒布新的節(jié)點(diǎn)級(jí)擴(kuò)展資源,集群操作員可以向 API 服務(wù)器提交 ?PATCH ?HTTP 請(qǐng)求, 以在集群中節(jié)點(diǎn)的 ?status.capacity? 中為其配置可用數(shù)量。 完成此操作后,節(jié)點(diǎn)的 ?status.capacity? 字段中將包含新資源。 kubelet 會(huì)異步地對(duì) ?status.allocatable? 字段執(zhí)行自動(dòng)更新操作,使之包含新資源。

由于調(diào)度器在評(píng)估 Pod 是否適合在某節(jié)點(diǎn)上執(zhí)行時(shí)會(huì)使用節(jié)點(diǎn)的 ?status.allocatable? 值, 調(diào)度器只會(huì)考慮異步更新之后的新值。 在更新節(jié)點(diǎn)容量使之包含新資源之后和請(qǐng)求該資源的第一個(gè) Pod 被調(diào)度到該節(jié)點(diǎn)之間, 可能會(huì)有短暫的延遲。

示例:

這是一個(gè)示例,顯示了如何使用 ?curl ?構(gòu)造 HTTP 請(qǐng)求,公告主節(jié)點(diǎn)為 ?k8s-master? 的節(jié)點(diǎn) ?k8s-node-1? 上存在五個(gè) ?example.com/foo? 資源。

curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \
http://k8s-master:8080/api/v1/nodes/k8s-node-1/status

Note: 在前面的請(qǐng)求中,?~1? 是在 patch 路徑中對(duì)字符 ?/? 的編碼。 JSON-Patch 中的操作路徑的值被視為 JSON-Pointer 類型。 有關(guān)更多詳細(xì)信息,請(qǐng)參見 IETF RFC 6901 第 3 節(jié)。

集群層面的擴(kuò)展資源 

集群層面的擴(kuò)展資源并不綁定到具體節(jié)點(diǎn)。 它們通常由調(diào)度器擴(kuò)展程序(Scheduler Extenders)管理,這些程序處理資源消耗和資源配額。

你可以在調(diào)度器策略配置 中指定由調(diào)度器擴(kuò)展程序處理的擴(kuò)展資源。

示例:

下面的調(diào)度器策略配置標(biāo)明集群層擴(kuò)展資源 "example.com/foo" 由調(diào)度器擴(kuò)展程序處理。

  • 僅當(dāng) Pod 請(qǐng)求 "example.com/foo" 時(shí),調(diào)度器才會(huì)將 Pod 發(fā)送到調(diào)度器擴(kuò)展程序。
  • ?ignoredByScheduler ?字段指定調(diào)度器不要在其 ?PodFitsResources ?斷言中檢查 "example.com/foo" 資源。

{
  "kind": "Policy",
  "apiVersion": "v1",
  "extenders": [
    {
      "urlPrefix":"<extender-endpoint>",
      "bindVerb": "bind",
      "managedResources": [
        {
          "name": "example.com/foo",
          "ignoredByScheduler": true
        }
      ]
    }
  ]
}

使用擴(kuò)展資源 

就像 CPU 和內(nèi)存一樣,用戶可以在 Pod 的規(guī)約中使用擴(kuò)展資源。 調(diào)度器負(fù)責(zé)資源的核算,確保同時(shí)分配給 Pod 的資源總量不會(huì)超過可用數(shù)量。

Note: 擴(kuò)展資源取代了非透明整數(shù)資源(Opaque Integer Resources,OIR)。 用戶可以使用 ?kubernetes.io? (保留)以外的任何域名前綴。

要在 Pod 中使用擴(kuò)展資源,請(qǐng)?jiān)谌萜饕?guī)范的 ?spec.containers[].resources.limits? 映射中包含資源名稱作為鍵。

Note: 擴(kuò)展資源不能過量使用,因此如果容器規(guī)范中同時(shí)存在請(qǐng)求和約束,則它們的取值必須相同。

僅當(dāng)所有資源請(qǐng)求(包括 CPU、內(nèi)存和任何擴(kuò)展資源)都被滿足時(shí),Pod 才能被調(diào)度。 在資源請(qǐng)求無法滿足時(shí),Pod 會(huì)保持在 ?PENDING ?狀態(tài)。

示例:

下面的 Pod 請(qǐng)求 2 個(gè) CPU 和 1 個(gè) "example.com/foo"(擴(kuò)展資源)。

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: myimage
    resources:
      requests:
        cpu: 2
        example.com/foo: 1
      limits:
        example.com/foo: 1

PID 限制 

進(jìn)程 ID(PID)限制允許對(duì) kubelet 進(jìn)行配置,以限制給定 Pod 可以消耗的 PID 數(shù)量。

疑難解答

我的 Pod 處于懸決狀態(tài)且事件信息顯示 FailedScheduling

如果調(diào)度器找不到該 Pod 可以匹配的任何節(jié)點(diǎn),則該 Pod 將保持未被調(diào)度狀態(tài), 直到找到一個(gè)可以被調(diào)度到的位置。每當(dāng)調(diào)度器找不到 Pod 可以調(diào)度的地方時(shí), 會(huì)產(chǎn)生一個(gè) Event。 你可以使用 ?kubectl ?來查看 Pod 的事件;例如:

kubectl describe pod frontend | grep -A 9999999999 Events
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  23s   default-scheduler  0/42 nodes available: insufficient cpu

在上述示例中,由于節(jié)點(diǎn)上的 CPU 資源不足,名為 “frontend” 的 Pod 無法被調(diào)度。 由于內(nèi)存不足(PodExceedsFreeMemory)而導(dǎo)致失敗時(shí),也有類似的錯(cuò)誤消息。 一般來說,如果 Pod 處于懸決狀態(tài)且有這種類型的消息時(shí),你可以嘗試如下幾件事情:

  • 向集群添加更多節(jié)點(diǎn)。
  • 終止不需要的 Pod,為懸決的 Pod 騰出空間。
  • 檢查 Pod 所需的資源是否超出所有節(jié)點(diǎn)的資源容量。例如,如果所有節(jié)點(diǎn)的容量都是?cpu:1?, 那么一個(gè)請(qǐng)求為 ?cpu: 1.1? 的 Pod 永遠(yuǎn)不會(huì)被調(diào)度。
  • 檢查節(jié)點(diǎn)上的污點(diǎn)設(shè)置。如果集群中節(jié)點(diǎn)上存在污點(diǎn),而新的 Pod 不能容忍污點(diǎn), 調(diào)度器只會(huì)考慮將 Pod 調(diào)度到不帶有該污點(diǎn)的節(jié)點(diǎn)上。

你可以使用 ?kubectl describe nodes? 命令檢查節(jié)點(diǎn)容量和已分配的資源數(shù)量。 例如:

kubectl describe nodes e2e-test-node-pool-4lw4
Name:            e2e-test-node-pool-4lw4
[ ... 這里忽略了若干行以便閱讀 ...]
Capacity:
 cpu:                               2
 memory:                            7679792Ki
 pods:                              110
Allocatable:
 cpu:                               1800m
 memory:                            7474992Ki
 pods:                              110
[ ... 這里忽略了若干行以便閱讀 ...]
Non-terminated Pods:        (5 in total)
  Namespace    Name                                  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------    ----                                  ------------  ----------  ---------------  -------------
  kube-system  fluentd-gcp-v1.38-28bv1               100m (5%)     0 (0%)      200Mi (2%)       200Mi (2%)
  kube-system  kube-dns-3297075139-61lj3             260m (13%)    0 (0%)      100Mi (1%)       170Mi (2%)
  kube-system  kube-proxy-e2e-test-...               100m (5%)     0 (0%)      0 (0%)           0 (0%)
  kube-system  monitoring-influxdb-grafana-v4-z1m12  200m (10%)    200m (10%)  600Mi (8%)       600Mi (8%)
  kube-system  node-problem-detector-v0.1-fj7m3      20m (1%)      200m (10%)  20Mi (0%)        100Mi (1%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests    CPU Limits    Memory Requests    Memory Limits
  ------------    ----------    ---------------    -------------
  680m (34%)      400m (20%)    920Mi (12%)        1070Mi (14%)

在上面的輸出中,你可以看到如果 Pod 請(qǐng)求超過 1120m CPU 或者 6.23Gi 內(nèi)存,節(jié)點(diǎn)將無法滿足。

通過查看 "Pods" 部分,你將看到哪些 Pod 占用了節(jié)點(diǎn)上的資源。

Pods 可用的資源量低于節(jié)點(diǎn)的資源總量,因?yàn)橄到y(tǒng)守護(hù)進(jìn)程也會(huì)使用一部分可用資源。 在 Kubernetes API 中,每個(gè) Node 都有一個(gè) ?.status.allocatable? 字段。

字段 ?.status.allocatable? 描述節(jié)點(diǎn)上可以用于 Pod 的資源總量(例如:15 個(gè)虛擬 CPU、7538 MiB 內(nèi)存)。

你可以配置資源配額功能特性以限制每個(gè)名字空間可以使用的資源總量。 當(dāng)某名字空間中存在 ResourceQuota 時(shí),Kubernetes 會(huì)在該名字空間中的對(duì)象強(qiáng)制實(shí)施配額。 例如,如果你為不同的團(tuán)隊(duì)分配名字空間,你可以為這些名字空間添加 ResourceQuota。 設(shè)置資源配額有助于防止一個(gè)團(tuán)隊(duì)占用太多資源,以至于這種占用會(huì)影響其他團(tuán)隊(duì)。

你還需要考慮為這些名字空間設(shè)置授權(quán)訪問: 為名字空間提供 全部 的寫權(quán)限時(shí),具有合適權(quán)限的人可能刪除所有資源, 包括所配置的 ResourceQuota。

我的容器被終止了

你的容器可能因?yàn)橘Y源緊張而被終止。要查看容器是否因?yàn)橛龅劫Y源限制而被殺死, 請(qǐng)針對(duì)相關(guān)的 Pod 執(zhí)行 ?kubectl describe pod?:

kubectl describe pod simmemleak-hra99

輸出類似于:

Name:                           simmemleak-hra99
Namespace:                      default
Image(s):                       saadali/simmemleak
Node:                           kubernetes-node-tf0f/10.240.216.66
Labels:                         name=simmemleak
Status:                         Running
Reason:
Message:
IP:                             10.244.2.75
Containers:
  simmemleak:
    Image:  saadali/simmemleak
    Limits:
      cpu:                      100m
      memory:                   50Mi
    State:                      Running
      Started:                  Tue, 07 Jul 2015 12:54:41 -0700
    Last Termination State:     Terminated
      Exit Code:                1
      Started:                  Fri, 07 Jul 2015 12:54:30 -0700
      Finished:                 Fri, 07 Jul 2015 12:54:33 -0700
    Ready:                      False
    Restart Count:              5
Conditions:
  Type      Status
  Ready     False
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  42s   default-scheduler  Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
  Normal  Pulled     41s   kubelet            Container image "saadali/simmemleak:latest" already present on machine
  Normal  Created    41s   kubelet            Created container simmemleak
  Normal  Started    40s   kubelet            Started container simmemleak
  Normal  Killing    32s   kubelet            Killing container with id ead3fb35-5cf5-44ed-9ae1-488115be66c6: Need to kill Pod

在上面的例子中,?Restart Count: 5? 意味著 Pod 中的 ?simmemleak ?容器被終止并且(到目前為止)重啟了五次。 原因 ?OOMKilled ?顯示容器嘗試使用超出其限制的內(nèi)存量。

你接下來要做的或許是檢查應(yīng)用代碼,看看是否存在內(nèi)存泄露。 如果你發(fā)現(xiàn)應(yīng)用的行為與你所預(yù)期的相同,則可以考慮為該容器設(shè)置一個(gè)更高的內(nèi)存約束 (也可能需要設(shè)置請(qǐng)求值)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)