概述
kubernetes的資源調(diào)度機(jī)制拄氯,包括kubernetes常用調(diào)度器和調(diào)度策略安聘,調(diào)度優(yōu)先級和搶占機(jī)制
? 描述什么是kubernetes資源調(diào)度
? 列舉常用的kubernetes資源調(diào)度策略
? 描述kubernetes的資源搶占機(jī)制
目錄
- Kubernetes資源管理
- Kubernetes調(diào)度器
- Kubernetes調(diào)度策略
- Kubernetes調(diào)度優(yōu)先級和搶占機(jī)制
1. Kubernetes資源管理
1.1 查看node的資源管理信息
Kubernetes管理的資源所管理的集群中的每一臺計(jì)算節(jié)點(diǎn)都包含一定的資源袱衷,我們通過kubectl get node xxx -o yaml得到節(jié)點(diǎn)有關(guān)資源的描述
[root@k8s-master ~]# k get node k8s-node1 -o yaml
apiVersion: v1
kind: Node
metadata:
annotations:
......
allocatable:
cpu: "2"
ephemeral-storage: "18561997179"
hugepages-1Gi: "0"
hugepages-2Mi: "0"
memory: 2796836Ki
pods: "110"
capacity:
cpu: "2"
ephemeral-storage: 19669Mi
hugepages-1Gi: "0"
hugepages-2Mi: "0"
memory: 2899236Ki
pods: "110"
.....
1.2 Capacity資源數(shù)據(jù)的獲取
? 由于capacity反映的是這臺機(jī)器的資源真實(shí)數(shù)量,所以確認(rèn)這個(gè)信息的任務(wù)理所應(yīng)當(dāng)交給運(yùn)行在每臺機(jī)器上面的 kubelet上朝刊。kubelet目前把cadvisor的大量代碼直接作為vendor引入残炮。在kubelet啟動(dòng)后,這個(gè)內(nèi)部的cadvisor子模塊也會(huì)相應(yīng)啟動(dòng)筒捺,并且獲取這臺機(jī)器上面的各種信息柏腻。其中就包括了有關(guān)這臺機(jī)器的資源信息,而這個(gè)信息也自然作為這臺機(jī)器的真實(shí)資源信息焙矛,通過kubelet再上報(bào)給 apiserver葫盼。
1.3 Kubernetes資源管理
- 實(shí)際上,Qos劃分的主要應(yīng)用場景村斟,是當(dāng)宿主機(jī)資源緊張的時(shí)候贫导,kubelet對Pod進(jìn)行Eviction(資源回收)時(shí)需要用到的。
- 當(dāng)kubernetes所管理的不可壓縮資源短缺時(shí)蟆盹,就有可能觸發(fā)Eviction孩灯,此類不可壓縮資源包括:可用內(nèi)存(memory.available),可用的宿主機(jī)磁盤nodefs.available)逾滥,容器運(yùn)行鏡像存儲空間(imagefs.available)等
- 在kubernetes峰档,設(shè)置的eviction默認(rèn)閾值為
memory.available<100Mi
nodefs.available<10%
nodefs.inodesFree<5%
imagefs.available<15%
1.4 Kubernetes資源管理
- 可以通過如下命令配置Evciton觸發(fā)的閾值
kubelet --eviction?hard=imagefs.available<10%,memory.available<500Mi,nodefs.available<5%,no
defs.inodesFree<5% --eviction?soft=imagefs.available<30%,nodefs.available<10% --eviction-soft-grace?period=imagefs.available=2m,nodefs.available=2m --eviction-max-pod?grace-period=600
- Evciton分為以下兩種模式
? Soft模式:允許為某一項(xiàng)參數(shù)設(shè)置一個(gè)“優(yōu)雅時(shí)間”,這段時(shí)間是為了給Pod預(yù)留出退出時(shí)間寨昙,當(dāng)達(dá)到閾值之后一定時(shí)間之后讥巡,kubelet才會(huì)啟動(dòng)Eviction過程
? Hard模式:當(dāng)某一項(xiàng)參數(shù)達(dá)到閾值之后立刻觸發(fā),直接殺掉Pod
1.5 Kubernetes資源管理
原則:
1.出現(xiàn)資源緊張時(shí)舔哪,先對資源不足節(jié)點(diǎn)進(jìn)行隔離
2.按照優(yōu)先級欢顷,刪除不重要的pod進(jìn)行資源回收
- 當(dāng)宿主機(jī)的Eviction閾值達(dá)到之后,就會(huì)進(jìn)入MemoryPressure或DiskPressure的狀態(tài)捉蚤,從而避免新的Pod被調(diào)度到該節(jié)點(diǎn)上(通過給節(jié)點(diǎn)打上“污點(diǎn)”的方式實(shí)現(xiàn))抬驴。
? 首先被刪除的是Besteffort類別的Pod
? 其實(shí)是Burstable類別的Pod炼七,并且使用的某一項(xiàng)缺少資源超出了requests值 ? 最后是Guaranteed類別的Pod,并且Kubernetes會(huì)保證只有當(dāng)該類型的Pod使用資源量超過了limits的限制布持,才會(huì)被Eviction選中
? 對于同類別Qos的Pod豌拙,kubernetes會(huì)根據(jù)優(yōu)先級來選擇移除的順序
2 .Kubernetes調(diào)度器
- API Server在接受客戶端提交Pod對象創(chuàng)建請求后,然后是通過調(diào)度器(kube?scheduler)從集群中選擇一個(gè)可用的最佳節(jié)點(diǎn)來創(chuàng)建并運(yùn)行Pod题暖。而這一個(gè)創(chuàng)建Pod對象按傅,在調(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ī)則對每個(gè)節(jié)點(diǎn)進(jìn)行檢查灌侣,將那些不符合條件的節(jié)點(diǎn)過濾推捐,
從而完成節(jié)點(diǎn)的預(yù)選。
? 節(jié)點(diǎn)優(yōu)選:對預(yù)選出的節(jié)點(diǎn)進(jìn)行優(yōu)先級排序侧啼,以便選出最合適運(yùn)行Pod對象的節(jié)點(diǎn)牛柒。
? 節(jié)點(diǎn)選定:從優(yōu)先級排序結(jié)果中挑選出優(yōu)先級最高的節(jié)點(diǎn)運(yùn)行Pod,當(dāng)這類節(jié)點(diǎn)多于1個(gè)時(shí)痊乾,則進(jìn)行隨機(jī)選擇皮壁。 - 節(jié)點(diǎn)預(yù)選:在具體的調(diào)度流程中,默認(rèn)調(diào)度器會(huì)首先調(diào)用一組叫做Predicate的算
法哪审,來檢查每個(gè)Node蛾魄。 - 節(jié)點(diǎn)優(yōu)選:然后再調(diào)用一組叫做Priority的調(diào)度算法,來給上一步預(yù)選到的每個(gè)Node
打分 - 最終得分最高的那個(gè)Node就是調(diào)度結(jié)果湿滓,當(dāng)調(diào)度器對一個(gè)Pod調(diào)度成功滴须,就會(huì)在
它的spec.nodeName字段填寫上調(diào)度結(jié)果的名字
2.1 Kubernetes調(diào)度策略
- 預(yù)選策略(Predicates)實(shí)際上就是節(jié)點(diǎn)過濾器,例如節(jié)點(diǎn)標(biāo)簽必須能夠匹配到Pod資源的標(biāo)簽選擇器(PodMatchNodeSelector實(shí)現(xiàn)的規(guī)則)叽奥,以及Pod容器的資源請求量不能大于節(jié)點(diǎn)上剩余的可分配資源(PodFitsResource規(guī)則)等等扔水。
執(zhí)行預(yù)選操作,調(diào)度器會(huì)逐一根據(jù)規(guī)則進(jìn)行篩選朝氓,如果預(yù)選沒能選定一個(gè)合適的節(jié)點(diǎn)魔市,此時(shí)Pod會(huì)一直處于Pending狀態(tài),直到有一個(gè)可用節(jié)點(diǎn)完成調(diào)度赵哲。其常用的預(yù)選策略如下
? CheckNodeCondition:檢查是否可以在節(jié)點(diǎn)報(bào)告磁盤待德、網(wǎng)絡(luò)不可用或未準(zhǔn)備好的情況下將Pod對象調(diào)度其上。
? CheckNodeLabelPresence:僅檢查節(jié)點(diǎn)上指定的所有標(biāo)簽的存在性枫夺,要檢查的標(biāo)簽以及其可否存在取決于用戶的定義将宪。
2.2 Predicates常用策略
? CheckNodeCondition:檢查是否可以在節(jié)點(diǎn)報(bào)告磁盤、網(wǎng)絡(luò)不可用或未準(zhǔn)備好的情況下將Pod對象調(diào)度其上。
? PodToleratesNodeTaints:如果Pod對象中定義了spec.tolerations屬性涧偷,則需要檢查該屬性值是否可以接納節(jié)點(diǎn)定義的污點(diǎn)(taints)。
? CheckServiceAffinity:根據(jù)當(dāng)前Pod對象所屬的Service已有其他Pod對象所運(yùn)行的節(jié)點(diǎn)調(diào)度毙死,目前是將相同的Service的Pod對象放在同一個(gè)或同一類節(jié)點(diǎn)上燎潮。
? CheckVolumeBinding:檢查節(jié)點(diǎn)上已綁定和未綁定的PVC是否滿足Pod對象的存儲卷需求。
? PodFitsResources:檢查節(jié)點(diǎn)上的CPU和內(nèi)存資源是否滿足Pod的requests字段扼倘。
2.3 Predicates常用策略
? CheckNodeMemoryPressure:在給定了節(jié)點(diǎn)已經(jīng)上報(bào)了存在內(nèi)存資源壓力過大的狀態(tài)确封,則需要檢查該P(yáng)od是否可以調(diào)度到該節(jié)點(diǎn)上。
? CheckNodePIDPressure:如果給定的節(jié)點(diǎn)已經(jīng)報(bào)告了存在PID資源壓力過大的狀態(tài)再菊,則需要檢查該P(yáng)od是否可以調(diào)度到該節(jié)點(diǎn)上爪喘。
? CheckNodeDiskPressure:如果給定的節(jié)點(diǎn)存在磁盤資源壓力過大,則檢查該P(yáng)od對象是否可以調(diào)度到該節(jié)點(diǎn)上纠拔。
? MatchInterPodAffinity:檢查給定的節(jié)點(diǎn)能否可以滿足Pod對象的親和性和反親和性條件秉剑,用來實(shí)現(xiàn)Pod親和性調(diào)度或反親和性調(diào)度。
2.4 Priorities常用策略
- 預(yù)選策略篩選出一個(gè)節(jié)點(diǎn)列表就會(huì)進(jìn)入優(yōu)選階段(Priorities)稠诲,在這個(gè)過程調(diào)度器會(huì)向每個(gè)通過預(yù)選的節(jié)點(diǎn)傳遞一系列的優(yōu)選函數(shù)來計(jì)算其優(yōu)先級分值侦鹏,優(yōu)先級分值介于0-10之間,其中0表示不適用臀叙,10表示最適合托管該P(yáng)od對象略水。
-
另外,調(diào)度器還支持給每個(gè)優(yōu)選函數(shù)指定一個(gè)簡單的值劝萤,表示權(quán)重渊涝,進(jìn)行節(jié)點(diǎn)優(yōu)先級分值計(jì)算時(shí),它首先將每個(gè)優(yōu)選函數(shù)的計(jì)算得分乘以權(quán)重床嫌,然后再將所有優(yōu)選函數(shù)的得分相加跨释,從而得出節(jié)點(diǎn)的最終優(yōu)先級分值。權(quán)重可以讓管理員定義優(yōu)選函數(shù)傾向性的能力厌处。
2.5 Priorities常用策略
? LeastRequested: 最低要求煤傍,(CPU((capacity?sum(requested))10/capacity)+memory((capacity-sum(requested))10/capacity))
得數(shù)越高,得分越高
? BalancedResourceAllocation: 以CPU和內(nèi)存資源占用比率相近的得分越高
? NodePreferAvoidPods:(優(yōu)先級很高 得分位10 權(quán)重10000)根據(jù)節(jié)點(diǎn)注解信息
annotations是否有 "scheduler.alpha.kubernetes.io/preferAvoidePods" 如果有 則
不能運(yùn)行
? TaintToleration: Pod對象的spec.tolerations與節(jié)點(diǎn)的taints的進(jìn)行匹配都檢查嘱蛋,匹配
度越高蚯姆,得分越低
? SelectorSpreading: 標(biāo)簽選擇器分散度,查找與當(dāng)前pod對象同屬一個(gè)標(biāo)簽選擇器運(yùn)行的pod的節(jié)點(diǎn)越少的得分越高
2.6 Priorities常用策略
? InterPodAffinity: 在節(jié)點(diǎn)對Pod所需的資源等進(jìn)行匹配洒敏,匹配的越多得分越高
? NodeAffinity: 根據(jù)Pod中的nodeSelector對節(jié)點(diǎn)進(jìn)行匹配都檢查龄恋,匹配數(shù)量越多得分
越高
? MostRequested: (CPU((capacity?sum(requested))10/capacity)+memory((capacity-sum(requested))10/capacity)),
用來替換 LeastRequestedPriority凶伙,給使用多資源的節(jié)點(diǎn)郭毕,更高的調(diào)度優(yōu)先級,即盡量將資源利用率最大化函荣。
? NodeLabel: 檢查節(jié)點(diǎn)是否擁有特定標(biāo)簽显押,無論標(biāo)簽值是否有值扳肛,只要存在就得分,條數(shù)越多分?jǐn)?shù)越高
? ImageLocality: 檢查節(jié)點(diǎn)已有Pod所需鏡像體積大小之和進(jìn)行判斷乘碑,存在的鏡像體積越大挖息,得分越高
4 Kubernetes調(diào)度優(yōu)先級和搶占機(jī)制
- 正常情況下,當(dāng)一個(gè)Pod被調(diào)度失敗時(shí)兽肤,它就會(huì)進(jìn)入Pending狀態(tài)套腹,直到Pod被更新,或者集群狀態(tài)發(fā)生變化资铡,調(diào)度器才會(huì)對這個(gè)Pod進(jìn)行重新調(diào)度电禀。但某些高優(yōu)先級的Pod在調(diào)度失敗后,并不會(huì)Pending笤休,而是會(huì)驅(qū)逐某個(gè)Node上一些低優(yōu)先級的Pod尖飞,這樣就可以保證這個(gè)高優(yōu)先級的Pod調(diào)度成功。
- 優(yōu)先級(Priority)和搶占(Preemption)這兩種機(jī)制是為了解決Pod調(diào)度失敗之后該如何處理的問題店雅,而非在Pod最開始的調(diào)度階段被觸發(fā)
4.1 PriorityClass
- 而在kubernetes中葫松,優(yōu)先級和搶占機(jī)制是在1.10版本后才逐步可用的。要使用這個(gè)機(jī)制底洗,首先需要在kubernetes里提交一個(gè)Priorityclass的定義
apiVersion:
scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
- 上述yaml文件中的globalDefault被設(shè)置成true的話腋么,那就意味著這個(gè)PriorityClass的值會(huì)成為系統(tǒng)的默認(rèn)值。false表示的是只希望聲明使用該P(yáng)riorityClass的Pod擁有值為1000000的優(yōu)先級亥揖,而對于沒有聲明Priority的Pod來說珊擂,優(yōu)先級就是0
4.2 Priorityclass
- kubernetes規(guī)定,優(yōu)先級是一個(gè)32bit的整數(shù)费变,最大值不超過1000000000(10億)摧扇,并且值越大優(yōu)先級越高。超過10億的挚歧,是被kubernetes保留下來分配給系統(tǒng)pod使用的扛稽。目的是保證系統(tǒng)pod不會(huì)被用戶搶占掉
[root@k8s-master ~]# k get priorityclasses.scheduling.k8s.io
NAME VALUE GLOBAL-DEFAULT AGE
system-cluster-critical 2000000000 false 88d
system-node-critical 2000001000 false 88d
[root@k8s-master ~]# k get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-584795fc57-76l7g 1/1 Running 303 103d
coredns-584795fc57-9nk6q 1/1 Running 303 104d
etcd-k8s-master 1/1 Running 75 104d
kube-apiserver-k8s-master 1/1 Running 75 104d
kube-controller-manager-k8s-master 1/1 Running 75 104d
kube-flannel-ds-amd64-6zdr2 1/1 Running 76 104d
kube-flannel-ds-amd64-hp2k7 1/1 Running 55 104d
kube-flannel-ds-amd64-wbbrw 1/1 Running 53 104d
kube-proxy-bcc2z 1/1 Running 74 104d
kube-proxy-c7kf4 1/1 Running 55 104d
kube-proxy-qpttz 1/1 Running 54 104d
kube-scheduler-k8s-master 1/1 Running 75 104d
[root@k8s-master ~]# k -n kube-system get pod kube-apiserver-k8s-master -o yaml | grep -i pri -A 5 -B 5
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.227.10
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
--
- --requestheader-username-headers=X-Remote-User
- --secure-port=6443
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
- --service-cluster-ip-range=10.96.0.0/12
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
image: k8s.gcr.io/kube-apiserver:v1.14.10
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
--
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
hostNetwork: true
nodeName: k8s-master
priority: 2000000000
priorityClassName: system-cluster-critical
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
tolerations:
[root@k8s-master ~]#
4.3 Priorityclass
- 創(chuàng)建完成后就可以在Pod創(chuàng)建過程中引用該對象
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority
4.4 示例
- 創(chuàng)建pri class
[root@k8s-master ~]# cat pr.yaml
apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false <== 設(shè)置該class是否為默認(rèn)class,如果建立pod時(shí)沒有指priclass滑负,則使用默認(rèn)class
description: "This priority class should be used for XYZ service pods only."
[root@k8s-master ~]# k apply -f pr.yaml
priorityclass.scheduling.k8s.io/high-priority created
[root@k8s-master ~]# k get priorityclasses.scheduling.k8s.io
NAME VALUE GLOBAL-DEFAULT AGE
high-priority 1000000 false 8s
system-cluster-critical 2000000000 false 104d
system-node-critical 2000001000 false 104d
確認(rèn)創(chuàng)建結(jié)果
[root@k8s-master ~]# k describe priorityclasses.scheduling.k8s.io high-priority
Name: high-priority
Value: 1000000
GlobalDefault: false
Description: This priority class should be used for XYZ service pods only.
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"scheduling.k8s.io/v1beta1","description":"This priority class should be used for XYZ service pods only.","globalDefault":false,"kind":"PriorityClass","metadata":{"annotations":{},"name":"high-priority"},"value":1000000}
Events: <none>
- 部署Pod在张,聲明使用該P(yáng)riorityClass對象
**編輯pod yaml文件
[root@k8s-master ~]# cat ~/ppod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx1
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority
**應(yīng)用ppod
[root@k8s-master ~]# k apply -f ppod.yaml
pod/nginx1 created
[root@k8s-master ~]# k get pod
NAME READY STATUS RESTARTS AGE
cm-test-pod 1/1 Running 57 21d
cmpod2 1/1 Running 55 21d
httpd-deployment-859778b7b6-5rwrn 1/1 Running 27 71d
httpd-deployment-859778b7b6-hfw9t 1/1 Running 27 71d
httpd-deployment-859778b7b6-l7vwd 1/1 Running 26 70d
nginx1 1/1 Running 0 5s
spod 1/1 Running 51 21d
**驗(yàn)證應(yīng)用結(jié)果
[root@k8s-master ~]# k describe pod nginx1
Name: nginx1
Namespace: default
Priority: 1000000
Priority Class Name: high-priority