敏态场景下,自研数据库如何做好技术演进和落地调优?点击预约直播 了解详情
写点什么

将 Kubernetes 扩展到超过 4k 个节点和 200k 个 Pod

  • 2022 年 2 月 23 日
  • 本文字数:3816 字

    阅读完需:约 13 分钟

将Kubernetes扩展到超过4k个节点和200k个Pod

摘要

在 PayPal,我们最近开始试水 Kubernetes。我们大部分的工作负载都运行在 Apache Mesos 上,而作为迁移的一部分,我们需要从性能方面了解下运行 Kubernetes 集群以及 PayPal 特有的控制平面。其中最主要的是了解平台的可扩展性,以及通过调整集群找出可以改进的地方。

正文

本文最初发布于 PayPal 技术博客。


在 PayPal,我们最近开始试水 Kubernetes。我们大部分的工作负载都运行在 Apache Mesos 上,而作为迁移的一部分,我们需要从性能方面了解下运行 Kubernetes 集群以及 PayPal 特有的控制平面。其中最主要的是了解平台的可扩展性,以及通过调整集群找出可以改进的地方。


与 Apache Mesos 不同的是,前者无需任何修改即可扩展到 10,000 个节点,而扩展 Kubernetes 则非常具有挑战性。Kubernetes 的可扩展性不仅仅体现在节点和 Pod 的数量上,还有其他多个方面,如创建的资源数量、每个 Pod 的容器数量、服务总数和 Pod 部署的吞吐量。本文描述了我们在扩展过程中遇到的一些挑战,以及我们如何解决这些问题。

集群拓扑

我们的生产环境中有各种不同规模的集群,包含数千个节点。我们的设置包括三个主节点和一个外部的三节点 etcd 集群,所有这些都运行在谷歌云平台(GCP)上。控制平面前面有一个负载平衡器,所有数据节点都与控制平面属于相同的区域。

工作负载

为了进行性能测试,我们使用了一个开源的工作负载生成器k-bench,并针对我们的场景做了修改。我们使用的资源对象是简单的 Pod 和部署。我们按不同的批次大小和部署间隔时间,分批次连续对它们进行部署。

扩展

开始时,Pod 和节点数量都比较少。通过压力测试,我们发现可以改进的地方,并继续扩大集群的规模,因为我们观察到性能有所改善。每个工作节点有四个 CPU 内核,最多可容纳 40 个 Pod。我们扩展到大约 4100 个节点。用于基准测试的应用程序是一个无状态的服务,运行在 100 个服务质量(QoS)有保证的毫核(millicores )上。


我们从 1000 个节点、2000 个 Pod 开始,接着是 16000 个 Pod,然后是 32000 个 Pod。之后,我们跃升到 4100 个节点、15 万个 Pod,接着是 20 万个 Pod。我们不得不增加每个节点的核数,以容纳更多的 Pod。

API 服务器

事实证明,API 服务器是一个瓶颈,有几个到 API 服务器的连接返回 504 网关超时,此外还有本地客户端限流(指数退避)。这些问题在扩展过程中呈指数级增长:


I0504 17:54:55.731559 1 request.go:655] Throttling request took 1.005397106s, request: POST:https://<>:443/api/v1/namespaces/kbench-deployment-namespace-14/Pods..

I0504 17:55:05.741655 1 request.go:655] Throttling request took 7.38390786s, request: POST:https://<>:443/api/v1/namespaces/kbench-deployment-namespace-13/Pods..

I0504 17:55:15.749891 1 request.go:655] Throttling request took 13.522138087s, request: POST:https://<>:443/api/v1/namespaces/kbench-deployment-namespace-13/Pods..

I0504 17:55:25.759662 1 request.go:655] Throttling request took 19.202229311s, request: POST:https://<>:443/api/v1/namespaces/kbench-deployment-namespace-20/Pods..

I0504 17:55:35.760088 1 request.go:655] Throttling request took 25.409325008s, request: POST:https://<>:443/api/v1/namespaces/kbench-deployment-namespace-13/Pods..

I0504 17:55:45.769922 1 request.go:655] Throttling request took 31.613720059s, request: POST:https://<>:443/api/v1/namespaces/kbench-deployment-namespace-6/Pods..


API 服务器上限制速率的队列的大小是通过 max-mutating-requests-inflight max-requests-inflight 更新的。1.20 版本中引入的优先级和公平性特性测试版,就是在 API 服务器上这两个标记的控制下将队列的总大小在不同的队列类别之间进行划分。例如,群首选举请求的优先级比 Pod 请求高。在每个优先级中,都有可配置队列的公平性。未来还可以通过 PriorityLevelConfiguration&FlowSchema API 对象做进一步调优。

控制器管理器

控制器管理器负责为副本集、命名空间等本地资源以及数量众多的部署(由副本集管理)提供控制器。控制器管理器与 API 服务器同步其状态的速度是有限的。有多个调节器用于调整这一行为:

  • kube-api-qps —— 控制器管理器在一秒钟内可以向 API 服务器进行查询的次数。

  • kube-api-burst —— 控制器管理器突发流量峰值,是 kube-api-qps 之上另一个并发调用数。

  • concurrent-deployment-syncs ——  部署、复制集等对象同步调用的并发性。

调度器

当作为一个独立的组件单独测试时,调度器可以支持每秒 1000 个 Pod 的高吞吐率。然而,在将调度器部署到一个在线集群中时,我们注意到,实际的吞吐量有所降低。etcd 实例速度慢导致调度器的绑定延迟增加,使得待处理队列的大小增加到数千个 Pod 的程度。我们的想法是在测试运行期间将这个数值保持在 100 以下,因为数量比较大的话会影响 Pod 的启动延迟。此外,我们最后还调整了群首选举参数,以应对短暂的网络分区或网络拥堵引发的虚假重启。

etcd

etcd 是 Kubernetes 集群中最关键的一部分。这一点从 etcd 在整个集群中引发的、以不同方式表现出来的大量问题可以看出来。经过非常仔细的研究,我们才找到根本原因,并扩展 etcd 以匹配我们预期的规模。


在扩展过程中,许多 Raft proposal 开始失败:



通过调查分析,我们发现,GCP 将 PD-SSD 磁盘的吞吐量限制在每秒 100MB 左右(如下图所示),我们的磁盘大小为 100G。GCP 没有提供增加吞吐量限制的方法——它只随着磁盘的大小增加。尽管 etcd 节点只需要不到 10G 的空间,我们首先尝试了 1TB PD-SSD。然而,当所有 4k 个节点同时加入 Kubernetes 控制平面时,磁盘再大也会成为一个瓶颈。我们决定使用本地 SSD,它的吞吐量非常高,代价是在出现故障时丢失数据的几率略高,因为它不是持久化的



在迁移到本地 SSD 后,我们并没有看到最快的 SSD 带来了预期的性能。我们用 FIO 直接在磁盘上做了一些基准测试,数值在意料之中。但是,对于所有成员的写入并发,etcd 基准测试讲述了一个不同的故事:


Plain TextLOCAL SSDSummary: Total: 8.1841 secs. Slowest: 0.5171 secs. Fastest: 0.0332 secs. Average: 0.0815 secs. Stddev: 0.0259 secs. Requests/sec: 12218.8374

PD SSD

Summary:

Total: 4.6773 secs.

Slowest: 0.3412 secs.

Fastest: 0.0249 secs.

Average: 0.0464 secs.

Stddev: 0.0187 secs.

Requests/sec: 21379.7235


本地 SSD 的表现更差!经过深入调查,这是由 ext4 文件系统的写屏障缓存提交导致的。由于 etcd 使用写前日志,并在每次提交到 Raft 日志时调用 fsync,所以可以禁用写屏障。此外,我们在文件系统级和应用程序级有 DB 备份作业,用于 DR。在这样修改之后,使用本地 SSD 的数值提高到了与 PD-SSD 相当的程度:


Plain TextLOCAL SSDSummary: Total: 4.1823 secs. Slowest: 0.2182 secs. Fastest: 0.0266 secs. Average: 0.0416 secs. Stddev: 0.0153 secs. Requests/sec: 23910.3658


这一改进的效果在 etcd 的 WAL 同步持续时间和后端提交延迟上体现了出来,如下图所示,在 15:55 左右这个时间点上,WAL 同步持续时间和后端提交延迟降低了 90%以上:




etcd 中默认的 MVCC 数据库大小为 2GB。在 DB 空间不足的告警被触发时,这个大小最大会增加到 8GB。由于该数据库的利用率约为 60%,所以我们能够扩展到 20 万个无状态 Pod。


经过上述这些优化,在预期的规模下,集群更加稳定了,然而,在 API 延迟方面,我们的 SLI 还差很多。


etcd 服务器还会偶尔重启,仅一次重启就会破坏基准测试结果,尤其是 P99 值。仔细观察发现,v1.20 版的 etcd YAML 中有一个存活探针Bug。为了解决这个问题,我们采用了一个变通办法,即增加失败阈值的计数。


在用尽所有方法对 etcd 进行了垂直扩展之后,主要是在资源方面(CPU、内存、磁盘),我们发现,etcd 的性能受到范围查询的影响。当范围查询很多时,etcd 的表现并不好,对 Raft 日志的写入也受到影响,增加了集群的延迟。以下是一次测试运行中影响性能的每个 Kubernetes 资源的范围查询的数量:


Plain Textetcd$ sudo grep -ir "events" 0.log.20210525-035918 | wc -l130830etcd$ sudo grep -ir "Pods" 0.log.20210525-035918 | wc -l107737etcd$ sudo grep -ir "configmap" 0.log.20210525-035918 | wc -l86274etcd$ sudo grep -ir "deployments" 0.log.20210525-035918 | wc -l6755etcd$ sudo grep -ir "leases" 0.log.20210525-035918 | wc -l4853etcd$ sudo grep -ir "nodes" 0.log.20210525-035918 | wc -l


由于这些查询很耗时,etcd 的后端延迟受到了很大的影响。在事件资源上对 etcd 服务器进行分片管理后,我们看到,在 Pod 高度竞争的情况下,集群的稳定性有所提高。将来,还可以进一步在 Pod 资源上对 etcd 集群进行分片。配置 API 服务器联系相关的 etcd 以与分片的资源进行交互很容易。

结果

在对 Kubernetes 的各种组件做完优化和调整后,我们观察到,延迟有大幅改善。下图展示了随着时间的推移,为满足 SLO 而实现的性能提升。其中,工作负载是 150k 个 Pod,每个部署 250 个副本,10 个并发工作进程。只要 Pod 启动的 P99 延迟在 5 秒之内,按照 Kubernetes SLO,我们就算是很好了。



下图显示了当集群有 20 万个 Pod 时,API 调用延迟完全符合SLO

我们还实现了 20 万个 Pod P99 启动延迟为 5 秒左右,而 Pod 部署速率远远高于 K8s 针对 5k 节点测试时所声称的 3000 个 Pod/分钟。



总结

Kubernetes 是一个复杂的系统,必须深入了解控制平面,才能知道如何扩展每个组件。通过这次操练,我们学到了很多东西,并将继续优化我们的集群。


查看英文原文:

将Kubernetes扩展到超过4k节点和200k个Pod

2022 年 2 月 23 日 17:164934

评论 1 条评论

发布
用户头像
存储(或者是状态管理)永远是分布式系统的痛

etcd 是 Kubernetes 集群中最关键的一部分。这一点从 etcd 在整个集群中引发的、以不同方式表现出来的大量问题可以看出来。经过非常仔细的研究,我们才找到根本原因,并扩展 etcd 以匹配我们预期的规模。

2022 年 06 月 23 日 10:56
回复
没有更多了
发现更多内容

【荣耀帐号服务】手把手教你快速web接入

荣耀开发者服务平台

前端 Web 服务器 安卓 honor

计算机上的高性能计算,你了解多少?

Finovy Cloud

高性能计算

死熬三天三夜,阿里高工码出Java150K字面试宝典,却遭Github全面封杀

Java-fenn

Java 编程 面试 java面试 java;

大数据平台 CDP 中如何配置 hive 作业的 YARN 队列以确保SLA?

明哥的IT随笔

hadoop spark hive YARN CDP

MASA MAUI Plugin 安卓蓝牙低功耗(二)蓝牙通讯

MASA技术团队

blazor MASA MAUI Xamarin MASA Blazor

Java面试笔试题大汇总一(最全+详细答案)

小小怪下士

大厂面试 java\ 面试真题 Java 面试题

前端必读2.0:如何在React 中使用SpreadJS导入和导出 Excel 文件

葡萄城技术团队

前端 Excel 框架

蚂蚁智能容量团队推出 TMaestro 智能参数调节产品

TRaaS

产品 互联网技术

阿里云物联网平台架构

阿里云AIoT

大数据 物联网平台 IoT 平台架构 设备管理

Mybatis工作流程及其原理与解析

小小怪下士

Java 程序员 架构 mybatis

百亿市场遭「卡脖子」,国产工业软件兴起正当时

ToB行业头条

2022前端面试遇到的手写题总结

helloworld1024fd

JavaScript 前端

数据中台必备的4个核心能力

阿泽🧸

数据中台 9月月更

帮助中心就是在线版的产品使用说明书?并非如此!

Baklib

产品 产品经理 帮助中心 在线编辑 产品说明书

什么是企业知识管理体系?它的基本原则是什么?我们又该怎样做?

Baklib

知识管理 知识 知识管理体系

用多线程实现归并排序

聚变

归并排序 Lambda函数

阿里巴巴高并发架构到底多牛逼?是如何抗住淘宝双11亿级并发量?

Java-fenn

Java 编程 程序员 面试

干货 | 精准化测试原理简介与实践探索

测吧(北京)科技有限公司

测试

MobTech 短信验证 Unity插件

MobTech袤博科技

ios android 短信验证

史上最详细的一线大厂Mysql面试题详解

小小怪下士

MySQL 面试 java面试

【喜讯】亚信安慧通过CMMI5级认证

亚信AntDB数据库

AntDB AntDB数据库

行业规模将达百亿,低代码是 “银弹” 还是 “鸡肋”?

SoFlu软件机器人

金三银四面试总结篇,汇总2022Java面试突击班后的面试小册

Java-fenn

Java 程序员 面试 java面试 java;

工作一年之后,这6个技术栈可以让你平均涨薪50%(涨薪篇)

Java-fenn

Java 编程 程序员 面试 java面试

两年工作经验,三面拼多多,最终获得offer!(面经总结)

Java-fenn

Java 编程 程序员 面试 java面试

什么是企业帮助中心?为什么要花钱建立?看这篇文章你就懂了!

Baklib

SaaS 企业 帮助中心 在线编辑

好家伙!全网开源对标P5~P7程序员技术成长路线,阿里这次是真卷

程序员小毕

Java 程序员 面试 程序人生 架构师

名列前茅!亚信科技AntDB入围工信部电信行业数据库场景榜单

亚信AntDB数据库

AntDB AntDB数据库

区块链公排互助合约模式系统开发方案

l8l259l3365

中小企业数字化转型需求增加,如何才能做好?先从在线协作工具开始!

Baklib

数字化转型 企业 在线协作文档 在线协作

RabbitMQ的深入理解和最简单的用途说明

小小怪下士

Java 程序员 架构 RabbitMQ

将Kubernetes扩展到超过4k个节点和200k个Pod_架构_Abdul Qadeer_InfoQ精选文章