调度器流程
kube-scheduler
是 kubernetes 的调度器,它的主要作用就是根据特定的调度算法和调度策略将 Pod 调度到合适的 Node 节点上去,启动之后会一直监听 API Server,获取到 PodSpec.NodeName 为空的 Pod,对每个 Pod 都会创建一个 binding。
调度主要分为以下几个部分:
- 首先是预选过程,过滤掉不满足条件的节点,这个过程称为
Predicate
- 然后是优选过程,对通过的节点按照优先级排序,称之为
Priority
- 最后从中选择优先级最高的节点 - 即node[0],如果中间任何一步骤有错误,就直接返回错误
API-Server到调度器流程
如上图:
- 当api-server(通过3A - 认证、鉴权、准入:Mutating和Validating)接收到请求
- 保存到etcd,这个时候是pod是没有node信息的,需要调度器介入 - 把pod的nodename字段赋值。
- 当pod被调度到合适的节点,将发请求到api-server通知etcd修改数据。
scheduler就是如下图:
调度器分成两个阶段
- 预选 - Predicate:过滤掉不满足条件的节点。
- 优选 - Priority:对满足条件的节点进行排序,选择排序第一位的节点进行调度。
预选 - Predicate
Predicate 阶段就是把不满足条件的节点过滤掉。
如果有满足条件的节点,则进入到优选阶段。
如果所有节点都不满足条件,那么Pod将一直处于Pending状态,直到有节点满足条件,在这期间调度器会不断的进行重试。
这里着重讲几个常见的过滤策略:
- HostPort - 端口冲突
- ResourceRequire - 资源需求
- PodAffinity - 亲和性
- PodToleratesNodeTaints - 检查pod是否容忍节点的taint
另外还有很多策略,类似这个节点要求PVC存储卷之类的。
更多策略请参考官网,这里不再叙述。
kube-scheduler 配置 (v1) | Kubernetes
PodFitsHostPort - 端口冲突
pod可能需要开hostport到节点(映射端口),如果节点已占用该端口,则该pod不会被调度到该节点。
ResourceRequire - 资源需求
如下图所示:本机由于没有10个cpu资源,它就处于pending状态。
# cat recourse-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: 1Gi
cpu: 10
requests:
memory: 256Mi
cpu: 10
# desribe 查看一下原因,提示2个node不够cpu资源进行调度。
kubectl describe po nginx-deployment-7696cd5d99-hdzht
PodAffinity - 亲和性
下面例子将演示:设置节点强亲和性 - 要求要有disktype=ssd的节点才能调度。
备注:Affinity有强亲和度和弱亲和度,
强亲和度:是在预选 - Predicate阶段进行筛选作用。表现为RequiredDuringSchedulingIgnoredDuringExecution
弱亲和度:是在优选 - Priority阶段进行排序作用。表现为
PreferredDuringSchedulingIgnoredDuringExecution
源码:
# cat affinity.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
PodToleratesNodeTaints - 检查pod是否容忍节点的taint
下面例子将演示:
当节点设置了taint,pod没设置相应的tolerates的时候是不可以调度到该节点
kubectl taint no vm-0-13-ubuntu special=taintNode:NoSchedule
#cat tolerate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
优选 - Priority
- SelectorSpreadPriority:优先减少节点上属于同一个Service 或 Replication Controller 的 Pod数量。
- LeastRequestedPriority:优先调度到请求资源少的节点上。
- BalancedResourceAllocation:优先平衡各节点的资源使用。
- NodeAffinityPriority:优先调度到匹配NodeAffinity的节点上。
- TaintTolerationPriority:优先调度到匹配TaintToleration的节点上。
LeastRequestedPriority 资源优先
说到资源,我们先要了解这些概念:
- Qos - 服务质量等级
- initContainer - 初始化容器
QoS(Quality of Service) 简介
QoS(Quality of Service)服务质量等级,是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级,可以是以下等级之一:
Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。如果一个容器只指明limit而未设定request,则request的值等于limit值。
Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。
BestEffort:容器没有设置任何内存或者 CPU 的限制或请求。
Qos等级还涉及到Evict-驱逐策略,后面文章会介绍。
initContainer - 初始化容器
initContainer是在主Container之前执行的。
当有多个initContainer的时候,顺序是由上执行顺序执行的,并且执行完成后立即退出。所有只计算cpu.request最多的initContainer即可,而不需要计算所有的InitContainer资源总和。
NodeAffinityPriority:亲和度优先
把Pod调度到指定节点上,可以通过nodeSelector、nodeAffinity、podAffinity以及Taints和Tolerates 策略将 Pod调度到需要的节点上。
类似,使用nodeSelector,给节点打上标签
kubectl label no nodeName distype=ssd
调度器只会把该pod调度到带有标签 distype=ssd的节点上。
亲和度相关规则上面已经讲述,只需要把required改为preferred就行
弱亲和度:是在优选 - Priority阶段进行排序作用。表现为
PreferredDuringSchedulingIgnoredDuringExecution