云原生之深入解析Airbnb的动态Kubernetes集群扩缩容
一、前言
- Airbnb 基础设施的一个重要作用是保证我们的云能够根据需求上升或下降进行自动扩缩容,我们每天的流量波动都非常大,需要依靠动态扩缩容来保证服务的正常运行。为了支持扩缩容,Airbnb 使用了 Kubernetes 编排系统,并且使用了一种基于 Kubernetes 的服务配置接口。
- 现在来讨论一下如何使用 Kubernetes Cluster Autoscaler 来动态调整集群的大小,这些改进增加了可定制性和灵活性,以满足 Airbnb 独特的业务需求。
二、Airbnb 的 Kubernetes 集群
- 在过去的几年中,Airbnb 已经将几乎所有的在线服务从手动编排的 EC2 实例迁移到了 Kubernetes。现如今,在近百个集群中运行了上千个节点来适应这些工作负载。
- 然而,这些变化并不是一蹴而就的,在迁移过程中,随着新技术栈上的工作负载和流量越来越多,底层的 Kubernetes 集群也随之变得越来越复杂。这些演变可以划分为如下三个阶段:
-
- 同质集群,手动扩容;
-
- 多集群类型,独立扩缩容;
-
- 异构集群,自动扩缩容。
① 同质集群,手动扩缩容
- 在使用 Kubernetes 之前,每个服务实例都运行在其所在的机器上,通过手动分配足够的容量来满足流量增加的场景。每个团队的容量管理方式都不尽相同,且一旦负载下降,很少会取消配置。
- 一开始 Kubernetes 集群的配置相对比较简单,配置有几个集群,每个集群都有单独的底层节点类型和配置,它们只运行无状态的在线服务。随着服务开始迁移到 Kubernetes,我们便开始在多租户环境中运行容器化的服务。这种聚合方式减少了资源浪费,并且将这些服务的容量管理整合到 Kuberentes 控制平面上。
- 在这个阶段,需要我们手动扩展集群,但相比之前仍然有着显著的提升。
② 多集群类型,独立扩缩容
- 集群配置的第二个阶段是因为更多样化的工作负载而出现的,每个试图在 Kubernetes 上运行的工作负载都有着不同的需求。为了满足这些需求,为此创建了一个抽象的集群类型,集群类型定义了集群的底层配置,这意味着集群类型的所有集群都是相同的,从节点类型到集群组件设置都是相同的。
- 越来越多的集群类型导致出现了越来越多的集群,最初通过手动方式来调节每个集群容量的方式,很快就变得崩溃了。为了解决这个问题,我们为每个集群添加了 Kubernetes Cluster Autoscaler 组件,该组件会基于pod requests 来动态调节集群的大小。如果一个集群的容量被耗尽,则 Cluster Autoscaler 会添加一个新的节点来满足 pending 状态的 pods。
- 同样,如果在一段时间内集群的某些节点的利用率偏低,则 Cluster Autoscaler 会移除这些节点。这种方式非常适合我们的场景,为我们节省了大约 5% 的总的云开销,以及手动扩展集群的运维开销。
③ 异构集群,自动扩缩容
- 当 Airbnb 的几乎所有在线计算都转移到 Kubernetes 时,集群类型的数量已经增长到 30 多个了,集群的数量也增加到了 100 多个。这种扩展使得 Kubernetes 集群管理相当乏味,例如,在集群升级时需要单独对每种类型的集群进行单独测试。
- 在第三个阶段,通过创建异构集群来整合集群类型,这些集群可以通过单个 Kubernetes 控制平面来容纳许多不同的工作负载:
-
- 首先,这种方式极大降低了集群管理的开销,因为拥有更少、更通用的集群会减少需要测试的配置数量;
-
- 其次,现在大多数 Airbnb 的服务已经运行在 Kubernetes 集群上,每个集群的效率可以为成本优化提供一个很大的杠杆。
- 整合集群类型允许在每个集群中运行不同的工作负载,这种工作负载类型的聚合(有些大,有些小)可以带来更好的封装和效率,从而提高利用率。通过这种额外的工作负载灵活性,可以有更多的空间来实施复杂的扩展策略,而不是默认的 Cluster Autoscaler 扩展逻辑。具体来说就是计划实现与 Airbnb 特定业务逻辑相关的扩缩容逻辑。
- 随着对集群的扩展和整合,就实现了异构(每个集群有多种实例类型),我们开始在扩展期间实现特定的业务逻辑,并且意识到有必要对扩缩容的行为进行某些变更。
三、Cluster Autoscaler 改进:自定义 gRPC 扩展器
- 要对 Cluster Autoscaler 所做的最重要的改进是提供一种新方法来确定要扩展的节点组,在内部 Cluster Autoscaler 会维护一系列映射到不同候选扩容对象的节点组,它会针对当前 Pending 状态的 pods 执行模拟调度,然后过滤掉不满足调度要求的节点组。如果存在 Pending 的 pods,Cluster Autoscaler 会尝试通过扩展集群来满足这些 pods,所有满足 pod 要求的节点组都会被传递给一个名为 Expander 的组件。
- Expander 负责根据需求进一步过滤节点组,Cluster Autoscaler 有大量内置的扩展器选项,每个选型都有不同的处理逻辑。例如,默认是随机扩展器,它会随机选择可用的节点组,另一个是 Airbnb 曾经使用过的优先级扩展器 ,它会根据用户指定的分级优先级列表来选择需要扩展的节点组。
- 当使用异构集群逻辑的同时,可以发现默认的扩展器无法在成本和实例类型选择方面满足复杂的业务需求。假设,想要实现一个基于权重的优先级扩展器,目前的优先级扩展器仅允许用户为节点组设置不同的等级,这意味着它会始终以确定的顺序来扩展节点组。如果某个等级有多个节点组,则会随机选择一个节点组。基于权重的优先级策略可以支持在同一个等级下设置两个节点组,其中 80% 的时间会扩展一个节点组,另外 20% 的时间会扩展另一个节点组,但默认并不支持基于权重的扩展器。
- 除了当前支持的扩展器的某些限制外,还有一些操作上的问题:
-
- Cluster Autoscaler 的发布流水线比较严格,在合并到上游之前,需要花大量时间来审核变更,但我们的业务逻辑和所需的扩展策略是在不断变化的,能够满足当前需求的扩展器并不一定能够满足未来的需求;
-
- 我们的业务逻辑是与 Airbnb 关联的,其他用户则没有这种业务逻辑,因此实现的特定逻辑并不一定对上游用户有用;
- 因此可以对 Cluster Autoscaler 中的新扩展器类型提出了一些要求:
-
- 我们希望扩展器是可扩展的,能够被其他用户使用,其他用户在使用默认的 Expanders 可能会遇到类似的限制,那么希望提供一个通用的解决方案,并回馈上游;
-
- 解决方案应该能够独立于 Cluster Autoscaler 部署,这样可以能够响应快速变更的业务需求。
-
- 解决方案应该能够融入 Kubernetes Cluster Autoscaler 生态系统,这样就无需一直维护一个 Cluster Autoscale 的分支。
- 鉴于这些需求,可以提出了一种设计,将扩展职责从 Cluster Autoscaler 的核心逻辑中分离出来,设计一种可插拔的“自定义扩展器” ,它实现 gRPC 客户端(类似 custom cloud provider),该自定义扩展器分为两个组件:
-
- 第一个组件是内置到 Cluster Autoscaler 中的 gRPC 客户端,这个 Expander 与 Cluster Autoscaler 中的其他扩展器遵循相同的接口,负责将 Cluster Autoscaler 中的有效节点组信息转换为定义好的 protobuf 格式,并接收来自 gRPC 服务端的输出,将其转换回 Cluster Autoscaler 要扩展的最终的可选列表。
service Expander {rpc BestOptions (BestOptionsRequest) returns (BestOptionsResponse)
} message BestOptionsRequest {repeated Option options;map<string, k8s.io.api.core.v1.Node> nodeInfoMap;
} message BestOptionsResponse {repeated Option options;
} message Option {// ID of node to uniquely identify the nodeGroupstring nodeGroupId;int32 nodeCount;string debug;repeated k8s.io.api.core.v1.Pod pod;
}
-
- 第二个组件是 gRPC 服务端,这需要由用户实现,该服务端作为一个独立的应用或服务运行,通过客户端传递的信息以及复杂的扩展逻辑来选择需要扩容的节点组。当前通过 gRPC 传递的 protobuf 消息是 Cluster Autoscaler 中传递给 Expander 的内容的(略微)转换版本。
- 在前面的例子中,可以非常容易地实现加权随机优先级扩展器,方法是让服务器从优先级列表中读取,并通过 confimap 读取权重百分比,然后进行相应的选择。
- 其实实现还包含一个故障保护选项,建议使用该选项将“多个扩展器”作为参数传递给 Cluster Autoscaler,使用该选择后,如果服务端出现故障,Cluster Autoscaler 仍然能够使用一个备用的扩展器进行扩展。
- 由于服务端作为一个独立的应用运行,因此可以在 Cluster Autoscaler 外开发扩展逻辑,且 gRPC 服务端可以根据用户需求实现自定义,因此这种方案对整个社区来说也非常有用。
- 在内部,从 2022 年开始,Airbnb 就一直在使用这种方案来扩缩容所有的集群,期间一直没有出现任何问题,它允许动态地选择何时去扩展特定的节点组来满足 Airbnb 的业务需求,从而实现可以开发一个可扩展的自定义扩展器。
相关文章:

云原生之深入解析Airbnb的动态Kubernetes集群扩缩容
一、前言 Airbnb 基础设施的一个重要作用是保证我们的云能够根据需求上升或下降进行自动扩缩容,我们每天的流量波动都非常大,需要依靠动态扩缩容来保证服务的正常运行。为了支持扩缩容,Airbnb 使用了 Kubernetes 编排系统,并且使…...

Django框架之模板其他补充
本篇文章是对django框架模板内容的一些补充。包含注释、html转义和csrf内容。 目录 注释 单行注释 多行注释 HTML转义 Escape Safe Autoescape CSRF 防止csrf方式 表单中使用 ajax请求添加 注释 单行注释 语法:{# 注释内容 #} 示例: {# 注…...

安装Maven 3.6.1:图文详细教程(适用于Windows系统)
一、官网下载对应版本 推荐使用maven3.6.1版本,对应下载链接: Maven3.6.1下载地址 或者,这里提供csdn下载地址,点击下载即可: Maven3.6.1直链下载 其他版本下载地址: 进入网址:http://mave…...

计算机图形学 | 实验八:Phong模型
计算机图形学 | 实验八:Phong模型 计算机图形学 | 实验八:Phong模型Phong模型光源设置 光照计算定向光点光源聚光 华中科技大学《计算机图形学》课程 MOOC地址:计算机图形学(HUST) 计算机图形学 | 实验八:…...
第三十一回:GestureDetector Widget
文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了ListView响应事件的内容t,本章回中将介绍 GestureDetector Widget.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在这里介绍的GestureDetector是一个事件响应Widget,它可以响应双击事件࿰…...

Java面试知识点(全)-Java并发-多线程JUC三- JUC集合/线程池
Java面试知识点(全) 导航: https://nanxiang.blog.csdn.net/article/details/130640392 注:随时更新 JUC集合类 为什么HashTable慢? 它的并发度是什么? 那么ConcurrentHashMap并发度是什么? Hashtable之所以效率低下主要是因为其实现使用了synchro…...

Android 如何获取有效的DeviceId
目录 前言官方唯一标识符建议使用广告 ID使用实例 ID 和 GUID不要使用 MAC 地址标识符特性常见用例和适用的标识符 解决方案DeviceIdANDROID_IDMac地址UUID补充 总结 前言 从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能访问设备的不可…...

<SQL>《SQL命令(含例句)精心整理版(2)》
《SQL命令(含例句)精心整理版(2)》 跳转《SQL命令(含例句)精心整理版(1)8 函数8.1 文本处理函数8.2 数值处理函数8.3 时间处理函数8.3.1 时间戳转化为自定义格式from_unixtime8.3.2 …...

完全自主研发,聚芯微发布3D dToF图像传感器芯片!
日前,由中国半导体行业协会IC设计分会(ICCAD)、芯原股份、松山湖管委会主办的主题为“AR/VR/XR元宇宙”的“2023松山湖中国IC创新高峰论坛”正式在广东东莞松山湖召开。武汉市聚芯微电子有限责任公司发布了完全自主知识产权的3D dToF图像传感…...

MySQL 事物(w字)
目录 事物 首先我们来看一个简单的问题 什么是事务 为什么会出现事务 事务的版本支持 事务提交方式 事务常见操作方式 设置隔离级别 事物操作 事物结论 事务隔离级别 理解隔离性 隔离级别 查看与设置隔离性 注意可重复读【Repeatable Read】的可能问题ÿ…...

字节跳动测试岗四面总结....
字节一面 1、 简单做一下自我介绍 2、 简要介绍一下项目/你负责的模块/选一个模块说一下你设计的用例 3 、get请求和post请求的区别 4、 如何判断前后端bug/3xx是什么意思 5、 说一下XXX项目中你做的接口测试/做了多少次 6、 http和https的区别 7、 考了几个ADB命令/查看…...

基于.NetCore开源的Windows的GIF录屏工具
推荐一个Github上Start超过20K的超火、好用的屏幕截图转换为 GIF 动图开源项目。 项目简介 这是基于.Net Core WPF 开发的、开源项目,可将屏幕截图转为 GIF 动画。它的核心功能是能够简单、快速地截取整个屏幕或者选定区域,并将其转为 GIF动画&#x…...

PCB 基础~典型的PCB设计流程,典型的PCB制造流程
典型的PCB设计流程 典型的PCB制造流程 • 从客户手中拿到Gerber, Drill以及其它PCB相关文件 • 准备PCB基片和薄片 – 铜箔的底片会被粘合在基材上 • 内层图像蚀刻 – 抗腐蚀的化学药水会涂在需要保留的铜箔上(例如走线和过孔) – 其他药水…...

Python logging使用
目录 logging模块 logging核心组件 logger handler StreamHandler:把日志内容在控制台中输出 FileHandler:把日志内容写入到文件中 filter formatter 注意日志级别的继承问题 logger.exception 上述样例的整体代码 日志的配置文件及其模板 lo…...
红黑树的实现原理和应用场景
红黑树的实现原理和应用场景; 有如图所示的表,现在希望查询的结果将列成行 建表语句如下: CREATE TABLE TEST_TB_GRADE2 ( ID int(10) NOT NULL AUTO_INCREMENT, USER_NAME varchar(20) DEFAULT NULL, CN_SCORE float DEFAULT NU…...

idea插件完成junit代码生成,和springboot代码示例
在idea环境下,可以用过插件的方式自动生成juint模板代码。不过具体要需要自己手动编写。 1、安装插件 打开idea,file–settings–plugins,搜索和安装插件(JunitGenerator V2.0和JUnit),安装后,后…...

【Redis面试点总结】
1、缓存 1.1、穿透 查询一个空数据,mysql也查不到也不会写入缓存可能导致多次请求数据库 方案一:缓存设空即可(可能发生数据不一致就是这条数据有了但此时缓存是空,消耗内存) 方案二:布隆过滤器&#x…...

打卡智能中国(五):博士都去哪儿了?
《打卡智能中国》系列更新了几期,有读者表示,很爱看这类接地气的真实故事,也有读者反映,不是电工,就是文员、农民、治沙人,人工智能不是高精尖学科吗?那些学历很高的博士都去哪儿了?…...

[Nacos] Nacos Client获取调用服务的提供者列表 (四)
文章目录 1.Nacos Client获取调用服务的提供者列表1.1 从Ribbon的负载均衡入手到Nacos Client获取调用服务的提高者列表1.2 getServers方法返回分析1.3 通过selectInstances方法查找Instances实例1.4 获取到要调用服务的serviceInfo Nacos Client 从Ribbon负载均衡调用服务。 …...
gcc编译一个程序的步骤(嵌入式学习)
1.预处理(Preprocessing): 在这个步骤中,预处理器将处理与#相关的代码,包括展开头文件、删除无用定义和替换宏定义。预处理器会生成一个经过宏替换和条件编译处理的中间文件。 gcc -E xxx.c -o xxx.i2.编译࿰…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...