竹笋

首页 » 问答 » 常识 » Kubernetes调度详解计算机j
TUhjnbcbe - 2023/10/29 17:04:00

KubernetesScheduler是Kubernetes控制平面的核心组件之一。它在控制平面上运行,将Pod分配给节点,同时平衡节点之间的资源利用率。将Pod分配给新节点后,在该节点上运行的kubelet会在KubernetesAPI中检索Pod定义,根据节点上的Pod规范创建资源和容器。换句话说,Scheduler在控制平面内运行,并将工作负载分配给Kubernetes集群。

本文将对KubernetesScheduler进行深入研究,首先概述一般的调度以及具有亲和力(affinity)和taint的驱逐调度,然后讨论调度程序的瓶颈以及生产中可能遇到的问题,最后研究如何微调调度程序的参数以适合集群。

调度简介

**Kubernetes调度是将Pod分配给集群中匹配节点的过程。**Scheduler监控新创建的Pod,并为其分配最佳节点。它会根据Kubernetes的调度原则和我们的配置选项选择最佳节点。最简单的配置选项是直接在PodSpec设置nodeName:

上面的nginxpod默认情况下将在node-01上运行,但是nodeName有许多限制导致无法正常运行Pod,例如云中节点名称未知、资源节点不足以及节点网络间歇性问题等。因此,除了测试或开发期间,我们最好不使用nodeName。

如果要在一组特定的节点上运行Pod,可以使用nodeSelector。我们在PodSpec中将nodeSelector定义为一组键值对:

对于上面的nginxpod,KubernetesScheduler将找到一个磁盘类型为ssd的节点。当然,该节点可以具有其他标签。我们可以在Kubernetes参考文档中查看标签的完整列表。

使用nodeSelector有约束Pod可以在有特定标签的节点上运行。但它的使用仅受标签及其值限制。Kubernetes中有两个更全面的功能来表达更复杂的调度需求:节点亲和力(nodeaffinity),标记容器以将其吸引到一组节点上;taint和toleration,标记节点以排斥Pod。这些功能将在下面讨论。

节点亲和力

**节点亲和力(NodeAffinity)是在Pod上定义的一组约束,用于确定哪些节点适合进行调度,即使用亲和性规则为Pod的节点分配定义硬性要求和软性要求。**例如可以将Pod配置为仅运行带有GPU的节点,并且最好使用NVIDIA_TESLA_V运行深度学习工作负载。Scheduler会评估规则,并在定义的约束内找到合适的节点。与nodeSelectors相似,节点亲和性规则可与节点标签一起使用,但它比nodeSelectors更强大。

我们可以为podspec添加四个相似性规则:

requiredDuringSchedulingIgnoredDuringExecutionrequiredDuringSchedulingRequiredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingRequiredDuringExecution**这四个规则由两个条件组成:必需或首选条件,以及两个阶段:计划和执行。**以required开头的规则描述了必须满足的严格要求。以preferred开头的规则是软性要求,将强制执行但不能保证。调度阶段是指将Pod首次分配给节点。执行阶段适用于在调度分配后节点标签发生更改的情况。

如果规则声明为IgnoredDuringExecution,Scheduler在第一次分配后不会检查其有效性。但如果使用RequiredDuringExecution指定了规则,Scheduler会通过将容器移至合适的节点来确保规则的有效性。

以下是示例:

上面的NginxPod具有节点亲和性规则,该规则让KubernetesScheduler将Pod放置在us-east的节点上。第二条规则指示优先使用us-east-1或us-east-2。

使用亲和性规则,我们可以让Kubernetes调度决策适用于自定义需求。

K8sMeetup

Taint与Toleration

集群中并非所有Kubernetes节点都相同。某些节点可能具有特殊的硬件,例如GPU、磁盘或网络功能。同样,我们可能需要将一些节点专用于测试、数据保护或用户组。我们可以将Taint添加到节点以排斥Pod,如以下示例所示:

kubectltaintnodesnode1test-environment=true:NoSchedule使用test-environment=true:NoScheduletaint时,除非在podspec具有匹配的toleration,否则KubernetesScheduler将不会分配任何pod:

taint和tolerations共同发挥作用,让KubernetesScheduler专用于某些节点并分配特定Pod。

调度瓶颈

尽管KubernetesScheduler能选择最佳节点,但是在Pod开始运行之后,“最佳节点”可能会改变。所以从长远来看,Pod的资源使用及其节点分配可能存在问题。

资源请求(Request)和限制(Limit):“NoisyNeighbor”

“NoisyNeighbor”并不特定于Kubernetes。任何多租户系统都是它们的潜在地。假设有两个容器A和B,它们在同一节点上运行。如果PodB试图通过消耗所有CPU或内存来创造noise,PodA将出现问题。如果我们为容器设置了资源请求和限制就能控制住neighbor。Kubernetes将确保为容器安排其请求的资源,并且不会消耗超出其资源限制的资源。如果在生产中运行Kubernetes,最好设置资源请求和限制以确保系统可靠。

系统进程资源不足

Kubernetes节点主要是连接到Kubernetes控制平面的虚拟机。因此,节点上也有自己的操作系统和相关进程。如果Kubernetes工作负载消耗了所有资源,则这些节点将无法运行,并会发生各种问题问题。我们需要在kubelet中使用–system-reserved设置保留资源,以防止发生这种情况。

抢占或调度Pod

如果KubernetesScheduler无法将Pod调度到可用节点,则可以从节点抢占(preempt)或驱逐(evict)一些Pod以分配资源。如果看到Pod在集群中移动而没有发现特定原因,可以使用优先级类对其进行定义。同样,如果没有调度好Pod,并且正在等待其他Pod,也需要检查其优先级。

以下是示例:

可以通过以下方式在podspec中为分配优先级:

调度框架

KubernetesScheduler具有可插拔的调度框架架构,可向框架添加一组新的插件。插件实现PluginAPI,并被编译到调度程序中。下面我们将讨论调度框架的工作流、扩展点和PluginAPI。

工作流和扩展点

调度Pod包括两个阶段:调度周期(schedulingcycle)和绑定周期(bindingcycle)。在调度周期中,Scheduler会找到一个可用节点,然后在绑定过程中,将决策应用于集群。

下图说明了阶段和扩展点的流程:

调度工作流(来源:Kubernetes文档)

工作流中的以下几点对插件扩展开放:

QueueSort:对队列中的Pod进行排序PreFilter:检查预处理Pod的相关信息以安排调度周期Filter:过滤不适合该Pod的节点PostFilter:如果找不到可用于Pod的可行节点,调用该插件PreScore:运行PreScore任务以生成一个可共享状态供Score插件使用Score:通过调用每个Score插件对过滤的节点进行排名NormalizeScore:合并分数并计算节点的最终排名Reserve:在绑定周期之前选择保留的节点Permit:批准或拒绝调度周期结果PreBind:执行任何先决条件工作,例如配置网络卷Bind:将Pod分配给KubernetesAPI中的节点PostBind:通知绑定周期的结果插件扩展实现了PluginAPI,是KubernetesScheduler的一部分。我们可以在Kubernetes存储库中检查。插件应使用以下名称进行注册:

插件还实现了相关的扩展点,如下所示:

Scheduler性能调整

KubernetesScheduler有一个工作流来查找和绑定Pod的可行节点。当集群中的节点数量非常多时,Scheduler的工作量将成倍增加。在大型集群中,可能需要很长时间才能找到最佳节点,因此要微调调度程序的性能,以在延迟和准确性之间找到折中方案。

percentageOfNodesToScore将限制节点的数量来计算自己的分数。默认情况下,Kubernetes在节点集群的50%和节点集群的10%之间设置线性阈值。默认最小值为5%,它要确保至少考虑集群中5%节点的调度。

下面的示例展示了如何通过性能调整kube-scheduler来手动设置阈值:

如果有一个庞大的集群并且Kubernetes工作负载不能承受KubernetesScheduler引起的延迟,那么更改百分比是个好主意。

总结

本文涵盖了Kubernetes调度的大多方面,从Pod和节点的配置开始,包括nodeSelector、亲和性规则、taint和toleration,然后介绍了KubernetesScheduler框架、扩展点、API以及可能发生的与资源相关的瓶颈,最后展示了性能调整设置。尽管KubernetesScheduler能简单地将Pod分配给节点,但是了解其动态性并对其进行配置以实现可靠的生产级Kubernetes设置至关重要。

1
查看完整版本: Kubernetes调度详解计算机j