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

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
19天前
|
存储 Kubernetes 调度
【赵渝强老师】什么是Kubernetes的Pod
Pod 是 Kubernetes 中的基本逻辑单位,代表集群上的一个应用实例。它可以由一个或多个容器组成,并包含数据存储和网络配置等资源。Pod 支持多种容器执行环境,如 Docker。Kubernetes 使用 Pod 管理容器,具有简化部署、方便扩展和调度管理等优点。视频讲解和图示详细介绍了 Pod 的组成结构和使用方式。
|
19天前
|
存储 Kubernetes Docker
【赵渝强老师】Kubernetes中Pod的基础容器
Pod 是 Kubernetes 中的基本单位,代表集群上运行的一个进程。它由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。基础容器负责维护 Pod 的网络空间,对用户透明。文中附有图片和视频讲解,详细介绍了 Pod 的组成结构及其在网络配置中的作用。
【赵渝强老师】Kubernetes中Pod的基础容器
|
19天前
|
运维 Kubernetes Shell
【赵渝强老师】K8s中Pod的临时容器
Pod 是 Kubernetes 中的基本调度单位,由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。临时容器用于故障排查和性能诊断,不适用于构建应用程序。当 Pod 中的容器异常退出或容器镜像不包含调试工具时,临时容器非常有用。文中通过示例展示了如何使用 `kubectl debug` 命令创建临时容器进行调试。
|
19天前
|
Kubernetes 调度 容器
【赵渝强老师】K8s中Pod中的业务容器
Pod 是 Kubernetes 中的基本调度单元,由一个或多个容器组成。除了业务容器,Pod 还包括基础容器、初始化容器和临时容器。本文通过示例介绍如何创建包含业务容器的 Pod,并提供了一个视频讲解。示例中创建了一个名为 &quot;busybox-container&quot; 的业务容器,并使用 `kubectl create -f firstpod.yaml` 命令部署 Pod。
|
19天前
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
|
20天前
|
弹性计算 Kubernetes Perl
k8s 设置pod 的cpu 和内存
在 Kubernetes (k8s) 中,设置 Pod 的 CPU 和内存资源限制和请求是非常重要的,因为这有助于确保集群资源的合理分配和有效利用。你可以通过定义 Pod 的 `resources` 字段来设置这些限制。 以下是一个示例 YAML 文件,展示了如何为一个 Pod 设置 CPU 和内存资源请求(requests)和限制(limits): ```yaml apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: example-container image:
115 1
|
22天前
|
Kubernetes Nacos 微服务
探讨了在Kubernetes中使用Nacos v2.2.3时,强制删除Pod后Pod仍存在的常见问题
本文深入探讨了在Kubernetes中使用Nacos v2.2.3时,强制删除Pod后Pod仍存在的常见问题。通过检查Pod状态、事件、配置,调整Nacos和Kubernetes设置,以及手动干预等步骤,帮助开发者快速定位并解决问题,确保服务稳定运行。
50 2
|
19天前
|
存储 Kubernetes 调度
深入理解Kubernetes中的Pod与Container
深入理解Kubernetes中的Pod与Container
27 0
|
19天前
|
Kubernetes Java 调度
Kubernetes中的Pod垃圾回收策略是什么
Kubernetes中的Pod垃圾回收策略是什么
|
19天前
|
存储 Kubernetes 调度
深度解析Kubernetes中的Pod生命周期管理
深度解析Kubernetes中的Pod生命周期管理