科技行业资讯门户

广告

广告

广告

广告

广告

突破 etcd 限制!字节自研 K8s 存储 KubeBrain

【蜂耘网  云计算】KubeBrain 是字节跳动针 Kubernetes 元信息存储的使用需求,基于分布 KV 存储引擎设计并实现的取 etcd 的元信息存储系统,支撑线上超 20,000 节点的超大规 Kubernetes 集群的稳定运行。

 

img1

 

. 背景

 

分布式应用编排调度系 Kubernetes 已经成为云原生应用基座的事实标准,但是其官方的稳定运行规模仅仅局限 5,000 节点。这对于大部分的应用场景已经足够,但是对于百万规模机器节点的超大规模应用场景 Kubernetes 难以提供稳定的支撑。

 

尤其随数字云原生的发展,全球整 IT 基础设施规模仍在加速增长,对于分布式应用编排调度系统,有两种方式来适应这种趋势:

 

水平扩  即构建管理多个集群的能力,在集群故障隔离、混合云等方面更具优势,主要通过集群联邦Cluster Federation)来实现;

 

垂直扩  即提高单个集群的规模,在降低集群运维管理成本、减少资源碎片、提高整体资源利用率方面更具优势。

 

img2

 

K8s 采用的是一种中心化的架构,所有组件都 APIServer 交互, APIServer 则需要将集群元数据持久化到元信息存储系统中。当前etcd  APIServer 唯一支持的元信息存储系统,随着单个集群规模的逐渐增大,存储系统的读写吞吐以及总数据量都会不断攀升etcd 不可避免地会成为整个分布式系统的瓶颈。

 

1.1 Kubernetes元信息存储需求

 

APIServer 并不能直接使用一般的强一 KV 数据库作为元信息存储系统,它与元信息存储系统的交互主要包括数据全量和增量同步 List/Watch,以及单 KV 读写。更近一步来说,它主要包含以下方面:

 

在版本控制方面,存储系统需要 APIServer 暴露数据的版本信息APIServer 侧依赖于数据的版本生成对应 ResourceVersion

 

在写操作方面,存储系统需要支 Create/Update/Delete 三种语义的操作,更为重要的是,存储系统需要支持在写入或者删除数据时对数据的版本信息进 CAS

 

在读操作方面,存储系统需要支持指定版本进行快 List 以此从存储中获取全量的数据,填APIServer  WatchCache 或供查询使用,此外也需要支持读取数据的同时获取对应的数据版本信息;

 

在事件监听方面,存储系统需要支持获取特定版本之后的有序变更,这 APIServer  List 从元信息存储中获取了全量的数据之后,可以监听快照版本之后的所有变更事件,进而以增量的方式来更 Watch Cache 以及向其他组件进行变更的分发,进而保 K8s 各个组件中数据的最终一致性。

 

1.2 etcd 的实现方式与瓶颈

 

etcd 本质上是一种主从架构的强一致、高可用分布 KV 存储系统:

 

节点之间,通 Raft 协议进行选举,将操作抽象 log  Raft 的日志同步机制在多个状态机上同步;

 

单节点上,按顺序 log 应用到状态机,基 boltdb 进行状态持久 

 

 APIServer 元信息存储需求etcd 大致通过以下方式来实:

 

在版本控制方面etcd 使 Revision 作为逻辑时钟,对每一个修改操作,会分配递增的版本Revision,以此进行版本控制,并且在内存中通 TreeIndex  Key  Revision 的索引;

 

在写操作方面etcd 以串 Apply Raft Log 的方式实现, Revision 为键Key/Value/Lease 等数据作为值存 BoltDB 中,在此基础上实现了支持 Revision  CAS 的写事务;

 

在读操作方面etcd 则是通过管 Key  Revision  TreeIndex 来查 Revision 进而查 Value,并在此基础上实现快照读;

 

在事件监听方面,历史事件可以 BoltDB 中指 Revision  KV 数据转换得到,而新事件则由写操作同 Notify 得到。

 

etcd 并不是一个专门 K8s 设计的元信息存储系统,其提供的能力 K8s 所需的能力的超集。在使用过程中,其暴露出来的主要问题有:

 

etcd 的网络接口层限流能力较弱,雪崩时自愈能力差;

 

etcd 所采用的是 raft group,存在单点瓶颈,单 raft group 增加节点数只能提高容错能力,并不能提高写性能;

 

etcd  ExpensiveRead 容易导 OOM,如果采用分页读取的话,延迟相对会提高;

 

boltdb 的串行写入,限制了写性能,高负载下写延迟会显著提高;

 

长期运行容易因为碎片问题导致写性能发生一定劣化,线上集群定期通 defrag 整理碎片,一方面会比较复杂,另一方面也可能会影响可用性。

 

. 新的元数据存储

 

过去面对生产环境 etcd 的性能问题,只能通过 Resource 拆分存储etcd 参数调优等手段来进行一定的缓解。但是面 K8s 更大范围的应用之后带来的挑战,我们迫切的需要一个更高性能的元数据存储系统作 etcd 的替代方案,从而能对上层业务有更有力的支撑。

 

在调研 K8s 集群的需求以及相关开源项目之后,我们借鉴 k3s 的开源项 kine 的思想,设计并实现了基于分布 KV 存储引擎的高性 K8s 元数据存储项 KubeBrain 

 

img3

 

KubeBrain 系统实现 APIServer 所使用的元信息存 API ,整体采用主从架构,主节点负责处理写操作和事件分发,从节点负责处理读操作,主节点和从节点之间共享一个分布式强一 KV 存储,在此基础上进行数据读写。下面介 KubeBrain 的核心模块。

 

2.1 存储引擎

 

img4

 

KubeBrain 统一抽象了逻辑层所使用 KeyValue 存储引擎接口,以此为基础,项目实现了核心逻辑与底层存储引擎的解耦:

 

逻辑层基于存储引擎接口来操作底层数据,不关心底层实现;

 

对接新的存储引擎只需要实现对应的适配层,以实现存储接口。

 

目前项目已经实现了 ByteKV  TiKV 的适配,此外还实现了用于测试的适配单机存 Badger 的版本。需要注意的是,并非所 KV 存储都能作 KubeBrain 的存储引擎。当 KubeBrain 对于存储引擎有着以下特性要求:

 

支持快照读

 

支持双向遍历

 

支持读写事务或者带CAS功能的写事务

 

对外暴露逻辑时钟

 

此外,由 KubeBrain 对于上层提供的一致性保证依赖于存储引擎的一致性保证 KubeBrain 要求存储引擎的事务需要达到以下级别(定义参 HATs ​​http://www.vldb.org/pvldb/vol7/p181-bailis.pdf

​​

Isolation Guarantee: Snapshot Isolation

 

Session Guarantee: Linearizable

 

img5

 

在内部生产环境中 KubeBrain  ByteKV 为存储引擎提供元信息存储服务ByteKV 是一种强一致的分布 KV 存储。 ByteKV 中,数据按 key 的字典序有序存储。当单 Partition 数据大小超过阈值时 Partition 自动地分裂,然后可以通 multi-raft group 进行水平扩展,还支持配置分裂的阈值以及分裂边界选择的规则的定制。此外 ByteKV 还对外暴露了全局的时钟,同时支持写事务和快照读,并且提供了极高的读写性能以及强一致的保证。

 

2.2 选主机制

 

img6

 

KubeBrain 基于底层强一致的分布 KV 存储引擎,封装实现了一 ResourceLock,在存储引擎中指向一组特定 KeyValueResourceLock 中包含主节点的地址以及租约的时长等信息。

 

KubeBrain 进程启动后均以从节点的身份对自己进行初始化,并且会自动在后台进行竞选。竞选时,首先尝试读取当前 ResourceLock。如果发现当 ResourceLock 为空,或 ResourceLock 中的租约已经过期,节点会尝试将自己的地址以及租约时长 CAS 的方式写 ResourceLock,如果写入成功,则晋升为主节点。

 

从节点可以通 ResourceLock 读取主节点的地址,从而和主节点建立连接,并进行必要的通信,但是主节点并不感知从节点的存在。即使没有从节点,单 KubeBrain 主节点也可以提供完成 APIServer 所需 API,但是主节点宕机后可用性会受损。

 

2.3 逻辑时钟

 

KubeBrain  etcd 类似,都引入 Revision 的概念进行版本控制KubeBrain 集群的发号器仅在主节点上启动。当从节点晋升为主节点时,会基于存储引擎提供的逻辑时钟接口来进行初始化,发号器Revision 初始值会被赋值成存储引擎中获取到的逻辑时间戳。

 

 Leader 的任期内,发号器发出的整数号码是单调连续递增的。主节点发生故障时,从节点抢到主,就会再次重复一个初始化的流程。由于主节点的发号是连续递增的,而存储引擎的逻辑时间戳可能是非连续的,其增长速度是远快于连续发号的发号器,因此能够保证切主之后 Revision 依然是递增的一个趋势,旧主节点上发号器所分配的最大 Revision 会小于新主节点上发号器所分配的最小Revision

 

KubeBrain 主节点上的发号是一个纯内存操作,具备极高的性能。由 KubeBrain 的写操作在主节点上完成,为写操作分 Revision 时并不需要进行网络传输,因此这种高性能的发号器对于优化写操作性能也有很大的帮助。

 

2.4 数据模型

 

KubeBrain  API Server 读写请求参数中 Raw Key,会进行编码出两 Internal Key写入存储引擎索引和数据。对于每 Raw Key,索 Revision Key 记录只有一条,记录当 Raw Key 的最新版本号 Revision Key 同时也是一把锁,每次 Raw Key 的更新操作需要对索引进 CAS。数据记Object Key 有一到多条,每条数据记录 Raw Key 的历史版本与版本对应 ValueObject Key 的编码方式magic+raw_key+split_key+revision,其中:

 

magic\x57\xfb\x80\x8b

 

raw_key为实 API Server 输入到存储系统中 Key 

 

split_key$

 

revision为逻辑时钟对写操作分配的逻辑操作序号通 BigEndian 编码成 Bytes 

 

img7

 

 Kubernetes 的校验规则raw_key 只能包含小写字母、数字,以'-'  '.',所以目前选 split_key  $ 符号。

 

特别的Revision Key 的编码方式 Object Key 相同revision取长度 8  Bytes 。这种编码方案保证编码前和编码后的比较关系不变。

 

在存储引擎中,同一 Raw Key 生成的所 Internal Key 落在一个连续区间 

 

img8

 

这种编码方式有以下优点:

 

编码可逆,即可以通Encode(RawKey,Revision)InternalKey,相对应的可以通Decode(InternalKey)RawkeyRevision

 

 Kubernetes 的对象数据都转换为存储引擎内部 Key-Value 数据,且每个对象数据都是有唯一的索引记录最新的版本号,通过索引实现锁操作;

 

可以很容易地构造出某行、某条索引所对应 Key,或者是某一块相邻的行、相邻的索引值所对应 Key 范围;

 

 Key 的格式非单调递增,可以避免存储引擎中的递 Key 带来的热点写问题

 

2.5 数据写入

 

每一个写操作都会由发号器分配一个唯一的写 revision ,然后并发地对存储引擎进行写入。 创建、更   Kubernetes 对象数据的时候,需要同时操作对象对应的索引和数据。由于索引和数据在底层存储引擎中是不同 Key-Value 对,需要使 写事 保证更新过程 原子性,并且要求至少达 Snapshot Isolation 

 

img9

 

 KubeBrain 依赖索引实现了乐观锁进行并发控制KubeBrain 写入时,会先根 APIServer 输入 RawKey 以及被发号器分配 Revision 构造出实际需要到存储引擎中 Revision Key  Object Key,以及希望写入 Revision Key  Revision Bytes。在写事务过程中,先进行索 Revision Key 的检查,检查成功后更新索 Revision Key,在操作成功后进行数 Object Key 的插入操作。

 

 Create 请求时, Revision Key 不存在时,才 Revision Bytes  Revision Key 中,随后 API Server 写入 Value  Object Key 中;

 

 Update 请求时, Revision Key 中存放的 Revision Bytes 符合预期时,才将 Revision Bytes 写入,随后 API Server 写入 Value  Object Key 中;

 

 Delete 请求时, Revision Key 中存放的 Revision Bytes 符合预期时,才将 Revision Bytes 附带上删除标记写入,随后 tombstone  Object Key 中。

 

由于写入数据时基于递增 Revision 不断写入新 KeyValue  KubeBrain 会进行后台的垃圾回收操作, Revision 过旧的数据进行删除,避免数据量无限增长。

 

2.6 数据读取

 

数据读取分成点读和范围查询查询操作,分别对 API Server  Get  List 操作。

 

img10

 

Get 需要指定读操作ReadRevision,需要读最新值时则 ReadRevision 置为最大MaxUint64  Iterator ,起始点Encode(RawKey, ReadRevision)Encode( RawKey, 0)遍历,取第一个。

 

img11

 

范围查询需要指定读操作ReadRevision 。对于范围查找 RawKey [RawKeyStart, RawKeyEnd)区间 KubeBrain 构造存储引擎 Iterator 快照读,通过编码 RawKey 的区间映射到存储引擎 InternalKey 的数据区间

 

InternalKey InternalKeyStartEncode(RawKeyStart, 0)

 

InternalKey 的下界InternalKeyEndEncode(RawKeyEnd, MaxRevision)

 

对于存储引擎[InternalKeyStart, InternalKeyEnd)内的所有数据按序遍历,通Decode(InternalKey)RawKeyRevision,对于一RawKey 相同的所ObjectKey,在满足条Revision<=ReadRevision的子集中Revision最大的,对外返回 2.7 事件机制

 

对于所有变更操作,会 TSO 分配一个连续且唯一 revision ,然后并发地写入存储引擎中。变更操作写入存储引擎之后,不论写入成功或失败,都会按 revision 从小到大的顺序,将变更结果提交到滑动窗口中,变更结果包括变更的类型、版本、键、值、写入成功与 。在记录变更结果的滑动窗口中,从起点到终点,所有变更数据中 revision 严格递增,相 revision  1

 

img12

 

记录变更结果的滑动窗口由事件生成器统一从起点开始消费,取出的变更结果后会根据变更 revision更新发号器 commit index ,如果变更执行成功,则还会构造出对应的修改事件,将并行地写入事件缓存和分发到所有监听所创建出的通知队列。

 

img13

 

在元数据存储系统中,需要监听指定逻辑时钟即指 revision 之后发生的所有修改事件,用于下游的缓存更新等操作,从而保证分布式系统的数据最终一致性。注册监听时,需要传入起 revision 和过滤参数,过滤参数包 key 前缀等等。

 

当客户端发起监听时,服务端在建立事件流之后的处理,分成以下几个主要步骤:

 

处理监听注册请求时首先创建通知队列,将通知队列注册到事件生成组件中,获取下发的新增事件;

 

从事件缓存中拉取事件 revision 大于等于给定要 revision 所有事件到事件队列中,并放到输出队列中,以此获取历史事件;

 

将通知队列中的事件取出,添加到输出队列中 revision 去重之后添加到输出队列;

 

 revision 从小到大的顺序,依次使用过滤器进行过滤;

 

将过滤后符合客户端要求的事件,通过事件流推送到元数据存储系统外部的客户端。

 

. 落地效果

 

img14

 

 Benchmark 环境下,基 ByteKV  KubeBrain 对比 etcd 纯写场景吞吐提 10 倍左右,延迟大幅度降低 PCT 50 降低 1/6 PCT 90 降低 1/20 PCT 99降低 1/4 ;读写混合场景吞吐提 4 倍左右;事件吞吐大约提5倍;

 

在模 K8s Workload 的压测环境中,配 APIServer 侧的优化和调优,支 K8s 集群规模达 5w Node  200w Pod

 

在生产环境中,稳定上量 2.1w Node ,高峰期写入超 1.2w QPS,读写负载合计超 1.8w QPS

 

. 未来演进

 

项目未来的演进计划主要包括四个方面的工作:

 

探索实现多点写入的方案以支持水平扩  KubeBrain 本质上还是一个单主写入的系统KubeBrain 后续会在水平扩展方面做进一步的探索,后续也会在社区中讨论;

 

提升切主的恢复速 当前切主会触 API Server  Re-list ,数据同步的开销较大,我们会在这方面进一步做优化;

 

实现内置存储引 实现两层存储融合,由于现在在存储引擎KubeBrain 中存在两 MVCC 设计,整体读写放大较多,实现融合有助于降低读写放大,更进一步提高性能;

 

完善周边组 包括数据迁移工具、备份工具等等,帮助用户更好地使 KubeBrain 

 

. 关于我们

 

字节基础架构编排调度团队,负责构建字节跳动内部的容器云平台,为产品线提供运行基石;以超大容器集群规模整体支撑了字节内产品线,涵盖今日头条、抖音、西瓜视频等。

 

团队支持业务同时覆盖在线、离线机器学习,推/广/搜索等多种应用场景;在持续多年的超高速增长中,积累了丰富 Kubernetes/容器超大规模应用经验,旨在打造覆盖多场景,多地域的千万级容器的大平台。

 

 

(蜂耘云计算网   责任编辑:行云)

2022-11-24 10:34

广告

来源: 字节跳动技术团队
KubeBrain 是字节跳动针对 Kubernetes 元信息存储的使用需求,基于分布式 KV 存储引擎设计并实现的取代 etcd 的元信息存储系统,支撑线上超过 20,000 节点的超大规模 Kubernetes 集群的稳定运行。

声明:凡来源标明“蜂耘网”的文章版权均为本站所有,如需转载请务必注明出处,违者本网将追究相关法律责任;所有未标明来源为“蜂耘网”的转载文章目的在于传递更多信息,均不代表本网立场及观点,“蜂耘网”不对这些第三方内容或链接做任何保证或承担任何责任;如涉及版权等问题,请在内容发表之日起一周内与本网联系,否则视为放弃相关权利。

所有评论仅代表网友意见,与本站立场无关

最新资讯

推荐阅读

热门排行

1、

2、

3、

4、

5、

6、

7、

8、

专题推荐

人物访谈

  • 一文了解查理·芒格:为什么他是巴菲特最推崇的人

    来源:
    ①巴菲特写道,“如果没有查理的灵感、智慧和参与,伯克希尔-哈撒韦公司不可能发展到今天的地位”;
    ②芒格曾表示,“如果世上未曾有过查理·芒格这个人,巴菲特的业绩依然会像现在这么漂亮 ”
    ③两周前,芒格还公开在节目中维护93岁的老友巴菲特。

    29 2023-11-29
  • 面壁者,拉里·佩奇

    来源:中欧商业评论
    这两年,硅谷钢铁侠埃隆·马斯克在社交媒体上口无遮拦,这为他的公司引来了铺天盖地的负面新闻,然而,他的好友、谷歌联合创始人拉里·佩奇却因为看不到人同样被媒体炮轰多时。他已经在公共视野中消失太久了。

    137 2022-06-15
  • 百岁中科院院士文圣常逝世!被誉为我国海浪研究的“点灯人”

    来源:南方都市报
     3月21日上午,中国海洋大学发布讣告,中国科学院院士、著名物理海洋学家、该校教授文圣常,因病医治无效,于3月20日15时37分在山东青岛逝世,享年101岁。

    163 2022-03-21

会议活动

微信公众号

广告

相关新闻