当前位置: 首页 > news >正文

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

Django框架之模板其他补充

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

安装Maven 3.6.1:图文详细教程(适用于Windows系统)

一、官网下载对应版本 推荐使用maven3.6.1版本&#xff0c;对应下载链接&#xff1a; Maven3.6.1下载地址 或者&#xff0c;这里提供csdn下载地址&#xff0c;点击下载即可&#xff1a; Maven3.6.1直链下载 其他版本下载地址&#xff1a; 进入网址&#xff1a;http://mave…...

计算机图形学 | 实验八:Phong模型

计算机图形学 | 实验八&#xff1a;Phong模型 计算机图形学 | 实验八&#xff1a;Phong模型Phong模型光源设置 光照计算定向光点光源聚光 华中科技大学《计算机图形学》课程 MOOC地址&#xff1a;计算机图形学&#xff08;HUST&#xff09; 计算机图形学 | 实验八&#xff1a…...

第三十一回:GestureDetector Widget

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了ListView响应事件的内容t,本章回中将介绍 GestureDetector Widget.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在这里介绍的GestureDetector是一个事件响应Widget,它可以响应双击事件&#xff0…...

Java面试知识点(全)-Java并发-多线程JUC三- JUC集合/线程池

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

Android 如何获取有效的DeviceId

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

<SQL>《SQL命令(含例句)精心整理版(2)》

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

完全自主研发,聚芯微发布3D dToF图像传感器芯片!

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

MySQL 事物(w字)

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

字节跳动测试岗四面总结....

字节一面 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 开发的、开源项目&#xff0c;可将屏幕截图转为 GIF 动画。它的核心功能是能够简单、快速地截取整个屏幕或者选定区域&#xff0c;并将其转为 GIF动画&#x…...

PCB 基础~典型的PCB设计流程,典型的PCB制造流程

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

Python logging使用

目录 logging模块 logging核心组件 logger handler StreamHandler&#xff1a;把日志内容在控制台中输出 FileHandler&#xff1a;把日志内容写入到文件中 filter formatter 注意日志级别的继承问题 logger.exception 上述样例的整体代码 日志的配置文件及其模板 lo…...

红黑树的实现原理和应用场景

红黑树的实现原理和应用场景&#xff1b; 有如图所示的表&#xff0c;现在希望查询的结果将列成行 建表语句如下&#xff1a; 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环境下&#xff0c;可以用过插件的方式自动生成juint模板代码。不过具体要需要自己手动编写。 1、安装插件 打开idea&#xff0c;file–settings–plugins&#xff0c;搜索和安装插件&#xff08;JunitGenerator V2.0和JUnit&#xff09;&#xff0c;安装后&#xff0c;后…...

【Redis面试点总结】

1、缓存 1.1、穿透 查询一个空数据&#xff0c;mysql也查不到也不会写入缓存可能导致多次请求数据库 方案一&#xff1a;缓存设空即可&#xff08;可能发生数据不一致就是这条数据有了但此时缓存是空&#xff0c;消耗内存&#xff09; 方案二&#xff1a;布隆过滤器&#x…...

打卡智能中国(五):博士都去哪儿了?

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

[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.预处理&#xff08;Preprocessing&#xff09;&#xff1a; 在这个步骤中&#xff0c;预处理器将处理与#相关的代码&#xff0c;包括展开头文件、删除无用定义和替换宏定义。预处理器会生成一个经过宏替换和条件编译处理的中间文件。 gcc -E xxx.c -o xxx.i2.编译&#xff0…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...