文章目錄
- k8s中的集群調度
- Pod 創建流程
- 通過指定節點來創建pod所在的node節點
- 通過標簽來指定pod創建在哪個節點上
- pod 的親和性
- Pod的親和性和反親和性
- 親和性(Affinity)
- 反親和性(Anti-Affinity)
- 污點與容忍
- 污點(Taint)
- 容忍(Tolerations)
k8s中的集群調度
Kubernetes 是通過 List-Watch 的機制進行每個組件的協作,保持數據同步的,每個組件之間的設計實現了解耦
在 Kubernetes 集群中,Pod 是最小的部署單元,它包含一個或多個容器。Pod 的創建和調度是由 Kubernetes 的多個組件共同完成的,包括 API Server、Controller Manager、Scheduler 和 kubelet。本文將帶您深入了解這一過程。
Pod 創建流程
- 用戶請求:用戶通過
kubectl
或其他 API 客戶端向 API Server 發送創建 Pod 的請求。 - 存儲請求:API Server 將 Pod 的元數據存儲到 etcd 中。一旦存儲成功,API Server 向客戶端確認請求完成。
- 事件通知:etcd 在存儲操作完成后,會向 API Server 發送一個創建事件。
- Controller Manager 監聽:Controller Manager 通過 List-Watch 機制監聽 API Server 的事件。當它接收到 Pod 創建事件時,會檢查是否有對應的 Replication Controller (RC) 或其他控制器來確保所需的 Pod 副本數量。
- 調度準備:如果 Pod 副本數量不足,Controller Manager 會創建新的 Pod 副本,并在 API Server 中記錄詳細信息。
- Scheduler 監聽:Scheduler 也通過 List-Watch 機制監聽 API Server 的事件。當它接收到新的 Pod 創建事件時,它將決定將該 Pod 調度到哪個 Node 上。
- 調度決策:Scheduler 根據一系列的調度算法和策略(如資源需求、節點親和性等)來選擇最佳的 Node。
- 綁定 Pod:Scheduler 更新 Pod 的信息,包括其被調度到的 Node,并將這些信息寫回 API Server,由 API Server 更新到 etcd。
- kubelet 監聽:在每個 Node 上運行的 kubelet 通過 List-Watch 機制監聽 API Server,等待被調度到該 Node 上的 Pod 事件。
- 容器啟動:當 kubelet 發現有一個新的 Pod 被調度到它所在的 Node 時,它會調用 Docker(或其他容器運行時)來啟動 Pod 中的容器。
- 狀態反饋:kubelet 將 Pod 及其容器的狀態反饋給 API Server,API Server 再將這些狀態信息存儲到 etcd 中。
通過指定節點來創建pod所在的node節點
沒有設置指定節點時會通過調度器來進行pod創建的調度
apiVersion: apps/v1
kind: Deployment
metadata:name: web1labels:app: web1
spec:replicas: 4selector:matchLabels:app: web1template:metadata:labels:app: web1spec:containers:- name: nginximage: nginx:1.16ports:- containerPort: 80
可以看到pod節點會平均創建在node01 和 node02 上
通過指定節點來指定創建在node01節點上
apiVersion: apps/v1
kind: Deployment
metadata:name: web1labels:app: web1
spec:replicas: 4selector:matchLabels:app: web1template:metadata:labels:app: web1spec:nodeName: node01 # 添加nodeName: node01 containers:- name: nginximage: nginx:1.16ports:- containerPort: 80
不通過調度器,直接通過指定節點將所有pod節點都部署在了node01節點上了
通過標簽來指定pod創建在哪個節點上
給node節點添標簽
kubectl label nodes node02 pji=a
kubectl label nodes node01 pji=b
可以看見node02 的標簽為 pji=a ,node01 的標簽為pji=b
apiVersion: apps/v1
kind: Deployment
metadata:name: web1labels:app: web1
spec:replicas: 4selector:matchLabels:app: web1template:metadata:labels:app: web1spec:nodeSelector: #添加標簽pji: a #標簽值pji: acontainers:- name: nginximage: nginx:1.16ports:- containerPort: 80
以上配置可以將pod節點部署到node02節點上
apiVersion: apps/v1
kind: Deployment
metadata:name: web1labels:app: web1
spec:replicas: 4selector:matchLabels:app: web1template:metadata:labels:app: web1spec:nodeSelector: pji: bcontainers:- name: nginximage: nginx:1.16ports:- containerPort: 80
以上配置可以將pod部署到node01上
pod 的親和性
在 Kubernetes 中,Pod 親和性(Pod Affinity)是一種調度策略,用于確保 Pod 調度到特定的節點上。這種策略可以通過標簽選擇器(Label Selector)來實現,使得具有特定標簽的 Pod 傾向于調度到具有相同標簽的節點上。
Pod 親和性可以分為以下幾種類型:
- 軟親和性(Soft Affinity):
podAffinityTerm
:指定 Pod 應該調度的節點集合。preferredDuringSchedulingIgnoredDuringExecution
:定義 Pod 應該優先調度到哪些節點上。
- 硬親和性(Hard Affinity):
podAffinityTerm
:指定 Pod 必須調度的節點集合。requiredDuringSchedulingIgnoredDuringExecution
:定義 Pod 必須調度到哪些節點上。
例如,如果您有一個包含兩個節點的集群,并且希望將特定的 Pod 調度到具有標簽node-role.kubernetes.io/master: ""
的節點上,
硬策略 匹配標簽pji=a的node的節點配置如下
apiVersion: apps/v1
kind: Deployment
metadata:name: web1labels:app: web1
spec:replicas: 4selector:matchLabels:app: web1template:metadata:labels:app: web1spec:containers:- name: nginximage: nginx:1.16ports:- containerPort: 80affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: pjioperator: Invalues:- a
若是配置一個不存在的標簽這會如下
出現Pending狀態
軟策略
設置標簽為bcde但是此集群沒有標簽bcde的主機
apiVersion: apps/v1
kind: Deployment
metadata:name: web1labels:app: web1
spec:replicas: 20selector:matchLabels:app: web1template:metadata:labels:app: web1spec:containers:- name: nginximage: nginx:1.16ports:- containerPort: 80affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:- key: pjioperator: Invalues:- bcde
則會調度在node01 (b)和 node02?上
Pod的親和性和反親和性
在 Kubernetes 中,親和性(Affinity)和反親和性(Anti-Affinity)是調度策略的一部分,用于影響 Kubernetes 調度器如何將 Pod 調度到集群中的節點上。這些特性可以幫助您確保 Pod 之間或 Pod 與節點之間保持特定的關系。
親和性(Affinity)
親和性是指調度器傾向于將 Pod 調度到滿足特定條件的節點上。它包括以下幾種類型:
- 節點親和性(Node Affinity):
- 軟親和性(Soft Affinity):如果節點不滿足條件,調度器可以忽略親和性。
- 硬親和性(Hard Affinity):如果節點不滿足條件,調度器將不會調度 Pod。
- Pod 親和性(Pod Affinity):
- 軟親和性:如果其他 Pod 不滿足條件,調度器可以忽略親和性。
- 硬親和性:如果其他 Pod 不滿足條件,調度器將不會調度 Pod。
- Pod 反親和性(Pod Anti-Affinity):
- 軟反親和性:如果其他 Pod 不滿足條件,調度器可以忽略反親和性。
- 硬反親和性:如果其他 Pod 不滿足條件,調度器將不會調度 Pod。
反親和性(Anti-Affinity)
反親和性是親和性的對立面。與親和性不同,反親和性用于防止 Pod 調度到某些節點上,或者避免與某些 Pod 一起調度。反親和性通常用于避免資源爭用或實現高可用性。
親和性配置
apiVersion: v1
kind: Pod
metadata:name: web5labels:app: web2
spec:containers:- name: nginximage: nginx:1.16ports:- containerPort: 80affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- web2 # 在有pod標簽app=web2的標簽上創建topologyKey: pji #在擁有pji標簽的節點上創建
反親和性
apiVersion: v1
kind: Pod
metadata:name: web5labels:app: web1
spec:containers:- name: nginximage: nginx:1.14ports:- containerPort: 80affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: "app"operator: Invalues:- web2topologyKey: "kubernetes.io/hostname"
之前的pod標簽為web2 ,設置非親緣性后 web5創建會避開node02
當然可以。
污點與容忍
污點(Taint)
污點是向節點添加的一個標簽,它告訴 Kubernetes 調度器不要將 Pod 調度到具有該污點的節點上。這通常用于防止 Pod 調度到不希望它們運行的節點上,例如,當節點正在進行維護或出現問題時。
污點可以具有以下三個屬性:
- 鍵(Key):污點的鍵,用于標識污點。
- 值(Value):與鍵關聯的值。
- 效果(Effect):當污點匹配時,Pod 應該受到的影響。有效果包括
NoSchedule
、PreferNoSchedule
和NoExecute
。
污點的創建
給node01創建一個鍵值對為ry=87的污點,使用NoSchedule策略
kubectl taint node node01 ry=87:NoSchedule
apiVersion: v1
kind: Pod
metadata:name: nginx4labels:app: nginx
spec:containers:- name: nginximage: nginx:latestports:- containerPort: 80
創建新的Pod都創建在node02下,而不會創建在node01上
容忍(Tolerations)
容忍是 Pod 上的一個標簽,它告訴 Kubernetes 調度器,盡管節點具有某個污點,但該 Pod 應該被調度到該節點上。容忍可以有多個鍵值對,并且可以設置不同的效果和時間范圍。
設置容忍
apiVersion: v1
kind: Pod
metadata:name: nginx4labels:app: nginx
spec:containers:- name: nginximage: nginx:latestports:- containerPort: 80tolerations:- key: "ry"operator: "Equal"value: "87"effect: "NoSchedule"
可以看見,node01的污點被無視了