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
label
是kubernetes
中一个非常重要的概念,用户可以非常灵活的利用 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调度在此台节点运行