Kubernetes 提供 Taints 和 Tolerations 機制,用於更精細地控制 Pod 排程。Taints 標記節點狀態,例如硬體故障或特定用途,而 Tolerations 則允許 Pod 忽略這些標記並在 Taint 節點上執行。本文將探討如何設定 Taints 和 Tolerations,並探討它們與 Node Affinity 的差異。藉由瞭解這些機制,可以更有效地管理節點資源並確保應用程式穩定執行。這對於維護高用性和彈性 Kubernetes 叢集至關重要,尤其在需要隔離特定工作負載或處理硬體維護的情況下。
Kubernetes 中的 Pod 排程進階技巧:Taints 與 Tolerations
在 Kubernetes 中,排程 Pod 至適當的 Node 是至關重要的任務。除了使用 Node Affinity 之外,Kubernetes 還提供了 Taints 和 Tolerations 機制來控制 Pod 的排程。本篇文章將探討 Taints 和 Tolerations 的使用方法及其與 Node Affinity 的差異。
使用 Taints 和 Tolerations
Taints 和 Tolerations 是 Kubernetes 中用於控制 Pod 排程的另一種機制。Taints 是對 Node 的標記,用於表示該 Node 具有某些限制或問題,而 Tolerations 則是對 Pod 的設定,允許 Pod 在具有特定 Taints 的 Node 上執行。
Taints 的結構
Taints 的結構為 <key>=<value>:<effect>,其中 <key> 和 <value> 用於識別 Taint,而 <effect> 則定義了 Taint 的效果。常見的 <effect> 包括:
NoSchedule:kube-scheduler 將不會排程 Pod 至此 Node。PreferNoSchedule:kube-scheduler 將盡量避免排程 Pod 至此 Node。NoExecute:kube-scheduler 將不會排程 Pod 至此 Node,並且會驅逐(終止並重新排程)正在執行的 Pod。
Taints 的應用
要為 Node 新增 Taint,可以使用以下命令:
$ kubectl taint node <nodeName> <key>=<value>:<effect>
例如,要為 Node minikube 新增一個 Taint,key 為 machine-check-exception,value 為 memory,effect 為 NoExecute,可以使用以下命令:
$ kubectl taint node minikube machine-check-exception=memory:NoExecute
要移除 Taint,可以使用以下命令:
$ kubectl taint node minikube machine-check-exception=memory:NoExecute-
Tolerations 的設定
要在 Pod 中設定 Tolerations,需要在 Pod 的 YAML 設定檔中新增 tolerations 欄位。例如:
apiVersion: v1
kind: Pod
metadata:
name: nginx-app
spec:
tolerations:
- key: "machine-check-exception"
operator: "Equal"
value: "memory"
effect: "NoExecute"
與 Node Affinity 的差異
Taints 和 Tolerations 與 Node Affinity 都可以用於控制 Pod 的排程,但它們有不同的使用場景和效果。Node Affinity 用於定義 Pod 對 Node 的偏好,而 Taints 和 Tolerations 則用於定義 Node 對 Pod 的限制。
Taints 和 Tolerations 的優勢在於,它們可以實作更細粒度的控制,例如,可以使用 NoExecute effect 來驅逐正在執行的 Pod。
內容解密:
本章節詳細介紹了 Kubernetes 中的 Taints 和 Tolerations 機制,包括其結構、應用和與 Node Affinity 的差異。透過瞭解 Taints 和 Tolerations 的使用方法,可以更好地控制 Pod 的排程和實作更靈活的資源管理。Taints 和 Tolerations 的主要優點在於,它們可以實作更細粒度的控制和更靈活的排程策略,從而提高資源利用率和應用效能。
Taints 和 Tolerations 的工作流程
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title 與 Node Affinity 的差異
rectangle "Tolerations" as node1
rectangle "Taints" as node2
rectangle "排程" as node3
rectangle "驅逐" as node4
node1 --> node2
node2 --> node3
node3 --> node4
@enduml此圖示展示了 Taints 和 Tolerations 的工作流程。當 Pod 具有與 Node 上的 Taint 相匹配的 Toleration 時,kube-scheduler 將排程 Pod 至該 Node。否則,kube-scheduler 將避免排程 Pod 至該 Node,或驅逐正在執行的 Pod。
內容解密:
此 Plantuml 圖表展示了 Taints 和 Tolerations 的工作流程,說明瞭 kube-scheduler 如何根據 Taints 和 Tolerations 排程或驅逐 Pod。這有助於讀者更好地理解 Taints 和 Tolerations 的機制和作用。圖表清晰地呈現了 Pod、Node、kube-scheduler 之間的互動關係,使得讀者能夠更容易地理解相關概念。
高階 Pod 排程技術:汙點(Taint)與容忍度(Toleration)
在 Kubernetes 叢集中,Pod 的排程是一個複雜的過程,涉及多種因素,如節點的資源可用性、Pod 的需求以及叢集的管理策略。其中,汙點(Taint)和容忍度(Toleration)是兩個重要的機制,用於控制 Pod 在節點上的排程和執行。
汙點(Taint)與容忍度(Toleration)的基本概念
汙點是一種標記,可以應用於節點上,用於指示該節點具有某些特殊屬性或限制。當節點被標記為汙點時,Kubernetes 的排程器(kube-scheduler)將不會把 Pod 排程到該節點上,除非該 Pod 具有對應的容忍度。
容忍度是 Pod 對汙點的容忍程度的定義。透過在 Pod 的規格中定義容忍度,可以使 Pod 忽略某些汙點,從而被排程到具有該汙點的節點上。
汙點的結構和型別
汙點的結構通常由三個部分組成:鍵(key)、值(value)和效果(effect)。效果可以是以下三種型別之一:
NoSchedule:表示 Kubernetes 不會將 Pod 排程到具有該汙點的節點上。PreferNoSchedule:表示 Kubernetes 盡量避免將 Pod 排程到具有該汙點的節點上,但不是絕對不會排程。NoExecute:表示 Kubernetes 不僅不會將 Pod 排程到具有該汙點的節點上,而且如果該節點已經執行了 Pod,則會將其驅逐。
容忍度的定義和作用
容忍度的定義是在 Pod 的規格中的 .spec.tolerations 欄位下進行的。一個典型的容忍度定義如下所示:
tolerations:
- key: machine-check-exception
operator: Equal
value: memory
effect: NoExecute
tolerationSeconds: 60
在這個例子中,Pod 定義了一個對 machine-check-exception=memory:NoExecute 汙點的容忍度。這意味著該 Pod 可以被排程到具有該汙點的節點上,並且在該汙點被觸發時,可以容忍該汙點 60 秒後再被驅逐。
內容解密:
key和value:指定了汙點的鍵和值。在這個例子中,鍵是machine-check-exception,值是memory。operator:指定了比較運算子。在這個例子中,使用的是Equal,表示鍵和值必須完全匹配。effect:指定了汙點的效果。在這個例子中,效果是NoExecute,表示如果節點具有該汙點,則 Pod 將被驅逐。tolerationSeconds:指定了 Pod 可以容忍該汙點的時間長度。在這個例子中,Pod 可以容忍該汙點 60 秒後再被驅逐。
實踐:使用汙點和容忍度控制 Pod 排程
假設我們有一個名為 nginx-app 的 Deployment,其 Pod 目前正在 minikube 節點上執行。現在,我們想要將 minikube 節點標記為具有 machine-check-exception=memory:NoExecute 汙點,以測試 Pod 的排程行為。
首先,我們對 minikube 節點應用汙點:
$ kubectl taint node minikube machine-check-exception=memory:NoExecute
node/minikube tainted
接著,我們檢查 Pod 的狀態和節點分配:
$ kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName"
NAME STATUS NODE
nginx-app-7d8c65464c-5j69n Pending <none>
nginx-app-7d8c65464c-c8j58 Pending <none>
nginx-app-7d8c65464c-cnczc Pending <none>
nginx-app-7d8c65464c-drpdh Pending <none>
nginx-app-7d8c65464c-xss9b Pending <none>
可以看到,所有 Pod 都處於 Pending 狀態,因為沒有節點可以滿足其排程需求。
接下來,我們編輯 nginx-deployment.yaml 檔案,移除原有的 Node affinity 規則,並新增對 machine-check-exception=memory:NoExecute 汙點的容忍度定義,如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
...
template:
...
spec:
tolerations:
- key: machine-check-exception
operator: Equal
value: memory
effect: NoExecute
tolerationSeconds: 60
然後,我們應用該組態到叢集中,並檢查 Pod 的狀態和節點分配:
$ kubectl apply -f 04_taints/nginx-deployment.yaml
$ kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName"
NAME STATUS NODE
nginx-app-84d755f746-4zkjd Running minikube
nginx-app-84d755f746-58qmh Running minikube-m02
nginx-app-84d755f746-5h5vk Running minikube-m03
nginx-app-84d755f746-psmgf Running minikube-m02
nginx-app-84d755f746-zkbc6 Running minikube-m03
內容解密:
- 為什麼 Pod 被排程到具有汙點的節點上?因為我們在 Pod 的規格中定義了對應的容忍度。
- 為什麼 Pod 在
minikube節點上會被反覆驅逐和重新排程?因為我們只定義了NoExecute汙點的容忍度,而沒有定義NoSchedule汙點的容忍度。 - 如何解決這個問題?可以透過新增
NoSchedule汙點來防止 Pod 被排程到具有NoExecute汙點的節點上。
為了修復這個問題,我們可以對 minikube 節點新增 NoSchedule 汙點:
$ kubectl taint node minikube machine-check-exception=memory:NoSchedule
node/minikube tainted
然後,再次檢查 Pod 的狀態和節點分配:
$ kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName"
NAME STATUS NODE
nginx-app-84d755f746-58qmh Running minikube-m02
nginx-app-84d755f746-5h5vk Running minikube-m03
nginx-app-84d755f746-psmgf Running minikube-m02
nginx-app-84d755f746-sm2cm Running minikube-m03
nginx-app-84d755f746-zkbc6 Running minikube-m03
可以看到,Pod 現在被正確地排程和執行在其他節點上。
Kubernetes 排程機制進階應用
在前面的章節中,我們探討了 Kubernetes 的基本排程機制,包括 Taints 和 Tolerations、Node Affinity 等。本章節將探討更進階的排程技術,包括靜態 Pod、管理排程器組態、節點隔離和排程器效能調優。
靜態 Pod
靜態 Pod 是由 kubelet 直接管理的 Pod,不受 API 伺服器的控制。它們通常用於引導重要的叢集元件,如 API 伺服器或控制器管理器。靜態 Pod 有兩個主要特點:
- 節點特定:靜態 Pod 與特定節點繫結,無法在叢集中移動。
- Kubelet 管理:kubelet 負責啟動、停止和重新啟動靜態 Pod。
靜態 Pod 可以透過兩種方式建立:檔案系統託管組態和網頁託管組態。檔案系統託管組態需要將 Pod 定義檔案放置在節點上的特定目錄中,而網頁託管組態則需要將 Pod 定義檔案託管在網頁伺服器上。
靜態 Pod 的建立方法
- 檔案系統託管組態:將 Pod 定義檔案以 YAML 或 JSON 格式放置在節點上的特定目錄。kubelet 會定期掃描該目錄並根據檔案內容管理 Pod。
- 網頁託管組態:將 Pod 定義檔案託管在網頁伺服器上,並組態 kubelet 使用該檔案的 URL。kubelet 會定期下載該檔案以管理靜態 Pod。
排程器組態
Kubernetes 排程器可以使用組態檔案進行自定義,該檔案定義了排程器如何根據各種標準對節點進行優先排序。主要概念包括:
- 排程組態檔案:組態檔案可以指定多個排程組態檔案,每個組態檔案都有不同的名稱和外掛集。
- 排程外掛:外掛是排程過程中的構建塊,用於執行特定任務,如根據資源可用性或硬體相容性篩選節點。
- 擴充套件點:擴充套件點是排程過程中插入外掛的階段,不同的外掛適用於不同的階段,如篩選不適合的節點或評分適合的節點。
排程器組態的優點
- 靈活性:允許根據需求自定義排程行為。
- 可擴充套件性:可以開發自定義外掛以處理預設外掛無法滿足的特殊排程需求。
- 粒度控制:可以為不同型別的 Pod 分配不同的排程組態檔案。
節點隔離和限制
Kubernetes 允許使用節點標籤隔離特定節點上的 Pod。這些標籤可以定義安全需求或法規遵從性等屬性,確保 Pod 只被排程到符合這些標準的節點上。
節點隔離的實作步驟
- 啟用 NodeRestriction 外掛和 Node 授權器。
- 新增具有受限字首的標籤到節點。
- 在 Pod 的 nodeSelector 組態中參照這些標籤。
排程器效能調優
在大規模 Kubernetes 叢集中,排程器的效能至關重要。其中一個關鍵的調優引數是 percentageOfNodesToScore。
percentageOfNodesToScore 的作用
- 該設定決定了排程器在搜尋合適的 Pod 放置時考慮的節點數量。
- 較高的值意味著排程器會檢查更多節點,可能找到更好的匹配,但需要更長的時間。
- 較低的值會導致排程速度更快,但可能會導致次優的放置。
您可以透過調整 percentageOfNodesToScore 的值來平衡排程速度和放置品質。
重大變更:Kubernetes v1.23 及之後版本的排程策略變更
在 Kubernetes v1.23 之前,可以透過 kube-scheduler 標誌或 ConfigMaps 指定排程策略。這些策略使用謂詞(篩選標準)和優先順序(評分函式)定義了排程器如何選擇節點。自 v1.23 起,此功能已被排程器組態取代,提供了更大的靈活性和對排程行為的控制。
Kubernetes Pod 與節點的自動擴充套件技術
在雲端環境中執行應用程式時,具備自動擴充套件(Autoscaling)能力可謂是最佳實踐。簡單來說,自動擴充套件是一種根據終端使用者的需求動態調整計算資源(如 CPU 和 RAM)的方法。其目標是根據活動和需求新增或移除資源,以確保應用程式的高用性並降低營運成本。例如,某個應用程式在白天使用者活躍時可能需要更多的 CPU 和 RAM,而在夜間則需求較低。同樣地,對於電子商務基礎設施來說,在黑色星期五等促銷活動期間可能會出現巨大的需求峰值。透過自動擴充套件,不僅可以為使用者提供更好的服務,還能減少雲端資源的消耗,從而降低成本。
Kubernetes 作為最成熟的容器協調系統,提供了多種內建的自動擴充套件功能。其中一些功能在每個 Kubernetes 叢集中都原生支援,而其他一些則需要安裝或特定的叢集佈署型別。此外,您還可以根據不同的維度進行擴充套件:
Pod 的垂直擴充套件
這涉及到調整 Pod 可用的 CPU 和記憶體資源。Pod 可以在指定的 CPU 和記憶體限制下執行,以防止過度消耗,但這些限制可能需要自動調整,而不是由人工操作員進行猜測。這是由 VerticalPodAutoscaler (VPA) 實作的。
垂直擴充套件的程式碼範例
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-vpa
spec:
selector:
matchLabels:
app: my-app
updateMode: Auto
內容解密:
apiVersion和kind定義了 VPA 的資源型別。metadata.name指定了 VPA 的名稱。spec.selector.matchLabels用於選擇要擴充套件的 Pod。updateMode設定為Auto表示 VPA 將自動調整資源。
Pod 的水平擴充套件
這涉及到動態更改 Deployment 或 StatefulSet 的 Pod 複本數量。這些物件具有不錯的擴充套件功能,但可以使用 HorizontalPodAutoscaler (HPA) 自動調整複本數量。
水平擴充套件的程式碼範例
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-hpa
spec:
selector:
matchLabels:
app: my-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
內容解密:
apiVersion和kind定義了 HPA 的資源型別。metadata.name指定了 HPA 的名稱。spec.selector.matchLabels用於選擇要擴充套件的 Pod。minReplicas和maxReplicas設定了 Pod 複本數量的範圍。metrics設定了根據 CPU 使用率進行擴充套件的規則。
自動擴充套件的優勢與挑戰
自動擴充套件可以根據實際需求動態調整資源,從而提高資源利用率並降低成本。然而,自動擴充套件也面臨著一些挑戰,例如如何選擇合適的指標、如何設定合理的擴充套件策略等。