Kubernetes Pod資源調度之全自動調度和定向調度


1、控制器類型

Kubernetes上,很少會直接創建一個Pod,在大多數情況下,會通過RCDeploymentDaemonSetJob等控制器完成對一組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目前發布了v1v2兩個版本,用戶 希望MyAppPod副本數保持為3個,可以同時包含v1v2版本的Pod, 就可以用ReplicaSet來實現這種控制,寫法如下

    selector:
      matchLables:
        version: v2
      matchExpressions:
        - {key: version, operator: In, values: [v1,v2]}

Kubernetes的滾動升級就是巧妙運用ReplicaSet的這個特性來實現的,同時,Deployment也是通過ReplicaSet來實現Pod副本自動控制功能的。我們不應該直接使用底層的ReplicaSet來控制Pod副本,而應該 使用管理ReplicaSetDeployment對象來控制副本,這是來自官方的建議。

2、全自動調度

全自動調度的控制器是DeploymentRCDeploymentRC的主要功能之一就是自動部署一個容器應用的 份副本,以及持續監控副本的數量,在集群內始終維持用戶指定的副本數量。

下面是一個Deployment配置的例子,使用這個配置文件可以創建一個ReplicaSet,這個ReplicaSet會創建3Nginx應用的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

查看DeploymentRSPod的狀態

# 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

從調度策略上來說,這3Nginx Pod由系統全自動完成調度。它們各自最終運行在哪個節點上,完全由MasterScheduler經過一系列算法計算得出,用戶無法干預調度過程和結果。

# 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)和PodnodeSelector屬性相匹配,來達到上述目的。

首先通過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

創建Podscheduler就會將該Pod調度到擁有zone=north標簽的Node

如果我們給多個Node都定義了相同的標簽(例如zone=north),則scheduler會根據調度算法從這組Node中挑選一個可用的Node進行Pod調度。

通過基於Node標簽的調度方式,我們可以把集群中具有不同特點的Node都貼上不同的標簽,例 如role=frontendrole=backend``、role=database等標簽,在部署應用時就可以根據應用的需求設置NodeSelector來進行指定Node范圍的調度。

如果我們指定了PodnodeSelector條件,且在集群中不存在包含相應標簽的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之間的親和或互斥關系

親和性調度功能包括節點親和性NodeAffinityPod親和性PodAffinity兩個維度的設置。節點親和性與NodeSelector類似,增 強了上述前兩點優勢;Pod的親和與互斥限制則通過Pod標簽而不是節點標簽來實現,也就是上面所陳述的方式,同時具有前兩點提到的優點。

NodeSelector將會繼續使用,隨着節點親和性越來越能夠表達nodeSelector的功能,最終NodeSelector會被廢棄。

文章參考來源:《kubernetes權威指南-第4版》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM