k8s 十一之kubernetes调度

kubernetes调度介绍

  • 调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。
  • kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群控制面的一部分。如果你真的希望或者有这方面的需求,kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。
  • 在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。
  • 默认策略可以参考:kube-scheduler官网
  • 调度框架:scheduling-framework官网

nodeName

  • nodeName 是节点选择约束的最简单方法,但一般不推荐。如果 nodeName 在 PodSpec 中指定了,则它优先于其他的节点选择方法。
  • 使用 nodeName 来选择节点的一些限制:
    (1)如果指定的节点不存在
    (2)如果指定的节点没有资源来容纳 pod,则 pod 调度失败。
    (3)云环境中的节点名称并非总是可预测或稳定的
1.编写文件(文件中指定节点server3)
vim pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: myapp:v1
  nodeName: server3 

2.运行文件
kubectl apply -f pod1.yml

3.查看pod
kubectl get pod -o wide 

4.更改文件再测试

在这里插入图片描述
在这里插入图片描述
若更改为一个不存在的server13
在这里插入图片描述
系统会忽视别的节点,一旦server13不存在,pod就会运行失败。
在这里插入图片描述

nodeSelector

nodeSelector 是节点选择约束的最简单推荐形式

1.编写文件
vim pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
  nodeSelector:
    disktype: ssd

2.给选择的节点添加标签
kubectl label nodes server2 disktype=ssd 

3.运行文件
kubectl apply -f pod1.yml

4.查看pod
kubectl get pod -o wide 
kubectl get node --show-labels 

在这里插入图片描述
添加标签后调度成功
在这里插入图片描述
在这里插入图片描述
若此时将server2上的标签去掉,会对pod有什么影响吗?发现并没有什么影响,因为pod已经调度到server2上了。
在这里插入图片描述

节点亲和与反亲和

亲和与反亲和简介

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

节点亲和

  • requiredDuringSchedulingIgnoredDuringExecution:必须满足
  • preferredDuringSchedulingIgnoredDuringExecution:倾向满足
  • IgnoreDuringExecution:表示如果在Pod运行期间Node的标签发生变化,导致亲和性策略不能满足,则继续运行当前的Pod。
  • 参考
  • nodeaffinity还支持多种规则匹配条件的配置如
    (1)In:label 的值在列表内
    (2)NotIn:label 的值不在列表内
    (3)Gt:label 的值大于设置的值,不支持Pod亲和性。
    (4)Lt:label 的值小于设置的值,不支持pod亲和性。
    (5)Exists:设置的label 存在
    (6)DoesNotExist:设置的 label 不存在
1.编写文件(require亲和)
vim pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: myapp:v1
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:   
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd

2.给选择的节点添加标签
kubectl label nodes server2 disktype=ssd 
kubectl label nodes server3 disktype=ssd 

3.运行文件
kubectl apply -f pod1.yml

4.查看pod
kubectl get pod -o wide 

5.重新编写文件(prefer亲和)
vim pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: myapp:v1
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:   
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - server3

6.运行文件
kubectl apply -f pod1.yml

7.查看pod
kubectl get pod -o wide 

在这里插入图片描述
由于server2先添加标签,因此首先选择server2。
在这里插入图片描述
修改原来的pod1.yaml文件
在这里插入图片描述
发现调度到server3上了
在这里插入图片描述

pod亲和性和反亲和性

  • podAffinity: 主要解决 pod 可以和哪些 pod 部署在同一个拓扑域中的问题(拓扑域用主机标签实现,可以是单个主机,也可以是多个主机组成的cluster、zone等)
  • podAntiAffinity: 主要解决 pod 不能和哪些 pod 部署在同一个拓扑域中的问题。它们处理的是Kubernetes集群内部 pod 和 pod 之间的关系。
  • pod 间亲和与反亲和在与更高级别的集合(例如 ReplicaSets,StatefulSets,Deployments 等)一起使用时,它们可能更加有用。可以轻松配置一组应位于相同定义拓扑(例如,节点)中的工作负载。

pod亲和性

1.编写文件(podAffinity)
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: myapp:v1
  affinity:
    podAffinity:    
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: run
            operator: In
            values:
            - demo
        topologyKey: kubernetes.io/hostname

2.运行文件和demo
kubectl apply -f pod2.yaml
kubectl run demo --image=busybox -it

3.查看pod
kubectl get pod -o wide
#发现亲和情况都在一个node,反亲和就不在一个node

4.编写文件(podAntiAffinity)
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: myapp:v1
  affinity:
    podAntiAffinity:    
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: run
            operator: In
            values:
            - demo
        topologyKey: kubernetes.io/hostname

5.运行文件
kubectl apply -f pod2.yaml
kubectl run demo --image=busybox -it

6.查看pod
kubectl get pod -o wide

在这里插入图片描述
发现都运行在server2上
在这里插入图片描述
在这里插入图片描述
发现运行在不同结点上
在这里插入图片描述

污点

污点简介

  • 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 server1 key=value:NoSchedule  //创建
kubectl describe nodes server1 | grep Taints      //查询
kubectl taint nodes server1 key:NoSchedule-       //删除

其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]

  • NoSchedule:pod 不会被调度到标记为 taints 节点
  • PreferNoSchedule:NoSchedule 的软策略版本
  • NoExecute:该选项意味着一旦 Taint 生效,如该节点内正在运行的 pod 没有对应 Tolerate 设置,会直接被逐出。

tolerations 中定义的 key、value、effect 要与 node上设置的taint 保持一致。

  • 如果 operator 是 Exists ,value可以省略。
  • 如果 operator 是 Equal ,则key与value之间的关系必须相等。
  • 如果不指定operator属性,则默认值为Equal。
  • 还有两个特殊值:
    (1)当不指定 key,再配合 Exists 就能匹配所有的 key 与 value ,可以容忍所有污点。
    (2)当不指定 effect ,则匹配所有的 effect。

污点部署

1.查看污点
kubectl describe nodes server1 | grep Taints

2.运行文件
kubectl apply -f pod2.yaml

3.添加污点
kubectl taint nodes server2 key=value:NoSchedule

4.查看pod
kubectl get pod -o wide

5.在pod3.yaml中设置容忍
vim pod3.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: nginx
        image: myapp:v1
      tolerations:
      - key: "key1"
        operator: "Equal"
        value: "v1"
        effect: "NoExecute"

6.运行文件
kubectl apply -f pod3.yaml

7.查看pod
kubectl get pod -o wide

我们查看server1上的污点,污点表明不允许在server1上调度,那为什么有这么多pod运行在server1上呢?这是因为添加了容忍属性
在这里插入图片描述
我们发现server2上的pod被驱离
在这里插入图片描述
设置容忍
在这里插入图片描述
发现都在server2上运行
在这里插入图片描述

影响Pod调度的指令

影响Pod调度的指令还有:cordon、drain、delete,后期创建的pod都不会被调度到该节点上,但操作的暴力程度不一样。

cordon(停止调度)

影响最小,只会将node调为SchedulingDisabled,新创建pod,不会被调度到该节点,节点原有pod不受影响,仍正常对外提供服务。

1.kubectl cordon server2

2.kubectl  get node

3.编写文件
vim pod3.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: myapp:v1

4.运行文件
kubectl apply -f pod3.yaml

5.查看pod
kubectl get pod -o wide

6.恢复server2
kubectl uncordon server2

7.查看node
kubectl get node

8.查看pod
kubectl get pod -o wide

在这里插入图片描述
在这里插入图片描述
发现pod运行在server3上
在这里插入图片描述
恢复server2
在这里插入图片描述

drain(驱逐节点)

首先驱逐node上的pod,在其他节点重新创建,然后将节点调为SchedulingDisabled。

1.查看pod
kubectl get pod -o wide

2.驱逐server3
kubectl drain server3 

3.ignore
kubectl drain server3 --ignore-daemonsets

4.查看pod
kubectl get pod -o wide

在这里插入图片描述
pod此时运行在server2上在这里插入图片描述
pod运行在server2上
在这里插入图片描述

delete(删除节点)

最暴力的一个,首先驱逐node上的pod,在其他节点重新创建,然后,从master节点删除该node,master失去对其控制,如要恢复调度,需进入node节点,重启kubelet服务。

1.查看node
kubectl get node

2.删除node
kubectl delete node server3

3.再次查看node
kubectl get node

4.恢复(在被删除节点执行)
systemctl restart kubelet	

5.重新查看node
kubectl get node

在这里插入图片描述
恢复
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值