企业级运维之云原生与Kubernetes实战课程
第二章第3讲 Kubernetes调度和资源管理
视频地址:https://developer.aliyun.com/learning/course/913/detail/14505
摘要:本小节主要内容为Pod调度和资源管理,包括Pod调度过程、资源源调度和关系调度、调度相关的配置和使用、K8s组件控制器、SVC创建及使用、Pod生命周期管理及Kubectl常用命令和使用技巧。
目录
- Pod调度过程
- 资源调度和关系调度
- 调度相关的配置和使用
- 优先调度
一、Pod调度过程
调度过程是把Pod放到合适Node上:
- 满足Pod资源要求;
- 满足Pod的特殊关系要求;
- 满足Node限制条件要求;
- 做到集群资源合理利用;
Controllers副本集控制器Kube-Scheduler调度组件,按照预定的调度策略,将Pod调度到相应的机器上,Kubelet负责维护容器的生命周期,同时也负责Volume和网络的管理。
使用kubectl或者在控制台创建deployment类型Pod,向Apiserver发送请求,scheduler监控到Pod调度请求后,如何调度呢?
Kubernetes的默认调度过程
- 客户端向api-server发出控制器 (deployment,statefulset,job,cronjob)创建请求,最终会转化为创建和调度Pod;
- kube-scheduler通过api-server获取还未调度的Pod列表,通过对应的筛选规则和算法循环遍历为每个Pod分配节点,筛选分为两阶段:
- Predicate:过滤(预选)阶段,将所有节点混在一起,通过一定算法对匹配项进行匹配,将不合格的节点剔出去,留下合格的节点,如果此时没有筛选出合适的节点,则Pod会进入pending状态,不断重试调度,直到有合适节点为止;
- Priority:优选阶段,对刚刚通过过滤阶段筛选出来的节点,通过权重和优先级进行计算得出一个最终得分,这个分值范围为(0-10),得分高的为最合适的调度节点。
- 选举得分最高的主机binding,结果存储etcd;
- 最终选举节点kubelet接收指令进行Pod的创建。
二、资源调度和关系调度
除了集群默认调度能力外,还有自定义调度,用户可以设置Pod的资源限额参数、亲和性、反亲和性、污点等,实现自定义调度策略,使Pod能够充分利用资源并且按照业务需求合理调度。
1. Kubernetes 基础调度能力
a. 资源调度:满足Pod资源要求
- Resources:CPU/Memory/Storage/GPU/FGPA(资源大小限制);
- QoS:Guaranteed/Burstable/BestEffort (服务质量要求);
- Resource Quota (配额限制);
b. 关系调度:满足Pod/Node的特殊关系/条件要求
- PodAffinity/PodAntiAffinity:Pod和Pod间关系(亲和性和反亲和性);
- NodeSelector/NodeAffinity:由Pod决定适合自己的Node (节点选择器);
- Taint/Tolerations:限制调度到某些Node (污点限制);
如果未做过节点nodeSelector,亲和性(node affinity) 或Pod亲和、反亲和性 (Pod affinity/anti-affinity) 等Pod高级调度策略设置,则没有办法指定服务部署到指定节点上,可能会造成CPU或内存等密集型的Pod同时分配到相同Node,造成资源竞争;另一方面,如果未对资源进行限制,一些关键的服务可能会因为资源竞争因OOM (Out of Memory) 等原因被kill掉,或者被限制CPU使用。
a. Pod的资源类型,可以对cpu、内存、存储、gpu资源的使用量进行限制
- Cpu
- Memory
- ephemeral-storage
- extended-resource:nvidia.com/gpu
b. 在应用的container标签下面增加resource 标签,即可对Pod资源的使用量进行限制;
示例:
apiversion:v1
kind:Pod
metadata:
namespace:demo-ns
namedemo-pod
Spec:
containers:
- image:nginx:latest
name:demo-container
requests:
cpu:2
memory:1Gi
1imits:
cpu:2
memory:1Gi
如上yaml文件中,指明了容器信息及资源限制,requests表示需要请求的资源大小,而limits表示容器限制资源的大小,如果容器内使用的内存超过了limits设置的内存大小,会发生OOM(out of memory),导致容器重启;如果容器内CPU使用超过了limits设置的CPU大小,并不会导致容器重启。
c. 如何判断请求的内存大小
- 通过执行命令kubectl describe node xxx(xxx为节点名),查看资源使用情况及请求资源统计。
2.如何满足Pod资源要求
a. 什么是PodQoS?
- Quality of Service
Kubernetes为了实现资源被有效调度和分配的同时提高资源利用率,Kubernetes针对不同服务质量的预期,通过QoS (Quality of Service) 来对Pod进行服务质量管理,提供了采用requests和limits两种类型对资源进行分配和使用限制。
b. QoS的三种类型:
- Guaranteed-高,保障(CPU/Memory必须request==limit,其余资源可不等);
- Burstable-中,弹性(CPU/Memory request和limit不相等);
- BestEffort-低,尽力而为(所有资源request/limit必须都不填);
c. 资源回收策略
- 当kubernetes集群中,某个节点上可用资源比较小时,kubernetes提供了资源回收策略保证被调度到该节点pod服务正常运行。当节点上的内存或者CPU资源耗尽时,可能会造成该节点上正在运行的pod服务不稳定。
- Kubernetes通过kubelet来进行回收策略控制,保证节点上Pod在节点点资源比较小时可以稳定运行。
d. QoS Pods被kill掉场景与顺序
- Best-effort类型的Pods:系统用完了全部内存时,该类型pods会最先被kill掉;
- Burstable类型Pods:系统用完了全部内存,且没有Best-Effort container可以被kill时,该类型Pods会被kill掉;
- Guaranteed Pods:系统用完了全部内存,且没有Burstable与Best-Effort container可以被kill,该类型的Pods会被kill掉;
注:如果Pod进程因使用超过预先设定的limites,而非Node资源紧张情况,系统倾向于在其原所在的机器上重启该container或本机或其他重新创建一个Pod。
e. ResourceQuota
作用:限制每个Namespace资源用量,如对Pod内存和CPU限制。
用法:
-pernamespace
-Scope
Terminating/NotTerminating BestEffort/NotBestEffort priorityClass
当Quota超限后会禁止创建:
-forbidden:exceeded quota
一个namespace下面可以创建多个ResourceQuota(ResourceQuota本身也可以限制ResourceQuota的数量),常规的使用是把计算资源quota(cpu、mem等),存储资源quota(storage、pvc等),对象数量quota(Pod、service等)分别创建在不同的ResourceQuota下面,但是各个ResourceQuota中的限制项是可以重复的,这时会取最小的值。
如下示例yaml文件中,限制demo-ns Namespace下非BestEffort QoS的Quota,cpu只能使用1000个、memory只能使用200Gi、Pods只能创建10个:
kind:ResourceQuota
metadata:
name:demo-quota
namespace:demo-ns
Spec:
hard:
cpu:"1000"
memory:200Gi
pods:"10"
scopeSelector:#可以不填
matchExpressions:
- operator:Exists
scopeName: NotBestEffort
三. 调度相关的配置和使用
1. 如何满足Pod与Pod之间的关系要求?—Pod亲和调度
a. Pod亲和调度 PodAffinity
- 必须和某些Pod调度到一起
requiredDuringSchedulinglgnoredDuringExecution
- 优先和某些Pod调度到一起
preferredDuringSchedulinglgnoredDuringExecution
b. Pod反亲和调度 PodAntiAffinity
- 禁止和某些Pod调度到一起
requiredDuringSchedulingIgnoredDuringExecution
- 优先不和某些Pod调度到一起
preferredDuringSchedulinglgnoredDuringExecution
c. Operator
- In/NotIn/Exists/DoesNotExist
d. nodeSelector标签选择器
- 节点选择约束的最简单推荐形式。可以将nodeSelector 字段添加到 Pod 的规约中设置你希望目标节点所具有的节点标签。Kubernetes 只会将 Pod 调度到指定的每个标签的节点上。
如下示例中,标签的Key为disktype,Value为 ssd。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
必须调度到带了K1=V1标签的Pod所在节点:
apiversion:vl
kind:Pod
metadata:
namespace:demo-ns
name:demo-pod
spec:
containers:
- image: nginx:1atest
name:demo-container
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:matchExpressions:
- key:k1
operator:In
values:
- vl
topologykey:"kubernetes.io/hostname"
禁止调度到带了K1=V1标签的Pod所在节点:
apiversion:vl
kind:Pod
metadata:
namespace:demo-ns
name:demo-pod
spec:
containers:
- image: nginx:1atest
name:demo-container
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- 1abelSelector:
matchExpressions:
- key:kl
operator:In
values:
- v1
topologykey:"kubernetes.io/hostname"
2. 如何满足Pod与Pod之间的关系要求?—Node亲和调度
a. 节点污点Node Taints
- 一个Node可以有多个Taints
- Effect(不能为空)
- NoSchedule:只是禁止新Pods调度上来;
- PreferNoSchedule:尽量不调度到这台;
- NoExecute:会驱逐没有对应toleration的Pods,并且也不会调度新的上来;
b. Pod Tolerations
- 一个Pod可以有多个Tolerations
- Effect可以为空,匹配所有
- 取值和Taints的Effect一致
- Operator
- Exists/Equal
示例:
Node上带了K1=V1且效果是NoSchedule的Taints:
apiversion:vl
Kind:Node
metadata:
name:demo-node
spec:
taints:
- key:"k1"
value:"v1"
effect:"Noschedule"
Pod上必须带有K1=V1且效果是NoSchedule的Tolerations:
apiversion:v1
kind:Pod
metadata:
namespace:demo-name
spec:
containers:
image:nginx=latest
name:demo-container
tolerations:
-key:"k1"
operatorEqual"
value:"v1" #当op=Exists可为空
effect:"Noschedule" #可以为空,匹配所有
四、集群资源优先级调度
1. 集群资源不够时怎么办?
- 先到先得策略(FIFO):简单、相对公平、上手快;
- 优先级策略(Priority):符合日常公司业务特点;
优先级和抢占机制,解决的是Pod调度失败时该怎么办的问题。正常情况下,当一个Pod调度失败后,它就会被暂时“搁置”起来,直到Pod被更新,或者集群状态发生变化,调度器才会对这个Pod进行重新调度。
2. 特殊要求的场景:
- 当一个高优先级的Pod调度失败后,该Pod并不会被“搁置”,而是会“挤走”某个Node上的一些低优先级的Pod,这样就保证这个高优先级Pod的调度成功;
- 如何使用优先级调度呢?需要创建一个priorityClass资源,然后再为每个Pod应用指定不同的priorityClassName,这样就完成了优先级以及优先级调度的配置。
3. 优先级调度的配置
- 创建PriorityClass优先级资源,声明优先级大小;
- 为各个Pod应用指定不同的priorityClassName;
- 内置默认优先级:DefaultPriorityWhenNoDefaultClassExists=0
- 用户可配置的最大优先级限制HighestUserDefinablePriority=1000000000
- 系统级别优先级SystemCriticalPriority=2000000000
- 内置系统级别优先级system-cluster-critical、system-node-critical
示例:
- 创建一个名为high的priorityClass,得分为10000,示例如下:
apiversion:scheduiing.K8s.io/v1
kind:Priorityclass
metadata:
name:high
value:10000
galobalDefault:false
- 创建一个名为low的priorityClass,得分为100,示例如下:
apiversion:scheduling.k8s.io/v1
kind:Priorityclass
metadata:
name:low
value=100
g1oba1Default:false