Kubernetes-调度、节点亲和反亲和、pod亲和反亲和、Taints污点的处理

一.kubernetes调度介绍

调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。

kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群控制面的一部分。如果你真的希望或者有这方面的需求,kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。

在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。

默认策略可以参考:https://kubernetes.io/zh/docs/concepts/scheduling/kube-scheduler/

二.nodename节点选择约束

nodeName 是节点选择约束的最简单方法,但一般不推荐。如果 nodeName 在 PodSpec 中指定了,则它优先于其他的节点选择方法。

使用 nodeName 来选择节点的一些限制:

如果指定的节点不存在。
如果指定的节点没有资源来容纳 pod,则pod 调度失败。
云环境中的节点名称并非总是可预测或稳定的。

三.nodeSelector 亲和

nodeSelector 是节点选择约束的最简单推荐形式。给选择的节点添加标签,通过标签来进行调度。

1.节点亲和

创建目录并,编写资源清单

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

请添加图片描述
节点亲和性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    

请添加图片描述

执行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

请添加图片描述

2.节点反亲和

注意:节点反亲和只需要将参数

operator: NotIn

请添加图片描述

1. pod亲和

删除前面实验的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上部署

请添加图片描述

2.pod反亲和

只需要将参数修改一下即可变为反亲和:

vim pod2.yaml

 podAntiAffinity:

请添加图片描述
删除节点,重新执行pod2.yaml文件,查看信息:

kubectl delete -f pod2.yaml
kubectl apply -f pod2.yaml
kubectl get pod -o wide

我们可以看到mysql节点并不在nginx服务的同个节点上,实现服务与数据分离。
请添加图片描述

四.Taints(污点)

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

请添加图片描述

1 .Nodename可以无视任何污点

本来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节点
请添加图片描述

执行 pod.yaml清单,查看pod节点信息:

kubectl apply -f pod.yaml
kubectl get pod -o wide

可以看到已经部署在server2上,说明nodename可以掩盖污点
请添加图片描述

2. 测试标签能否无视污点

为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可以无视任何污点
请添加图片描述

3. 添加容忍

vim pod.yaml

  tolerations:
  - operator: "Exists"
    effect: "NoSchedule"

请添加图片描述
再次执行清单,可以看到调度到了server2上,说明容忍生效!

kubectl apply -f pod.yaml
kubectl get pod -o wide

请添加图片描述

4. NoSchedule

手动给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"

请添加图片描述
重新执行清单,查看pod节点!

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

请添加图片描述

5.NoExecute

去掉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-

请添加图片描述

6. cordon、drain、delete

关闭server3的集群调度:

kubectl cordon server3
kubectl get node

可以看到server3状态变化了!
请添加图片描述

重新调度server3!

kubectl uncordon server3
kubectl get node

请添加图片描述
关闭server3的调度,但不关闭部分必要pod

kubectl drain server3 --ignore-daemonsets
kubectl get node

请添加图片描述

直接删除掉节点server3

kubectl delete node server3

请添加图片描述

那么问题来了?
怎么将server3重新加入调度node节点呢??

只需要在server3上重启kubelet服务即可!

systemctl restart kubelet

请添加图片描述

可以看到server3又加入集群中了:

kubectl get node

请添加图片描述

7. 添加新的集群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)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dudududu--

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值