一、Pod的调度策略总述

Kubernetes中的容器编排功能的最大需要解决的问题就是将创建的Pod,调度到Node上去。那么Pod在选择调度到哪个Node上去时,是如何决策的。这就涉及到了我们在前面安装Kubernetes集群时,其中介绍的kube-scheduler组件。

kube-scheduler 给一个 pod 做调度选择的依据包含两个步骤:

(1)过滤:根据Pod对调度的要求,过滤掉一些Node,例如资源是否匹配,标签是否匹配,污点是否容忍等。

(2)打分:在满足了过滤要求的情况下,给这些Node进行打分,打分高的Node,会被确立为整个Pod调度的节点。

Pod对于资源的需求,我们在前面的内容中已经给读者介绍过。只有当对应的Node的资源满足Pod对于资源的请求时,才具备调度的可能性。

还有两种策略的指定,会直接影响到我们对于Pod的调度,那就是:

(1)标签

(2)污点

二、Label的调度实战

标签label,可以定义在Kubernetes集群中的各种资源上,上层的资源可以根据标签来选择对应的资源。常见的有三种对于标签的使用:

(1)Deployment,与Service根据标签选择对应的Pod。后文会介绍。

(2)PVC可以根据标签选择器选择满足资源要求的打了此标签的的PV。后文会介绍。

(3)Pod在定义的时候可以显示定义,部署在满足什么样的要求的标签的节点上面。

接下来,我们通过一个例子,来给节点打标签,并在Pod中定义部署在什么样标签的节点上,来验证效果。

给我们在Kubernetes集群中的资源添加标签,可以通过在yaml文件的metadata中定义,如下所示:

metadata: labels: key1: value1key2: value2

对于Kubernetes集群中的Worker节点,我们可以通过命令操作,给节点打标签,与去除标签的命令如下:

(1)kubectl label nodes node1 key1=value1

(2)kubectl label nodes node1 key1-

第一步,先给节点打标签:

kubectl label nodes kubernetes-worker01 scheduler-node=node1

验证下节点上是否打上了标签,查询的结果,如图所示,发现已经成功的打上了标签。

[root@kubernetes-master01 ~]# kubectl describe node kubernetes-worker01
Name:               kubernetes-worker01
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64beta.kubernetes.io/os=linuxkubernetes.io/arch=amd64kubernetes.io/hostname=kubernetes-worker01kubernetes.io/os=linuxscheduler-node=node1

第二步,我们用yaml来定义一个Pod,文件内容如下:

apiVersion: v1
kind: Pod
metadata:name: pod-nginx
spec:containers:- name: nginximage: nginxports:- containerPort: 80hostPort: 80nodeSelector:scheduler-node: node1

创建这个Pod:

kubectl apply -f pod-nginx-select.yaml

我们来查看下Pod调度到哪个节点上了,如图所示,此Pod已经被定义到了对应的节点上。

[root@kubernetes-master01 ~]# kubectl get pod -o wide
NAME        READY   STATUS    RESTARTS   AGE    IP            NODE
pod-nginx   1/1     Running   0          102s   10.244.1.28   kubernetes-worker01

第三步,修改Pod的定义,将节点定义的标签 scheduler-node 的值改为node2,yaml文件改动的地方如下:

nodeSelector:scheduler-node: node2

第四步,删除之前的Pod,并重新创建这个Pod,如图所示,执行对应的命令。

[root@kubernetes-master01 ~]# kubectl delete pod pod-nginx
pod "pod-nginx" deleted
[root@kubernetes-master01 ~]# kubectl apply -f pod-nginx-select.yaml
pod/pod-nginx created

第五步,我们来查看下Pod的状态,如图所示,Pod的状态为Pending状态。

[root@kubernetes-master01 ~]# kubectl get pod -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP       NODE
pod-nginx   0/1     Pending   0          7s    <none>   <none>

第六步,查看Pod的具体运行情况,为什么没有调度成功,如图所示,因为没有找到nodeSelector对应的node。

Events:Type     Reason            Age                  From               Message----     ------            ----                 ----               -------Warning  FailedScheduling  78s (x4 over 4m11s)  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.

接下来,我们来总结下标签的相关内容,标签是在对应的资源上打上对应的标签,本例中是在node上打上对应的标签,进而让Pod根据标签选择参数nodeSelector来决定部署到特定类型的节点node上面。

对于Deployment与Service等高级资源,他们在选择Pod的策略上,也是同样的道理,可以在Pod上面打上对应的标签,在Deployment或Service等资源上设定对应的Pod的标签范围,就可以让这些高级资源找到对应的Pod了。

在yaml文件中,上层资源指定匹配标签的格式如下:

selector:matchLabels:component: redismatchExpressions:- {key: tier, operator: In, values: [cache]}- {key: environment, operator: NotIn, values: [dev]}

其中:

(1)matchLabels 是由 {key,value} 对组成的映射。

(2)matchLabels 映射中的单个 {key,value } 等同于 matchExpressions 的元素, 其 key 字段为 “key”,operator 为 “In”,而 values 数组仅包含 “value”。

(3)matchExpressions 是 Pod 选择算符需求的列表。

(4) 有效的运算符包括 In、NotIn、Exists 和 DoesNotExist。

(5) 在 In 和 NotIn 的情况下,设置的值必须是非空的。

(6)来自 matchLabels 和 matchExpressions 的所有要求都按逻辑与的关系组合到一起 – 它们必须都满足才能匹配。

三、污点的调度实战

我们除了使用标签让资源进行相应的匹配外,还有一种叫做污点的机制,污点一般都是不好的东西,当我们的节点因为一些情况,不想让Pod调度到上面的时候,就可以给节点打上污点。打了污点的节点,Pod不会调度到上面去,除非是Pod上明确标明,可以容忍对应的污点。

给节点打污点的命令为:

kubectl taint nodes node1 key1=value1:NoSchedule

其中:

(1)node1:是节点的名字。

(2)key1:是污点的可以。

(3)value1:是污点的value。

(4)NoSchedule:代表污点起到的效果。

污点起到的效果的值可以为:

(1)NoSchedule:Pod不会调度到这个节点上。

(2)PreferNoSchedule:Pod可能会调度到这个节点上,都是不会优先调度到这个节点上。

(3)NoExecute:Pod如果没在这个节点上运行,那么不会调度到这个节点上,如果Pod已经在这个节点上运行,则这个Pod将会被驱逐。

我们用一个例子,来带领读者去实践和理解下污点的概念。例子中我们给一个节点打上污点,正常的创建一个Pod,然后查看Pod的调度情况。然后我们将Pod的定义修改为可以容忍这个污点,再次查看Pod的调度情况。

第一步:给两个Worker节点都打上污点。

kubectl taint node kubernetes-worker01 key1=value1:NoSchedule
kubectl taint node kubernetes-worker02 key1=value1:NoSchedule

查看节点上的污点的情况,如图所示,已经成功的给节点打上了污点。

[root@kubernetes-master01 ~]# kubectl describe node kubernetes-worker01
Name:               kubernetes-worker01
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64beta.kubernetes.io/os=linuxkubernetes.io/arch=amd64kubernetes.io/hostname=kubernetes-worker01kubernetes.io/os=linuxscheduler-node=node1
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"82:5b:4d:5a:49:f8"}flannel.alpha.coreos.com/backend-type: vxlanflannel.alpha.coreos.com/kube-subnet-manager: trueflannel.alpha.coreos.com/public-ip: 192.168.8.22kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.socknode.alpha.kubernetes.io/ttl: 0volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sun, 14 Mar 2021 10:47:25 +0800
Taints:             key1=value1:NoSchedule
[root@kubernetes-master01 ~]# kubectl describe node kubernetes-worker02
Name:               kubernetes-worker02
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64beta.kubernetes.io/os=linuxkubernetes.io/arch=amd64kubernetes.io/hostname=kubernetes-worker02kubernetes.io/os=linux
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"96:a9:e7:6c:c6:32"}flannel.alpha.coreos.com/backend-type: vxlanflannel.alpha.coreos.com/kube-subnet-manager: trueflannel.alpha.coreos.com/public-ip: 192.168.8.33kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.socknode.alpha.kubernetes.io/ttl: 0volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sun, 14 Mar 2021 10:47:25 +0800
Taints:             key1=value1:NoSchedule

第二步:正常的定义一个Pod,其yaml文件内容如下:

apiVersion: v1
kind: Pod
metadata:name: pod-nginx
spec:containers:- name: nginximage: nginxports:- containerPort: 80hostPort: 80

创建这个Pod:

kubectl apply -f pod-nginx-toleration.yaml

第三步:查看Pod的状态,如图所示,Pod没有调度成功。

[root@kubernetes-master01 k8s-yaml]# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
pod-nginx   0/1     Pending   0          67s

第四步:查看Pod没有调度成功的原因,如图所示, 因为master上面有污点,两个node上面也有污点,所以调度失败。

Events:Type     Reason            Age               From               Message----     ------            ----              ----               -------Warning  FailedScheduling  3s (x3 over 93s)  default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) had taint {key1: value1}, that the pod didn't tolerate.

第五步:我们删除之前的Pod。

kubectl delete pod pod-nginx

第六步:修改Pod的定义,让其可以容忍对应的污点。

apiVersion: v1
kind: Pod
metadata:name: pod-nginx
spec:containers:- name: nginximage: nginxports:- containerPort: 80hostPort: 80tolerations:- key: "key1"operator: "Exists"effect: "NoSchedule"

创建这个Pod:

kubectl apply -f pod-nginx-toleration.yaml

第七步:查看Pod的调度状态,如图所示,Pod已经调度成功。

[root@kubernetes-master01 k8s-yaml]# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
pod-nginx   1/1     Running   0          56s

查看具体的Pod的运行状态,如图所示,发现已经调度成功到节点kubernetes-worker01上面。

Events:Type    Reason     Age   From                          Message----    ------     ----  ----                          -------Normal  Scheduled  21s   default-scheduler             Successfully assigned default/pod-nginx to kubernetes-worker01Normal  Pulling    20s   kubelet, kubernetes-worker01  Pulling image "nginx"Normal  Pulled     4s    kubelet, kubernetes-worker01  Successfully pulled image "nginx"Normal  Created    4s    kubelet, kubernetes-worker01  Created container nginxNormal  Started    4s    kubelet, kubernetes-worker01  Started container nginx

接下里,总结一下关于污点的相关情况,一般污点会定义某些节点的运行不良的状况,正常的情况下Pod不会调度到有污点的节点上。除非Pod中定义了可以容忍对应的污点。Kubernetes集群中的节点会根据节点的运行情况,会自动的给节点添加上对应的污点:

(1)node.kubernetes.io/not-ready:节点未准备好。这相当于节点状态 Ready 的值为 “False”。

(2)node.kubernetes.io/unreachable:节点控制器访问不到节点. 这相当于节点状态 Ready 的值为 “Unknown”。

(3)node.kubernetes.io/out-of-disk:节点磁盘耗尽。

(4)node.kubernetes.io/memory-pressure:节点存在内存压力。

(5)node.kubernetes.io/disk-pressure:节点存在磁盘压力。

(6)node.kubernetes.io/network-unavailable:节点网络不可用。

(7)node.kubernetes.io/unschedulable: 节点不可调度。

(8)node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 启动时指定了一个 “外部” 云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点。

那么什么情况下,我们需要在生产中主动的给节点添加污点呢?一般基于以下两种情况:

(1)专用节点:当我们需要某些Pod运行在特定的节点上,那么我们可以在这些节点上打上污点,让这些对应的Pod容忍这些污点。

(2)配备了特殊硬件的节点:因为某些Pod对资源的使用有一些特殊的要求,这时候,可以使用污点机制来解决,达到Pod运行在这些特殊资源上的目标。

本节中,为读者说明了Pod的调度策略,首先需要对应的Node满足Pod对于资源你的要求,然后基于标签以及污点的机制,可以达到干预Pod的调度的目的,使Pod可以决定运行或不能运行或不优先运行在某些节点上,最后根据打分的机制,在满足要求的Node节点中,选择最优的Node来运行。

四、猜你喜欢

如果你对容器化技术的相关知识感兴趣,可以阅读:秀丽的容器化技术Kubernetes专栏

本专栏特点:

  • 理论结合实战
  • 讲解深入浅出

容器化技术(十一):Kubernetes中Pod的调度策略-标签与污点实战相关推荐

  1. Kubernetes中Pod的调度策略

    Kubernetes中Pod的调度策略 1.Pod调度 在 Kubernetes 平台上,我们很少会直接创建一个 Pod,在大多数情况下会通过 RC.Deployment. DaemonSet.Job ...

  2. 容器化技术【Kubernetes】

    Kubernetes 主要内容 Kubernetes 架构 Kubernetes 集群搭建 Kubernetes 基础概念 Kubernetes 部署容器化应用 DashBoard 工具 Ingres ...

  3. 容器化单页面应用中Nginx反向代理与Kubernetes部署

    在<容器化单页面应用中RESTful API的访问>一文中,我介绍了一个在容器化环境中单页面应用访问后端服务的完整案例.这里我将继续使用这个案例,介绍一下容器化单页面应用部署的另一个场景: ...

  4. tcpip路由技术卷一_减少与开发的撕战,结合容器化技术轻松重构运维平台

    荔枝微服务化进程较早,目前已有上千个服务模块,先前的运维平台渐渐无法满足微服务架构下运维管理的需求,于是决定从2018年开始重构运维平台,结合容器化技术,让开发人员尽可能无感知迁移的同时享受容器化带来 ...

  5. 容器编排技术 -- 了解Kubernetes对象

    容器编排技术 -- 了解Kubernetes对象 1 了解Kubernetes对象 1.1 对象(Object)规范和状态 1.2 描述Kubernetes对象 1.3 必填字段 2 下一步? 了解K ...

  6. 容器化技术最佳实践1--容器化技术简介与Docker入门

    容器化技术最佳实践1–容器化技术简介与Docker入门 文章目录 容器化技术最佳实践1--容器化技术简介与Docker入门 容器化简介 通过虚拟化了解容器化 对开发和运维的好处 容器化部署特点 什么情 ...

  7. 容器化技术与微服务结合---SpringCloud框架与阿里云serverless k8s的结合(六)

    目录 系列 写在前面 Serverless K8S 概念 创建集群 微服务搭建 项目地址 环境区分以及dockerFile注意 阿里云日志接入 创建阿里云日志project 配置 测试 Kuberne ...

  8. 容器化技术与微服务结合---docker(一)

    目录 系列 微服务 docker场景 mac上docker安装 系统要求 安装 linux上docker安装 Docker的一些命令 springcloud结合docker部署 docker buil ...

  9. 容器化技术与微服务结合---结合springcloud微服务框架进行部署(含切换成阿里云docker仓库)(五)

    目录 系列 更换成阿里云仓库 开通阿里云镜像服务 创建仓库 本地k8s切换成阿里云的镜像仓库 测试阿里云镜像 准备简单的微服务 eureka 应用配置 k8s配置: demo-a 应用配置 k8s配置 ...

最新文章

  1. 第二讲 词向量表示 word2vec
  2. docker-compose 安装mysql
  3. android-创建流式布局,并修改最后一行的最后一个view
  4. win7如何添加开机启动程序(开机就自动运行打开)
  5. Swish激活 hswish激活
  6. 一网打尽深度学习之卷积神经网络的经典网络(LeNet-5、AlexNet、ZFNet、VGG-16、GoogLeNet、ResNet)
  7. python 余弦距离_距离公式汇总以及Python实现
  8. Node.js-中文分词【1】-node-segment
  9. 41岁,她破格提拔为高校副校长
  10. java常用的组件和框架总结
  11. Django开发教程 第一节 HelloWorld
  12. 基于矢量网络分析仪的天线近场测试方案
  13. 雷达多普勒频率计算公式_人体感应和雷达感应的区别
  14. 求:生意参谋 data 破解,最好是用php
  15. AutoCAD .Net 不同文档间复制对象
  16. Genymotion目前速度最快的Android模拟器+ova包
  17. [Beta] Scrum Meeting 7 - TEAM LESS ERROR
  18. 北京大学计算机就业报告,【计算机考研就业】北京大学2017年毕业生就业质量年度报告...
  19. linux 修改xt_recent参数 ip_list_tot ip_pkt_list_tot
  20. 网页防篡改技术的前世与今生

热门文章

  1. Python使用Turtle画国旗系列,Python相关方法的梳理和总结
  2. Javascript——高级进阶
  3. 图解ReentrantLock底层公平锁和非公平锁实现原理
  4. Linux工具的基本使用
  5. 学习笔记:全局变量定义“无须”初始化,局部变量必须初始化
  6. 偶像 贝尔·格里尔斯(Bear Grylls)
  7. 2、TWS API接口的使用说明
  8. java scanner 教程,Java Scanner 类 - Java 入门教程
  9. 企业ERP系统开发总结及建议
  10. Struts2介绍(一个大的工具库)