今天主要介绍一下kubernetes中调度的一些用法
简介
- Scheduler
当用户请求创建一个Pod通过ApiServer认证完成以后,将请求送达到调度器上,然后通过一系列的调度算法,将Pod调度到合理的Node节点上
1. Scheduler
1.1 NodeScheduler
在实际情况下我们可能需要将Pod调度到指定的一些Node节点上,可以通过Node的标签(Label)和Pod的NodeSelector属性相匹配,来达到上述目的。
NodeScheduler实现方式
我们可以通过在节点打上Label,通过定义Pod时,指定Label将Pod调度到指定的节点上
kubectl label node nodename label=labelname
[root@k8s-master01 ~]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-master01 Ready <none> 6d6h v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-master02 Ready <none> 6d6h v1.19.0 app=linux,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master02,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-node01 Ready <none> 6d6h v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ds=true,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux,node.kubernetes.io/node=,xinyuan=liu
k8s-node02 Ready <none> 6d6h v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ds=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux,node.kubernetes.io/node=,zone=foo
[root@k8s-master01 ~]#
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# kubectl label node k8s-node01 itax=app
配置yaml文件
在template.metadata.spec.nodeSelector定义node标签
[root@k8s-master01 ~]# cat deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginxapp
labels:
app: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
containers:
- name: nginxweb1
image: nginx:1.15-alpine
nodeSelector: #定义node标签调度
itax: app #标签名字和值
注意
- 如果我们在其它的node上也定义了这个标签,这时调度器会根据一系列的调度算法选择最优的node将Pod调度上去
- 如果资源清单里设置的node标签不存做,那么Pod就不会被创建成功一直处于Pending状态,找不到定义的标签
1.2 NodeAffinity节点亲和性
NodeAffinity称之为Node节点亲和性调度有两种调度策略
-
RequiredDuringSchedulingIgnoredDuringExecution
称之为硬亲和,必须满足指定定义的规则才会将Pod调度到Node上 -
PreferredDuringSchedulingIgnoredDuringExecution
软亲和,尽量将Pod调度到满足条件的Node上,如果没有满足的,调度器会根据算法选择一个最合适的节点
PreferredDuringSchedulingIgnoredDuringExecution实现方式
在template.spec下定义
[root@k8s-master01 ~]# cat deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginxapp
labels:
app: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: zone #标签名
operator: In #表示值在key的里面,下边可以定义多个key
values:
- foo #标签值
weight: 1
containers:
- name: nginxweb
image: nginx:1.15-alpine
此Pod定义的是软亲和,表示将此Pod尽量调度到node节点标签名为zone值是foo的节点上
RequiredDuringSchedulingIgnoredDuringExecution实现方式
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginxapp
labels:
app: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: zone
operator: In
values:
- foo
weight: 1
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- bar1
containers:
- name: nginxweb
image: nginx:1.15-alpine
如果两个同时使用那么先匹配硬亲和然后再从匹配到的硬亲和去匹配软亲和
1.2 PodAffinity节点亲和性
Pod的亲和性和反亲和性(互斥)
能让用户从另一个角度来限制Pod所能运行的节点,Pod的亲和和互斥是基于Pod标签进行判断的
注意Pod的亲和和互斥是基于namespace进行匹配的
podAffinity亲和性
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginxapp
labels:
app: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
containers:
- name: nginxweb1
image: nginx:1.15-alpine
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- mynginx
topologyKey: kubernetes.io/hostname # 表示只要hostname值一样就说明是同一位置拓扑域
表示将Pod部署到Pod的标签名app值为mynginx的Pod所在节点的node上
podAntiAffinity亲和性
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginxapp
labels:
app: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
containers:
- name: nginxweb1
image: nginx:1.15-alpine
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- mynginx
topologyKey: kubernetes.io/hostname # 表示只要hostname值一样就说明是同一位置拓扑域
1.3 NodeTaintTolerations
对于Node affinity,无论是强制约束(hard)或偏好(preference)方式,都是调度pod到预期节点上,而Taints恰好与之相反,如果一个节点标记为Taints,除非 Pod也被标识为可以耐受污点节点,否则该Taints节点不会被调度pod。Taints与tolerations当前处于beta阶段, Taints节点应用场景比如用户希望把Kubernetes Master节点保留给 Kubernetes 系统组件使用,或者把一组具有特殊资源预留给某些pod。pod不会再被调度到taint标记过的节点
如果想为特殊的用户指定一组node,可以添加一个污点到这组node上(运行命令: kubectl taint nodes nodename dedicated=groupName:NoSchedule)。然后添加对应的容忍到这个Pod上(这个最容易实现的方法是写一个客户端准入控制器)。带有相应容忍的Pod就可以像被调度到集群中其他node一样被调度到带有相应污点的node上。
污点是定义节点上的一种键值属性;主要用于让节点拒绝Pod的(拒绝那些不能容忍污点的Pod);所以说我们得在Pod建议能够容忍的污点
Taint的定义对Pod的排斥结果
- NoSchedul
只影像调度过程,如果不能容忍那么就不被调度上,对现在的Pod对象不产生影像 - NoExecute
即影像调度过程,也影响现在节点的Pod,不能容忍的Pod将会被驱逐
可用于此node故障打上污点驱逐现有node的Pod
NodeTaint
设置node污点
[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-type=production:NoSchedule #此处node现有的Pod不会被驱逐
[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-type=production:NoExecute #此处node现有的Pod会被驱除
设置Pod的容忍
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginxapp
labels:
app: nginx-deploy
spec:
replicas: 2
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
containers:
- name: nginxweb1
image: nginx:1.15-alpine
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- mynginx
topologyKey: kubernetes.io/hostname # 表示只要hostname值一样就说明是同一位置拓扑域
tolerations:
- key: "node-type" # 污点的key
operator: "Equal" # 容忍程度
value: "producction" # 污点的volue
effect: "NoSchedule"
2. 调度器的过程
具体的调度过程,一般如下:首先,客户端通过API Server的REST API/kubectl/helm创建pod/service/deployment/job等,支持类型主要为JSON/YAML/helm tgz。 接下来,API Server收到用户请求,存储到相关数据到etcd。 调度器通过API Server查看未调度(bind)的Pod列表,循环遍历地为每个Pod分配节点,尝试为Pod分配节点。
调度过程分为2个阶段:
第一阶段:预选过程,过滤节点,调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
第二阶段:优选过程,节点优先级打分,对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
选择主机:选择打分最高的节点,进行binding操作,结果存储到etcd中。 所选节点对于的kubelet根据调度结果执行Pod创建操作