使用Karpenter优化Amazon EKS集群:DevOps实战分享

2024/10/25 21:03:09

本文主要是介绍使用Karpenter优化Amazon EKS集群:DevOps实战分享,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

我们的动机如下:

嘿,最近我们遇到了一个EKS集群上的小麻烦:(EKS集群可能需要额外解释)

我们发现,我们预配的资源中有一大部分没有被使用。查看CPU使用情况后,发现我们可以在EKS计算成本上省下不少钱。

因为我们有许多具有不同计算需求的工作负载(有些工作负载对CPU需求较高;而其他工作负载则主要依赖内存),我们的大部分节点只有一部分被使用。因此,我们决定尝试一下Karpenter,这是一个不同的节点调度机制。

先剧透一下:用了 Karpenter 后,我们来聊聊我们的资源使用情况吧

这两个图表的绝对的CPU请求数量相同。

作为Karpenter迁移准备的一部分,我们审核了现有资源的请求和限制。特别是将它们添加到Daemon Sets时,这影响了最终资源使用图的客观性。

简介

简而言之,Karpenter 是 Amazon EKS 该链接解释了为什么应该从节点终止处理器迁移 的 cluster-autoscaler 和 aws-node-termination-handler 的替代方案,并提供一系列强大的功能来帮助管理集群中的节点。

先说一下:Karpenter for AKS (Azure) 已于2023年11月7日上线。然而,本文主要介绍在 EKS 集群中使用 Karpenter 的经历。

Karpenter 相比 cluster-autoscaler 的优点:
  • Karpenter 的 NodePool 相比 EKS 的 NodeGroup 更具灵活性。你可以调整许多节点特性:竞价型/按需型(或两者兼有)、可接受的 CPU 数量限制、可用区等。
  • 在观察未分配的 Pod 时,Karpenter 会考虑 NodePool 和 Pod 亲和性配置,找出最具有成本效益的实例类型和大小来提供资源。
  • Karpenter 积极监控空闲的节点容量,并重新安排现有的 Pod 以尽量减少已提供的节点容量。
  • Karpenter 通过跳过整个 EKS NodeGroup 到自动伸缩组的集群自动缩放过程,直接启动实例来加速节点的供应。
  • Karpenter 的竞价实例中断处理功能 提供了对 EC2 事件的监控,确保能够平滑处理可能的实例终止。
它是怎么工作的

一旦安装了 Karpenter,它会留意集群中任何不可调度的 Pod。要添加新节点,你需要至少一个 NodePool,NodePool 实际上是指 NodeClass 这个概念。

NodeClass 是一组 AWS 特定的节点配置:AMI、资源标签、EBS 映射等英文术语。

NodePool 是一组节点要求:可用区、CPU 数量、实例家族等。它还描述了污点(taints)和标签(labels)以及 kubelet 配置。你可以创建多个 NodePools 以确保能充分利用购买的预留实例和节省计划(https://karpenter.sh/preview/concepts/scheduling/#savings-plans-and-reserved-instances)或在不使用污点和容忍的情况下维持多架构环境(https://karpenter.sh/preview/concepts/scheduling/#fallback)。

#提示:请注意正确使用权重参数。它让您能够设定NodePool选择的优先级,但不保证Pod一定会被调度到权重最高的节点上。请参见本节的说明.

以下图示是参照Karpenter文档制作的。(注:Karpenter是相关领域的专有名词。)

为了配置新的节点,Karpenter 通过与 EC2 Fleet API 通信,并试图根据基于价格和容量优化的分配策略来配置实例。

为了处理突发中断事件,Karpenter 使用默认的 EventBridge 事件总线和一个用于接收 Instances 中断事件的 SQS 队列。这种方式让 Karpenter 能够监控潜在的实例终止事件,并为优雅终止的 Pods 准备替代节点。

该突发中断处理功能可以通过指定_Helm图表配置的settings.interruptionQueue 来启用。

安装前提条件

Karpenter 最佳实践 特别强调 两次 检查您的工作负载的资源请求和限制。必须准确设置内存资源的请求量等于限制量,以避免在迁移到 Karpenter 后内存不足导致的任务失败。

设置EKS组件工作负载的资源时,使用组件配置中的值。

当然,你希望在已经准备好的节点上运行Karpenter,这些节点不管怎样都能正常运行。因为没有其他节点的情况下,Karpenter无法自己创建节点,所以你需要创建一个EKS节点组。

#小贴士:您可以使用AWS Graviton实例族来创建Karpenter EKS节点组,以节省一些成本,同时保持Karpenter的功能不变。

安装

为了简化,我们使用了EKS模块中的Terraform Karpenter子模块。该子模块包含了用于在集群中部署Karpenter所必需的必要AWS资源。

使用 karpenter.sh/discovery 标签指定目标安全组和VPC子网,这样Karpenter就知道在哪里部署节点了。

现在,先在你的集群中安装Karpenter Helm chart,并将 tolerationnodeSelector 设置为 Helm 图表的值,让 Karpenter 在 Karpenter NodeGroup 上运行。

在安装过程中,你可能会遇到Helm图表的拉取、探索Karpenter标签等问题。这个优秀的Karpenter部署示例(请参见链接)可以快速帮助你解决这些问题。

注意点
  • 实施 Karpenter 之后,我们遇到了一个问题:一些工作负载变得非常不稳定,导致。通过研究,我们发现一个实例类别无法处理 pod 的负载需求,而其他实例类别则能够。因此,尽管定义了资源限制,但这些资源定义在不同实例类别之间并不通用。

我们将NodePools修改为仅使用经过测试且能够处理我们工作负载的实例类别。

  • 一些旧的工作在优化请求和限制的过程中被忽视了,导致了持续的内存不足(OOM Killed)错误。

我们用新的内存资源更新了工作负载,因此请求和限制相等。

  • 使用 Karpenter 一周之后,我们遇到了一个问题,就是 Pods 无法调度到任何节点上,并且没有新的节点被创建出来。

原因是我们达到了节点池的资源上限。必须设置合理的资源上限以限制和控制集群中的资源数量。这是必须的。

Karpenter + Uniskai ,来自 Profisea Labs

尽管 Karpenter 还未直接由 Uniskai 支持,但 Cloudsitter 功能可以帮助你安排让 Kubernetes 命名空间(命名空间)进入休眠。

这就是我们做事的方式哦:

假设你有一个安装了 Karpenter 的 EKS 集群。在该集群中,命名空间可以划分为几个逻辑分组:

  • Karpenter 本身这个工具。
  • 集群管理工具(监控、日志收集以及 CI/CD 工具)。
  • 根据情况在不同命名空间间分配的工作负载。

我们希望 Karpenter 能够一直正常运行,因此我们将为它创建一个全天候运行的 Cloudsitter 策略。

我们希望所有的管理工具从周一到周五的特定时间都能正常运作,因此,我们打算制定一个相应的策略。

我们希望根据实际情况手动启动工作负载,因此将创建一个24/7休眠策略。当实际需要时,我们只唤醒所需的命名空间。

不过,这种方法有个问题,无法完全保证Karpenter在禁用了所有Namespace后释放所有节点。但通常情况下,只会有少量实例未被释放。

随着时间的推移,我们发现这种方法在较小的集群中效果不佳。我们也遇到了在处理难以轻松缩减的负载量时的挑战。尽管如此,这个解决方案在多种场景下仍然很有优势——关键是根据每个集群及其特定负载特性进行调整。

借助 Karpenter 和 Uniskai Cloudsitter,我们创建了一个集群,该集群让我们按需控制哪些工作负载,并在最省钱的实例上运行它们。

最后

在采用Karpenter为我们的EKS集群时,我们见证了一种变革性的转变,这种转变体现在云资源优化和成本效益方面。Karpenter的NodePools所提供的控制的精细程度,加上其快速的资源分配和智能处理突发性中断的能力,大幅度提升了资源利用效率。

尽管遇到了一些挑战,比如调整 NodePools 以适应特定实例类别和精确设置资源限制,Karpenter 和 Cloudsitter 的集成使我们能够动态管理 Kubernetes 命名空间,从而实现了可用性和成本效益之间的微妙平衡。



这篇关于使用Karpenter优化Amazon EKS集群:DevOps实战分享的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程