1、调度介绍

Kubernetes Scheduler 的作用是将待调度的 Pod 按照一定的调度算法和策略绑定到集群中一个合适的 Worker Node 上,并将绑定信息写入到 etcd 中,之后目标 Node 中 kubelet 服务通过 API Server 监听到 Scheduler 产生的 Pod 绑定事件获取 Pod 信息,然后下载镜像启动容器。

Scheduler 提供的调度流程分为预选 (Predicates) 和优选 (Priorities) 两个步骤:

  • 预选,K8S会遍历当前集群中的所有 Node,筛选出其中符合要求的 Node 作为候选
  • 优选,K8S将对候选的 Node 进行打分

经过预选筛选和优选打分之后,K8S选择分数最高的 Node 来运行 Pod,如果最终有多个 Node 的分数最高,那么 Scheduler 将从当中随机选择一个 Node 来运行 Pod。

2、cordon

kubectl crodon k8s-node1 # k8s-node1不可调度
kubectl drain k8s-node1 # 驱逐k8s-node1服务器的所有pod
kubectl uncordon k8s-node1 # 解除调度

3、NodeSelector

labelkubernetes中一个非常重要的概念,用户可以非常灵活的利用 label 来管理集群中的资源,POD 的调度可以根据节点的 label 进行特定的部署。

官网:​https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/

kubectl get nodes --show-labels # 查看节点标签
kubectl label node k8s-master disktype=ssd # 打标签

当 node 被打上了相关标签后,在调度的时候就可以使用这些标签了,只需要在spec 字段中添加nodeSelector字段,里面是我们需要被调度的节点的 label。

...
spec:
hostNetwork: true # 声明pod的网络模式为host模式,效果通docker run --net=host
nodeSelector: # 使用节点选择器将Pod调度到指定label的节点
component: mysql
containers:
- name: mysql
image: 192.168.136.10:5000/demo/mysql:5.7
volumes:
- name: mysql-data
hostPath:
path: /opt/mysql/data
...

4、NodeName

通过节点名字来进行调度到指定的node

spec:
hostNetwork: true # 声明pod的网络模式为host模式,效果通docker run --net=host
nodeName: 172.31.7.111
containers:
- name: mysql
image: 192.168.136.10:5000/demo/mysql:5.7

5、亲和性和反亲和性

策略

亲和性 nodeAffinity     反亲和性 nodeantiAffinity

节点亲和性 , 比上面的​​nodeSelector​​更加灵活,它可以进行一些简单的逻辑组合,不只是简单的相等匹配 。分为两种,硬策略和软策略。

requiredDuringSchedulingIgnoredDuringExecution : 硬策略,如果没有满足条件的节点的话,就不断重试直到满足条件为止,简单说就是你必须满足我的要求,不然我就不会调度Pod。

preferredDuringSchedulingIgnoredDuringExecution:软策略,如果你没有满足调度要求的节点的话,Pod就会忽略这条规则,继续完成调度过程。


affinity与NodeSelector对比

1、亲和和反亲和对目的标签的选择匹配不仅仅支持and,还支持ln、Notln、Exists、DoesNotExist、Gt、Lt

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值大于某个值
  • Lt:label 的值小于某个值
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

亲和性的配置规则

亲和性调度策略分为

Node亲和性(硬亲和、软亲和)

Pod亲和性(硬亲和、软亲和)

Pod反亲和性(硬亲和、软亲和)

节点亲和性权重

你可以为 ​​preferredDuringSchedulingIgnoredDuringExecution​​​ 亲和性类型的每个实例设置 ​​weight​​​ 字段,其取值范围是 1 到 100。 当调度器找到能够满足 Pod 的其他调度请求的节点时,调度器会遍历节点满足的所有的偏好性规则, 并将对应表达式的 ​​weight​​ 值加和。

node新和性说明:

如果你同时指定了 ​​nodeSelector​​​ 和 ​​nodeAffinity​​,两者 必须都要满足, 才能将 Pod 调度到候选节点上。

如果你指定了多个与 ​​nodeAffinity​​​ 类型关联的 ​​nodeSelectorTerms​​​, 只要其中一个 ​​nodeSelectorTerms​​ 满足的话,Pod 就可以被调度到节点上。

如果你指定了多个与同一 ​​nodeSelectorTerms​​​ 关联的 ​​matchExpressions​​​, 则只有当所有 ​​matchExpressions​​ 都满足时 Pod 才可以被调度到节点上。

6、node亲和性示例

spec: 
hostNetwork:
nodeSelector:
component: mysql
containers:
- name: demo
image: 192.168.136.10:5000/demo/myblog:v1
ports:
- containerPort: 8002
affinity:
nodeAffinity: # 亲和
requiredDuringSchedulingIgnoredDuringExecution: # 硬亲和
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 192.168.136.128
- 192.168.136.132
- matchExpressions:
- key: project
operator: In
values:
- mmm
- nnn
preferredDuringSchedulingIgnoredDuringExecution: #软亲和
- weight: 100 #软亲和条件1,weight值越大优先级越高,越优先匹配调度
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- =
- weight: 10 #软亲和条件2,在条件1不满足时匹配条件2
preference:
matchExpressions:
- key: project
operator: In
values:
- laf
- weight: 1 #软亲和条件3,在条件2不满足时匹配条件3
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd

#要求 Pod 运行在128或32或mmm或nnn四个任意一个即可。并且需要运行在节点标签为component: mysql上。

同时如果有节点满足another-node-label-key=another-node-label-value 优先调度到这类节点上。否则匹配条件2,条件2不满足匹配条件3,都不匹配,则按调schedule调度规则完成调度。

affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #匹配条件1,同一个key的多个value只有有一个匹配成功就认为当前key匹配成功
- key: disktype
operator: In
values:
- ssd
- hddx
- key: project #匹配条件2,当前key也要匹配成功一个value,即条件1和条件2必须同时每个key匹配成功一个value,否则不调度
operator: In
values:
- magedu

7、topologyKey

topologyKey在pod的亲和性或者反亲和性一定需要使用

pod亲和性使用了topologyKey,表示部署的pod一定需要部署在同一台主机上

pod反亲和性使用了topologyKey,表示部署的pod一定不能部署在同一台主机上

8、pod亲和示例(软硬亲和)

匹配node节点标签为project: python的主机就部署tomcat,否则按照schedule自行完成调度

并且部署的test容器所有副本必须在同一台主机上。

containers:
- name: test
image: tomcat:7.0.94-alpine
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
podAffinity: #Pod亲和
#requiredDuringSchedulingIgnoredDuringExecution: #硬亲和,必须匹配成功才调度,如果匹配失败则拒绝调度。
preferredDuringSchedulingIgnoredDuringExecution: #软亲和,能匹配成功就调度到一个topology,匹配不成功会由kubernetes自行调度。
- weight: 100
podAffinityTerm:
labelSelector: #标签选择
matchExpressions: #正则匹配
- key: project
operator: In
values:
- python
topologyKey: kubernetes.io/hostname

9、pod反亲和示例(软硬亲和)

必须匹配node节点标签为project: python的主机才能部署。并且部署的test容器所有副本必须 不能 在同一台主机上。

containers:
- name: test
image: tomcat:7.0.94-alpine
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
podAntiAffinity: # 反亲和
requiredDuringSchedulingIgnoredDuringExecution: # 硬亲和
#preferredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: project
operator: In
values:
- python
topologyKey: "kubernetes.io/hostname"

10、污点与容忍

污点(taints),用于node节点排斥 Pod调度,与亲和的作用是完全相反的,即taint的node和pod是排斥调度关系。

容忍(toleration),用于Pod容忍node节点的污点信息,即node有污点信息也会将新的pod调度到node


tolerations容忍:

定义 Pod 的容忍度(可以接受node的哪些污点),容忍后可以将Pod调度至含有该污点的node。


官网​https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/​

污点类型与设置污点

$ kubectl taint node [node_name] key=value:[effect]   
其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]
NoSchedule:一定不能被调度。
PreferNoSchedule:尽量不要调度。
NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。
示例:kubectl taint node k8s-slave1 smoke=true:NoSchedule

去除污点

# 去除指定key及其effect:
kubectl taint nodes [node_name] key:[effect]- #这里的key不用指定value

# 去除指定key所有的effect:
kubectl taint nodes node_name key-

# 示例:
kubectl taint node k8s-master smoke=true:NoSchedule # 设置污点
kubectl taint node k8s-master smoke:NoExecute- # 去除指定key及其effect:
kubectl taint node k8s-master smoke- # 去除指定key所有的effect:

查询污点

kubectl describe node node_name

基于operator的污点匹配

如果operator是Exists,则容忍度不需要value而是直接匹配污点类型。

 如果operator是Equal,则需要指定value并且value的值需要等于tolerations的key。


Pod容忍污点示例

kubectl taint nodes node1 key1=smoke:NoSchedule
kubectl taint nodes node1 key1=drunk:NoExecute

...
spec:
containers:
- name: demo
image: 192.168.136.10:5000/demo/myblog:v1
tolerations: #设置容忍性
- key: "smoke"
operator: "Equal" #如果操作符为Equal,必需指定value。不指定operator,默认为Equal
value: "true"
effect: "NoSchedule"
- key: "drunk"
operator: "Exists" #如果操作符为Exists,那么value属性可省略
effect: "NoSchedule"
# 意思是该pod能够容忍key为smoke,value为true,effect为NoSchedule的污点
# 同时亦能够容忍key为drunk,effect为NoSchedule污点
# 该pod必须两个污点都要配置容忍,方能把pod调度在此台节点运行