天天看点

企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

企业运维实战--k8s学习笔记9.k8s调度(上)

  • 前言--调度器简介
  • k8s调度
    • NodeName
    • nodeSelector 亲和
      • 节点亲和
      • pod亲和
      • Taints污点与容忍

前言–调度器简介

调度器通过 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
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

拉起容器并查看

kubectl apply -f pod.yaml
kubectl get pod
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

此时未给任何node节点添加标签,pod节点处于Pending状态,

稍后添加标签后,pod将在被添加的node拉起

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

kubectl label nodes server3 disktype=ssd
kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl label nodes server3 disktype-
kubectl get node --show-labels
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度
kubectl get pod
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

测试结束后删除节点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    
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl apply -f pod1.yaml
kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

vim pod1.yaml
kubectl delete -f pod1.yaml
kubectl apply -f pod1.yaml
kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl label nodes server3 disktype=ssd
kubectl delete -f pod1.yaml
kubectl apply -f pod1.yaml
kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

可以看到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

           

与亲和文件的比较,不同之处

企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl delete -f pod2.yaml
kubectl apply -f pod2.yaml
kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

测试1:Nodename可以无视任何污点

编辑资源清单创建pod,采用nodename指定node节点

vim pod.yaml
cat pod.yaml
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

拉起容器

kubectl apply -f pod.yaml
kubectl get pod
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

查看节点所在node

kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

测试结果表明,虽然server2为master且设置了污点,但是nodename可以无视污点。

测试完成删除测试pod

kubectl delete -f pod.yaml
           

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

kubectl label nodes server2 roles=master
kubectl get nodes --show-labels
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

vim pod.yaml
cat pod.yaml
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

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

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

添加容忍

vim pod.yaml
cat pod.yaml
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl taint nodes server3 key=value:NoSchedule
           

此时server3是有污点的

kubectl describe nodes server3|grep Taint
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

vim pod.yaml
cat pod.yaml
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度
kubectl apply -f pod.yaml
kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl delete -f pod.yaml
vim pod.yaml
cat pod.yaml
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

通过标签选择server3,

kubectl apply -f pod.yaml
kubectl get pod
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

测试完成后取消NoSchedule的值

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

kubectl taint nodes server3 key=value:NoExecute
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl get pod -o wide
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

测试完成,取消NoExecute的值

企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

关闭server3的所有调度

kubectl cordon server3
kubectl get node
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

重新开启server3的调度

kubectl uncordon server3
kubectl get node
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

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

kubectl drain server3
kubectl get node
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

删除node

kubectl delete node server3
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

node节点重启服务即可恢复node信息

企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度
kubectl get node
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度

故,删除node步骤为:先驱逐pod,再删除node。

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

kubeadm token list
kubeadm token create
kubeadm token list
           
企业运维实战--k8s学习笔记9.k8s调度前言–调度器简介k8s调度