1、控制器類型
在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
對象來控制副本,這是來自官方的建議。
2、全自動調度
全自動調度的控制器是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>
3、定向調度
定向調度通過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
之間的親和或互斥關系
親和性調度功能包括節點親和性NodeAffinity
和Pod
親和性PodAffinity
兩個維度的設置。節點親和性與NodeSelector
類似,增 強了上述前兩點優勢;Pod
的親和與互斥限制則通過Pod
標簽而不是節點標簽來實現,也就是上面所陳述的方式,同時具有前兩點提到的優點。
NodeSelector
將會繼續使用,隨着節點親和性越來越能夠表達nodeSelector
的功能,最終NodeSelector
會被廢棄。
文章參考來源:《kubernetes權威指南-第4版》