调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。
kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群控制面的一部分。如果你真的希望或者有这方面的需求,kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。
在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。
默认策略可以参考:https://kubernetes.io/zh/docs/concepts/scheduling/kube-scheduler/
nodeName 是节点选择约束的最简单方法,但一般不推荐。如果 nodeName 在 PodSpec 中指定了,则它优先于其他的节点选择方法。
使用 nodeName 来选择节点的一些限制:
如果指定的节点不存在。
如果指定的节点没有资源来容纳 pod,则pod 调度失败。
云环境中的节点名称并非总是可预测或稳定的。
nodeSelector 是节点选择约束的最简单推荐形式。给选择的节点添加标签,通过标签来进行调度。
创建目录并,编写资源清单
mdir schedu
cd schedu/
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
执行pod.yaml清单,查看pod节点:
kubectl apply -f pod.yaml
kubectl get pod
我们发现pod节点处于Pending状态,是因为未给任何node节点添加标签!
添加标签后,查看pod节点状态
kubectl label nodes server3 disktype=ssd
kubectl get pod -o wide
删除标签之后发现pod节点还在运行
为什么?
因为节点已经生效了!
kubectl label nodes server3 disktype-
kubectl get node --show-labels
完成实验后删除节点pod
kubectl delete -f pod.yaml
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
name: node-affinity
spec:
containers:
- name: nginx
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #必须满足
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- server3
- server4
preferredDuringSchedulingIgnoredDuringExecution: #倾向满足
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
执行pod1.yaml清单,查看pod节点的信息:
kubectl apply -f pod1.yaml
kubectl get pod -o wide
发现亲和到server4
然后注释掉倾向满足,再次执行清单,查看节点信息:
vim pod1.yaml
#- weight: 1
# preference:
# matchExpressions:
# - key: disktype
# operator: In
# values:
# - ssd
kubectl delete -f pod1.yaml
kubectl apply -f pod1.yaml
kubectl get pod -o wide
发现还在server4上:
为server3添加标签ssd,删除节点重启拉起容器,服务亲和到server3
kubectl delete -f pod1.yaml
kubectl label nodes server3 disktype=ssd
kubectl apply -f pod1.yaml
kubectl get pod -o wide
注意:节点反亲和只需要将参数
operator: NotIn
删除前面实验的pod1.yaml
kubectl delete -f pod1.yaml
pod亲和,mysql容器亲和nginx pod
注意使用的mysql镜像版本为 image: mysql:5.7
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: "MYSQL_ROOT_PASSWORD"
value: "westos"
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: kubernetes.io/hostname
执行清单pod2.yaml,查看信息
kubectl apply -f pod2.yaml
kubectl get pod -o wide
可以看到mysql与nginx在同一个node节点server4上部署
只需要将参数修改一下即可变为反亲和:
vim pod2.yaml
podAntiAffinity:
kubectl delete -f pod2.yaml
kubectl apply -f pod2.yaml
kubectl get pod -o wide
我们可以看到mysql节点并不在nginx服务的同个节点上,实现服务与数据分离。
NodeAffinity节点亲和性,是Pod上定义的一种属性,使Pod能够按我们的要求调度到某个Node上,而Taints则恰恰相反,它可以让Node拒绝运行Pod,甚至驱逐Pod。
Taints(污点)是Node的一个属性,设置了Taints后,所以Kubernetes是不会将Pod调度到这个Node上的。
于是Kubernetes就给Pod设置了个属性Tolerations(容忍),只要Pod能够容忍Node上的污点,那么Kubernetes就会忽略Node上的污点,就能够(不是必须)把Pod调度过去。
可以使用命令 kubectl taint 给节点增加一个 taint:
$ kubectl taint nodes node1 key=value:NoSchedule //创建
$ kubectl describe nodes server1 |grep Taints //查询
$ kubectl taint nodes node1 key:NoSchedule- //删除
其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]
NoSchedule:POD 不会被调度到标记为 taints 节点。
PreferNoSchedule:NoSchedule 的软策略版本。
NoExecute:该选项意味着一旦 Taint 生效,如该节点内正在运行的 POD 没有对应 Tolerate 设置,会直接被逐出。
如Kubernetes集群主机,就是被设置了污点,因此一般部署pod时候不选择该节点为部署节点
matser的污点 的信息为:
kubectl describe nodes server2 | grep Taints
Taints: node-role.kubernetes.io/master:NoSchedule
本来server2是不加入集群的,我们现在设置让他加入集群中!
我们来测试:
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeName: server2
执行 pod.yaml清单,查看pod节点信息:
kubectl apply -f pod.yaml
kubectl get pod -o wide
可以看到已经部署在server2上,说明nodename可以掩盖污点
为server2设置标签,使用标签方式测试污点
kubectl label nodes server2 roles=master
kubectl get nodes --show-labels
编辑资源清单,使用标签方式选择node
vim pod.yaml
roles: master
再次运行pod.yaml文件,发现pod节点不能成功running
kubectl apply -f pod.yaml
kubectl get pod -o wide
kubectl delete -f pod.yaml #测试之后,删掉
测试证明,标签选择无法覆盖污点。只有Nodename可以无视任何污点
vim pod.yaml
tolerations:
- operator: "Exists"
effect: "NoSchedule"
再次执行清单,可以看到调度到了server2上,说明容忍生效!
kubectl apply -f pod.yaml
kubectl get pod -o wide
手动给server3添加污点:
NoSchedule:POD 不会被调度到标记为 taints 节点。
kubectl delete -f pod.yaml
kubectl taint nodes server3 key=value:NoSchedule
kubectl describe nodes server3|grep Taint
然后将清单中的 角色和容忍先注释掉:
# nodeSelector:
# roles: master
# tolerations:
# - operator: "Exists"
# effect: "NoSchedule"
kubectl apply -f pod.yaml
kubectl get pod -o wide
测试之后删除节点
kubectl delete -f pod.yaml
可以看到只会调度到server4上!
再次将pod.yaml中的容忍和角色取消注释,更改为disktype
vim pod.yaml
nodeSelector:
disktype: ssd
tolerations:
- operator: "Exists"
effect: "NoSchedule"
可以想象,会调度到server3,因为和server3的标签保持一致!
kubectl apply -f pod.yaml
kubectl get pod
kubectl get pod -o wide
去掉server3的NoSchedule的值
添加NoExecute:
该选项意味着一旦 Taint 生效,如该节点内正在运行的 POD 没有对应 Tolerate 设置,会直接被逐出。被驱逐到其他node节点。
kubectl taint node server3 key:NoSchedule-
kubectl taint nodes server3 key=value:NoExecute
查看节点pod信息,过一会server3就会自动被驱逐,需要等待一段时间:
kubectl get pod -o wide
可以在server3上查看docker进程,之前拉取得镜像都没了,只剩下k8s集群所必须的镜像了!!!
docker ps
测试完成,取消NoExecute的值
kubectl taint nodes server3 key:NoExecute-
关闭server3的集群调度:
kubectl cordon server3
kubectl get node
重新调度server3!
kubectl uncordon server3
kubectl get node
kubectl drain server3 --ignore-daemonsets
kubectl get node
直接删除掉节点server3
kubectl delete node server3
那么问题来了?
怎么将server3重新加入调度node节点呢??
只需要在server3上重启kubelet服务即可!
systemctl restart kubelet
可以看到server3又加入集群中了:
kubectl get node
因为token只会存在23小时,所以需要重新创建
kubeadm token create
kubeadm token list
还需要token-cert-hash:
这个值不会变化,查出来即可!
openssl x509 -pubky -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubinoutform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
然后用下述指令加入集群即可!!
kubeadm join 172.25.0.2:6443 --token ******** --discovery-token-ca-cert-hash sha256:*******************![请添加图片描述](https://img-blog.csdnimg.cn/69828dc828b148ff973ffa21d2bad116.png)