容器化技术(十一):Kubernetes中Pod的调度策略-标签与污点实战
一、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的调度策略-标签与污点实战相关推荐
- Kubernetes中Pod的调度策略
Kubernetes中Pod的调度策略 1.Pod调度 在 Kubernetes 平台上,我们很少会直接创建一个 Pod,在大多数情况下会通过 RC.Deployment. DaemonSet.Job ...
- 容器化技术【Kubernetes】
Kubernetes 主要内容 Kubernetes 架构 Kubernetes 集群搭建 Kubernetes 基础概念 Kubernetes 部署容器化应用 DashBoard 工具 Ingres ...
- 容器化单页面应用中Nginx反向代理与Kubernetes部署
在<容器化单页面应用中RESTful API的访问>一文中,我介绍了一个在容器化环境中单页面应用访问后端服务的完整案例.这里我将继续使用这个案例,介绍一下容器化单页面应用部署的另一个场景: ...
- tcpip路由技术卷一_减少与开发的撕战,结合容器化技术轻松重构运维平台
荔枝微服务化进程较早,目前已有上千个服务模块,先前的运维平台渐渐无法满足微服务架构下运维管理的需求,于是决定从2018年开始重构运维平台,结合容器化技术,让开发人员尽可能无感知迁移的同时享受容器化带来 ...
- 容器编排技术 -- 了解Kubernetes对象
容器编排技术 -- 了解Kubernetes对象 1 了解Kubernetes对象 1.1 对象(Object)规范和状态 1.2 描述Kubernetes对象 1.3 必填字段 2 下一步? 了解K ...
- 容器化技术最佳实践1--容器化技术简介与Docker入门
容器化技术最佳实践1–容器化技术简介与Docker入门 文章目录 容器化技术最佳实践1--容器化技术简介与Docker入门 容器化简介 通过虚拟化了解容器化 对开发和运维的好处 容器化部署特点 什么情 ...
- 容器化技术与微服务结合---SpringCloud框架与阿里云serverless k8s的结合(六)
目录 系列 写在前面 Serverless K8S 概念 创建集群 微服务搭建 项目地址 环境区分以及dockerFile注意 阿里云日志接入 创建阿里云日志project 配置 测试 Kuberne ...
- 容器化技术与微服务结合---docker(一)
目录 系列 微服务 docker场景 mac上docker安装 系统要求 安装 linux上docker安装 Docker的一些命令 springcloud结合docker部署 docker buil ...
- 容器化技术与微服务结合---结合springcloud微服务框架进行部署(含切换成阿里云docker仓库)(五)
目录 系列 更换成阿里云仓库 开通阿里云镜像服务 创建仓库 本地k8s切换成阿里云的镜像仓库 测试阿里云镜像 准备简单的微服务 eureka 应用配置 k8s配置: demo-a 应用配置 k8s配置 ...
最新文章
- 第二讲 词向量表示 word2vec
- docker-compose 安装mysql
- android-创建流式布局,并修改最后一行的最后一个view
- win7如何添加开机启动程序(开机就自动运行打开)
- Swish激活 hswish激活
- 一网打尽深度学习之卷积神经网络的经典网络(LeNet-5、AlexNet、ZFNet、VGG-16、GoogLeNet、ResNet)
- python 余弦距离_距离公式汇总以及Python实现
- Node.js-中文分词【1】-node-segment
- 41岁,她破格提拔为高校副校长
- java常用的组件和框架总结
- Django开发教程 第一节 HelloWorld
- 基于矢量网络分析仪的天线近场测试方案
- 雷达多普勒频率计算公式_人体感应和雷达感应的区别
- 求:生意参谋 data 破解,最好是用php
- AutoCAD .Net 不同文档间复制对象
- Genymotion目前速度最快的Android模拟器+ova包
- [Beta] Scrum Meeting 7 - TEAM LESS ERROR
- 北京大学计算机就业报告,【计算机考研就业】北京大学2017年毕业生就业质量年度报告...
- linux 修改xt_recent参数 ip_list_tot ip_pkt_list_tot
- 网页防篡改技术的前世与今生