在 AWS EKS 中通过对 ClickHouse Pod 进行分箱来节省数百万美元

2024-04-21 21:44

本文主要是介绍在 AWS EKS 中通过对 ClickHouse Pod 进行分箱来节省数百万美元,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

图片

本文字数:5025;估计阅读时间:13 分钟

作者:Vinay Suryadevara & Jianfei Hu

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

图片

介绍

在 ClickHouse Cloud,我们热爱 Kubernetes,并在 Kubernetes 中运行客户 ClickHouse 的集群(servers和keepers)。我们使用 Elastic Kubernetes Service(EKS)来托管在 AWS 中的 ClickHouse 集群。来自不同 ClickHouse 集群的服务器 pod 可以被调度到同一个 EKS 节点上。我们使用 Kubernetes 命名空间 + Cilium 进行隔离。随着为了支持我们的客户而在新区域中部署 EKS 集群,我们的机群规模正在显著增长,EC2 实例的基础设施成本也在增加。

为了优化成本,我们分析了 EKS 节点利用率。EC2 实例按小时计费,而不是基于使用情况,因此低利用率的节点/机群意味着我们正在损失利润。通过提高利用率和减少所需的 EC2 节点总数来降低成本。请继续阅读本文,了解我们如何改进 pod 分配并节省了数百万美元。

评估 EKS 节点利用率

为了使我们的资源消耗尽可能高效,我们进行了一项测试,以确定我们的 pod 是如何分配的。我们分析了我们的 EKS 集群节点的 CPU/内存利用率。下面的截图来自 eks-node-viewer,这是一个可视化 EKS 资源利用率的工具。

图片

图片

图片 1 显示了我们一个较大的 EKS 集群中的 CPU 利用率百分比。整个集群的 CPU 利用率约为 50%。此外,许多大型和昂贵的节点(如图片 2 所示)未被充分利用。根据我们集群的 eks-node-viewer 结果,我们得出结论,服务器 pod 在节点之间没有被稠密地分配。本应安排在同一节点上的两个 ClickHouse pod 却被安排在不同的节点上,导致我们需要更多的 EC2 节点来承载相同数量的 pod,节点的资源利用率降低,并且机群成本更高。我们集群中的许多节点上的 CPU/内存资源大多处于空闲状态,但我们仍在为这些节点付费。

根本原因分析

经过一些调查,我们确定了低利用率的根本原因。

  1. Kubernetes 默认调度器在将待处理的 pod 调度到可用节点上时,使用 LeastAllocated 评分策略对节点进行评分。LeastAllocated 评分策略更喜欢具有更多可用资源的节点,这导致集群节点上的 pod 分布稀疏。

  2. 这种 LeastAllocated 评分策略使节点规模缩小的可能性非常小。

    想象一下,在一个节点上终止了一个旧的 pod。然后调度器将首选该节点来安排新的 pod。因此,节点利用率很难降到集群自动扩展器的阈值以下,以便被回收利用。

与此同时,我们还对新解决方案提出了三个额外的要求和约束:

  1. 提高我们机群中的资源(CPU/内存)利用率(减少我们的 EC2 占用面积和成本)。

  2. 不影响客户体验,比如增加 ClickHouse 实例的配置时间。

  3. 尽量减少对我们客户正在运行的实例的干扰。

考虑到这些因素,我们探讨了几种潜在的解决方案。

调整集群自动扩展器和过度配置(已放弃)

一个显然的方法是调整集群自动扩展器的缩减阈值。但是,这意味着更多的客户 pod 会经常被驱逐,这不符合要求 #3(对客户查询的干扰)。

我们还曾短暂考虑通过调整资源请求和限制来过度配置节点。然而,过度配置资源可能会导致争用。但无论是 CPU 争用(查询被限制)还是内存争用(可能会被 OOM 杀死),都不符合我们客户体验的要求。

主动对 pod 进行分箱(已放弃)

我们还考虑为 ClickHouse pod 添加注释 cluster-autoscaler.kubernetes.io/safe-to-evict。这允许 Kubernetes 集群自动扩展器在节点利用率低于某个阈值时驱逐 pod。但是,pod 驱逐可能会给我们的客户带来干扰。例如,长时间运行的查询将被中断。

我们已经为 ClickHouse 服务器配置了 PodDisruptionBudget,以限制在任何时候 StatefulSet 中的一个 pod 不可用。但根据我们的经验,让集群自动扩展器在随机时间终止一些 pod 对于像 ClickHouse 这样的有状态工作负载来说仍然会产生太多干扰。

因此,我们决定不选择这种方法。

使用 MostAllocated 评分策略对 pod 进行分箱

相反,我们决定将 kube-scheduler(默认的 Kubernetes 调度器)评分策略从 LeastAllocated 更改为 MostAllocated,以更有效地打包我们的集群。这个解决方案为我们的 pod 实现了分箱范式。这有什么帮助?

  1. 当需要创建新的 pod 时,调度器现在更倾向于具有更高利用率比例的节点。这使得集群的整体利用率随着时间的推移而提高。

  2. 当旧的 pod 在一个节点上终止时,该节点不太可能被考虑,因此更有可能达到低利用率阈值。最终,集群自动扩展器可以将此节点从集群中移除,从而降低总成本。

此策略是 NodeResourcesFit 插件的一部分,默认在 Kubernetes 中启用。一旦启用了此设置,在 pod 调度阶段,Kubernetes 调度器执行以下操作:

  • 首先,它识别出集群中具有根据 pod 请求规范指定的资源可用的节点。这是“过滤阶段”。

  • 接下来,它将对已过滤的节点按其组合资源利用率(CPU 和内存)进行降序排列。这被称为“评分阶段”。

  • 被选择用于 pod 的节点将始终是适合该 pod 并具有最高资源利用率的节点。

有了一个符合我们所有要求的解决方案,我们决定调查如何在 EKS 中指定此调度策略。

EKS 设置支持 kube-scheduler 定制

当我们开始研究如何为 EKS 中的 kube-scheduler 设置此策略时,我们发现 EKS 不支持通过 EKS 设置/配置自定义 kube-scheduler。许多用户已经提出了这个功能请求,但目前从 AWS 方面没有任何迹象表明将来会增加支持。由于我们无法通过 EKS 设置进行此操作,我们选择在我们的 Kubernetes 集群中自己设置一个自定义调度器。

使用 MostAllocated 评分策略的自定义调度器

为了在我们的集群中为 pod 设置一个自定义调度器,我们主要遵循了 Kubernetes 提供的便捷指南。Kubernetes 还允许您创建自己的调度器二进制文件,但在我们的情况下这并不是必要的,因为具有 MostAllocated 评分策略的现有 kube-scheduler 镜像已经满足了我们的要求。为了在我们的集群中创建此调度器,我们采取了以下步骤:

  1. 构建并将 kube-scheduler 镜像部署到我们的容器注册表中。我们找不到托管此镜像的公共注册表。对于我们来说,维护这个镜像并不理想,但目前没有替代方案。

  2. 按照指南中提到的方式为调度器创建了一个部署。在 configMap 中,我们提供了评分策略的相关设置 - ‘MostAllocated’,以及在考虑分配时的 CPU/内存权重。configMap 的配置部分如下所示:

 profiles:- pluginConfig:- args:apiVersion: kubescheduler.config.k8s.io/v1beta3kind: NodeResourcesFitArgsscoringStrategy:resources:- name: cpuweight: 1- name: memoryweight: 1type: MostAllocatedname: NodeResourcesFitplugins:score:enabled:- name: NodeResourcesFitweight: 1schedulerName: <schedulerName>
  1. 为了确保高可用性,我们选择在自定义调度器部署中定义了三个 pod,并启用了领导选举,以便只有一个 pod 会执行主动调度,另外两个 pod 处于待机状态。

  2. 我们将这个调度器部署到了我们的集群中,然后通过在 PodSpec 中指定 schedulerName 来更新我们的 pod,以使用这个最优分配的调度器。

通过这种设置,我们可以确保调度的吞吐量与现有的 kube-scheduler 类似,同时在自定义调度器设置中构建了冗余。我们还可以最小化干扰的情况下提高集群资源利用率。

系统实用工作负载

我们的 EKS 集群有一些负责实用工作负载的系统 pod,例如 CoreDNS、ArgoCD、Cilium Cluster Mesh 等。有时,这些 pod 是低利用率节点上唯一剩余的 pod。由于它们使用本地存储,集群自动伸缩器可能无法清理其中一些 pod。这些被占用的节点也无法缩容。

为了解决这个问题,我们对所有这些系统实用工作负载进行了标注,设置 safe-to-evict: true。

过度预留以实现更平滑的扩容

EKS 集群自动伸缩器本身的 pod 也可能阻止节点被回收。对于自动伸缩器,我们选择让其运行在一个较小的节点上,而不是配置 safe-to-evict: true。这样做可以提供更好的稳定性。

在 ClickHouse Cloud 中,我们使用了 EKS 集群自动伸缩器推荐的过度预留工作负载。我们创建了具有类似资源需求但较低优先级类别的工作负载。这种较低的优先级允许对过度预留的 pod 进行逐出,以便 ClickHouse pod 运行。

我们注意到,当过度预留的 pod 使用默认调度器时,而 ClickHouse pod 使用自定义调度器时,抢占功能不起作用。因为每个调度器只会抢占由自己调度的 pod。在这种情况下,集群自动伸缩器也错误地认为不需要扩容。为了解决这个问题并使事情更加一致,我们还让过度预留的 pod 也使用自定义调度器。

测试和部署

为了确保自定义调度器不会导致性能下降,我们还进行了一些 pod 调度压力测试。我们创建了一个作业,连续创建 pod 以供自定义调度器调度。然后,我们杀死了持有租约锁的自定义调度器 pod。我们观察到其他调度器待机 pod 很快接管了任务。pod 调度几乎没有受到影响,并且根据我们的测试结果,调度吞吐量也不成问题。

另一个潜在的风险是增加 pod 冷启动时间。现在集群更加紧凑,理论上,新实例的创建更有可能触发节点组的扩容,以安排待定的 pod。为了观察这一点,我们测量了 P90 和 P99 的冷启动时间以检查影响。我们验证了这种影响可以忽略不计。这可能是因为为容纳 ClickHouse 服务而进行的节点预配不够频繁,无法产生较大的影响。

在最终部署时,我们仍然谨慎行事:

  1. 我们按区域逐步推出了调度器更改,并从几个小区域开始。

  2. 在单个区域内,我们首先只更新了较小的 ClickHouse 实例,然后逐渐将此调度器应用于集群中的所有实例。

  3. 一旦 pod 规范中的 'schedulerName' 字段更新为此自定义调度器,正在运行的 Clickhouse pod 将使用新调度器进行重新调度。由于我们已经配置了具有 pod 中断预算的有状态集以及优雅的关闭(以避免中断正在运行的查询),当调度器更改时,我们的客户实例没有遇到任何中断。经过一次重新调度后,正在运行的 pod 将不会再受到调度器更改的影响,这在某种程度上满足了先前解决方案所不具备的第三个要求。

部署后的集群利用率

由于这些变化的直接结果,集群利用率提高到了 70%。

图片

我们注意到节点数量减少了约 10%,最大的节省来自清理了几个大型的 24xl 节点。与大型节点减少一起,我们在 EC2 成本方面实现了超过 20% 的降低。

最后,我们还与 AWS 成本和使用报告进行了交叉参考,确认了类似金额的节省。

结论

总而言之,通过将 Kubernetes 调度器评分策略更改为 MostAllocated,我们显著降低了 EKS 基础设施成本。我们通过在 EKS 集群中设置自定义调度器(带有 MostAllocated 评分策略的 kube-scheduler 镜像)来实现这一点。这种方法很好地平衡了成本的降低和维护我们客户工作负载的稳定性。我们还彻底对一些可抢占的系统工作负载进行了标注,以确保节点可以及时回收。

对我们来说,该项目的成功是通过降低成本并且不影响客户的可靠性或性能来衡量的。

通过上述变更,我们能够将 EKS 集群的资源利用率提高 20% 到 30%,并且在我们的 EKS 集群中也实现了相应的 EC2 实例成本节省。

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com

图片

​​联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

这篇关于在 AWS EKS 中通过对 ClickHouse Pod 进行分箱来节省数百万美元的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/924105

相关文章

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述。以下是从不同角度对气象站的种类和应用范围的介绍: 一、气象站的种类 根据用途和安装环境分类: 农业气象站:专为农业生产服务,监测土壤温度、湿度等参数,为农业生产提供科学依据。交通气象站:用于公路、铁路、机场等交通场所的气象监测,提供实时气象数据以支持交通运营和调度。林业气象站:监测林区风速、湿度、温度等气象要素,为林区保护和

企业如何进行员工的网络安全意识培训?

企业网络安全意识培训的重要性         企业网络安全意识培训是提升员工网络安全素质的关键环节。随着网络技术的快速发展,企业面临的网络安全威胁日益增多,员工的网络安全意识和技能水平直接关系到企业的信息安全和业务连续性。因此,企业需要通过系统的网络安全意识培训,提高员工对网络安全的认识和防范能力,从而降低企业在面对潜在安全风险时的损失和影响。 企业网络安全意识培训的方法         企

使用JWT进行安全通信

在现代Web应用中,安全通信是至关重要的。JSON Web Token(JWT)是一种流行的安全通信方式,它允许用户和服务器之间安全地传输信息。JWT是一种紧凑的、URL安全的表示方法,用于在两方之间传输信息。本文将详细介绍JWT的工作原理,并提供代码示例帮助新人理解和实现JWT。 什么是JWT? JWT是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSO

ccp之间是不可以直接进行+,-的,要用ccpSub和ccpAdd。

1.  http://www.cnblogs.com/buaashine/archive/2012/11/12/2765691.html  上面有好多的关于数学的方面的知识,cocos2dx可能会用到的 2.学到了   根据tilemap坐标得到层上物体的id int oneTiled=flagLayer->tileGIDt(tilePos);

Clickhouse 的性能优化实践总结

文章目录 前言性能优化的原则数据结构优化内存优化磁盘优化网络优化CPU优化查询优化数据迁移优化 前言 ClickHouse是一个性能很强的OLAP数据库,性能强是建立在专业运维之上的,需要专业运维人员依据不同的业务需求对ClickHouse进行有针对性的优化。同一批数据,在不同的业务下,查询性能可能出现两极分化。 性能优化的原则 在进行ClickHouse性能优化时,有几条

使用 GoPhish 和 DigitalOcean 进行网络钓鱼

配置环境 数字海洋VPS 我创建的丢弃物被分配了一个 IP 地址68.183.113.176 让我们登录VPS并安装邮件传递代理: ssh root@68.183.113.176apt-get install postfix 后缀配置中的点变量到我们在 DigitalOcean 中分配的 IP:mynetworks nano /etc/postfix/main.cf

自动驾驶规划中使用 OSQP 进行二次规划 代码原理详细解读

目录 1 问题描述 什么是稀疏矩阵 CSC 形式 QP Path Planning 问题 1. Cost function 1.1 The first term: 1.2 The second term: 1.3 The thrid term: 1.4 The forth term: 对 Qx''' 矩阵公式的验证 整体 Q 矩阵(就是 P 矩阵,二次项的权重矩阵)

使用obdumper对oceanbase进行备份,指定2881端口

1.安装obdumper (1)下载软件 OceanBase分布式数据库-海量数据 笔笔算数https://www.oceanbase.com/softwarecenter (2)安装软件 参考:https://www.oceanbase.com/docs/common-oceanbase-dumper-loader-1000000000628759https://www.oceanb