本篇文章將會介紹 k8s 中 PodSpec 最常見的幾個與 container 本身有關的設定,特別是 Resources 以及 Probes。。在上一篇中最後提到 Pod 的基本信息,快速地複習一下幾個重點:
這裡我們來簡單的看看 Pod 的常用設定:
這裡只會提到最常見的幾個設定,並以 k8s@1.17
為主,可以參考 Pod API Reference 來看設定細項。
<template>
<div>
Some default layout shared across all pages
<slot />
</div>
</template>
apiVersion: v1
kind: Pod
metadata:
labels:
app: echoserver
name: echoserver
spec:
initContainers:
- name: init
image: busybox:1.28
command:
- "sh"
- "-c"
- 'echo "preparing application"'
containers:
- name: server
image: ewocker/slim-echoserver:1.0.0
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: "100m"
memory: "50Mi"
requests:
cpu: "100m"
memory: "50Mi"
ports:
- name: service-port
containerPort: 8080
readinessProbe:
httpGet:
path: /healthy
port: service-port
initialDelaySeconds: 5
failureThreshold: 2
periodSeconds: 10
livenessProbe:
httpGet:
path: /ready
port: service-port
initialDelaySeconds: 5
failureThreshold: 2
periodSeconds: 10
restartPolicy: Always
terminationGracePeriodSeconds: 5
首先是 containers
和 initContainers
,一個 Pod 可以包含多個容器,而在 k8s 中還將其分為兩種,分別是 主容器運行前先運行的 **initContainers**
和 包含主容器的 containers
。
initContainers
時,會依序逐個運行。常見的 initContainer
有像是用 nslookup
確保 DNS reachability,或是預先將 configuration 處理成所需的格式等等。(這裡因為演示需要,就隨便 echo 一串字)initContainer
運行結束後才開始的,如果有多個 containers
時,所有 containers
會同時運行。接著來看看 ContainerSpec,這裡使用的幾個常見的 field 是:
request
- 是容器所請求的資源,kube-scheduler
會在創建 Pod 時會根據所有 container request 的資源來決定該 Pod 將發派到哪一個 Node 上,被發配到的 Node 必須有足夠的資源。limit
- 是限制容器不能超過的資源用量,如果 cpu 超過 limit 的話 container 會被 throttle (每當超過時會被壓抑回限制的用量)。如果 memory 超標的話則是會被 OOMKill (Out of Memory Kill,該容器會因為內存不足而被刪掉),這種狀況下在 k8s 中 container 等於是被重啟了。resources 的設定非常重要,它會被用於確保 Pod 至少保有屬於自己 request 的資源。Application owner 必須要了解怎麼樣的資源配置對自己的 app 是最有效率的,並且與以後會提到的自適應擴縮 autoscaling 有關。(下面有更多信息)kubelet
會根據 livenessProbe 的定義來檢查 container 是否健康的在運行,如果 livenessProbe 發生錯誤則 container 會被是於 不健康 (Unhealthy),kubelet
會重啟該 container。上面是以最常見的 httpGet
為例子,如果 container 沒辦法準時回應 /healthy
HTTP GET 的要求或發生錯誤等等,則會被視為 Unhealthy 並且被重啟。(除了 httpGet
以外還有其他方法,請參考 Probe)kubelet
會根據 readinessProbe 的定義來檢查 container 是否處於準備好的狀態,當readinessProbe 發生錯誤時 container 並不會像 livenessProbe Failure 一樣被重啟,但 container 會被當作處於 未就緒 (Unready) 的狀態,並且如果是 Service 所選擇的 Pod 時則會被剔除於 Service 的 LoadBalancing 選擇中 。(以後說到 Service 時會在多加說明)舉個常見 readinessProbe 的用法,像是 container 需要構通一個 database,但是 database 卻因為某些原因而無法架設連結,這時候 container 雖然是_健康的狀態 (Healthy)_ 卻也是 未就緒狀態 (Unready)。(下面有更多信息)了解自己 container 所需的資源是非常重要的一件事,除了在自適應擴縮(autoscaling)上有極大的影響外, 在 k8s 中還有非常重要的意義,那就是 Pod 的 QoS 屬性。
💡 k8s 說到底就是多個 Node (機器/伺服器) 和再一起共同的集合體。在機器的資源不夠用的時候,k8s 會根據 Pod 的重要性來依次將 Pod 剔除 (eviction),直到系統有足夠的資源使用。Pod 的重要性首先是看 PriorityClass,接著就是看 QoS。(以後會在提到 PriorityClass)
首先要在細說下當 container 使用超過 Request 和 Limit 時會發生什麼事:
CPU exceeds request
,當 CPU 使用超過要求的資源時,無論是否有設置 CPU limit Pod 可以使用系統中多餘的 CPU。CPU exceeds limit
,當 CPU 使用超過限制的資源時, Pod 中的 container 會被壓抑 (throttling)。Memory exceeds request
,當 Memory 使用超過要求時,- 如果 Pod 有設置 Memory limit,Pod 中的 container 可以使用系統中多餘的 Memory。但如果 Pod 沒有設置 Memory limit,在系統需要內存資源時 Pod 中的 container 可能會被刪除 (OOM Killed,Out of Memory Kill)。Memory exceeds limit
,當 Memory 使用超過限制時 Pod 中的 container 會被刪除 (OOM Killed,Out of Memory Kill)。💡 CPU - Compressible (可壓縮)
💡 Memory - Incompressible (不可壓縮)
QoS (Quality of Service) 中文直翻服務質量,用於表示 Pod 的可變動性。QoS 有三個值,分別是:
Guaranteed - High Priority
(高重要性,不容易被刪除的 Pod) 當所有 container 中 resource 的 request 和 limit 相同時,Pod 的 QoS 將會是 Guaranteed。簡單來說就是使用者保證自己的 Pod 不會使用超過 resource 的定義。Burstable - Medium Priority
(中等重要性,有可能被刪除的 Pod) 當條件不符合 Guaranteed 時,並且 Pod 中有任一 container 有設置 resource request 時,Pod 的 QoS 將會是 Burstable。BestEffort - Low Priority
(低重要性,容易被刪除的 Pod) 當 Pod 中沒有任一 container 有設置 resource request 時,Pod 的 QoS 將會是 Burstable。所以 QoS 究竟代表什麼呢?簡單來說如果今天有兩個正在運行的 Pod,分別有 QoS Guaranteed 和 Burstable,在系統資源不夠用時,k8s 會首先剔除 QoS 為 Burstable 的 Pod 來緩解系統的壓力。
❗️ 創建新的 Pod 時,當 k8s cluster 中資源不夠用時,即便有較低的 QoS Pod 存在,k8s 也不會因為新要創建的 Pod 有較高的 QoS 而剔除較低 QoS 的 Pod。這種為了 High Priority 而剔除 Low Priority 的型態叫做 Preemption,是屬於 PriorityClass 相關的內容,和 QoS 並無關連。
QoS 只有在系統資源不足時必須剔除 Pod 時才會被考慮進去,如果你使用的 cluster 有高手在後面細心關照,並且有設置 kubelet reservation 及 system reservation,則這種事情將會很少發生。
因為 livenessProbe 及 readinessProbe 是非常重要的概念,所以這裡細說一下例子中的幾個設定 initialDelaySeconds、periodSeconds、failureThreshold:
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 2
以上面的設定來說就是,container 創建好 5 秒後開始 liveness/readiness Probe,每 10 秒一次,不能連續失敗兩次。
除了上面的設定以外,Pod 還有許多其他的設定,這裡只介紹了幾個創建 Pod 時必須要知道的設定,特別是 livenessProbe/readinessProbe 以及 resource。一般來說使用者不會自己創建 Pod,而是會在其它 k8s
工作附載資源 (Workload Resource) 中透過定義 PodTemplate 來創建 Pod。接下來幾個章節會慢慢介紹幾個常見的 Workloads。