天天看點

Kubernetes Pod資源排程之全自動排程和定向排程

目錄

  • 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之間的親和或互斥關系