k8s资源调度

k8s资源调度

在这里插入图片描述
Scheduler调度器做为Kubernetes三大核心组件之一, 承载着整个集群资源的调度功能,其根据特定调度算法和策略,将Pod调度到最优工作节点上,从而更合理与充分的利用集群计算资源。其作用是根据特定的调度算法和策略将Pod调度到指定的计算节点(Node)上,其做为单独的程序运行,启动之后会一直监听API Server,获取PodSpec.NodeName为空的Pod,对每个Pod都会创建一个绑定。默认情况下,k8s的调度器采用扩散策略,将同一集群内部的pod对象调度到不同的Node节点,以保证资源的均衡利用。
在这里插入图片描述
具体的调度过程,一般如下:

  1. 首先,客户端通过API Server的REST API/kubectl/helm创建pod/service/deployment/job等,支持类型主要为JSON/YAML/helm tgz。

  2. 接下来,API Server收到用户请求,存储到相关数据到etcd。

  3. 调度器通过API Server查看未调度(bind)的Pod列表,循环遍历地为每个Pod分配节点,尝试为Pod分配节点。调度过程分为2个阶段:

    • 第一阶段:预选过程,过滤节点,调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
    • 第二阶段:优选过程,节点优先级打分,对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
  4. 选择主机:选择打分最高的节点,进行binding操作,结果存储到etcd中。

  5. 所选节点对于的kubelet根据调度结果执行Pod创建操作。

nodeSelector

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

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

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

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

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

当然,你也可以通过 kubectl label node 删除指定的 labels(标签 key 接 - 号即可)

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


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

[root@k8s-master ~]# kubectl label node k8s-node1 disktype=xx
node/k8s-node1 labeled
[root@k8s-master ~]# kubectl get node k8s-node1 --show-labels
NAME        STATUS   ROLES    AGE     VERSION   LABELS
k8s-node1   Ready    <none>   5d11h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=xx,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
[root@k8s-master ~]# cat test.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    env: test
spec:
  containers:
  - name: test
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: xx

查看pod调度的节点

[root@k8s-master ~]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
test   1/1     Running   0          2m21s   10.244.1.48   k8s-node1   <none>           <none>
xx     1/1     Running   0          36s     10.244.2.32   k8s-node1   <none>           <none>

可以看出,test这个pod被强制调度到了有disktype=ssd这个label的node上。

nodeAffinity

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

  1. RequiredDuringSchedulingIgnoredDuringExecution:
    必须满足制定的规则才可以调度pode到Node上。相当于硬限制
  2. PreferredDuringSchedulingIgnoreDuringExecution:
    强调优先满足制定规则,调度器会尝试调度pod到Node上,但并不强求,相当于软限制。多个优先级规则还可以设置权重值,以定义执行的先后顺序。
    IgnoredDuringExecution的意思是:

如果一个pod所在的节点在pod运行期间标签发生了变更,不在符合该pod的节点亲和性需求,则系统将忽略node上lable的变化,该pod能机选在该节点运行。

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

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Exists:某个 label 存在
  • DoesNotExit:某个 label 不存在
  • Gt:label 的值大于某个值
  • Lt:label 的值小于某个值
    nodeAffinity规则设置的注意事项如下:
  1. 如果同时定义了nodeSelector和nodeAffinity,name必须两个条件都得到满足,pod才能最终运行在指定的node上。
  2. 如果nodeAffinity指定了多个nodeSelectorTerms,那么其中一个能够匹配成功即可。
  3. 如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该pod。
[root@k8s-master ~]# cat test1.yaml 
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:
            - xx
            operator: In
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 10
        preference:
          matchExpressions:
          - key: name
            values:
            - kk
            operator: In   

给node2打上disktype=xx的标签

[root@k8s-master ~]# kubectl label node k8s-node2 disktype=xx
node/k8s-node2 labeled
[root@k8s-master ~]# kubectl get node k8s-node2 --show-labels
NAME        STATUS   ROLES    AGE     VERSION   LABELS
k8s-node2   Ready    <none>   5d11h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=xx,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux

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

[root@k8s-master ~]# kubectl label node k8s-node1 name=kk
node/k8s-node1 labeled
[root@k8s-master ~]# kubectl get node k8s-node1 --show-labels
NAME        STATUS   ROLES    AGE     VERSION   LABELS
k8s-node1   Ready    <none>   5d11h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=xx,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux,name=kk
[root@k8s-master ~]# kubectl apply -f test1.yaml 
pod/test1 created
[root@k8s-master ~]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
test    1/1     Running   0          11m     10.244.1.48   k8s-node1   <none>           <none>
test1   1/1     Running   0          12s     10.244.1.49   k8s-node1   <none>           <none>
xx      1/1     Running   0          9m25s   10.244.2.32   k8s-node1   <none>           <none>

删除node1上name=kk的label

[root@k8s-master ~]# kubectl label node k8s-node1 name-
node/k8s-node1 labeled
[root@k8s-master ~]# kubectl get node k8s-node1 --show-labels
NAME        STATUS   ROLES    AGE     VERSION   LABELS
k8s-node1   Ready    <none>   5d11h   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=xx,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
[root@k8s-master ~]# kubectl apply -f test1.yaml 
pod/test1 unchanged
[root@k8s-master ~]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
test    1/1     Running   0          12m   10.244.1.48   k8s-node1   <none>           <none>
test1   1/1     Running   0          92s   10.244.1.49   k8s-node2   <none>           <none>
xx      1/1     Running   0          10m   10.244.2.32   k8s-node2   <none>           <none>
[root@k8s-master ~]# 

上面这个pod首先是要求要运行在有disktype=xx这个label的node上,如果有多个node上都有这个label,则优先在有name=kk这个label上创建

taint

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

key=value:effect

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

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

创建一个名为test2的pod测试

[root@k8s-master ~]# cat test2.yaml 
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:
            - xx
            operator: In
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: name
            values:
            - kk
            operator: In

[root@k8s-master ~]# kubectl apply -f test2.yaml 
pod/test2 created
[root@k8s-master ~]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
test    1/1     Running   0          17m     10.244.1.48   k8s-node1   <none>           <none>
test1   1/1     Running   0          6m11s   10.244.1.49   k8s-node2   <none>           <none>
test2   1/1     Running   0          6s      10.244.2.33   k8s-node2   <none>           <none>
xx      1/1     Running   0          15m     10.244.2.32   k8s-node2   <none>          

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

[root@k8s-master ~]# kubectl taint node k8s-node1 name-
node/k8s-node1 untainted
[root@k8s-master ~]# kubectl describe node k8s-node1|grep -i taint
Taints:             <none>
[root@k8s-master ~]# kubectl apply -f test2.yaml pod/test2 unchanged
[root@k8s-master ~]# kubectl get pod -o wideNAME    READY   STATUS    RESTARTS   AGE    IP            NODE        NOMINATED NODE   READINESS GATES
test    1/1     Running   0          18m    10.244.1.48   k8s-node1   <none>           <none>
test1   1/1     Running   0          7m3s   10.244.1.49   k8s-node2   <none>           <none>
test2   1/1     Running   0          58s    10.244.2.33   k8s-node1   <none>           <none>
xx      1/1     Running   0          16m    10.244.2.32   k8s-node2   <none>           <none>

删除污点后,test2就被创建在了node1上
effect说明

上面的例子中effect的取值为NoSchedule,下面对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定义节点故障时持续多久才被逐出。

tolerations

设置了污点的Node将根据taint的effect:NoSchedule、PreferNoSchedule、NoExecute和Pod之间产生互斥的关系,Pod将在一定程度上不会被调度到Node上。

但我们可以在Pod上设置容忍 (Toleration),意思是设置了容忍的Pod将可以容忍污点的存在,可以被调度到存在污点的Node上

  tolerations:
  - key: name
    value: test
    operator: Equal
    effect: NoSchedule

其中key,vaule,effect要与Node上设置的taint保持一致

operator的值为Exists将会忽略value值

tolerationSeconds 用于描述当 Pod 需要被驱逐时可以在 Pod 上继续保留运行的时间

[root@k8s-master ~]# kubectl taint node k8s-node2 name=kk:NoSchedule
node/k8s-node2 tainted
[root@k8s-master ~]# kubectl describe node k8s-node2|grep -i taint
Taints:             name=kk:NoSchedule
[root@k8s-master ~]# kubectl apply -f test2.yaml
pod/test2 unchanged
[root@k8s-master ~]# kubectl get pod -o wideNAME    READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
test    1/1     Running   0          24m     10.244.1.48   k8s-node1   <none>           <none>
test1   1/1     Running   0          13m     10.244.1.49   k8s-node2   <none>           <none>
test2   1/1     Running   0          7m48s   10.244.2.33   k8s-node2   <none>           <none>
xx      1/1     Running   0          23m     10.244.2.32   k8s-node2   <none>           <none>

可以看到,虽然我们在node2上设置了污点,但因为我们在资源清单中定义了污点容忍,所以pod依旧能创建在node2上。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kubernetes(K8s)是一种用于容器编排和管理的开源平台,它提供了多维资源调度算法来实现高效的资源管理和利用。 K8s使用多维资源调度算法来平衡集群中所有节点的资源负载,确保每个节点能够充分利用其可用的计算和存储资源。这些资源包括CPU、内存、存储和网络带宽等。K8s通过采集集群中每个节点的资源使用情况,并将其报告给调度策略,从而实现资源的智能分配。 在K8s中,多维资源调度算法主要涉及以下几个方面: 1. 资源分配:K8s通过分配节点上的资源来满足容器的需求。调度器会考虑所有容器的资源需求,并将其分配到合适的节点上。该算法会根据容器的资源请求和节点的可用资源进行匹配,从而避免资源的浪费和不平衡。 2. 负载均衡:K8s通过负载均衡算法将容器分散到不同的节点上,以避免资源瓶颈和单点故障。该算法会根据节点的负载情况和容器的资源需求,将容器分配到最佳节点上,从而实现负载的均衡。 3. 弹性调度:K8s具有弹性调度的能力,可以根据节点的可用资源和容器的优先级,自动对容器进行调度。当集群容量不足或节点发生故障时,该算法可以自动将容器从一个节点迁移到另一个节点上,以确保容器的正常运行。 总之,K8s的多维资源调度算法是为了实现高效、均衡和可靠的资源管理。通过合理分配和调度容器的资源需求,K8s可以最大化地利用集群的资源,并提供高可用性和可伸缩性的应用环境。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值