当前位置: 首页 > 科技观察

几种超实用的KubernetesPod高级调度策略

时间:2023-03-20 16:37:47 科技观察

在很多场景下,基于资源约束来调度Pod是一种理想的行为。但是,在某些用例中,尤其是一些高级调度场景,Kubernetes管理员希望根据其他约束将pod调度到特定节点。在本文中,我将回顾Kubernetes中高级pod调度的一些场景,以及在实际情况下实现它的最佳实践。这对于希望实现高级应用程序部署模式的应用程序工程师和K8s管理员尤其有用,这些模式涉及数据本地化、pod共存、高可用性和K8s集群的资源高效利用。1.手动将Pod调度到节点的场景在生产Kubernetes设置中,自定义如何将Pod调度到节点非常重要。以下是一些最常见的调度场景:在具有专用硬件的节点上运行pod:一些Kubernetes应用程序可能有特定的硬件要求。例如,运行ML作业的Pod需要高性能GPU而不是CPU,而ElasticsearchPod在SSD上比在HDD上更高效。因此,任何资源感知型K8s集群管理的最佳实践是将pod分配给具有正确硬件的节点。Pod托管和相互依赖性:在微服务设置或紧密耦合的应用程序堆栈中,一些Pod应该托管在同一台机器上以提高性能,避免网络延迟问题和连接失败。例如,在同一台机器上运行Web服务器作为Memcached服务或数据库是一种很好的做法。数据局部性:数据密集型应用程序的数据局部性要求与以前的用例类似。为了确保更快的读取和更好的写入吞吐量,这些应用程序可能需要将数据库部署在与应用程序相同的机器上。高可用性和容错性:为了使应用程序部署具有高可用性和容错性,在不同可用性区域的节点上部署和运行pod是一个很好的做法。2.Pod高级调度方式Kubernetes提供了很多API资源和策略来帮助实现这些场景。接下来介绍nodeSelector、nodeaffinity、inter-Podaffinity的概念。我还将向您介绍一些示例,并向您展示如何在K8s集群中实现它们。使用nodeSelector手动调度Pod在K8s早期版本中,用户可以使用PodSpec的nodeSelector字段来实现手动Pod调度。本质上,nodeSelector是一种基于标签的pod到节点调度方法,其中用户将某些标签分配给节点并确保nodeSelector字段与这些标签匹配。例如,假设其中一个节点标签是“storage=ssd”,以指示节点上的存储类型。要将pod安排到具有此标签的节点上,我在podyaml文件中指定了一个具有该标签的nodeSelector字段。节点选择器是高级pod调度的最简单方法。但是,当在Pod调度期间应考虑其他规则和条件时,它不是很有用。节点亲和性节点亲和性特征是对上面讨论的手动pod放置方法的质的改进。它使用逻辑运算符和约束提供了一种富有表现力的亲和力语言,允许对pod放置进行细粒度控制。它还支持“软”和“硬”调度规则,允许根据用户要求控制节点关联约束的严格程度。在下面的示例中,我们使用节点亲和性将Pod放置在特定的可用节点上。让我们看看下面的编排文件:“硬”亲和性规则是在pod编排文件的nodeAffinity部分的requiredduringschedulingignoredduringexecution字段下指定的。在此示例中,我告诉调度程序仅将pod放置在标签为kubernetes.io/cp-az-name且值为cp-1a或cp-1b的节点上。为此,我使用了In逻辑运算符来过滤现有标记值的数组。我可以使用的其他运算符包括NotIn、Exists、DoesNotExist、Gt、Lt。“软”规则在规范的执行期间优先调度期间忽略字段下指定。在这个例子中,它指出在满足“硬”标准的节点中,我想使用一个标签的节点,该标签具有名为“custom-key”的键和一个名为“custom-value”的值。但是,如果不存在这样的节点,我不反对将pod安排给满足“硬”标准的其他候选者。以结合“硬”和“软”规则的方式构建节点关联规则是一种很好的做法。遵循这种“尽力而为”的方法——尽可能使用一个选项,但如果该选项不可用则不拒绝调度——使部署调度更加灵活和可预测。Inter-PodAffinityKubernetes中的Inter-PodAffinity是一项允许您根据Pod与其他Pod的关系来安排Pod的功能。此功能支持各种有趣的场景,例如作为相互依赖的服务的一部分的pod的托管或数据本地化的实现,其中数据pod与主服务pod在同一台机器上运行。Pod间亲和力的定义类似于节点亲和力。但是,在这种情况下,我将使用pod规范的podAffinity字段。与节点亲和性类似,pod亲和性支持表达式匹配和逻辑运算符。然而,在这种情况下,它们应用于在特定节点上运行的pod标签选择器。如果指定的表达式与目标pod的pod标签匹配,则新pod将与目标pod放在同一台机器上。反亲和性在某些情况下,最好采用“黑名单”方式进行pod调度。在这种方法中,当某些条件不满足时,Pod无法被调度到特定节点上。此功能在Kubernetes节点到Pod反亲和性和Pod间反亲和性中实现。pod-to-node反亲和性的主要用途是使用专用节点。为了控制集群中的资源利用率,K8s管理员可以将某些节点分配给特定的Pod类型或应用程序。Pod间反亲和性的其他用例包括:避免单点故障:这可以通过在不同机器上为同一服务分发Pod来实现,这需要防止Pod与其他相同类型的Pod共存。防止服务之间的资源争用:要提高某些服务的性能,请避免将它们与消耗大量资源的其他服务放在一起。Pod到节点的反亲和性可以通过Kubernetes中的污点和容忍来实现。让我们仔细看看这个特性。污点和容忍度污点(条件)和容忍度可帮助您控制Pod到特定节点的调度,而无需修改现有Pod。默认情况下,所有不能容忍污点的pod都将被拒绝或从节点中逐出。如果您不希望pod在特定节点上运行,则此行为允许灵活的集群和应用程序部署模式,而无需更改pod定义。实施污染和容忍非常简单。首先,为需要应用一些非标准调度行为的节点添加污点。例如:污点格式为=:。我在这里使用的污点效果可以防止任何没有匹配容差的pod被调度到这个节点。其他受支持的污点效果包括NoExecute和PreferNoSchedule(NoSchedule的“软”版本)。如果应用了PreferNoSchedule污点,则kube-scheduler不会将没有所需容忍度的pod放置到污点上。最后,NoExecute效果导致所有pod被立即驱逐,对节点没有容忍度。如果您已经在节点上运行了pod并且不再需要它们,请使用此标签。创建污点只是配置的第一部分。为了允许pod被调度到污点上,我们需要添加容忍度:在这个例子中,我使用“Equal”运算符对上述污点添加了容忍度,你也可以使用“Exists”运算符,它将容忍任何键匹配的节点。但是,不需要指定值值。在这种情况下,我会使用污点“storage=ssd:NoSchedule”将我们在上面定义的pod调度到该节点。Pod反亲和性通过Pod反亲和性特性使Pod可以相互排斥。如上所述,Kubernetes中的最佳实践之一是通过将Pod分布在不同的可用区来避免单点故障。我可以在pod规范的反亲和性部分配置类似的行为。对于pod反亲和性,我们需要两个pod:Pod1:注意pod1被标记为“security:s1”。第二个pod引用spec.affinity.podAntiAffinity下的标签选择器“security:s1”。因此,pod不会被调度到已经托管任何带有“security:s1”标签的pod的节点。3.总结Kubernetes中的高级pod调度允许实现许多有趣的场景和最佳实践,以便在Kubernetes上部署复杂的应用程序和微服务。借助Pod亲和力,您可以为紧密耦合的应用程序堆栈和微服务实现Pod托管和数据本地化。您可以在下面找到每种资源类型的一些关键调度方案的备忘单。用于高级Pod调度的Kubernetes资源概述。使用节点互斥和污点,您可以运行具有专用于特定应用程序和服务的硬件的节点,从而在集群中实现高效的资源利用。通过Pod反亲和和节点反亲和,您还可以通过在不同节点上运行不同组件来确保应用程序的高可用性并避免单点故障。