Kubernetes之Pod调度

简介: Kubernetes调度器根据特定的算法与策略将pod调度到工作节点上。在默认情况下,Kubernetes调度器可以满足绝大多数需求,例如调度pod到资源充足的节点上运行,或调度pod分散到不同节点使集群节点资源均衡等。

Kubernetes调度器根据特定的算法与策略将pod调度到工作节点上。在默认情况下,Kubernetes调度器可以满足绝大多数需求,例如调度pod到资源充足的节点上运行,或调度pod分散到不同节点使集群节点资源均衡等。但一些特殊的场景,默认调度算法策略并不能满足实际需求,例如使用者期望按需将某些pod调度到特定硬件节点(数据库服务部署到SSD硬盘机器、CPU/内存密集型服务部署到高配CPU/内存服务器),或就近部署交互频繁的pod(例如同一机器、同一机房、或同一网段等)。


Kubernetes中的调度策略主要分为全局调度与运行时调度2种。其中全局调度策略在调度器启动时配置,而运行时调度策略主要包括选择节点(nodeSelector),节点亲和性(nodeAffinity),pod亲和与反亲和性(podAffinity与podAntiAffinity)。Node Affinity、podAffinity/AntiAffinity以及后文即将介绍的污点(Taints)与容忍(tolerations)等特性,在Kuberntes1.6中均处于Beta阶段。

本文着重介绍运行时调度策略。

设置节点label

Label是Kubernetes核心概念之一,其以key/value的形式附加到各种对象上,如Pod、Service、Deployment、Node等,达到识别这些对象,管理关联关系等目的,如Node和Pod的关联。
获取当前集群中的全部节点:

kubectl get nodes

为指定节点设置label:

kubectl label nodes <node-name> <label-key>=<label-value>

确认节点label是否设置成功:

kubectl get nodes -l label_key=label_value

选择节点(nodeSelector)

nodeSelector是目前最为简单的一种pod运行时调度限制,目前在Kubernetes1.7.x及以下版本可用。Pod.spec.nodeSelector通过kubernetes的label-selector机制选择节点,由调度器调度策略匹配label,而后调度pod到目标节点,该匹配规则属于强制约束。后文要讲的nodeAffinity具备nodeSelector的全部功能,所以未来Kubernetes会将nodeSelector废除。

nodeSelector举例:

设置label

$ kubectl label nodes bjo-rpt-re-002.dev.fwmrm.net disktype=ssd
node "bjo-rpt-re-002.dev.fwmrm.net" labeled

查看满足非master节点且disktype类型为ssd的节点:

kubectl get nodes -l 'role!=master, disktype=ssd'
NAME STATUS AGE VERSION
bjo-rpt-re-002.dev.fwmrm.net Ready 39d v1.7.1

pod.yaml文件内容:

apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers: - name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd

创建pod:

kubectl create -f pod.yaml

查看pod nginx被调度到预期节点运行:

$ kubectl get po nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 10s 10.244.3.13 bjo-rpt-re-002.dev.fwmrm.net

注:如果非默认namespace,需要指定具体namespace,例如:

kubectl -n kube-system get pods -o wide

内置节点label

Kubernetes自v1.4开始,节点有一些built-in label,罗列如下:

  • kubernetes.io/hostname
  • failure-domain.beta.kubernetes.io/zone
  • failure-domain.beta.kubernetes.io/region
  • beta.kubernetes.io/instance-type
  • beta.kubernetes.io/os
  • beta.kubernetes.io/arch
built-in label举例

yaml文件内容:

apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers: - name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
kubernetes.io/hostname: bjo-ep-svc-017.dev.fwmrm.net

创建pod,并检查结果符合预期,pod被调度在预先设置的节点 bjo-ep-svc-017.dev.fwmrm.net:

$ kubectl get po nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 3m 10.244.1.58 bjo-ep-svc-017.dev.fwmrm.net

亲和性(Affinity)与非亲和性(anti-affinity)

前面提及的nodeSelector,其仅以一种非常简单的方式、即label强制限制pod调度到指定节点。而亲和性(Affinity)与非亲和性(anti-affinity)则更加灵活的指定pod调度到预期节点上,相比nodeSelector,Affinity与anti-affinity优势体现在:

  • 表述语法更加多样化,不再仅受限于强制约束与匹配。
  • 调度规则不再是强制约束(hard),取而代之的是软限(soft)或偏好(preference)。
  • 指定pod可以和哪些pod部署在同一个/不同拓扑结构下。

亲和性主要分为3种类型:node affinity与inter-pod affinity/anti-affinity,下文会进行详细说明。

节点亲和性(Node affinity)

Node affinity在Kubernetes 1.2做为alpha引入,其涵盖了nodeSelector功能,主要分为requiredDuringSchedulingIgnoredDuringExecution与preferredDuringSchedulingIgnoredDuringExecution 2种类型。前者可认为一种强制限制,如果 Node 的标签发生了变化导致其没有符合 Pod 的调度要求节点,那么pod调度就会失败。而后者可认为理解为软限或偏好,同样如果 Node 的标签发生了变化导致其不再符合 pod 的调度要求,pod 依然会调度运行。

Node affinity举例

设置节点label:

$ kubectl label nodes bjo-ep-dep-040.dev.fwmrm.net cpu=high
node "bjo-ep-dep-040.dev.fwmrm.net" labeled

$ kubectl label nodes bjo-ep-svc-017.dev.fwmrm.net cpu=mid
node "bjo-ep-svc-017.dev.fwmrm.net" labeled

$ kubectl label nodes bjo-rpt-re-002.dev.fwmrm.net cpu=low
node "bjo-rpt-re-002.dev.fwmrm.net" labeled

部署pod的预期是到非master节点(role!=master)、且CPU高配的机器上(cpu=high)。
查看满足条件节点:

$ kubectl get nodes -l 'cpu=high, role!=master'
NAME STATUS AGE VERSION
bjo-ep-dep-040.dev.fwmrm.net Ready 41d v1.7.1

pod.yaml文件内容如下:

apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
affinity:
nodeAffinity:
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms: - matchExpressions: - key: role
 operator: NotIn
 values: - master
 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1
 preference:
 matchExpressions: - key: cpu
 operator: In
 values: - high
containers: - name: nginx
image: nginx
imagePullPolicy: IfNotPresent

检查结果符合预期,pod nginx成功部署到非master节点且CPU高配的机器上。

$ kubectl get po nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 32s 10.244.2.185 bjo-ep-dep-040.dev.fwmrm.net

pod亲和性(Inter-pod affinity)与反亲和性(anti-affinity)

inter-pod affinity与anti-affinity由Kubernetes 1.4引入,当前处于beta阶段,其中podAffinity用于调度pod可以和哪些pod部署在同一拓扑结构之下。而podAntiAffinity相反,其用于规定pod不可以和哪些pod部署在同一拓扑结构下。通过pod affinity与anti-affinity来解决pod和pod之间的关系。
与Node affinity类似,pod affinity与anti-affinity同样分为requiredDuringSchedulingIgnoredDuringExecution and preferredDuringSchedulingIgnoredDuringExecution等2种类型,前者被认为是强制约束,而后者后者可认为理解软限(soft)或偏好(preference)。

pod affinity与anti-affinity举例

本示例中假设部署场景为:期望is服务与oltp服务就近部署,而不希望与solr服务部署同一拓扑结构上。
yaml文件部分内容:

spec:
replicas: 1 template:
metadata:
 labels:
 app: is

spec:
 affinity:
 podAffinity:
 requiredDuringSchedulingIgnoredDuringExecution: - labelSelector:
 matchExpressions: - key: app
 operator: NotIn
 values: - solr
 topologyKey: kubernetes.io/hostname
 podAntiAffinity:
 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1
 podAffinityTerm:
 labelSelector:
 matchExpressions: - key: app
 operator: In
 values: - oltp
 topologyKey: beta.kubernetes.io/os

查看部署结果,is服务与oltp部署到了同一台机器,而solr被部署在其他机器上。

$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
is-3059482752-5s14t 0/1 Running 1 1m 10.244.1.60 bjo-ep-svc-017.dev.fwmrm.net
oltp-282283610-kdvnp 1/1 Running 0 1m 10.244.1.53 bjo-ep-svc-017.dev.fwmrm.net
solr-908150957-rswlm 1/1 Running 0 1m 10.244.3.5 bjo-rpt-re-002.dev.fwmrm.net

亲和性/反亲和性调度策略比较

调度策略 匹配标签 操作符 拓扑域支持 调度目标
nodeAffinity 主机 In, NotIn, Exists,  pod到指定主机 DoesNotExist, Gt, Lt 
podAffinity Pod In, NotIn, Exists,  pod与指定pod同一拓扑域 DoesNotExist PodAntiAffinity Pod In, NotIn, Exists,  pod与指定pod非同一拓扑域 DoesNotExist 

污点(Taints)与容忍(tolerations)

对于Node affinity,无论是强制约束(hard)或偏好(preference)方式,都是调度pod到预期节点上,而Taints恰好与之相反,如果一个节点标记为 Taints ,除非 Pod也被标识为可以耐受污点节点,否则该Taints节点不会被调度pod。Taints)与tolerations当前处于beta阶段,
Taints节点应用场景比如用户希望把Kubernetes Master节点保留给 Kubernetes 系统组件使用,或者把一组具有特殊资源预留给某些 pod。pod不会再被调度到taint标记过的节点。

taint标记节点举例如下:
$ kubectl taint nodes bjo-ep-dep-039.dev.fwmrm.net key=value:NoSchedule
node "bjo-ep-dep-039.dev.fwmrm.net" tainted

如果仍然希望某个pod调度到taint节点上,则必须在 Spec 中做出Toleration 定义,才能调度到该节点,举例如下:

tolerations: - key: "key" operator: "Equal"
value: "value"
effect: "NoSchedule"

effect 共有三个可选项,可按实际需求进行设置:

  • NoSchedule:pod不会被调度到标记为taints节点。
  • PreferNoSchedule:NoSchedule的“preference”或“soft”版本。
  • NoExecute:该选项意味着一旦Taint 生效,如该节点内正在运行的 Pod 没有对应 Tolerate 设置,会直接被逐出。

总结

使用者可根据实际需求,充分利用pod的相关高级调度策略,使Kubernetes更好的服务于我们的需求。

本文转自中文社区-Kubernetes之Pod调度

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
6月前
|
Kubernetes Docker 容器
Kubernetes与Docker参数对照:理解Pod中的command、args与Dockerfile中的CMD、ENTRYPOINT。
需要明确的是,理解这些都需要对Docker和Kubernetes有一定深度的理解,才能把握二者的区别和联系。虽然它们都是容器技术的二个重要组成部分,但各有其特性和适用场景,理解它们的本质和工作方式,才能更好的使用这些工具,将各自的优点整合到生产环境中,实现软件的快速开发和部署。
213 25
|
5月前
|
人工智能 Serverless 调度
突破地域限制,实现算力无限供给 —阿里云ACK One注册集群开启多地域Serverless算力调度
本文介绍了阿里云ACK One注册集群多地域Serverless算力调度解决方案,解决传统数据中心在AI时代面临的算力不足问题。方案通过分钟级接入、100%兼容Kubernetes操作及云上Serverless弹性,实现跨地域弹性算力供给,支持高并发请求与模型快速迭代。文中详细描述了快速接入步骤、指定地域调度及动态调度方法,并提供了相关代码示例。该方案助力企业实现AI推理服务的规模化部署,提升商业落地效率。
|
5月前
|
人工智能 Serverless 调度
突破地域限制,实现算力无限供给 -- 阿里云ACK One注册集群开启多地域Serverless算力调度
传统单地域算力难以支撑AI推理场景的高并发实时响应、突发高流量的要求,阿里云容器服务ACK One注册集群推出多地域Serverless算力调度方案完美解决此问题。
|
6月前
|
人工智能 分布式计算 调度
打破资源边界、告别资源浪费:ACK One 多集群Spark和AI作业调度
ACK One多集群Spark作业调度,可以帮助您在不影响集群中正在运行的在线业务的前提下,打破资源边界,根据各集群实际剩余资源来进行调度,最大化您多集群中闲置资源的利用率。
|
10月前
|
Prometheus Kubernetes 监控
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
|
6月前
|
Kubernetes Shell Windows
【Azure K8S | AKS】在AKS的节点中抓取目标POD的网络包方法分享
在AKS中遇到复杂网络问题时,可通过以下步骤进入特定POD抓取网络包进行分析:1. 使用`kubectl get pods`确认Pod所在Node;2. 通过`kubectl node-shell`登录Node;3. 使用`crictl ps`找到Pod的Container ID;4. 获取PID并使用`nsenter`进入Pod的网络空间;5. 在`/var/tmp`目录下使用`tcpdump`抓包。完成后按Ctrl+C停止抓包。
218 12
|
10月前
|
存储 Kubernetes Docker
【赵渝强老师】Kubernetes中Pod的基础容器
Pod 是 Kubernetes 中的基本单位,代表集群上运行的一个进程。它由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。基础容器负责维护 Pod 的网络空间,对用户透明。文中附有图片和视频讲解,详细介绍了 Pod 的组成结构及其在网络配置中的作用。
173 1
【赵渝强老师】Kubernetes中Pod的基础容器
|
10月前
|
运维 Kubernetes Shell
【赵渝强老师】K8s中Pod的临时容器
Pod 是 Kubernetes 中的基本调度单位,由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。临时容器用于故障排查和性能诊断,不适用于构建应用程序。当 Pod 中的容器异常退出或容器镜像不包含调试工具时,临时容器非常有用。文中通过示例展示了如何使用 `kubectl debug` 命令创建临时容器进行调试。
180 1
|
10月前
|
Kubernetes 调度 容器
【赵渝强老师】K8s中Pod中的业务容器
Pod 是 Kubernetes 中的基本调度单元,由一个或多个容器组成。除了业务容器,Pod 还包括基础容器、初始化容器和临时容器。本文通过示例介绍如何创建包含业务容器的 Pod,并提供了一个视频讲解。示例中创建了一个名为 &quot;busybox-container&quot; 的业务容器,并使用 `kubectl create -f firstpod.yaml` 命令部署 Pod。
138 1
|
10月前
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
171 1

推荐镜像

更多