企业入门实战--k8s之kubernetes调度
简介
调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。
kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群控制面的一部分。如果你真的希望或者有这方面的需求,kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。
在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等
nodeName
nodeName 是节点选择约束的最简单方法,但一般不推荐。如果 nodeName 在 PodSpec 中指定了,则它优先于其他的节点选择方法。
使用 nodeName 来选择节点的一些限制:
如果指定的节点不存在。
如果指定的节点没有资源来容纳 pod,则pod 调度失败。
云环境中的节点名称并非总是可预测或稳定的。
创建工作目录并进入,编写资源清单
mkdir 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
拉起容器进行查看
kubectl apply -f pod.yaml
kubectl get pod
此时的pod正在等待状态因为没有符合的标签 这时给node节点加上对应标签
kubectl label nodes server3 disktype=ssd
kubectl get pod -o wide
Node的标签发生变化,导致亲和性策略不能满足,则继续运行当前的Pod。
kubectl label nodes server3 disktype-
kubectl get pod
节点亲和性
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
先注释掉倾向满足部分
拉起容器发现倾向满足server3
kubectl apply -f pod1.yaml
kubectl get pod -o wide
为server3添加标签ssd,删除节点重启拉起容器,服务亲和到server4
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
为server4打上ssd的标签
kubectl label nodes server4 disktype=ssd
kubectl apply -f pod1.yaml
kubectl get pod -o wide
这时由于节点亲和性服务运行在了server4上
pod亲和性
亲和
server1
将所需的镜像上传至仓库
docker load -i mysql-xtrabackup.tar
docker push reg.westos.org/library/xtrabackup:1.0
server2
vim pod3.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
拉起容器
kubectl apply -f pod2.yaml
kubectl get pod -o wide 看到nginx和mysql在一块运行
反亲和
编辑pod2.yaml文件
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:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: kubernetes.io/hostname
kubectl delete pod mysql
kubectl apply -f pod2.yaml
kubectl get pod -o wide 看到nginx和mysql不在一块运行
Taints污点与容忍
aints(污点)是Node的一个属性,设置了Taints后,所以Kubernetes是不会将Pod调度到这个Node上的,于是Kubernetes就给Pod设置了个属性Tolerations(容忍),只要Pod能够容忍Node上的污点,那么Kubernetes就会忽略Node上的污点,就能够(不是必须)把Pod调度过去。
kubectl taint nodes node1 key=value:NoSchedule #创建
kubectl describe nodes server1 |grep Taints #查询
kubectl taint nodes node1 key:NoSchedule- #删除
示例:
server2为k8smaster主机,默认会不加入集群调度,
查看server2污点
kubectl describe nodes server2|grep Taint
测试1:Nodename可以无视任何污点
编辑资源清单创建pod,采用nodename指定node节点
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
# nodeSelector:
# disktype: ssd
拉起容器
kubectl apply -f pod.yaml
kubectl get pod
查看节点所在node
kubectl get pod -o wide
server2作为master且设置了污点,但是nodename可以无视污点。
测试完成删除测试pod
为server2设置标签,使用标签方式测试污点
kubectl label nodes server2 roles=master
kubectl get nodes --show-labels
编辑资源清单,使用标签方式选择node
[root@server2 schedu]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
roles: master
[root@server2 schedu]# kubectl apply -f pod.yaml
[root@server2 schedu]# kubectl get pod -o wide
拉起容器,发现pod处于pending,不能成功
测试证明,标签选择无法覆盖污点。
添加容忍
[root@server2 schedu]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
roles: master
tolerations:
- operator: "Exists"
effect: "NoSchedule"
添加容忍,NoSchedule:POD 不会被调度到标记为 taints 节点。
kubectl taint nodes server3 key=value:NoSchedule
server3上存在污点
kubectl describe nodes server3|grep Taint
注释容忍,拉起容器,发现容器在server4端运行,说明污点生效。
[root@server2 schedu]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
# nodeSelector:
# roles: master
# tolerations:
# - operator: "Exists"
# effect: "NoSchedule"
删除pod.yaml后,打开容忍,通过标签选择server3
[root@server2 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
tolerations:
- operator: "Exists"
effect: "NoSchedule"
完成后取消NoSchedule的值
kubectl taint node server3 key:NoSchedule-
NoExecute:该选项意味着一旦 Taint 生效,如该节点内正在运行的 POD 没有对应 Tolerate 设置,会直接被逐出。被驱逐到其他node节点
kubectl taint nodes server3 key=value:NoExecute
测试完成,取消NoExecute的值
kubectl taint nodes server3 key:NoExecute-
关闭server3的所有调度
kubectl cordon server3
kubectl get node
关闭server3的调度,但不关闭部分必要pod
kubectl drain server3
kubectl get node
关闭server3的调度,但不关闭部分必要pod
kubectl drain server3
kubectl get node
删除node
kubectl delete node server3
server3重新加入k8s集群
systemctl restart kubelet.service
控制端查看,server3加入集群
删除node的步骤为:先驱逐pod,再删除node。
拓展
当有新的node想加入k8s集群中,我们就需要生成新的token,注意,每一次生成的token只有24小时有效期
在控制端上生成token