目錄
- 1、控制器類型
- 2、全自動排程
- 3、定向排程
在Kubernetes上,很少會直接建立一個Pod,在大多數情況下,會通過RC、Deployment、DaemonSet、Job等控制器完成對一組Pod副本的建立、排程和整個生命周期的自動化控制。
在最早的Kubernetes版本裡沒有這麼多Pod副本控制器的,隻有一 個Pod副本控制器RC(Replication Controller),這個控制器是這樣設計 實作的:RC獨立于所控制的Pod,并通過Label标簽這個松耦合關聯關系 控制目标Pod執行個體的建立和銷毀,随着Kubernetes的發展,RC也出現了新的繼任者Deployment,用于更加自動地完成Pod副本的部署、版 本更新、復原等功能。
嚴謹地說,RC的繼任者其實并不是Deployment,而是ReplicaSet, 因為ReplicaSet進一步增強了RC标簽選擇器的靈活性。之前RC的标簽選擇器隻能選擇一個标簽,而ReplicaSet擁有集合式的标簽選擇器,可以選擇多個Pod标簽,如下所示
selector:
matchLables:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
與RC不同,ReplicaSet被設計成能控制多個不同标簽的Pod副本。 一種常見的應用場景是,應用MyApp目前釋出了v1與v2兩個版本,使用者 希望MyApp的Pod副本數保持為3個,可以同時包含v1和v2版本的Pod, 就可以用ReplicaSet來實作這種控制,寫法如下
selector:
matchLables:
version: v2
matchExpressions:
- {key: version, operator: In, values: [v1,v2]}
Kubernetes的滾動更新就是巧妙運用ReplicaSet的這個特性來實作的,同時,Deployment也是通過ReplicaSet來實作Pod副本自動控制功能的。我們不應該直接使用底層的ReplicaSet來控制Pod副本,而應該 使用管理ReplicaSet的Deployment對象來控制副本,這是來自官方的建議。
全自動排程的控制器是Deployment或RC,Deployment或RC的主要功能之一就是自動部署一個容器應用的 份副本,以及持續監控副本的數量,在叢集内始終維持使用者指定的副本數量。
下面是一個Deployment配置的例子,使用這個配置檔案可以建立一個ReplicaSet,這個ReplicaSet會建立3個Nginx應用的Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
運作kubectl create指令建立這個Deployment
# kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
檢視Deployment、RS、Pod的狀态
# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 58s
# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-7bffc778db 3 3 3 85s
# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-7bffc778db-j5czg 1/1 Running 0 1m34s
nginx-deployment-7bffc778db-lbpjg 1/1 Running 0 1m34s
nginx-deployment-7bffc778db-zcn6m 1/1 Running 0 1m34s
從排程政策上來說,這3個Nginx Pod由系統全自動完成排程。它們各自最終運作在哪個節點上,完全由Master的Scheduler經過一系列算法計算得出,使用者無法幹預排程過程和結果。
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-7bffc778db-j5czg 1/1 Running 0 3m36s 172.20.3.229 k8s-node-1 <none> <none>
nginx-deployment-7bffc778db-lbpjg 1/1 Running 0 3m36s 172.20.4.27 k8s-node-2 <none> <none>
nginx-deployment-7bffc778db-zcn6m 1/1 Running 0 3m36s 172.20.5.203 k8s-node-3 <none> <none>
定向排程通過NodeSelector标簽實作, Master上的Scheduler服務(kube-scheduler程序)負責實作Pod的排程,整個排程過程通過執行一系列複雜的算法,最終為每個Pod都計算出一個最佳的目标節點,這一過程是自動完成的,通常我們 無法知道Pod最終會被排程到哪個節點上。在實際情況下,也可能需要将Pod排程到指定的一些Node上,可以通過Node的标簽(Label)和Pod的nodeSelector屬性相比對,來達到上述目的。
首先通過kubectl label指令給目标Node打上一些标簽
# kubectl label nodes k8s-node-1 zone=north
然後,在Pod的定義中加上nodeSelector的設定,以redismaster-controller.yaml為例
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: master
image: redis
ports:
- containerPort: 6379
nodeSelector:
zone: north
建立Pod,scheduler就會将該Pod排程到擁有zone=north标簽的Node上
如果我們給多個Node都定義了相同的标簽(例如zone=north),則scheduler會根據排程算法從這組Node中挑選一個可用的Node進行Pod排程。
通過基于Node标簽的排程方式,我們可以把叢集中具有不同特點的Node都貼上不同的标簽,例 如role=frontend、role=backend``、role=database等标簽,在部署應用時就可以根據應用的需求設定NodeSelector來進行指定Node範圍的排程。
如果我們指定了Pod的nodeSelector條件,且在叢集中不存在包含相應标簽的Node,則即使在叢集中還有其他可供使用的Node,這個Pod也無法被成功排程。
除了使用者可以自行給Node添加标簽,Kubernetes也會給Node預定義 一些标簽,包括
- kubernetes.io/hostname
- beta.kubernetes.io/os(從1.14版本開始更新為穩定版,到1.18版 本删除)
- beta.kubernetes.io/arch(從1.14版本開始更新為穩定版,到1.18 版本删除)
- kubernetes.io/os(從1.14版本開始啟用)
- kubernetes.io/arch(從1.14版本開始啟用)
也可以使用這些系統标簽進行Pod的定向排程。
NodeSelector通過标簽的方式,簡單實作了限制Pod所在節點的方法。親和性排程機制則極大擴充了Pod的排程能力,主要的增強功能如 下。
- 更具表達力(不僅僅是“符合全部”的簡單情況)
- 可以使用軟限制、優先采用等限制方式,代替之前的硬限制, 這樣排程器在無法滿足優先需求的情況下,會退而求其次,繼續運作該Pod
- 可以依據節點上正在運作的其他Pod的标簽來進行限制,而非節點本身的标簽。這樣就可以定義一種規則來描述Pod之間的親和或互斥關系