K8s资源调度

K8s资源调度

Kubernetes的整体架构

在这里插入图片描述

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 调度器

典型的流程

创建Pod的整个流程,时序图如下:

在这里插入图片描述

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

nodeSelector

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

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

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

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

[root@master ~]#  kubectl label node node1.example.com disktype=ssd
node/node1.example.com labeled
[root@master ~]# kubectl get node node1.example.com --show-labels
NAME                STATUS   ROLES    AGE    VERSION   LABELS
node1.example.com   Ready    <none>   4d6h   v1.23.1   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

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

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

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

[root@master ~]# kubectl label node node1.example.com disktype=ssd
node/node1.example.com labeled
[root@master ~]# kubectl get node node1.example.com --show-labels
NAME                STATUS   ROLES    AGE    VERSION   LABELS
node1.example.com   Ready    <none>   4d6h   v1.23.1   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 ~]# vi test.yml
[root@master ~]# 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调度的节点,test这个pod被强制调度到了有disktype=ssd这个label的node上。

[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS       AGE     IP            NODE                NOMINATED NODE   READINESS GATES
httpd1-57c7b6f7cb-sk86h   1/1     Running   4 (173m ago)   2d      10.244.1.93   node2.example.com   <none>           <none>
nginx1-7cf8bc594f-8j8tv   1/1     Running   1 (173m ago)   3h40m   10.244.1.94   node2.example.com   <none>           <none>

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。

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 ~]# kubectl label node node2.example.com disktype=ssd
node/node2.example.com labeled
[root@master ~]# kubectl get node node2.example.com --show-labels
NAME                STATUS   ROLES    AGE    VERSION   LABELS
node2.example.com   Ready    <none>   4d7h   v1.23.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2.example.com,kubernetes.io/os=linux

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

[root@master ~]# kubectl label node node1.example.com name=test
node/node1.example.com labeled
[root@master ~]# kubectl get node node1.example.com --show-labels
NAME                STATUS   ROLES    AGE    VERSION   LABELS
node1.example.com   Ready    <none>   4d7h   v1.23.1   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,name=test

[root@master ~]# kubectl apply -f test.yml 
pod/test created
[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS       AGE     IP            NODE                NOMINATED NODE   READINESS GATES
httpd1-57c7b6f7cb-sk86h   1/1     Running   4 (178m ago)   2d      10.244.1.93   node2.example.com   <none>           <none>
nginx1-7cf8bc594f-8j8tv   1/1     Running   1 (178m ago)   3h45m   10.244.1.94   node2.example.com   <none>           <none>
test                      1/1     Running   0              13s     10.244.1.95   node2.example.com   <none>           <none>

删除node1上name=test的label

[root@master ~]# kubectl label node node1.example.com name-
node/node1.example.com unlabeled
[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS       AGE     IP            NODE                NOMINATED NODE   READINESS GATES
httpd1-57c7b6f7cb-sk86h   1/1     Running   4 (179m ago)   2d1h    10.244.1.93   node2.example.com   <none>           <none>
nginx1-7cf8bc594f-8j8tv   1/1     Running   1 (179m ago)   3h46m   10.244.1.94   node2.example.com   <none>           <none>
test                      1/1     Running   0              44s     10.244.1.95   node2.example.com   <none>           <none>

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

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

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

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

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

  • 基于Taint的驱逐

#Taint(污点)
[root@master haproxy]# kubectl describe node master
Name:               master.example.com
Roles:              control-plane,master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=master.example.com
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/control-plane=
                    node-role.kubernetes.io/master=
                    node.kubernetes.io/exclude-from-external-load-balancers=
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"8e:50:ba:7a:30:2b"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 192.168.240.30
                    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sun, 19 Dec 2021 02:41:49 -0500
Taints:             node-role.kubernetes.io/master:NoSchedule  #aints:避免Pod调度到特定Node上
Unschedulable:      false


#Tolerations(污点容忍)
[root@master ~]# kubectl describe pod httpd1-57c7b6f7cb-sk86h 
Name:         httpd1-57c7b6f7cb-sk86h
Namespace:    default
·····
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s ##Tolerations(污点容忍)允许Pod调度到持有Taints的Node上	

Events:
  Type     Reason                  Age                From     Message
  ----     ------                  ----               ----     -------
  Warning  FailedCreatePodSandBox  12m                kubelet  Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "2126da4117ba6ce45ddff8a2e0b9de59bac65f05c7be343249d50edea2cacf37" network for pod "httpd1-57c7b6f7cb-sk86h": networkPlugin cni failed to set up pod "httpd1-57c7b6f7cb-sk86h_default" network: open /run/flannel/subnet.env: no such file or directory
  Warning  FailedCreatePodSandBox  12m                kubelet  Failed to create pod "best2001/httpd"
  Normal   Pulled                  11m                kubelet  Successfully pulled image "best2001/httpd" in 16.175310708s
  Normal   Created                 11m                kubelet  Created container httpd1
  Normal   Started                 11m                kubelet  Started container httpd1

节点添加污点
格式: kubectl taint node [node] key=value:[effect]
例如: kubectl taint node k8s-node1 gpu=yes:NoSchedule验证: kubectl describe node k8s-node1 |grep Taint

其中[effect]可取值:

  • NoSchedule :一定不能被调度
  • PreferNoSchedule:尽量不要调度,非必须配置容忍
  • NoExecute:不仅不会调度,还会驱逐Node上已有的Pod

添加污点容忍(tolrations)字段到Pod配置中

#添加污点disktype
[root@master haproxy]# kubectl taint node node1.example.com disktype:NoSchedule
node/node1.example.com tainted

#查看
[root@master haproxy]# kubectl describe node node1.example.com
Name:               node1.example.com
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=node1.example.com
                    kubernetes.io/os=linux
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"12:9e:43:99:21:bd"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 192.168.240.50
                    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sun, 19 Dec 2021 03:27:16 -0500
Taints:             disktype:NoSchedule  #污点添加成功

#测试创建一个容器
[root@master haproxy]# kubectl apply -f nginx.yml 
deployment.apps/nginx1 created
service/nginx1 created
[root@master haproxy]# kubectl get pods -o wide
NAME                      READY   STATUS    RESTARTS      AGE   IP            NODE                NOMINATED NODE   READINESS GATES
nginx1-7cf8bc594f-8j8tv   1/1     Running   0             14s   10.244.1.92   node2.example.com   <none>           <none>  #因为node1上面有污点,所以创建的容器会在node2上面跑

去掉污点:
kubectl taint node [node] key:[effect]-

[root@master haproxy]# kubectl taint node node1.example.com disktype-  
node/node1.example.com untainted

[root@master haproxy]# kubectl describe node node1.example.com
Name:               node1.example.com
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=node1.example.com
                    kubernetes.io/os=linux
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"12:9e:43:99:21:bd"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 192.168.240.50
                    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sun, 19 Dec 2021 03:27:16 -0500
Taints:             <none>   #污点已经删除成功
Unschedulable:      false

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枯木逢秋࿐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值