【深度】阿里巴巴万级规模 K8s 集群全局高可用体系之美

  • 性能优化和高可用架构建设:主要是从性能优化和架构升级的角度来提升整个集群支撑的业务类型和业务量。

  • 组件规范全生命周期管理:主要从规范的角度在组件的整个生命周期去落地,从出生启用和集群准入开始,到每一次变更,到下线整个生命周期都要防止组件乱用、野蛮生长、无限膨胀,控制组件在系统可承受范围之内。

  • 攻防体系建设:主要从 ASI 系统本身触发,在从攻击和防御的角度来提升系统的安全,防御和风控能力。

5.png

下面针对我们的一些痛点进行几个关键能力建设的描述。

2. K8s 单集群架构的痛点


  • 对 ApiServer 的掌控能力不够,应急能力不足,我们自己的经历,历次集群 Master 出现异常的次数超过 20+,历次恢复时间最长超过 1 小时。

  • ApiServer 是 APIServer 集群的单点,爆炸半径大。

  • 单集群规模大, Apiserver 内存水位比较高,压力来源于频繁的查询,写入更多更大的资源对象。

  • 在业务层缺少跨机房的容灾能力,当 ASI 不可用的时候,只能依赖 ASI 的恢复能力。

  • 集群规模的持续扩大,离线任务的大量创建和删除对集群的造成更大压力。

这里面从两个大的角度可以去提高集群架构的可用性,除了在单集群进行架构优化以及性能突破外,还要通过多集群这样的横向扩展能力去支撑更大的规模。

  • 一是通过联邦这样的多集群能力来解决单集群的横向扩展能力以及单地域跨集群容灾能力。

  • 另外一个单集群本身的架构还可以从隔离和优先级策略的架构角度来进行差异化 SLO 保障。

3. ASI 架构升级落地


1)APIServer 多路架构升级

核心方案就是通过对 apiserver 进行分组,通过不同的优先级策略进行对待,从而对服务进行差异化 SLO 保障。

  • 通过分流以降低主链路 apiserver 压力(核心诉求)

  • P2 及以下组件接入旁路 apiserver,并可以在紧急情况(如自身稳定性收到影响)下,做整体限流。

  • 旁路 apiserver 配合主链路做蓝绿、灰度(次级诉求)

  • 旁路 apiserver 可以使用独立版本,增加新功能灰度维度,如使用独立的限流策略,如开启新的 feature 功能验证。

  • SLB 灾备(次级诉求)

  • 旁路 apiserver 可以在主 apiserver 发生异常时,对外提供服务(需 controller 自行切换目标地址)。

6.png

2)ASI 多集群联邦架构升级

目前张北中心的一个机房就几万节点,如果不解决多集群的管理问题,带来的问题如下:

  • 容灾层面:把核心交易应用的中心单元部署在一个集群的风险是很大的,最坏情况下集群不可用导致整个应用服务不可用。

  • 性能层面:对于业务来说,如因核心应用在某一时点使用时极其敏感而设定各种单机最大限制、CPU 互斥独占保证,如果都部署在一个集群的话,会因为集群节点规模限制,导致应用发生堆叠,造成 cpu 热点,性能不满足要求;对于 ASI 管控 Master 来说,单集群无限制扩大,性能总会出现瓶颈,总有一天会无法支撑。

  • 运维层面:当某个应用扩容发现没资源,SRE 还得考虑节点加到哪个集群,额外加大了 SRE 集群管理的工作。

因此 ASI 需要达成统一的多集群管理解决方案,帮助上层各个 Pass、SRE、应用研发等提供更好的多集群管理能力,通过它来屏蔽多集群的差异、方便的进行多方资源共享。

ASI 选择基于社区联邦 v2 版本来开发满足我们的需求。

4. K8s 集群遭遇规模增长带来的极大性能挑战


在一个大规模的 K8s 集群中性能会遇到哪些问题呢?

  • 首先是查询相关问题。在大集群中最重要的就是如何最大程度地减少 expensive request。对百万级别的对象数量来说,按标签、namespace 查询 Pod,获取所有 Node 等场景时,很容易造成 etcd 和 kube-apiserver OOM 和丢包,乃至雪崩等问题发生。

  • 其次是写入相关问题。etcd 适用场景是读多写少,大量写请求可能会导致 db size 持续增长、写性能达到瓶颈被限速、影响读性能。如大量的离线作业需要频繁的创建和删除 pod,通过 ASI 链路对 pod 对象的写放大,最终对 etcd 的写压力会放大几十倍之大。

  • 最后是大资源对象相关问题。etcd 适合存储较小的 key-value 数据,在大 value 下,性能急速下降。

5. ASI 性能瓶颈突破


ASI 性能优化的方向

7.png

ASI 的性能优化可以从 apiserver 客户端、apiserver 服务端、etcd 存储 3 个方面来进行优化。

  • 客户端侧,可以做 cache 优化,让各个 client 优先访问本地 informer cache,也需要做负载均衡优化,主要包括对 apiserver,etcd 的负载均衡。同时针对客户端的各种优化,可以通过组件性能规范,在组件启用,准入的时候进行校验是否满足。

  • APIServer 侧,可以从访问层,缓存层,存储层 3 个层次进行优化。在缓存层,我们重点建设了 cache 的索引优化以及 watch 优化,在存储层上重点通过 snappy 压缩算法对 pod 进行数据压缩,在访问层上重点建设了限流能力。

8.png

  • etcd 存储侧的优化,我们也从几个方面做了很多工作,包括 etcd 内核层面各种算法优化工作,还有通过将不同资源拆分到不同 etcd 集群的能力实现了基本的水平拆分能力,同时也在 etcd server 层做 multi boltdb 的扩展能力提升。

6. K8s 集群的预防能力薄弱


在 K8s 中,kube-apiserver 作为统一入口,所有的控制器/client 都围绕 kube-apiserver 在工作,尽管我们 SRE 通过组件的全生命周期进行规范约束卡点改进,比如通过在组件的启用和集群准入阶段进行了卡点审批,通过各个组件 owner 的全面配合改造后,大量的低级错误得到防范,但还是有部分控制器或部分行为并不可控。

除了基础设施层面的故障外,业务流量的变化,是造成 K8s 非常不稳定的因素,突发的 pod 创建和删除,如果不加以限制,很容易把 apiserver 打挂。

另外非法的操作或代码 Bug 有可能造成业务 pod 影响,如不合法的 pod 删除。

结合所有风险进行分层设计,逐层进行风险防控。

9.png

7. ASI 单集群的预防能力加强


1)支持 API 访问层的多维度(resource/verb/client)精细化限流

社区早期采用的限流方式主要通过 inflight 控制读写总体并发量,我们当时在 apf 没有出来之前就意识到限流能力的不足,没有能力去对请求来源做限流。而 apf 通过 User 来做限流(或者说要先经过 authn filter)存在一些不足,一方面因为Authn 并不是廉价的,另外一方面它只是将 API Server 的能力按配置来做分配,并不是一种限流方案和应急预案。我们需要紧急提供一种限流能力,以应对紧急情况,自研了 ua limiter 限流能力,并基于 ua limiter 简单的配置方式实现了一套限流管理能力,能够很方便在几百个集群当中进行默认限流管理,以及完成应急限流预案。

下面是我们自研的 ua limiter 限流方案和其他限流方案的详细对比:

10.jpg

ua limiter、APF、sentinel 在限流上的侧重点是不一样的:

  • ua limiter 是根据 ua 提供一个简单的 QPS hard limit。

  • apf 更加侧重于并发度的控制,考虑的是流量的隔离和隔离后的公平性。

  • sentinel 功能全面,但是对于公平性的支持并没有 APF 全面,同时复杂度有一些过高。

考虑我们现阶段的需求和场景,发现 ua limiter 落地最为合适,因为我们通过 user agent 的不同,来对于组件进行限流。当然后续进行更加精细的限流,还是可以考虑结合使用 APF 等方案进一步加强。

限流策略如何管理,数百套集群,每套集群规模都不太一样,集群节点数、pod 数都是不同的,内部组件有近百个,每个组件请求的资源平均有 4 种,对不同资源又有平均 3 个不同的动作,如果每个都做限流,那么规则将会爆炸式增长,即便做收敛后维护成本也非常的高。因此我们抓最核心的:核心资源 pod\node、核心动作(创建、删除、大查询);最大规模的:daemonset 组件、PV/PVC 资源。并结合线上实际流量分析,梳理出二十条左右的通用限流策略,并将其纳入到集群交付流程中实现闭环。

当新的组件接入,我们也会对其做限流设计,如果比较特殊的,则绑定规则并在集群准入和部署环节自动下发策略,如果出现大量的限流情况,也会触发报警,由 SRE 和研发去跟进优化和解决。

2)支持业务 POD 级别的精细化限流

所有 pod 相关的操作都会对接 Kube Defender 统一风控中心,进行秒级别、分钟级、小时级、天级别的流控。该全局风控限流组件,实行中心端部署,维护各场景下的接口调用限流功能。

defender 是站在整个 K8s 集群的视角,针对用户发起的或者系统自动发起的有风险的操作进行防护(流控、熔断、校验)和审计的风控系统。之所以做 defender,主要从以下几个方面考虑:

  • 类似 kubelet/controller 这样的组件,在一个集群中存在多个进程,任一单一进程都无法看到全局的视图,无法进行准确的限流。

  • 从运维视角,分散在各个组件中的限速规则难以配置与审计,当部分操作因为限流原因失败时,排查链路过长影响问题定位的效率。

  • K8s 面向终态的分布式设计,每个组件都有决策的能力,那么就需要一个集中的服务对那些危险决策进行风控。

defender 的框架图如下所示:

11.png

  • defender server 是 K8s 集群级的服务,可以部署多个,其中一个 active,其余 standby。

  • 用户可以通过kubectl配置风控规则。

  • K8s 中的组件,例如 controller,kubelet,extension-controller 等,都可以通过 defender sdk 接入 defender(改动很小),在进行危险操作前请求 defender 进行风控,根据风控结果决定是否继续该危险操作。defender 作为一个集群级的风控防护中心,为 K8s 集群的整体稳定性进行保驾护航。

3)数字化容量治理

在只有几个 core 集群的场景下,依靠专家经验管理容量完全可以轻松搞定,但随着容器业务的快速发展,覆盖泛交易、中间件、新生态、新计算以及售卖区等业务在接入 ASI,短短几年时间就发展了几百个集群,再发展几年数以千计万计?如此多的集群依靠传统的人肉资源管理方式难以胜任,人力成本越来越高,特别是面临诸如以下问题,极易造成资源使用率低下,机器资源的严重浪费,最终造成部分集群容量不足导致线上风险。

  • 组件变更不断,业务类型和压力也在变化,线上真实容量(到底能扛多少 qps)大家都不得而知,当业务需要增大流量时是否需要扩容?是否横向扩容也无法解决问题?

  • 早期申请容器资源随意,造成资源成本浪费严重,需要基于容器成本耗费最小化明确指导应该合理申请多少资源(包括 cpu,内存及磁盘)。同一个地域,同一个元集群的业务集群,一个集群浪费了资源就会造成其他集群资源的紧张。

在 ASI 中,组件变化是常态,组件容量如何自适应这种变化也是一个非常大的挑战。而日常的运维及诊断须要有精准的容量数据来作为备容支撑。

因此我们决定通过数据化指导组件申请合理的(成本低,安全)容器资源。通过数据化提供日常运维所需要的容量相关数据,完成备容,在生产水位异常时,完成应急扩容。

12.png

目前我们完成了水位监控、全量风险播报、预调度、profile 性能数据定时抓取、进而通过组件规范中推进 CPU 内存以及 CPU 内存比例优化。正在做的包括自动化的规格建议,节点资源补充建议,以及自动化导入节点,结合 chatops 正在打造钉群“一键备容”闭环。另外还在结合全链路压测服务数据,得出各个组件的基线对比,通过风险决策,进行发布卡点,确保组件上线安全。同时未来会结合线上真实的变更,来持续回答真实环境的 SLO 表现,精准预测容量。

13.png

全局高可用应急能力建设

================================================================================

高可用基础能力的建设可以为 ASI 提供强有力的抗风险保障,从而在各种风险隐患出现时,尽可能保证我们服务的可用性。但是在风险出现后,如何快速介入消灭隐患,或者在高可用能力无法覆盖的故障出现后,进行有序止损,就变成了一个非常具有技术深度和横向复杂度的工程难题,也让 ASI 的应急能力建设成为我们非常重要的投入方向。

在建设应急体系之初,我们的系统由于迅速的发展和变化,不断出现的事故和险情,明显的暴露出当时我们面临的几个严重的问题:

  • 为什么客户总是早于我们发现问题?

  • 为什么恢复需要这么长的时间?

  • 为什么同样的问题会重复出现?

  • 为什么只有几个人能处理线上的问题?

针对这些问题,我们也进行了充分的脑暴和探讨,并且总结出以下几个核心原因:

  • 发现问题手段单一:只有 metrics 数据作为最基本暴露问题的手段。

  • 定位问题能力缺乏:只有少数监控大盘,核心组件的可观测能力建设程度没有统一。

  • 恢复手段缺乏体系:线上问题的修复需要临时敲命令,写脚本,效率低且风险大。

  • 应急缺少体系规范:缺乏与业务方联动,工程师思维严重,不是以止损为第一目标,对问题严重度缺乏意识。

  • 长期问题缺乏跟踪:线上发现的隐患,或者事故复盘的跟进项,缺乏持续跟进能力,导致重复踩坑。

  • 缺乏能力保鲜机制:业务变化非常快速,导致一些能力在一段时间后,进入一个“不会用也不敢用,也不能保证一定能用”的尴尬境地。

1. 应急能力建设顶层设计


针对这些亟待解决的问题,我们也做了应急能力的顶层设计,架构图如下:

14.png

应急能力建设整体可以分为几个部分:

  • 1-5-10 应急体系:针对线上出现的任何突发风险,都能做到“一分钟发现,五分钟定位,十分钟恢复”的底层能力和机制。

  • 问题追踪跟进:针对线上发现的所有风险隐患,无论严重与否,都能持续跟踪推进的能力。

  • 能力保鲜机制:针对建设的 1-5-10 能力,鉴于其使用频率比较低的本质特性。

2. 应急能力建设子模块建设


针对顶层设计中的每个子模块,我们都已经做出了一些阶段性的工作和成果。

1)一分钟发现:问题发现能力

为了解决无法早于客户发现问题的难题,我们的工作最重要的目标就是要做到:让一切问题都无处遁形,被系统主动发现。

所以这就像是一场持久战,我们要做的,就是通过各种可能的手段去覆盖一个又一个新的问题,攻占一个又一个城池。

在这个目标的驱使下,我们也总结出一套非常行之有效的“战略思想”,即**「1+1 思想」**。它的核心观点在于,任何发现问题的手段,都可能因为对外部的依赖或者自身稳定性的缺陷,导致偶发的失效,所以必须有能够作为互备的链路来进行容错。

在这个核心思想的指导下,我们团队建设了两大核心能力,即黑盒/白盒报警双通道,这两个通道的各有各的特点:

  • 黑盒通道:基于黑盒思想,从客户视角把 ASI 整体当做黑盒,直接发出指令,探测正向功能;比如直接扩容一个 statefulset。

  • 白盒通道:基于白盒思想,借助系统内部暴露出来的各种维度的可观测性数据的异常波动来发现潜在问题;比如 APIServer 的内存异常上涨。

黑盒通道对应的具体产品叫做 kubeprobe,是由我们团队脱胎于社区 kuberhealthy 项目的思想上进行更多的优化和改造形成的新产品,并且也成为我们判断集群是否出现严重风险的重要利器。

白盒通道的建设相对更为复杂,它需要建设在完备的可观测数据的基础之上,才能够真正发挥它的功力。所以为此我们首先从 metrics、日志、事件 3 个维度分别基于 SLS 建设 3 种数据通道,将所有可观测数据统一到 SLS 上管理。另外我们也建设了告警中心,负责完成对当前上百套集群的告警规则的批量管理,下发能力,最终构造了出了一个数据完备,问题覆盖广泛的白盒告警系统。最近还在进一步将我们的告警能力向 SLS 告警 2.0 迁移,实现更加丰富的告警功能。

2)五分钟定位:问题根因自动定位能力

随着线上问题排查经验的不断丰富,我们发现有很多问题会比较频繁地出现。它们的排查方法和恢复手段基本已经比较固化。即便某个问题背后的原因可能有多种,但是随着线上排查经验的丰富,基本都可以慢慢迭代出对这个问题的排查路线图。如下图所示,是针对 etcd 集群不健康的告警设计的排查路线:

15.png

如果把这些相对比较确认的排查经验固化到系统中,在问题出现后可以自动触发形成决策,势必可以大幅减少我们对线上问题的处理耗时。所以在这个方面,我们也开始了一些相关能力的建设。

从黑盒通道方面,kubeprobe 构建了一套自闭环的根因定位系统,将问题排查的专家经验下沉进系统中,实现了快速和自动的问题定位功能。通过普通的根因分析树以及对失败巡检探测事件/日志的机器学习分类算法(持续开发投入中),为每一个 KubeProbe 的探测失败 Case 做根因定位,并通过 KubeProbe 内统一实现的问题严重性评估系统(目前这里的规则仍比较简单),为告警的严重性做评估,从而判断应该如何做后续的处理适宜,比如是否自愈,是否电话告警等等。

16.png

从白盒通道方面,我们通过底层的 pipeline 引擎的编排能力,结合已经建设的数据平台中的多维度数据,实现了一个通用的根因诊断中心,将通过各种可观测数据从而排查问题根因的过程通过 yaml 编排的方式固化到系统中,形成一个根因诊断任务,并且在触发任务后形成一个问题的诊断结论。并且每种结论也会绑定对应的恢复手段,比如调用预案、自愈等等。

17.png

最后

面试题文档来啦,内容很多,485页!

由于笔记的内容太多,没办法全部展示出来,下面只截取部分内容展示。

1111道Java工程师必问面试题

MyBatis 27题 + ZooKeeper 25题 + Dubbo 30题:

Elasticsearch 24 题 +Memcached + Redis 40题:

Spring 26 题+ 微服务 27题+ Linux 45题:

Java面试题合集:

100cde242f446189.png)

最后

面试题文档来啦,内容很多,485页!

由于笔记的内容太多,没办法全部展示出来,下面只截取部分内容展示。

1111道Java工程师必问面试题

[外链图片转存中…(img-EMBGsM1M-1714531010950)]

MyBatis 27题 + ZooKeeper 25题 + Dubbo 30题:

[外链图片转存中…(img-IIg2KsRk-1714531010951)]

Elasticsearch 24 题 +Memcached + Redis 40题:

[外链图片转存中…(img-1Fc12jyS-1714531010951)]

Spring 26 题+ 微服务 27题+ Linux 45题:

[外链图片转存中…(img-DWPkJ53F-1714531010951)]

Java面试题合集:

[外链图片转存中…(img-ZiZ2rf7k-1714531010951)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值