6. kubernetes 資源和調(diào)度

6. kubernetes 資源和調(diào)度

一揭保、資源配額與限制

資源配額用于管理命名空間(NameSpace)中對(duì)象使用的資源量,我們可以按 CPU內(nèi)存用量饶碘、對(duì)象數(shù)量來設(shè)置配額笨腥。通過資源配額拓哺,可以確保租戶不會(huì)使用超過其分配份額的集群資源。

資源配額的工作方式如下:

  • 管理員為每個(gè) namespace 創(chuàng)建一個(gè)或多個(gè)資源配額對(duì)象
  • 用戶在 namespace 下創(chuàng)建資源 (pods脖母、 services 等)士鸥,同時(shí)配額系統(tǒng)會(huì)跟蹤使用情況,來確保其不超過資源配額中定義的硬性資源限額
  • 如果資源的創(chuàng)建或更新違反了配額約束谆级,則請(qǐng)求會(huì)失敗烤礁,并返回 HTTP 狀態(tài)碼 403 FORBIDDEN,以及說明違反配額約束的信息
  • 如果 namespace 下的計(jì)算資源(如 cpu 和 memory)的配額被啟用肥照,則用戶必須為這些資源設(shè)定請(qǐng)求值(request) 和約束值(limit)脚仔,否則配額系統(tǒng)將拒絕 Pod 的創(chuàng)建。

Kubernetes 中主要有3個(gè)層級(jí)的資源配額控制:

  • 容器:可以對(duì) CPU 和 Memory 進(jìn)行限制
  • POD:可以對(duì)一個(gè) Pod 內(nèi)所有容器的的資源進(jìn)行限制
  • Namespace:為一個(gè)命名空間下的資源進(jìn)行限制

其中容器層次主要利用容器本身的支持舆绎,比如 Docker 對(duì) CPU鲤脏、內(nèi)存等的支持;Pod 方面可以限制系統(tǒng)內(nèi)創(chuàng)建 Pod 的資源范圍,比如最大或者最小的 CPU猎醇、memory 需求窥突;Namespace 層次就是對(duì)用戶級(jí)別的資源限額了,包括 CPU硫嘶、內(nèi)存波岛,還可以限定 Pod、RC音半、Service 的數(shù)量则拷。

要使用資源配額的話需要確保 api server的 --enable-admission-plugins= 參數(shù)中包含 ResourceQuota,當(dāng) namespace 中存在一個(gè) ResourceQuota 對(duì)象時(shí)曹鸠,該 namespace 即開始實(shí)施資源配額的管理工作了煌茬,另外需要注意的是一個(gè) namespace 中最多只應(yīng)存在一個(gè) ResourceQuota 對(duì)象

資源配額控制器支持的配額控制資源主要包括:計(jì)算資源配額彻桃、存儲(chǔ)資源配額坛善、對(duì)象數(shù)量資源配額

1. 計(jì)算資源配額

在namespace下我們可以針對(duì)性的設(shè)置計(jì)算資源配額邻眷,有兩種方式:ResourceQuotaLimitRange

資源名稱 資源類型 描述
limits.cpu cpu 所有容器的cpu 請(qǐng)求資源總和
limits.memory memory 所有容器的內(nèi)存 請(qǐng)求資源總和
requests.cpu cpu 所有容器的cpu 限制資源總和
requests.memory memory 所有容器的內(nèi)存 限制資源總和

在創(chuàng)建pod時(shí)眠屎,無論是 請(qǐng)求資源超出限制 或者是 限制資源超出限制,都無法創(chuàng)建成功K寥摹8鸟谩!

ResourceQuota

下面是一個(gè)演示案例

這里要注意的是:

我們?cè)?resourcequota中 設(shè)勝多負(fù)少的置 cpu 和 memory 的格式 要和 pod 文件中 cpu驯镊、 memory 的格式保存統(tǒng)一葫督。

比如: resourcequota memory 賦值時(shí) 我們是用的 "300Mi", 那么我們?cè)趐od 中配置 memory 時(shí) 也應(yīng)該用相同的格式 "xxMi"

# 首先我們新建一個(gè)namespace
kubectl create ns  tmp-quota

# 創(chuàng)建 計(jì)算資源配額 文件
vim quota-mem-cpu.yaml
#-------------------------------
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-test1
  namespace: tmp-quota
spec:
  hard: # 硬件配額
    requests.cpu: "1"   # cpu 請(qǐng)求資源配額總和,這里有兩個(gè)單位 100m = 0.1 cpu;1000m cpu = 1 cpu; 精度1m;
    requests.memory: "300Mi"   # 內(nèi)存 請(qǐng)求資源配額總和板惑,這里和我們平時(shí)使用的單位一樣橄镜,默認(rèn)是 byte,也可以用 E冯乘、P洽胶、T、G裆馒、M姊氓、K為單位后綴或Ei、Pi...
    limits.cpu: "2"   # cpu 限制資源總和
    limits.memory: "600Mi" # 內(nèi)存 限制資源總和
#-------------------------------

# 運(yùn)行
kubectl apply -f quota-mem-cpu.yaml
#---------------------------------
resourcequota/quota-test1 created
#---------------------------------

# 然后我們查看資源詳情
# kubectl describe quota 資源文件name屬性 -n namespace名稱
kubectl describe quota quota-test1 -n tmp-quota
#---------------------------------
Name:            quota-test1
Namespace:       tmp-quota
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     2
limits.memory    0     600m
requests.cpu     0     1
requests.memory  0     300m
#---------------------------------

# 而后我們創(chuàng)建一個(gè)pod 并申請(qǐng)限額
vim quta-pod-test1.yaml
#---------------------------------
apiVersion: v1
kind: Pod
metadata:
  name: quta-pod-test1
  namespace: tmp-quota
spec:
  containers:
  - name: quota-mem-cpu-demo-ctr
    image: nginx
    resources:
      limits:
        cpu: 1000m
        memory: 200M
      requests:
        cpu: 300m
        memory: 150M
#---------------------------------

# 啟動(dòng)pod
kubectl apply -f quta-pod-test1.yaml

# 我們查看 資源占用情況
# 通過describe查詢
kubectl describe quota quota-test1 -n tmp-quota
#---------------------------------
Name:            quota-test1
Namespace:       tmp-quota
Resource         Used   Hard
--------         ----   ----
limits.cpu       1      2
limits.memory    200Mi  600Mi
requests.cpu     800m   1500m
requests.memory  150Mi  500Mi
#---------------------------------

# 通過 get resourcequota查詢
kubectl get resourcequota -n tmp-quota
#---------------------------------
NAME          AGE    REQUEST                                                  LIMIT
quota-test1   108m   requests.cpu: 800m/1500m, requests.memory: 150Mi/500Mi   limits.cpu: 1/2, limits.memory: 200Mi/600Mi
#---------------------------------

# 下面我們看一下不滿足資源限制的情況

# 我們新建一個(gè) quta-pod-test2.yaml
vim quta-pod-test2.yaml
#-------------------------
apiVersion: v1
kind: Pod
metadata:
  name: quta-pod-test2
  namespace: tmp-quota
spec:
  containers:
  - name: quota-mem-cpu-demo-ctr
    image: nginx
    resources:
      limits:
        cpu: "1000m"
        memory: "200Mi"
      requests:
        cpu: "800m"
        memory: "550Mi" # 這里我們的 request.memory 超過了 資源限制 "300Mi"
#-------------------------

# 創(chuàng)建pod
kubectl apply -f quta-pod-test2.yaml
# 報(bào)錯(cuò)信息如下
#-------------------------
The Pod "quta-pod-test2" is invalid: spec.containers[0].resources.requests: Invalid value: "550Mi": must be less than or equal to memory limit
#-------------------------


ResourceQuota 用來限制 namespace 中所有的 Pod 占用的總的資源 request 和 limit

LimitRange

而實(shí)際場(chǎng)景中 我們會(huì)出現(xiàn)這樣的情況:

  • 我們要對(duì)單個(gè)容器進(jìn)行配額的限制
  • 我們新建了一個(gè)namespace 并未他設(shè)置了配額领追,但是pod 并沒有配置request 和limit他膳,這樣我們也無法成功創(chuàng)建pod。

使用LimitRange 我們就可以很好的解決上述問題绒窑。

LimitRange 用來限制 namespace 中 單個(gè)Pod 默認(rèn)資源 request 和 limit

# 首先我們新建一個(gè)namespace
kubectl create ns tmp-quota-range

# 新建 limitRange 資源文件
vim quota-range.yaml
#-------------------------
apiVersion: v1
kind: LimitRange
metadata:
  name: quta-limit-range
  namespace: tmp-quota-range
spec:
  limits:
    - default:
        memory: "130Mi"   # default  limits.memory = 130Mi
        cpu: "600m"
      defaultRequest:
        cpu: "550m"
        memory: "110Mi"   # default request.memory = 110Mi
      max:
        cpu: "800m"
        memory: "200Mi"   # max memory = 200Mi
      min:
        cpu: "500m"
        memory: "100Mi"  # min memory = 100Mi
      type: Container
#-------------------------

# 生效配置
kubectl apply -f quota-range.yaml

# 然后我們查看 describe
kubectl describe limits quta-limit-range -n tmp-quota-range
#-------------------------
Name:       quta-limit-range
Namespace:  tmp-quota-range
Type        Resource  Min    Max    Default Request  Default Limit  Max Limit/Request Ratio
----        --------  ---    ---    ---------------  -------------  -----------------------
Container   cpu       500m   800m   550m             600m           -
Container   memory    100Mi  200Mi  110Mi            130Mi          -
#-------------------------


# 新建一個(gè)pod.yaml
vim quta-pod-test3.yaml
#-------------------
apiVersion: v1
kind: Pod
metadata:
  name: quta-pod-test3
  namespace: tmp-quota-range
spec:
  containers:
  - name: quota-mem-cpu-demo-ctr2
    image: nginx
#------------------------

# 運(yùn)行
kubectl apply -f quta-pod-test3.yaml

# 然后我們檢查pod describe
kubectl describe pod quta-pod-test3 -n tmp-quota-range
#------------------------
Name:         quta-pod-test3
Namespace:    tmp-quota-range
Priority:     0
Node:         k8s-slave03/192.168.56.107
Start Time:   Tue, 05 Jul 2022 15:29:46 +0800
Labels:       <none>
Annotations:  cni.projectcalico.org/containerID: bd8322be8529794f3350dcd4ecc5aa579e496ca384a2bfbc990c0f14c768bf55
              cni.projectcalico.org/podIP: 10.244.211.196/32
              cni.projectcalico.org/podIPs: 10.244.211.196/32
              kubernetes.io/limit-ranger:
                LimitRanger plugin set: cpu, memory request for container quota-mem-cpu-demo-ctr2; cpu, memory limit for container quota-mem-cpu-demo-ctr2
Status:       Running
IP:           10.244.211.196
IPs:
  IP:  10.244.211.196
Containers:
  quota-mem-cpu-demo-ctr2:
    Container ID:   docker://68ece5793c03b4d7aae8a37977cdb389509ec8e24b3f10fb7be498d691866efd
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Tue, 05 Jul 2022 15:29:48 +0800
    Ready:          True
    Restart Count:  0
    # 看這里棕孙,pod 使用了默認(rèn)的 limit 和 request 配置 ---------------------
    Limits:
      cpu:     600m
      memory:  130Mi
    Requests:
      cpu:        550m
      memory:     110Mi
     # --------------------------------------------------------------  
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-plgww (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-plgww:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  53s   default-scheduler  Successfully assigned tmp-quota-range/quta-pod-test3 to k8s-slave03
  Normal  Pulling    52s   kubelet            Pulling image "nginx"
  Normal  Pulled     51s   kubelet            Successfully pulled image "nginx" in 927.414978ms
  Normal  Created    51s   kubelet            Created container quota-mem-cpu-demo-ctr2
  Normal  Started    51s   kubelet            Started container quota-mem-cpu-demo-ctr2
#------------------------

2. 存儲(chǔ)資源配額

PersistentVolume (PV) 是外部存儲(chǔ)系統(tǒng)中的一塊存儲(chǔ)空間,由管理員創(chuàng)建和維護(hù)。與 Volume 一樣蟀俊,PV 具有持久性钦铺,生命周期獨(dú)立于 Pod。

PersistentVolumeClaim (PVC) 是對(duì) PV 的申請(qǐng) (Claim)肢预。PVC 通常由普通用戶創(chuàng)建和維護(hù)矛洞。需要為 Pod 分配存儲(chǔ)資源時(shí),用戶可以創(chuàng)建一個(gè) PVC烫映,指明存儲(chǔ)資源的容量大小和訪問模式(比如只讀)等信息沼本,Kubernetes 會(huì)查找并提供滿足條件的 PV。

有了 PersistentVolumeClaim锭沟,用戶只需要告訴 Kubernetes 需要什么樣的存儲(chǔ)資源抽兆,而不必關(guān)心真正的空間從哪里分配,如何訪問等底層細(xì)節(jié)信息族淮。這些 Storage Provider 的底層信息交給管理員來處理辫红,只有管理員才應(yīng)該關(guān)心創(chuàng)建 PersistentVolume 的細(xì)節(jié)信息。

資源名稱 描述
requests.storage 所有的pvc中祝辣,存儲(chǔ)資源的需求不能超過該值
persistentvolumeclaims namespace中所允許的pvc總量
<storage-class-name>.storageclass.storage.k8s.io/requests.storage 所有該storage-class-name相關(guān)的pvc中贴妻,存儲(chǔ)資源的需求不能超過改值
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims namespace中所允許的該storage-class-name相關(guān)的pvc的總量

這里我們簡(jiǎn)單帶過,只演示下核心的資源文件,使用方法和 計(jì)算資源配額 類似

# 不管多少個(gè)PVC蝙斜,現(xiàn)在只要pvc總和請(qǐng)求量超過10G名惩,就不會(huì)讓其創(chuàng)建了
[root@master volume]# cat storage-resource.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage-resources
  namespace: dev1
spec:
  hard:
    requests.storage: "10G" # 設(shè)置pvc 10G
    # managed-nfs-storage.storageclass.storage.k8s.io/requests.storage: "5G"
[root@master volume]# kubectl apply -f storage-resource.yaml 
resourcequota/storage-resources created
[root@master volume]# kubectl get quota -n dev1
NAME                AGE   REQUEST                   LIMIT
storage-resources   12s   requests.storage: 0/10G   
 
 
[root@master volume]# cat pvc-nfs-dy.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
  namespace: dev1
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests: 
      storage: 11Gi  
  storageClassName: managed-nfs-storage
 
[root@master volume]# kubectl apply -f  pvc-nfs-dy.yaml 
Error from server (Forbidden): error when creating "pvc-nfs-dy.yaml": persistentvolumeclaims "nfs-pvc" is forbidden: exceeded quota: storage-resources, requested: requests.storage=11Gi, used: requests.storage=0, limited: requests.storage=10G

3. 對(duì)象數(shù)量資源配額

這個(gè)就比較好理解了,我們可以限制 pods 乍炉、deployment绢片、 services configmaps 等的數(shù)量

apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-counts
  namespace: test
spec:
hard:
  pods: "10"
  count/deployments.apps: "3"
  count/services: "3"

二滤馍、資源調(diào)度

在k8s上有一個(gè)非常重要的組件kube-scheduler岛琼,它主要作用是監(jiān)聽apiserver上的pod資源中的nodename字段是否為空,如果該字段為空就表示對(duì)應(yīng)pod還沒有被調(diào)度巢株,此時(shí)kube-scheduler就會(huì)從k8s眾多節(jié)點(diǎn)中槐瑞,根據(jù)pod資源的定義相關(guān)屬性,從眾多節(jié)點(diǎn)中挑選一個(gè)最佳運(yùn)行pod的節(jié)點(diǎn)阁苞,并把對(duì)應(yīng)主機(jī)名稱填充到對(duì)應(yīng)pod的nodename字段困檩,然后把pod定義資源存回apiserver;此時(shí)apiserver就會(huì)根據(jù)pod資源上的nodename字段中的主機(jī)名那槽,通知對(duì)應(yīng)節(jié)點(diǎn)上的kubelet組件來讀取對(duì)應(yīng)pod資源定義悼沿,kubelet從apiserver讀取對(duì)應(yīng)pod資源定義清單,根據(jù)資源清單中定義的屬性骚灸,調(diào)用本地docker把對(duì)應(yīng)pod運(yùn)行起來糟趾;然后把pod狀態(tài)反饋給apiserver,由apiserver把對(duì)應(yīng)pod的狀態(tài)信息存回etcd中;整個(gè)過程义郑,kube-scheduler主要作用是調(diào)度pod蝶柿,并把調(diào)度信息反饋給apiserver,那么問題來了非驮,kube-scheduler它是怎么評(píng)判眾多節(jié)點(diǎn)哪個(gè)節(jié)點(diǎn)最適合運(yùn)行對(duì)應(yīng)pod的呢交汤?

在k8s上調(diào)度器的工作邏輯是根據(jù)調(diào)度算法來實(shí)現(xiàn)對(duì)應(yīng)pod的調(diào)度的;不同的調(diào)度算法劫笙,調(diào)度結(jié)果也有所不同芙扎,其評(píng)判的標(biāo)準(zhǔn)也有所不同,當(dāng)調(diào)度器發(fā)現(xiàn)apiserver上有未被調(diào)度的pod時(shí)填大,它會(huì)把k8s上所有節(jié)點(diǎn)信息纵顾,挨個(gè)套進(jìn)對(duì)應(yīng)的預(yù)選策略函數(shù)中進(jìn)行篩選,把不符合運(yùn)行pod的節(jié)點(diǎn)淘汰掉栋盹,我們把這個(gè)過程叫做調(diào)度器的預(yù)選階段(Predicate)施逾;剩下符合運(yùn)行pod的節(jié)點(diǎn)會(huì)進(jìn)入下一個(gè)階段優(yōu)選(Priority),所謂優(yōu)選是在這些符合運(yùn)行pod的節(jié)點(diǎn)中根據(jù)各個(gè)優(yōu)選函數(shù)的評(píng)分例获,最后把每個(gè)節(jié)點(diǎn)通過各個(gè)優(yōu)選函數(shù)評(píng)分加起來汉额,選擇一個(gè)最高分,這個(gè)最高分對(duì)應(yīng)的節(jié)點(diǎn)就是調(diào)度器最后調(diào)度結(jié)果榨汤,如果最高分有多個(gè)節(jié)點(diǎn)蠕搜,此時(shí)調(diào)度器會(huì)從最高分相同的幾個(gè)節(jié)點(diǎn)隨機(jī)挑選一個(gè)節(jié)點(diǎn)當(dāng)作最后運(yùn)行pod的節(jié)點(diǎn);我們把這個(gè)這個(gè)過程叫做pod選定過程(select);簡(jiǎn)單講調(diào)度器的調(diào)度過程會(huì)通過三個(gè)階段收壕,第一階段是預(yù)選階段妓灌,此階段主要是篩選不符合運(yùn)行pod節(jié)點(diǎn),并將這些節(jié)點(diǎn)淘汰掉蜜宪;第二階段是優(yōu)選虫埂,此階段是通過各個(gè)優(yōu)選函數(shù)對(duì)節(jié)點(diǎn)評(píng)分,篩選出得分最高的節(jié)點(diǎn)圃验;第三階段是節(jié)點(diǎn)選定掉伏,此階段是從多個(gè)高分節(jié)點(diǎn)中隨機(jī)挑選一個(gè)作為最終運(yùn)行pod的節(jié)點(diǎn);大概過程如下圖所示


image.png

提示:預(yù)選過程是一票否決機(jī)制澳窑,只要其中一個(gè)預(yù)選函數(shù)不通過斧散,對(duì)應(yīng)節(jié)點(diǎn)則直接被淘汰蔼卡;剩下通過預(yù)選的節(jié)點(diǎn)會(huì)進(jìn)入優(yōu)選階段节值,此階段每個(gè)節(jié)點(diǎn)會(huì)通過對(duì)應(yīng)的優(yōu)選函數(shù)來對(duì)各個(gè)節(jié)點(diǎn)評(píng)分,并計(jì)算每個(gè)節(jié)點(diǎn)的總分户辫;最后調(diào)度器會(huì)根據(jù)每個(gè)節(jié)點(diǎn)的最后總分來挑選一個(gè)最高分的節(jié)點(diǎn)麻裁,作為最終調(diào)度結(jié)果箍镜;如果最高分有多個(gè)節(jié)點(diǎn)瞻鹏,此時(shí)調(diào)度器會(huì)從對(duì)應(yīng)節(jié)點(diǎn)集合中隨機(jī)挑選一個(gè)作為最后調(diào)度結(jié)果,并把最后調(diào)度結(jié)果反饋給apiserver鹿寨;

影響調(diào)度的因素:

  • nodeName
  • nodeSelector: 選擇節(jié)點(diǎn)
  • nodeAffinity:節(jié)點(diǎn)親和性
  • podAffinity:pod親和性
  • taints:污點(diǎn)
  • tolerations:容忍

解析

集群調(diào)度原理

Scheduler調(diào)度步驟
  1. 首先用戶在通過 Kubernetes 客戶端 Kubectl 提交創(chuàng)建 Pod 的 Yaml 的文件新博,向Kubernetes 系統(tǒng)發(fā)起資源請(qǐng)求,該資源請(qǐng)求被提交到Kubernetes 系統(tǒng)脚草。

  2. Kubernetes 系統(tǒng)中赫悄,用戶通過命令行工具 Kubectl 向 Kubernetes 集群即用API Server 的方式發(fā)送“POST”請(qǐng)求,即創(chuàng)建 Pod 的請(qǐng)求馏慨。

  3. API Server 接收到請(qǐng)求后把創(chuàng)建 Pod 的信息存儲(chǔ)到 Etcd 中埂淮,從集群運(yùn)行那一刻起,資源調(diào)度系統(tǒng)Scheduler 就會(huì)定時(shí)去監(jiān)控 API Server

  4. 通過 API Server 得到創(chuàng)建 Pod 的信息写隶,Scheduler 采用 watch 機(jī)制倔撞,一旦 Etcd 存儲(chǔ) Pod 信息成功便會(huì)立即通知API Server

  5. API Server 會(huì)立即把Pod創(chuàng)建的消息通知Scheduler慕趴,Scheduler發(fā)現(xiàn) Pod 的屬性中 Dest Node 為空時(shí)(Dest Node="")便會(huì)立即觸發(fā)調(diào)度流程進(jìn)行調(diào)度痪蝇。

  6. 而這一個(gè)創(chuàng)建Pod對(duì)象,在調(diào)度的過程當(dāng)中有3個(gè)階段:節(jié)點(diǎn)預(yù)選冕房、節(jié)點(diǎn)優(yōu)選躏啰、節(jié)點(diǎn)選定,從而篩選出最佳的節(jié)點(diǎn)

    • 節(jié)點(diǎn)預(yù)選:基于一系列的預(yù)選規(guī)則對(duì)每個(gè)節(jié)點(diǎn)進(jìn)行檢查耙册,將那些不符合條件的節(jié)點(diǎn)過濾给僵,從而完成節(jié)點(diǎn)的預(yù)選
    • 節(jié)點(diǎn)優(yōu)選:對(duì)預(yù)選出的節(jié)點(diǎn)進(jìn)行優(yōu)先級(jí)排序,以便選出最合適運(yùn)行Pod對(duì)象的節(jié)點(diǎn)
    • 節(jié)點(diǎn)選定:從優(yōu)先級(jí)排序結(jié)果中挑選出優(yōu)先級(jí)最高的節(jié)點(diǎn)運(yùn)行Pod详拙,當(dāng)這類節(jié)點(diǎn)多于1個(gè)時(shí)帝际,則進(jìn)行隨機(jī)選擇
集群調(diào)度策略

Kubernetes調(diào)度器作為集群的大腦,在如何提高集群的資源利用率饶辙、保證集群中服務(wù)的穩(wěn)定運(yùn)行中也會(huì)變得越來越重要Kubernetes的資源分為兩種屬性蹲诀。

  1. 可壓縮資源(例如CPU循環(huán),Disk I/O帶寬)都是可以被限制和被回收的畸悬,對(duì)于一個(gè)Pod來說可以降低這些資源的使用量而不去殺掉Pod侧甫。
  2. 不可壓縮資源(例如內(nèi)存、硬盤空間)一般來說不殺掉Pod就沒法回收蹋宦。未來Kubernetes會(huì)加入更多資源,如網(wǎng)絡(luò)帶寬咒锻,存儲(chǔ)IOPS的支持冷冗。

集群調(diào)度特別復(fù)雜,有各種各樣的規(guī)則惑艇。調(diào)度器會(huì)根據(jù)各種規(guī)則計(jì)算出一個(gè)分?jǐn)?shù)蒿辙,根據(jù)分?jǐn)?shù)的大小來選擇節(jié)點(diǎn)拇泛。

常用預(yù)選策略
預(yù)選策略 作用
CheckNodeCondition 檢查節(jié)點(diǎn)網(wǎng)絡(luò)、磁盤等是否正常
HostName 如果Pod對(duì)象擁有spec.hostname屬性思灌,則檢查節(jié)點(diǎn)名
稱字符串是否和該屬性值匹配俺叭。
PodFitsHostPorts Pod的spec.hostPort屬性時(shí),檢查端口是否被占用
MatchNodeSelector Pod的spec.nodeSelector屬性時(shí)泰偿,檢查節(jié)點(diǎn)標(biāo)簽
NoDiskConflict Pod依賴的存儲(chǔ)卷在此節(jié)點(diǎn)是否可用
PodFitsResources 檢查節(jié)點(diǎn)上的資源(CPU熄守、內(nèi)存)可用性是否滿足Pod對(duì)
象的運(yùn)行需求。
PodToleratesNodeTaints Pod的spec.tolerations屬性耗跛,僅關(guān)注NoSchedule和
NoExecute兩個(gè)效用標(biāo)識(shí)的污點(diǎn)
PodToleratesNodeNoExecuteTaints Pod的spec.tolerations屬性裕照,是否能接納節(jié)點(diǎn)的
NoExecute類型污點(diǎn),默認(rèn)沒有啟用
CheckNodeLabelPresence 僅檢查節(jié)點(diǎn)上指定的所有標(biāo)簽的存在性,默認(rèn)沒有啟用
CheckServiceAffinity 將相同Service的Pod對(duì)象放置在同一個(gè)或同一類節(jié)點(diǎn)上
以提高效率,默認(rèn)沒有啟用
MaxEBSVolumeCount 檢查節(jié)點(diǎn)已掛載的EBS(亞馬遜彈性塊存儲(chǔ))存儲(chǔ)卷數(shù)量是
否超過設(shè)置的最大值,默認(rèn)為39
MaxGCEPDVolumeCount 檢查節(jié)點(diǎn)上已掛載的GCE PD(谷歌云存儲(chǔ)) 存儲(chǔ)卷數(shù)量
是否超過最大值调塌,默認(rèn)為16
MaxAzureDiskVolumeCount 檢查節(jié)點(diǎn)上已掛載的Azure Disk存儲(chǔ)卷數(shù)量是否超過最
大值晋南,默認(rèn)為16
CheckVolumeBinding 檢查節(jié)點(diǎn)上已綁定和未綁定的PVC是否滿足需求
NoVolumeZoneConflict 在給定區(qū)域zone限制下,檢查此節(jié)點(diǎn)部署的Pod對(duì)象是
否存在存儲(chǔ)卷沖突
CheckNodeMemoryPressure 檢查節(jié)點(diǎn)內(nèi)存壓力羔砾,如果壓力過大负间,那就不會(huì)講pod調(diào)度
至此
CheckPodePIDPressure 檢查節(jié)點(diǎn)PID資源壓力
CheckNodeDiskPressure 檢查節(jié)點(diǎn)磁盤資源壓力
MatchInterPodAffinity 檢查節(jié)點(diǎn)是否滿足Pod對(duì)象親和性或反親和性條件
常用優(yōu)先函數(shù)
函數(shù)名稱 說明
LeastRequestedPriority 節(jié)點(diǎn)的優(yōu)先級(jí)就由節(jié)點(diǎn)空閑資源與節(jié)點(diǎn)總?cè)萘康谋戎担从桑側(cè)萘?節(jié)點(diǎn)上
Pod的容量總和-新Pod的容量)/總?cè)萘浚﹣頉Q定姜凄。 CPU和內(nèi)存具有相同權(quán)
重唉擂,資源空閑比越高的節(jié)點(diǎn)得分越高。 cpu((capacity –
sum(requested)) * 10 / capacity) + memory((capacity –
sum(requested)) * 10 / capacity) / 2
BalancedResourceAllocation CPU和內(nèi)存使用率越接近的節(jié)點(diǎn)權(quán)重越高檀葛,該策略不能單獨(dú)使用玩祟,必須和
LeastRequestedPriority組合使用,盡量選擇在部署Pod后各項(xiàng)資源更均衡
的機(jī)器屿聋。 如果請(qǐng)求的資源(CPU或者內(nèi)存)需求大于節(jié)點(diǎn)的capacity空扎,那么
該節(jié)點(diǎn)永遠(yuǎn)不會(huì)被調(diào)度到。
InterPodAffinityPriority 通過迭代 weightedPodAffinityTerm 的元素計(jì)算和润讥,并且如果對(duì)該節(jié)點(diǎn)滿足
相應(yīng)的PodAffinityTerm转锈,則將 “weight” 加到和中,具有最高和的節(jié)點(diǎn)是最
優(yōu)選的楚殿。
SelectorSpreadPriority 為了更好的容災(zāi)撮慨,對(duì)同屬于一個(gè)service、replication controller或者replica
的多個(gè)Pod副本脆粥,盡量調(diào)度到多個(gè)不同的節(jié)點(diǎn)上砌溺。 如果指定了區(qū)域,調(diào)度器
則會(huì)盡量把Pod分散在不同區(qū)域的不同節(jié)點(diǎn)上变隔。當(dāng)一個(gè)Pod的被調(diào)度時(shí)规伐,會(huì)
先查找Pod對(duì)于的service或者replication controller, 然后查找service或
replication controller中已存在的Pod匣缘,運(yùn)行Pod越少的節(jié)點(diǎn)的得分越高猖闪。本
質(zhì)就是往運(yùn)行同類pod少的節(jié)點(diǎn)上分配鲜棠。
NodeAffinityPriority 親和性機(jī)制。Node Selectors(調(diào)度時(shí)將pod限定在指定節(jié)點(diǎn)上)培慌, 支持多
種操作符(In, NotIn, Exists, DoesNotExist, Gt, Lt)豁陆,而不限于對(duì)節(jié)點(diǎn)labels
的精確匹配。 另外支持兩種類型的選擇器吵护,一種是
“hard(requiredDuringSchedulingIgnoredDuringExecution)”選擇器盒音,
它保證所選的主機(jī)必須滿足所有Pod對(duì)主機(jī)的規(guī)則要求。 這種選擇器更像是
之前的nodeselector何址,在nodeselector的基礎(chǔ)上增加了更合適的表現(xiàn)語法里逆。
另一種是“soft(preferresDuringSchedulingIgnoredDuringExecution)”選
擇器, 它作為對(duì)調(diào)度器的提示用爪,調(diào)度器會(huì)盡量但不保證滿足NodeSelector的
所有要求原押。
NodePreferAvoidPodsPriority(權(quán)重1W) 如果 節(jié)點(diǎn)的 Anotation (注解信息)沒有設(shè)置 key-value:scheduler.
alpha.kubernetes.io/ preferAvoidPods = "...",則節(jié)點(diǎn)對(duì)該 policy 的得分
就是10分偎血, 加上權(quán)重10000诸衔,那么該node對(duì)該policy的得分至少10W分。如
果Node的Anotation設(shè)置了颇玷,
scheduler.alpha.kubernetes.io/preferAvoidPods = "..." 笨农,如果該 pod 對(duì)應(yīng)
的 Controller 是 ReplicationController 或 ReplicaSet, 則該 node 對(duì)該
policy 的得分就是0分帖渠。
TaintTolerationPriority 使用 Pod 中 tolerationList 與 節(jié)點(diǎn) Taint 列表項(xiàng)進(jìn)行匹配谒亦,配對(duì)成功的項(xiàng)越
多,則得分越低空郊。污點(diǎn)越匹配份招,得分越低
ImageLocalityPriority 根據(jù)Node上是否存在一個(gè)pod的容器運(yùn)行所需鏡像大小對(duì)優(yōu)先級(jí)打分,分值
為0-10狞甚。遍歷全部Node锁摔, 如果某個(gè)Node上pod容器所需的鏡像一個(gè)都不存
在,分值為0哼审; 如果Node上存在Pod容器部分所需鏡像谐腰,則根據(jù)滿足當(dāng)前需
求的鏡像的大小來決定分值,鏡像越大涩盾,分值就越高十气;如果Node上存在pod
所需全部鏡像,分值為10旁赊。默認(rèn)沒有啟用
EqualPriority 是一個(gè)優(yōu)先級(jí)函數(shù)桦踊,它給予所有節(jié)點(diǎn)相等權(quán)重。
MostRequestedPriority 在 ClusterAutoscalerProvider 中终畅,替換 LeastRequestedPriority籍胯,給使用
多資源的節(jié)點(diǎn),更高的優(yōu)先級(jí)离福。 計(jì)算公式為: (cpu(10 sum(requested)
/ capacity) + memory(10 sum(requested) / capacity)) / 2 默認(rèn)沒
有啟用

1. label

label是kubernetes核心概念之一杖狼,以key / value 的形式附加到各種對(duì)象上,如Pod妖爷、Service蝶涩、DeploymentNode等絮识。達(dá)到識(shí)別對(duì)象绿聘,關(guān)聯(lián)關(guān)系等目的。

查看 label

# 通常我們?cè)趉ubectl 命令上追加`--show-labels` 命令即可
# 下面我們演示一下常用對(duì)象的label 查看情況

# 查看node label
kubectl get node --show-labels
#--------------------------
NAME           STATUS                     ROLES                  AGE     VERSION   LABELS
k8s-master01   Ready,SchedulingDisabled   control-plane,master   7d16h   v1.23.8   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-slave02    Ready                      <none>                 6d22h   v1.23.8   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-slave02,kubernetes.io/os=linux
k8s-slave03    Ready                      <none>                 6d21h   v1.23.8   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-slave03,kubernetes.io/os=linux
#--------------------------

# 查看 pods label
kubectl get pods --show-labels
#--------------------------

NAME                               READY   STATUS    RESTARTS   AGE     LABELS
demonsetdemo-bgtgc                 1/1     Running   0          40h     app=demonsetdemo,controller-revision-hash=84978464f6,pod-template-generation=1
demonsetdemo-xnnf6                 1/1     Running   0          40h     app=demonsetdemo,controller-revision-hash=84978464f6,pod-template-generation=1
deploymentdemo1-5bc649f558-92bc9   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-fwhdr   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-gmpzz   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-pzvmd   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-qtt4r   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-slg5r   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-vskqr   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-xtp9s   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-xwt2s   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
deploymentdemo1-5bc649f558-z5xhr   1/1     Running   0          41h     app=deploymentdemo1,pod-template-hash=5bc649f558
nginx-app-74d589986c-bdf66         1/1     Running   0          5d15h   app=nginx,pod-template-hash=74d589986c
nginx-app-74d589986c-gfmsd         1/1     Running   0          5d15h   app=nginx,pod-template-hash=74d589986c
nginx-app-74d589986c-kdq6r         1/1     Running   0          5d15h   app=nginx,pod-template-hash=74d589986c
nginx-app-74d589986c-p4mbl         1/1     Running   0          5d16h   app=nginx,pod-template-hash=74d589986c
nginx-app-74d589986c-slszp         1/1     Running   0          5d15h   app=nginx,pod-template-hash=74d589986c
#--------------------------

# 查看deployment label
kubectl get deployment --show-labels
#--------------------------
NAME              READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
deploymentdemo1   10/10   10           10          45h     app=deploymentdemo1
nginx-app         5/5     5            5           5d16h   <none>
#--------------------------

# 查看service label
kubectl get service --show-labels
#--------------------------
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE     LABELS
deploymentdemo1-service   NodePort    10.222.58.200    <none>        8002:32002/TCP   44h     app=deploymentdemo1
kubernetes                ClusterIP   10.222.0.1       <none>        443/TCP          7d16h   component=apiserver,provider=kubernetes
nginx-app-service         NodePort    10.222.191.172   <none>        8001:32001/TCP   4d21h   app=nginx-app
#--------------------------

# 查看namespace label
kubectl get ns --show-labels
#--------------------------
NAME                   STATUS   AGE     LABELS
default                Active   7d17h   kubernetes.io/metadata.name=default
kube-node-lease        Active   7d17h   kubernetes.io/metadata.name=kube-node-lease
kube-public            Active   7d17h   kubernetes.io/metadata.name=kube-public
kube-system            Active   7d17h   kubernetes.io/metadata.name=kube-system
kubernetes-dashboard   Active   7d15h   kubernetes.io/metadata.name=kubernetes-dashboard
tmp-quota              Active   19h     kubernetes.io/metadata.name=tmp-quota
tmp-quota-range        Active   17h     kubernetes.io/metadata.name=tmp-quota-range
#--------------------------

設(shè)置 label

# 我們先選擇一個(gè)pods 節(jié)點(diǎn)
# NAME                               READY   STATUS    RESTARTS   AGE     LABELS
# nginx-app-74d589986c-slszp         1/1     Running   0          5d16h   app=nginx,pod-template-hash=74d589986c

# 然后我們對(duì)該節(jié)點(diǎn)次舌,設(shè)置label
# 語法: kubectl label 對(duì)象類型 對(duì)象名稱 key=value
kubectl label pods nginx-app-74d589986c-slszp myCustomLabel=abc123
#---------------------------
pod/nginx-app-74d589986c-slszp labeled
#---------------------------

# 我們查詢驗(yàn)證下
kubectl get pods --show-labels
#---------------------------
NAME                               READY   STATUS    RESTARTS   AGE     LABELS
nginx-app-74d589986c-slszp         1/1     Running   0          5d16h   app=nginx,myCustomLabel=abc123,pod-template-hash=74d589986c
#---------------------------

# 我們發(fā)現(xiàn)在 LABELS 項(xiàng)中 多了 我們自定義添加的這一項(xiàng)`myCustomLabel=abc123`

修改 label

# 修改label 與 設(shè)置label 一樣熄攘,只需要在 最后加上`--overwrite`即可
kubectl label pods nginx-app-74d589986c-slszp myCustomLabel=abc456 --overwrite

# 修改后
kubectl get pods --show-labels
#---------------------------
NAME                               READY   STATUS    RESTARTS   AGE     LABELS
nginx-app-74d589986c-slszp         1/1     Running   0          5d16h   app=nginx,myCustomLabel=abc456,pod-template-hash=74d589986c
#---------------------------

刪除 label

# 刪除label 也很簡(jiǎn)單,我們只要把 label 的value替換成`-`即可
kubectl label pods nginx-app-74d589986c-slszp myCustomLabel-
#---------------------------
pod/nginx-app-74d589986c-slszp unlabeled
#---------------------------

# 驗(yàn)證
kubectl get pods --show-labels
#---------------------------
nginx-app-74d589986c-slszp         1/1     Running   0          5d16h   app=nginx,pod-template-hash=74d589986c
#---------------------------

2. nodeName

nodeName是節(jié)點(diǎn)選擇約束的最簡(jiǎn)單形式彼念,但是由于其限制挪圾,通常很少使用它。nodeName是PodSpec的領(lǐng)域逐沙。

正常調(diào)度我們是不會(huì)在 master 節(jié)點(diǎn)上創(chuàng)建pod的

<font color=red size=4>pod.spec.nodeName將Pod直接調(diào)度到指定的Node節(jié)點(diǎn)上(包括master)哲思,會(huì)【跳過Scheduler的調(diào)度策略】,該匹配規(guī)則是【強(qiáng)制】匹配吩案∨锱猓可以越過Taints污點(diǎn)進(jìn)行調(diào)度。</font>

nodeName用于選擇節(jié)點(diǎn)的一些限制是:

  • 如果指定的節(jié)點(diǎn)不存在徘郭,則容器將不會(huì)運(yùn)行靠益,并且在某些情況下可能會(huì)自動(dòng)刪除。
  • 如果指定的節(jié)點(diǎn)沒有足夠的資源來容納該P(yáng)od崎岂,則該P(yáng)od將會(huì)失敗捆毫,并且其原因?qū)⒈恢赋觯鏞utOfmemory或OutOfcpu冲甘。
  • 云環(huán)境中的節(jié)點(diǎn)名稱并非總是可預(yù)測(cè)或穩(wěn)定的绩卤。
  • 如果指定的節(jié)點(diǎn)不存在,容器不會(huì)運(yùn)行江醇,一直處于Pending狀態(tài)

資源配置文件

vim scheduler_node-name.yml
#---------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-name-test
  labels:
    app: node-name-test
spec:
  replicas: 3
  template:
    metadata:
      name: node-name-test
      labels:
        app: node-name-test
    spec:
      containers:
        - name: node-name-test
          image: nginx
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      nodeName: k8s-master01 # 指定node節(jié)點(diǎn)
  selector:
    matchLabels:
      app: node-name-test
#---------------------------
# 執(zhí)行
kubectl apply -f scheduler_node-name.yml

# 查詢驗(yàn)證
kubectl get pods -o wide
#---------------------------

NAME                               READY   STATUS    RESTARTS   AGE     IP               NODE           NOMINATED NODE   READINESS GATES
node-name-test-7fd854bfc9-4l2kd    1/1     Running   0          12s     10.244.32.135    k8s-master01   <none>           <none>
node-name-test-7fd854bfc9-hgvzf    1/1     Running   0          12s     10.244.32.136    k8s-master01   <none>           <none>
node-name-test-7fd854bfc9-vr995    1/1     Running   0          12s     10.244.32.134    k8s-master01   <none>           <none>
#---------------------------


3. nodeSelector

nodeSelector是節(jié)點(diǎn)選擇約束的最簡(jiǎn)單推薦形式濒憋。nodeSelector是PodSpec的領(lǐng)域。它指定鍵值對(duì)的映射(label)陶夜。

<font color=red size=4>Pod.spec.nodeSelector是通過Kubernetes的label-selector機(jī)制選擇調(diào)度到那個(gè)節(jié)點(diǎn)凛驮。可以為一批node節(jié)點(diǎn)打上指定的標(biāo)簽条辟,由調(diào)度器去匹配符合的標(biāo)簽黔夭,并讓Pod調(diào)度到這些節(jié)點(diǎn)宏胯,該匹配規(guī)則屬于【強(qiáng)制】約束。由于是調(diào)度器調(diào)度本姥,因此不能越過Taints污點(diǎn)進(jìn)行調(diào)度肩袍。</font>

資源配置文件

# 我們先簡(jiǎn)述下操作流程:
# 演示業(yè)務(wù)場(chǎng)景: 我們把磁盤io高的服務(wù),部署到有ssd的node節(jié)點(diǎn)上婚惫。
# > step 1: 我們針對(duì)node `k8s-slave02` 設(shè)置label氛赐,標(biāo)識(shí)當(dāng)前節(jié)點(diǎn)是 ssd
# > step 2: 我們創(chuàng)建deployment資源文件,并指定`nodeSelector=ssd`
# > step 3: 查詢驗(yàn)證先舷,是否所有的pod 都運(yùn)行在 node `k8s-slave02`上

# step 1
kubectl label nodes k8s-slave02 disk=ssd
# 驗(yàn)證
kubectl get nodes --show-labels
# ---------------------
NAME           STATUS                     ROLES                  AGE     VERSION   LABELS
k8s-master01   Ready,SchedulingDisabled   control-plane,master   7d22h   v1.23.8   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-slave02    Ready                      <none>                 7d3h    v1.23.8   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-slave02,kubernetes.io/os=linux
k8s-slave03    Ready                      <none>                 7d2h    v1.23.8   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-slave03,kubernetes.io/os=linux
# ---------------------

# step 2
vim scheduler_node-selector.yml
# ---------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-selector-test
  labels:
    app: node-selector-test
spec:
  replicas: 5
  template:
    metadata:
      name: node-selector-test
      labels:
        app: node-selector-test
    spec:
      containers:
        - name: node-selector-test
          image: nginx
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      # nodeSelector 選擇 disk = ssd
      nodeSelector:
        disk: ssd
  selector:
    matchLabels:
      app: node-selector-test
# ---------------------

# 執(zhí)行
kubectl apply -f scheduler_node-selector.yml

# step 3
kubectl get pods -o wide
# ---------------------

NAME                                  READY   STATUS    RESTARTS   AGE     IP               NODE          NOMINATED NODE   READINESS GATES
node-selector-test-8485477cbf-492lg   1/1     Running   0          11s     10.244.220.252   k8s-slave02   <none>           <none>
node-selector-test-8485477cbf-8vgx8   1/1     Running   0          11s     10.244.220.250   k8s-slave02   <none>           <none>
node-selector-test-8485477cbf-d2gwf   1/1     Running   0          11s     10.244.220.251   k8s-slave02   <none>           <none>
node-selector-test-8485477cbf-nzmbp   1/1     Running   0          11s     10.244.220.249   k8s-slave02   <none>           <none>
node-selector-test-8485477cbf-r8bk8   1/1     Running   0          11s     10.244.220.248   k8s-slave02   <none>           <none>
# ---------------------

# 驗(yàn)證通過艰管,我們發(fā)現(xiàn)所有的 pod 都運(yùn)行在了 ssd 節(jié)點(diǎn) node `k8s-slave02` 上

4. nodeAffinity 親和性

nodeAffinity 比 nodeSelector 更靈活。它可以在nodeSelector的基礎(chǔ)上進(jìn)行一些簡(jiǎn)單的邏輯組合蒋川。不只是簡(jiǎn)單的匹配牲芋。調(diào)度可以分成軟策略硬策略兩種。其中邏輯支持操作符

節(jié)點(diǎn)親和性規(guī)則

required(硬親和性尔破,硬策略街图,不能商量,必須執(zhí)行) 懒构、preferred(軟親和性餐济,軟策略,可以商量,選擇執(zhí)行)。

  • 硬親和性規(guī)則不滿足時(shí)侥祭,Pod會(huì)置于Pending狀態(tài),軟親和性規(guī)則不滿足時(shí)篙悯,會(huì)選擇一個(gè)不匹配的節(jié)點(diǎn)

  • 當(dāng)節(jié)點(diǎn)標(biāo)簽改變而不再符合此節(jié)點(diǎn)親和性規(guī)則時(shí),不會(huì)將Pod從該節(jié)點(diǎn)移出铃绒,僅對(duì)新建的Pod對(duì)象生效

    nodeAffinity可對(duì)應(yīng)的兩種策略: preferredDuringSchedulingrequiredDuringScheduling

類型 描述
requiredDuringScheduling pod資源在配置中聲明一種標(biāo)簽鸽照,只有node節(jié)點(diǎn)跟我聲明的標(biāo)簽一致,pod才能
被調(diào)度到此節(jié)點(diǎn)颠悬,如果沒有匹配上矮燎,那我就一直等有匹配上的節(jié)點(diǎn)。
preferredDuringScheduling pod資源在配置中聲明一種標(biāo)簽赔癌,只有node節(jié)點(diǎn)跟我聲明的標(biāo)簽一致诞外,pod才能
被調(diào)度到此節(jié)點(diǎn),但如果沒有匹配上灾票,那我就不等了峡谊,隨機(jī)找節(jié)點(diǎn)。
IgnoredDuringExecution 如果pod已經(jīng)部署到此節(jié)點(diǎn),但如果此節(jié)點(diǎn)labels發(fā)生變化既们,已經(jīng)運(yùn)行的pod會(huì)
怎么辦濒析?pod也會(huì)繼續(xù)運(yùn)行,直到停止此pod生命周期贤壁。
RequiredDuringExecution 如果pod已經(jīng)部署到此節(jié)點(diǎn)悼枢,但如果此節(jié)點(diǎn)labels發(fā)生變化埠忘,已經(jīng)運(yùn)行的pod會(huì)
怎么辦脾拆?立刻停止生命周期,pod會(huì)重新調(diào)度到滿足條件的節(jié)點(diǎn)莹妒。

如果同時(shí)部署硬策略名船、軟策略,當(dāng)然兩種策略都會(huì)執(zhí)行旨怠,但是硬策略會(huì)苛刻一些渠驼,所以必須滿足硬策略的節(jié)點(diǎn),然后在這些節(jié)點(diǎn)中選擇滿足軟策略的節(jié)點(diǎn)鉴腻,但如果軟策略一個(gè)都不滿足迷扇,觸發(fā)軟策略的忽略這個(gè)軟策略規(guī)則,讓默認(rèn)調(diào)度算法爽哎,調(diào)度這個(gè)滿足硬策略的節(jié)點(diǎn)蜓席,直到遇到同時(shí)滿足硬策略、軟策略课锌。

硬策略

一個(gè)pod資源聲明了一個(gè)策略厨内,這個(gè)策略中可以寫限制條件,比如標(biāo)簽渺贤,在此pod資源交付到k8s集群后雏胃,他會(huì)在集群中所有節(jié)點(diǎn)找到符合我這個(gè)策略的節(jié)點(diǎn),比如定義的標(biāo)簽志鞍,如果在所有節(jié)點(diǎn)中找到符合我定義的標(biāo)簽瞭亮,我就在這個(gè)節(jié)點(diǎn)部署我的pod,如果所有節(jié)點(diǎn)都沒有滿足條件的話固棚,就不斷重試直到遇見滿足條件的node節(jié)點(diǎn)為止统翩,不然這個(gè)pod就別啟動(dòng)。將一直處于掛起玻孟,直到有符合要求才會(huì)在匹配上的節(jié)點(diǎn)上創(chuàng)建pod唆缴。硬策略適用于 pod 必須運(yùn)行在某種節(jié)點(diǎn),否則會(huì)出現(xiàn)問題的情況黍翎,比如集群中節(jié)點(diǎn)的架構(gòu)不同面徽,而運(yùn)行的服務(wù)必須依賴某種架構(gòu)提供的功能。

  • 方式一:Pod使用 spec.nodeSelector (基于等值關(guān)系);Pod使用 spec.nodeName
  • 方式二:Pod使用 spec.affinity 支持matchExpressions屬性 (復(fù)雜標(biāo)簽選擇機(jī)制)

requiredDuringScheduling<font color=red>IgnoredDuringExecution</font>
表示pod必須部署到滿足條件的節(jié)點(diǎn)上,如果沒有滿足條件的節(jié)點(diǎn)趟紊,就不停重試氮双。其中IgnoreDuringExecution表示pod部署之后運(yùn)行的時(shí)候,如果節(jié)點(diǎn)標(biāo)簽發(fā)生了變化霎匈,不再滿足pod指定的條件戴差,pod也會(huì)繼續(xù)運(yùn)行,直到停止此pod生命周期铛嘱。

requiredDuringScheduling<font color=red>RequiredDuringExecution</font>
表示pod必須部署到滿足條件的節(jié)點(diǎn)上暖释,如果沒有滿足條件的節(jié)點(diǎn),就不停重試墨吓。其中RequiredDuringExecution表示pod部署之后運(yùn)行的時(shí)候球匕,如果節(jié)點(diǎn)標(biāo)簽發(fā)生了變化,不再滿足pod指定的條件帖烘,停止此pod生命周期亮曹,重新選擇符合要求的節(jié)點(diǎn)。

軟策略

跟硬策略一樣秘症,都是pod資源聲明了一個(gè)策略照卦,這個(gè)策略中可以寫限制條件,比如標(biāo)簽乡摹,如果有節(jié)點(diǎn)能滿足我的條件役耕,就在此節(jié)點(diǎn)部署pod,但是如果所有節(jié)點(diǎn)全部沒有滿足調(diào)度要求的話趟卸,POD 就會(huì)忽略這條規(guī)則蹄葱,通過默認(rèn)的Scheduler調(diào)度算法,進(jìn)行pod部署锄列,直到有符合要求node節(jié)點(diǎn)图云,才會(huì)重新按照軟策略匹配到符合的節(jié)點(diǎn)上創(chuàng)建pod,說白了就是滿足條件最好了邻邮,沒有的話也無所謂了的策略竣况,此調(diào)度適用于服務(wù)最好運(yùn)行在某個(gè)區(qū)域,減少網(wǎng)絡(luò)傳輸?shù)韧惭稀_@種區(qū)分是用戶的具體需求決定的丹泉,并沒有絕對(duì)的技術(shù)依賴。

  • 柔性控制邏輯鸭蛙,當(dāng)條件不滿足時(shí)摹恨,能接受被編排于其他不符合條件的節(jié)點(diǎn)之上
  • 權(quán)重 weight 定義優(yōu)先級(jí),1-100 值越大優(yōu)先級(jí)越高

preferredDuringScheduling<font color=red>IgnoredDuringExecution</font>
表示優(yōu)先部署到滿足條件的節(jié)點(diǎn)上娶视,如果沒有滿足條件的節(jié)點(diǎn)晒哄,就忽略這些條件睁宰,按照正常邏輯部署。其中IgnoreDuringExecution表示pod部署之后運(yùn)行的時(shí)候寝凌,如果節(jié)點(diǎn)標(biāo)簽發(fā)生了變化柒傻,不再滿足pod指定的條件,pod也會(huì)繼續(xù)運(yùn)行较木,直到停止此pod生命周期红符。

preferredDuringScheduling<font color=red>RequiredDuringExecution</font>
表示優(yōu)先部署到滿足條件的節(jié)點(diǎn)上,如果沒有滿足條件的節(jié)點(diǎn)伐债,就忽略這些條件预侯,按照正常邏輯部署。其中RequiredDuringExecution表示如果后面節(jié)點(diǎn)標(biāo)簽發(fā)生了變化泳赋,滿足了條件雌桑,停止此pod生命周期,重新調(diào)度到滿足條件的節(jié)點(diǎn)祖今。

操作符

  • In: label的值在某個(gè)列表中
  • NotIn:label的值不在某個(gè)列表中
  • Exists:某個(gè)label存在
  • DoesNotExist:某個(gè)label不存在
  • Gt:label的值大于某個(gè)值(字符串比較)
  • Lt:label的值小于某個(gè)值(字符串比較)

資源配置文件

# 節(jié)點(diǎn)親和性,相對(duì)來說要復(fù)雜一些拣技。也更靈活千诬。
# 完整的文件太多,這里我們只挑重點(diǎn)膏斤。
# 推薦參考文章: https://blog.csdn.net/Jerry00713/article/details/124003264

# 硬策略(硬親和性)
# pod.sepc.affinity
#----------------------------
    affinity:
        nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                    - matchExpressions:
                        - key: kubernetes.io/hostname #node節(jié)點(diǎn)的標(biāo)簽
                          operator: In
                          values:
                            - k8s-node05 #集群真實(shí)節(jié)點(diǎn)名稱

#----------------------------

# 軟親和性
# pod.sepc.affinity
#----------------------------
...
    affinity:
        nodeAffinity:
            preferredDuringSchedulingIgnoredDuringExecution:
                - preference:
                    matchExpressions:
                        - key: kubernetes.io/hostname
                          operator: In
                          values:
                        - k8s-node02
                weight: 1 # 配置權(quán)重分
#----------------------------

5. podAffinity 親和性

podAffinity 和 nodeAffinity 相似徐绑。

同樣 適用上述:硬親和性軟親和性莫辨、操作符

pod硬親和性調(diào)度

Pod親和性描述一個(gè)Pod與具有某特征的現(xiàn)存Pod運(yùn)行位置的依賴關(guān)系傲茄;即需要事先存在被依賴的pod對(duì)象。

pod軟親和性調(diào)度

pod軟親和性調(diào)度用于 分散同一類應(yīng)用沮榜,調(diào)度至不同區(qū)域盘榨、機(jī)架、節(jié)點(diǎn)等蟆融。

6. taints 污點(diǎn)與容忍

<font color=red> 污點(diǎn)taints 是定義在node節(jié)點(diǎn)</font> 上的鍵值型屬性數(shù)據(jù)草巡,用于讓節(jié)點(diǎn)拒絕將Pod調(diào)度運(yùn)行于其上,除非Pod有接納節(jié)點(diǎn)污點(diǎn)的容忍度型酥。

<font color=red> 容忍度 tolerations 是定義在Pod </font>上的鍵值屬性數(shù)據(jù)山憨,用于配置可容忍的污點(diǎn),且調(diào)度器將Pod調(diào)度至其能容忍該節(jié)點(diǎn)污點(diǎn)的節(jié)點(diǎn)上或沒有污點(diǎn)的節(jié)點(diǎn)上 弥喉。

對(duì)于nodeAffinity無論是硬策略(硬親和)還是軟策略(軟親和)方式郁竟,都是調(diào)度 pod 到預(yù)期節(jié)點(diǎn)上,而Taints恰好與之相反由境,如果一個(gè)節(jié)點(diǎn)標(biāo)記為 Taints 棚亩,除非 pod 也被標(biāo)識(shí)為可以容忍污點(diǎn)節(jié)點(diǎn),否則該Taints 節(jié)點(diǎn)不會(huì)被調(diào)度 pod。

節(jié)點(diǎn)親和性蔑舞,是 pod 的一種屬性(偏好或硬性要求)拒担,它使 pod 被吸引到一類特定的節(jié)點(diǎn)。Taint 則相反攻询,它使節(jié)點(diǎn) 能夠 排斥 一類特定的 pod

Taint 和 toleration 相互配合从撼,可以用來避免 pod 被分配到不合適的節(jié)點(diǎn)上。每個(gè)節(jié)點(diǎn)上都可以應(yīng)用一個(gè)或多個(gè)taint 钧栖,這表示對(duì)于那些不能容忍這些 taint 的 pod低零,是不會(huì)被該節(jié)點(diǎn)接受的。如果將 toleration 應(yīng)用于pod上拯杠,則表示這些 pod 可以(但不要求)被調(diào)度到具有匹配 taint 的節(jié)點(diǎn)上

定義污點(diǎn)和容忍度

污點(diǎn)定義:nodes.spec.taints

容忍度定義:pods.spec.tolerations

使用kubectl taint命令可以給某個(gè)Node節(jié)點(diǎn)設(shè)置污點(diǎn)掏婶,Node被設(shè)置上污點(diǎn)之后就和Pod之間存在一種互斥的關(guān)系,可以讓node 拒絕 pod的調(diào)度執(zhí)行潭陪,甚至將node 已經(jīng)存在的pod驅(qū)逐出去

污點(diǎn)

污點(diǎn)的命令和 label比較像雄妥,除了要設(shè)置key / value 之外 還要指定 排斥等級(jí) effect

排斥等級(jí) 說明 說明
NoSchedule 不能容忍
但僅影響調(diào)度過程,已調(diào)度上去的pod不受影響依溯,僅對(duì)新增的pod效老厌。
表示 k8s 將不會(huì)將 Pod 調(diào)度到具有該污點(diǎn)的 Node 上
NoExecute 不能容忍
當(dāng)污點(diǎn)變動(dòng)時(shí),Pod對(duì)象會(huì)被驅(qū)逐黎炉。
表示 k8s 將不會(huì)將 Pod 調(diào)度到具有該污點(diǎn)的 Node 上枝秤,
同時(shí)會(huì)<font color=red>將 Node 上已經(jīng)存在的Pod 驅(qū)逐出去 </font>
PreferNoSchedule 柔性約束
節(jié)點(diǎn)現(xiàn)存Pod不受影響,如果實(shí)在是沒有符合的節(jié)點(diǎn)慷嗜,也可以被調(diào)度
表示 k8s 將盡量不會(huì)將 Pod 調(diào)度到具有該污點(diǎn)的 Node 上 淀弹。
盡量不把pod調(diào)度到此節(jié)點(diǎn)上運(yùn)行,若POD資源無法容忍所有節(jié)點(diǎn)庆械,改成可以容忍 所有污點(diǎn)薇溃,通過默認(rèn)調(diào)度算法啟動(dòng)POD,要容忍就容忍所有的污點(diǎn)干奢,不會(huì)按照污點(diǎn)數(shù)少進(jìn)行優(yōu)先調(diào)度

為了不影響之前的環(huán)境痊焊,我們先創(chuàng)建一個(gè)namespace :taint-demo-ns

kubectl create namespace taint-demo-ns

環(huán)境情況:

Node effect
k8s-master01 -
k8s-slave02 -
k8s-slave03 -
創(chuàng)建污點(diǎn)
# 創(chuàng)建單個(gè)污點(diǎn)
kubectl taint nodes k8s-slave03 taintKey=abc123:NoSchedule
# 創(chuàng)建多個(gè)污點(diǎn)
kubectl taint nodes k8s-slave03 taintKey=abc123:NoSchedule key2=def456:NoSchedule key3=ghj789:NoSchedule
刪除污點(diǎn)
 kubectl taint nodes k8s-slave03 taintKey=abc123:NoExecute-
修改污點(diǎn)
kubectl taint nodes k8s-slave03 taintKey=abc456:NoSchedule --overwrite
查看污點(diǎn)
kubectl describe node k8s-slave03 | grep -i taint
#-----------------------------------
Taints:             <none>
#-----------------------------------

# 我們對(duì)`k8s-slave03` 添加污點(diǎn)后再查看
kubectl describe node k8s-slave03 | grep -i taint
#-----------------------------------
Taints:             taintKey=abc123:NoSchedule
#-----------------------------------
資源配置文件
污點(diǎn)effect - NoSchedule

測(cè)試案例:

新部署的pod不會(huì)被調(diào)度到具有污點(diǎn)標(biāo)記且 effect = NoSchedule 的節(jié)點(diǎn)上。

> step 1:

  我們針對(duì) node `k8s-slave03` 設(shè)置污點(diǎn)忿峻, effect 規(guī)則為`NoSchedule`薄啥。

> step 2:

  我們編寫一個(gè)deployment,然后執(zhí)行逛尚。

> step 3:

  我們查看pods所在節(jié)點(diǎn)垄惧,是否存在在 `k8s-slave03`節(jié)點(diǎn)上

污點(diǎn)effect情況

Node effect
k8s-master01 -
k8s-slave02 -
k8s-slave03 NoSchedule
# step 1
kubectl taint nodes k8s-slave03 taintKey=abc123:NoSchedule

# step 2
vim scheduler_taint-test1.yml
#----------------------------
# 污點(diǎn)測(cè)試1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint-test1
  # 指定命名空間
  namespace: taint-demo-ns
  labels:
    app: taint-test1
spec:
  replicas: 3
  template:
    metadata:
      name: taint-test1
      labels:
        app: taint-test1
    spec:
      containers:
        - name: taint-test1
          image: nginx
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
  selector:
    matchLabels:
      app: taint-test1
#----------------------------
kubectl apply -f scheduler_taint-test1.yml

# step 3
kubectl get pods -n taint-demo-ns -o wide
#----------------------------
NAME                           READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
taint-test1-74dd797cc4-hr9qc   1/1     Running   0          50s   10.244.220.254   k8s-slave02   <none>           <none>
taint-test1-74dd797cc4-ncffj   1/1     Running   0          50s   10.244.220.253   k8s-slave02   <none>           <none>
taint-test1-74dd797cc4-qwhtw   1/1     Running   0          50s   10.244.220.255   k8s-slave02   <none>           <none>
#----------------------------

# 結(jié)論,符合我們的期望绰寞。k8s-slave02 設(shè)置了NoSchedule到逊,新建的pods不會(huì)被調(diào)度給 k8s-slave02
污點(diǎn)effect - NoExecute

測(cè)試案例:

node 節(jié)點(diǎn) 設(shè)置 污點(diǎn)-effect-NoExecute后铣口,此節(jié)點(diǎn)上的pod 會(huì)被驅(qū)逐。(我們會(huì)驅(qū)逐k8s-slave03上的所有pods)

> step 1:

  我們先查看node`k8s-slave03` 上 的pods觉壶,記錄下來脑题。

> step 2:

  我們針對(duì) node `k8s-slave03` 設(shè)置污點(diǎn), effect 規(guī)則為`NoSchedule`铜靶。

> step 3:

  我們查看pods所在節(jié)點(diǎn)叔遂,是否存在在 `k8s-slave02`節(jié)點(diǎn)上

污點(diǎn)effect情況

Node effect
k8s-master01 -
k8s-slave02 -
k8s-slave03 NoExecute
# step 1
kubectl describe node k8s-slave03
#-------------------------
...

  Namespace                   Name                                CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                                ------------  ----------  ---------------  -------------  ---
  default                     demonsetdemo-xnnf6                  0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d17h
  default                     deploymentdemo1-5bc649f558-92bc9    0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d18h
  default                     deploymentdemo1-5bc649f558-qtt4r    0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d18h
  default                     deploymentdemo1-5bc649f558-vskqr    0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d18h
  default                     deploymentdemo1-5bc649f558-xtp9s    0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d18h
  default                     deploymentdemo1-5bc649f558-z5xhr    0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d18h
  default                     nginx-app-74d589986c-bdf66          0 (0%)        0 (0%)      0 (0%)           0 (0%)         6d16h
  default                     nginx-app-74d589986c-gfmsd          0 (0%)        0 (0%)      0 (0%)           0 (0%)         6d16h
  default                     nginx-app-74d589986c-p4mbl          0 (0%)        0 (0%)      0 (0%)           0 (0%)         6d16h
  default                     nginx-app-74d589986c-slszp          0 (0%)        0 (0%)      0 (0%)           0 (0%)         6d16h
  kube-system                 calico-node-q789c                   250m (12%)    0 (0%)      0 (0%)           0 (0%)         7d22h
  kube-system                 kube-proxy-wwn68                    0 (0%)        0 (0%)      0 (0%)           0 (0%)         5d19h
  tmp-quota-range             quta-pod-test3                      550m (27%)    600m (30%)  110Mi (6%)       130Mi (7%)     41h
  tmp-quota                   quta-pod-test1                      800m (40%)    1 (50%)     150Mi (8%)       200Mi (11%)    42h

...
#-------------------------

# step 2
kubectl taint nodes k8s-slave03 taintKey=abc123:NoExecute 

# step 3
kubectl describe nodes k8s-slave03
#-------------------------
...
  Namespace                   Name                 CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                 ------------  ----------  ---------------  -------------  ---
  kube-system                 calico-node-q789c    250m (12%)    0 (0%)      0 (0%)           0 (0%)         7d23h
  kube-system                 kube-proxy-wwn68     0 (0%)        0 (0%)      0 (0%)           0 (0%)         5d19h
...
#-------------------------

# 結(jié)論,符合我們的期望争剿。node `k8s-slave03` 上的所有節(jié)點(diǎn)被驅(qū)逐已艰。我們發(fā)現(xiàn)`kube-system` namespace 還存在兩個(gè)節(jié)點(diǎn)`calico` 和 `kube-proxy`
污點(diǎn)effect - PreferNoSchedule

測(cè)試案例:

node 節(jié)點(diǎn) 設(shè)置 污點(diǎn)-effect-PreferNoSchedule后,如果沒有其他滿足條件的節(jié)點(diǎn)蚕苇,那么新建的pods會(huì)被分配到 有PreferNoSchedule的節(jié)點(diǎn)上哩掺。

> step 1:

  我們針對(duì) node `k8s-slave02` 設(shè)置污點(diǎn), effect 規(guī)則為`PreferNoSchedule`涩笤。

> step 2:

  我們針對(duì) node `k8s-slave03` 設(shè)置污點(diǎn)嚼吞, effect 規(guī)則為`NoSchedule`。

  我們新建deployment并運(yùn)行辆它。

> step 3:

  查看驅(qū)逐過程誊薄,查看pods所在節(jié)點(diǎn),是否存在在 `k8s-slave02`節(jié)點(diǎn)上

污點(diǎn)effect情況

Node effect
k8s-master01 -
k8s-slave02 PreferNoSchedule
k8s-slave03 NoSchedule
# step 1
kubectl taint nodes k8s-slave02 taintKey=abc123:PreferNoSchedule

# step 2
vim scheduler_taint-test2.yml
#---------------------------
# 污點(diǎn)測(cè)試2
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint-test2
  namespace: taint-demo-ns
  labels:
    app: taint-test2
spec:
  replicas: 3
  template:
    metadata:
      name: taint-test2
      labels:
        app: taint-test2
    spec:
      containers:
        - name: taint-test2
          image: nginx
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
  selector:
    matchLabels:
      app: taint-test2
#---------------------------
kubectl apply -f scheduler_taint-test2.yml

# step 3
kubectl get pods -n taint-demo-ns -o wide
#---------------------------
NAME                           READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
taint-test2-6878fdbc99-j2tvj   1/1     Running   0          26s   10.244.220.195   k8s-slave02   <none>           <none>
taint-test2-6878fdbc99-mmzrj   1/1     Running   0          26s   10.244.220.194   k8s-slave02   <none>           <none>
taint-test2-6878fdbc99-xfl57   1/1     Running   0          26s   10.244.220.193   k8s-slave02   <none>           <none>
#---------------------------

# 結(jié)論锰茉,符合我們的期望,PreferNoSchedule 是柔性約束切心,如果除了他之外沒有滿足條件的node飒筑,那么pods 會(huì)被調(diào)度給 具有PreferNoSchedule的節(jié)點(diǎn)上。

容忍度

容忍度是針對(duì)pod的配置绽昏。 通過 Pod.spec.tolerations屬性設(shè)置

資源配置文件

測(cè)試案例:

node k8s-slave02: 我們?cè)O(shè)置 污點(diǎn) NoSchedule协屡;

node k8s-slave03:我們?cè)O(shè)置污點(diǎn) NoExecute;

正常情況下全谤,我們新建的pods是無法被調(diào)度到 k8s-slave02 或 k8s-slave03 上的肤晓。

我們配置容忍度,然后再觀察調(diào)度情況

> step 1:

  我們針對(duì) node `k8s-slave02` 設(shè)置污點(diǎn)认然, effect 規(guī)則為`NoSchedule`补憾。

> step 2:

  我們針對(duì) node `k8s-slave03` 設(shè)置污點(diǎn), effect 規(guī)則為`NoExecute`卷员。

  我們新建deployment盈匾,配置容忍度,容忍` k8s-slave03`污點(diǎn)的所有情況

  執(zhí)行

> step 3:

查看pods所在節(jié)點(diǎn)毕骡,是否存在在 k8s-slave03節(jié)點(diǎn)上

污點(diǎn)effect情況

Node effect
k8s-master01 -
k8s-slave02 NoSchedule
k8s-slave03 NoExecute
# step 1
kubectl taint nodes k8s-slave02 taintKey=abc123:NoSchedule

# step 2
kubectl taint nodes k8s-slave03 taintKey=abc123:NoExecute
vim  scheduler_tolerations.yml
#----------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tolerations-test
  namespace: taint-demo-ns
  labels:
    app: tolerations-test
spec:
  replicas: 10
  template:
    metadata:
      name: tolerations-test
      labels:
        app: tolerations-test
    spec:
      containers:
        - name: tolerations-test
          image: nginx
          imagePullPolicy: IfNotPresent
      # 容忍度配置饺汹,要與對(duì)應(yīng)的污點(diǎn) 設(shè)置信息【完全匹配】,才會(huì)生效
      tolerations:
        - key: "taintKey"
          operator: "Equal"
          value: "abc123"
          effect: "NoExecute"
      restartPolicy: Always
  selector:
    matchLabels:
      app: tolerations-test
#----------------------------------
kubectl apply -f scheduler_tolerations.yml

# step 3
kubectl get pods -n taint-demo-ns -o wide
#----------------------------------
NAME                               READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
tolerations-test-f47f9d965-56zvf   1/1     Running   0          9s    10.244.211.205   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-7rwvm   1/1     Running   0          9s    10.244.211.198   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-87n4v   1/1     Running   0          9s    10.244.211.202   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-dnjcs   1/1     Running   0          9s    10.244.211.204   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-fdlm8   1/1     Running   0          9s    10.244.211.207   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-gkjbf   1/1     Running   0          9s    10.244.211.200   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-kps9d   1/1     Running   0          9s    10.244.211.199   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-nq2fm   1/1     Running   0          9s    10.244.211.197   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-p4s2k   1/1     Running   0          9s    10.244.211.203   k8s-slave03   <none>           <none>
tolerations-test-f47f9d965-pf5mb   1/1     Running   0          9s    10.244.211.206   k8s-slave03   <none>           <none>
#----------------------------------
kubectl describe node k8s-slave03 | grep -i taint
#----------------------------------
Taints:             taintKey=abc123:NoExecute
  taint-demo-ns               tolerations-test-f47f9d965-56zvf    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-7rwvm    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-87n4v    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-dnjcs    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-fdlm8    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-gkjbf    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-kps9d    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-nq2fm    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-p4s2k    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
  taint-demo-ns               tolerations-test-f47f9d965-pf5mb    0 (0%)        0 (0%)      0 (0%)           0 (0%)         70s
#----------------------------------

# 結(jié)論破讨,符合我們的期望就谜;我們對(duì)`k8s-slave03`配置了容忍度,因此在創(chuàng)建新的pods時(shí)展融,有可能會(huì)被調(diào)度到`k8s-slave03`上。 注意:是有可能,具體還要看每個(gè)節(jié)點(diǎn)的effect配置密末。

附錄

參考資料

Kubernetes 多租戶:資源配額

Kubernetes最佳實(shí)踐(四):資源請(qǐng)求和限制

Kubernetes 資源配額 ResourceQuota

k8s資源調(diào)度

【k8s】kubectl label命令(對(duì)node添加、刪除label)

Kubernetes K8S節(jié)點(diǎn)選擇

K8s資源調(diào)度方式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宰啦,一起剝皮案震驚了整個(gè)濱河市苏遥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赡模,老刑警劉巖田炭,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異漓柑,居然都是意外死亡教硫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門辆布,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞬矩,“玉大人,你說我怎么就攤上這事锋玲【坝茫” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵惭蹂,是天一觀的道長伞插。 經(jīng)常有香客問我,道長盾碗,這世上最難降的妖魔是什么媚污? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮廷雅,結(jié)果婚禮上耗美,老公的妹妹穿的比我還像新娘。我一直安慰自己航缀,他們只是感情好商架,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谬盐,像睡著了一般甸私。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上飞傀,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天皇型,我揣著相機(jī)與錄音诬烹,去河邊找鬼。 笑死弃鸦,一個(gè)胖子當(dāng)著我的面吹牛绞吁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播唬格,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼家破,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了购岗?” 一聲冷哼從身側(cè)響起汰聋,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喊积,沒想到半個(gè)月后烹困,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乾吻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年髓梅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绎签。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡枯饿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诡必,到底是詐尸還是另有隱情奢方,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布爸舒,位于F島的核電站袱巨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏碳抄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一场绿、第九天 我趴在偏房一處隱蔽的房頂上張望剖效。 院中可真熱鬧,春花似錦焰盗、人聲如沸璧尸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爷光。三九已至,卻和暖如春澎粟,著一層夾襖步出監(jiān)牢的瞬間蛀序,已是汗流浹背欢瞪。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留徐裸,地道東北人遣鼓。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像重贺,于是被迫代替她去往敵國和親骑祟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容