资源调度(nodeSelector、nodeAffinity、taint、Tolrations)

资源调度(nodeSelector、nodeAffinity、taint、Tolrations)

Kubernetes属于主从分布式架构,主要由Master Node和Worker Node组成,以及包括客户端命令行工具kubectl和其它附加项。

  • Master Node:作为控制节点,对集群进行调度管理;Master Node由API Server、Scheduler、Cluster State Store和Controller-Manger Server所组成;
  • Worker Node:作为真正的工作节点,运行业务应用的容器;Worker Node包含kubelet、kube proxy和Container Runtime;
    kubectl:用于通过命令行与API Server进行交互,而对Kubernetes进行操作,实现在集群中进行各种资源的增删改查等操作;
  • Add-on:是对Kubernetes核心功能的扩展,例如增加网络和网络策略等能力。
  • repliceation 用于伸缩副本数量
  • endpoint 用于管理网络请求
  • scheduler 调度器

Kubernetes的整体架构如下:
在这里插入图片描述

Kubernetes的调度流程:

  • 用户提交创建Pod的请求,可以通过API Server的REST API ,也可用Kubectl命令行工具,支持Json和Yaml两种格式;
  • API Server 处理用户请求,存储Pod数据到Etcd;
  • Schedule通过和 API Server的watch机制,查看到新的pod,尝试为Pod绑定Node;
  • 过滤主机:调度器用一组规则过滤掉不符合要求的主机,比如Pod指定了所需要的资源,那么就要过滤掉资源不够的主机;
  • 主机打分:对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等;
  • 选择主机:选择打分最高的主机,进行binding操作,结果存储到Etcd中;
  • kubelet根据调度结果执行Pod创建操作: 绑定成功后,会启动container, docker run, scheduler会调用API Server的API在etcd中创建一个bound pod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步bound pod信息,一旦发现应该在该工作节点上运行的bound pod对象没有更新,则调用Docker API创建并启动pod内的容器。

在这里插入图片描述

1.nodeSelector

nodeSelector是最简单的约束方式。nodeSelector是pod.spec的一个字段

通过–show-labels可以查看指定node的labels

[root@master ~]# kubectl get node node1 --show-labels
NAME    STATUS   ROLES    AGE     VERSION   LABELS
node1   Ready    <none>   4d18h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux
[root@master haproxy]# 

如果没有额外添加 nodes labels,那么看到的如上所示的默认标签。我们可以通过 kubectl label node 命令给指定 node 添加 labels:

[root@master mainfest]# kubectl get node node1 --show-labels  
NAME    STATUS   ROLES    AGE     VERSION   LABELS
node1   Ready    <none>   4d18h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux
[root@master haproxy]# 

也可以通过 kubectl label node 删除指定的 labels

[root@maste mainfest]# kubectl label node node1 disktype-
node/node1 labeled
[root@master haproxy]# kubectl get node node1 --show-labels
NAME    STATUS   ROLES    AGE     VERSION   LABELS
node1   Ready    <none>   4d18h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux
[root@master haproxy]# 

创建测试 pod 并指定 nodeSelector 选项绑定节点:

[root@master mainfest]# kubectl label node node1.example.com disktype=ssd
node/node1.example.com labeled
[root@master mainfest]# kubectl get node node1.example.com --show-labels
NAME                STATUS   ROLES    AGE    VERSION   LABELS
node1.example.com   Ready    <none>   4d18h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1.example.com,kubernetes.io/os=linux

[root@master mainfest]# vi test.yml
[root@master mainfest]# cat test.yml 
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    env: test
spec:
  containers:
  - name: test
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

//查看pod调度的节点
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
test   1/1     Running   0          6s    10.244.1.92   node1   <none>           <none>

2.nodeAffinity

nodeAffinity意为node亲和性调度策略。是用于替换nodeSelector的全新调度策略。目前有两种节点亲和性表达:

  • RequiredDuringSchedulingIgnoredDuringExecution:
    必须满足制定的规则才可以调度pode到Node上。相当于硬限制

  • PreferredDuringSchedulingIgnoreDuringExecution:
    强调优先满足制定规则,调度器会尝试调度pod到Node上,但并不强求,相当于软限制。多个优先级规则还可以设置权重值,以定义执行的先后顺序。
    IgnoredDuringExecution的意思是:
    如果一个pod所在的节点在pod运行期间标签发生了变更,不在符合该pod的节点亲和性需求,则系统将忽略node上lable的变化,该pod能机选在该节点运行。

  • NodeAffinity 语法支持的操作符包括:

  • In:label 的值在某个列表中

  • NotIn:label 的值不在某个列表中

  • Exists:某个 label 存在

  • DoesNotExit:某个 label 不存在

  • Gt:label 的值大于某个值

  • Lt:label 的值小于某个值

nodeAffinity规则设置的注意事项如下:

  • 如果同时定义了nodeSelector和nodeAffinity,name必须两个条件都得到满足,pod才能最终运行在指定的node上。
  • 如果nodeAffinity指定了多个nodeSelectorTerms,那么其中一个能够匹配成功即可。
  • 如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该pod。
[root@master mainfest]# cat test.yml 
apiVersion: v1
kind: Pod
metadata:
  name: test1
  labels:
    app: nginx
spec:
  containers:
  - name: test1
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            values:
            - ssd
            operator: In
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 10
        preference:
          matchExpressions:
          - key: name
            values:
            - test
            operator: In 

//给node2主机也打上disktype=ssd的标签
[root@master mainfest]# kubectl label node node2 disktype=ssd
node/node2 labeled
[root@master mainfest]# kubectl get node node2 --show-labels
NAME    STATUS   ROLES    AGE     VERSION   LABELS
node2   Ready    <none>   4d22h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2,kubernetes.io/os=linux

测试

给node1打上name=test的标签

[root@master ~]# kubectl label node node1 name=test
node/node1 labeled
[root@master ~]# kubectl get node node1 --show-labels
NAME    STATUS   ROLES    AGE     VERSION   LABELS
node1   Ready    <none>   4d18h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux,name=sb
[root@master ~]# 

给node1打上name=test的label和删除name=test的label并测试查看结果

[root@master ~]# kubectl label node node1 name=test
node/node1 labeled
[root@master ~]# kubectl get node node1 --show-labels
NAME    STATUS   ROLES    AGE     VERSION   LABELS
node1   Ready    <none>   4d22h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux,name=test

[root@master mainfest]# kubectl apply -f test1.yaml 
pod/test1 created
[root@master mainfest]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
test    1/1     Running   0          46m   10.244.1.92   node1   <none>           <none>
test1   1/1     Running   0          28s   10.244.1.93   node1   <none>           <none>

3.Taint(污点)与Tolerations(污点容忍)

Taints:避免Pod调度到特定Node上
olerations:允许Pod调度到持有Taints的Node上
应用场景:

  • 专用节点:根据业务线将Node分组管理,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配

  • 配备特殊硬件:部分Node配有SSD硬盘、GPU,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配
    基于Taint的驱逐
    effect说明

对effect的值作下简单说明:

  • NoSchedule: 如果一个pod没有声明容忍这个Taint,则系统不会把该Pod调度到有这个Taint的node上
  • PreferNoSchedule:NoSchedule的软限制版本,如果一个Pod没有声明容忍这个Taint,则系统会尽量避免把这个pod调度到这一节点上去,但不是强制的。
  • NoExecute:定义pod的驱逐行为,以应对节点故障。NoExecute这个Taint效果对节点上正在运行的pod有以下影响:
  • 没有设置Toleration的Pod会被立刻驱逐
  • 配置了对应Toleration的pod,如果没有为tolerationSeconds赋值,则会一直留在这一节点中
  • 配置了对应Toleration的pod且指定了tolerationSeconds值,则会在指定时间后驱逐
  • 从kubernetes 1.6版本开始引入了一个alpha版本的功能,即把节点故障标记为Taint(目前只针对node unreachable及node not ready,相应的NodeCondition "Ready"的值为Unknown和False)。激活TaintBasedEvictions功能后(在–feature-gates参数中加入TaintBasedEvictions=true),NodeController会自动为Node设置Taint,而状态为"Ready"的Node上之前设置过的普通驱逐逻辑将会被禁用。注意,在节点故障情况下,为了保持现存的pod驱逐的限速设置,系统将会以限速的模式逐步给node设置Taint,这就能防止在一些特定情况下(比如master暂时失联)造成的大量pod被驱逐的后果。这一功能兼容于tolerationSeconds,允许pod定义节点故障时持续多久才被逐出。

使用kubeclt taint命令可以给某个node设置五点,node被设置污点之后就和pod之间存在了一种相斥的关系,可以让node拒绝pod的调度执行,甚至将node上本已存在的pod驱逐出去

污点的组成如下:
每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用

[root@master mainfest]# kubectl taint node node1 name=test:NoSchedule
node/node1 tainted
[root@master mainfest]# kubectl describe node node1|grep -i taint
Taints:             name=test:NoSchedule

创建一个名为test2的pod测试

apiVersion: v1
kind: Pod
metadata:
  name: test2
  labels:
    app: nginx
spec:
  containers:
  - name: test2
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            values:
            - ssd
            operator: In
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: name
            values:
            - test
            operator: In

            
[root@master mainfest]# kubectl apply -f test2.yaml 
pod/test2 created
[root@master mainfest]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP             NODE     NOMINATED NODE   READINESS GATES



正常情况下,test2应该创建在node1上,但由于node1上我们设置了污点,所以并不会创建在node1上,当我们删除污点后,就可以创建在node1上

[root@master mainfest]# kubectl taint node node1 name-
node/node1 untainted
[root@master mainfest]# kubectl describe node node1|grep -i taint
Taints:             <none>

[root@master mainfest]# kubectl apply -f test2.yaml 
pod/test2 created
[root@master mainfest]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
test    1/1     Running   0          58m     10.244.1.92    node1      <none>           <none>
test1   1/1     Running   0          5m12s   10.244.2.93    node2      <none>           <none>
test2   1/1     Running   0          12m38s  10.244.2.132   node2      <none>           <none>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值