前言–调度器简介

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

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

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

k8s调度

NodeName

NodeName 是节点选择约束的最简单方法,它优先于其他的节点选择方法。换言之,NodeName都无法解决的调度需求,则其他调度方法也无法做到。

缺点与限制:

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

稍后实验会对边演示。

nodeSelector 亲和

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

亲和与反亲和

  • nodeSelector 提供了一种非常简单的方法来将 pod
    约束到具有特定标签的节点上。亲和/反亲和功能极大地扩展了你可以表达约束的类型。
  • 你可以发现规则是“软”/“偏好”,而不是硬性要求,因此,如果调度器无法满足该要求,仍然调度该 pod。
  • 你可以使用节点上的 pod 的标签来约束,而不是使用节点本身的标签,来允许哪些 pod 可以或者不可以被放置在一起。

节点亲和

包含两部分:
requiredDuringSchedulingIgnoredDuringExecution 必须满足
preferredDuringSchedulingIgnoredDuringExecution 倾向满足

示例:

创建工作目录并进入,编写资源清单

mkdir schedu
cd schedu/
vim pod.yaml
cat 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节点添加标签,pod节点处于Pending状态,
稍后添加标签后,pod将在被添加的node拉起

添加标签后,查看pod节点状态

kubectl label nodes server3 disktype=ssd
kubectl get pod -o wide

在这里插入图片描述

删除标签后不会消失,因为容器已经运行

kubectl label nodes server3 disktype-
kubectl get node --show-labels

在这里插入图片描述

kubectl get pod

在这里插入图片描述

测试结束后删除节点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    

在这里插入图片描述

先注释掉倾向满足,发现亲和到server4

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

在这里插入图片描述

打开倾向满足,删除节点,重新拉起容器,还在server4

vim pod1.yaml
kubectl delete -f pod1.yaml
kubectl apply -f pod1.yaml
kubectl get pod -o wide

在这里插入图片描述

为server3添加标签ssd,删除节点重启拉起容器,服务亲和到server3

kubectl label nodes server3 disktype=ssd
kubectl delete -f pod1.yaml
kubectl apply -f pod1.yaml
kubectl get pod -o wide

在这里插入图片描述

pod亲和

pod亲和,mysql容器亲和nginx pod

示例:
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

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

在这里插入图片描述
可以看到mysql与nginx在同一个node节点server4上部署,这不是巧合,而是资源清单的亲和部署。

反亲和:

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

与亲和文件的比较,不同之处
在这里插入图片描述

重新拉起容器,查看mysql节点并不在nginx服务的同个节点上,实现服务与数据分离。

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

在这里插入图片描述

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 设置,会直接被逐出。

示例:
server2为k8smaster主机,默认会不加入集群调度,
查看server2污点

kubectl describe nodes server2|grep Taint

在这里插入图片描述

测试1:Nodename可以无视任何污点
编辑资源清单创建pod,采用nodename指定node节点

vim pod.yaml
cat pod.yaml

在这里插入图片描述

拉起容器

kubectl apply -f pod.yaml
kubectl get pod

在这里插入图片描述

查看节点所在node

kubectl get pod -o wide

在这里插入图片描述
测试结果表明,虽然server2为master且设置了污点,但是nodename可以无视污点。
测试完成删除测试pod

kubectl delete -f pod.yaml

为server2设置标签,使用标签方式测试污点

kubectl label nodes server2 roles=master
kubectl get nodes --show-labels

在这里插入图片描述

编辑资源清单,使用标签方式选择node

vim pod.yaml
cat pod.yaml

在这里插入图片描述

拉起容器,发现pod节点不能成功running

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

测试证明,标签选择无法覆盖污点。

添加容忍

vim pod.yaml
cat pod.yaml

在这里插入图片描述

添加容忍,NoSchedule:POD 不会被调度到标记为 taints 节点。

kubectl taint nodes server3 key=value:NoSchedule

此时server3是有污点的

kubectl describe nodes server3|grep Taint

在这里插入图片描述

首先注释容忍,拉起容器,发现容器在server4端运行,说明污点生效。

vim pod.yaml
cat pod.yaml

在这里插入图片描述

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

在这里插入图片描述

删除pod节点,重新打开容忍,

kubectl delete -f pod.yaml
vim pod.yaml
cat pod.yaml

在这里插入图片描述

通过标签选择server3,

kubectl apply -f pod.yaml
kubectl get pod

在这里插入图片描述

测试完成后取消NoSchedule的值

kubectl taint node server3 key:NoSchedule-

NoExecute:该选项意味着一旦 Taint 生效,如该节点内正在运行的 POD 没有对应 Tolerate 设置,会直接被逐出。被驱逐到其他node节点。

kubectl taint nodes server3 key=value:NoExecute

在这里插入图片描述

驱逐后 ,所有server3上再无pod,驱逐是一个过程,需要一定的时间。

kubectl get pod -o wide

在这里插入图片描述

测试完成,取消NoExecute的值

kubectl taint nodes server3 key:NoExecute-

在这里插入图片描述

关闭server3的所有调度

kubectl cordon server3
kubectl get node

在这里插入图片描述

重新开启server3的调度

kubectl uncordon server3
kubectl get node

在这里插入图片描述

关闭server3的调度,但不关闭部分必要pod

kubectl drain server3
kubectl get node

在这里插入图片描述

删除node

kubectl delete node server3

在这里插入图片描述

node节点重启服务即可恢复node信息
在这里插入图片描述

kubectl get node

在这里插入图片描述
故,删除node步骤为:先驱逐pod,再删除node。

token信息查看和创建方法,只有23h的保存时间

kubeadm token list
kubeadm token create
kubeadm token list

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐