服务运维

更新时间:

本文将主要分享大规模服务网格,在蚂蚁集团当前体量下,落地到支撑蚂蚁金服双十一大促过程中,运维所面临的挑战与演进。

云原生化的选择与问题

传统的 Service Mesh:

  • 在软件形态上:将中间件的能力从框架中剥离成独立软件。

  • 在具体部署上:保守的做法是以独立进程的方式与业务进程共同存在于业务容器内。

蚂蚁集团从开始就选择了拥抱云原生。

Sidecar 模式

业务容器内独立进程的优缺点为:

  • 优点:与传统的部署模式兼容,易于快速上线。

  • 缺点:强侵入业务容器,对于镜像化的容器更难于管理。

而云原生化,可以解决独立进程的缺点,并带来一些优点:

  • 可以将 Service Mesh 本身的运维与业务容器解耦开来,实现中间件运维能力的下沉。

  • 在业务镜像内,仅保留长期稳定的 Service Mesh 相关 JVM 参数,从而仅通过少量环境变量完成与 Service Mesh 的联结。

  • 考虑到面向容器的运维模式的演进,接入 Service Mesh 还同时要求业务完成镜像化,为进一步的云原生演进打下基础。

优势

劣势

独立进程

兼容传统的部署模式改造成本低快速上线

侵入业务容器镜像化难于运维

Sidecar

面向终态运维解耦

依赖 K8s 基础设施运维环境改造成本高应用需要镜像化改造

在接入 Service Mesh 之后,一个典型的 Pod 结构可能包含多个 Sidecar:

  • MOSN:RPC Mesh、MSG Mesh 等。

  • 其它 Sidecar。

运维1.png

这些 Sidecar 容器,与业务容器共享相同的网络 Namespace,使得业务进程可以从本地端口访问 Service Mesh 提供的服务,保证了与保守做法一致的体验。

基础设施云原生支撑

蚂蚁团队也在基础设施层面同步推进了面向云原生的改造,以支撑 Service Mesh 的落地。

业务全面镜像化

首先是在蚂蚁集团内部推进了全面的镜像化,完成了内部核心应用的全量容器的镜像化改造。改造点包括:

  • 基础镜像层面增加对于 Service Mesh 的环境变量支撑。

  • 应用 Dockerfile 对于 Service Mesh 的适配。

  • 由于历史原因,前后端分离管理的静态文件还有一些存量,蚂蚁团队推进解决了存量文件的镜像化改造。

  • 对于大量使用前端区块分发的应用,进行了推改拉的改造。

  • 大批量的 VM 模式的容器升级与替换。

容器 Pod 化

除了业务镜像层面的改造,Sidecar 模式还需要业务容器全部跑在 Pod 上,来适应多容器共享网络。由于直接升级的开发和试错成本很高,接入 Service Mesh 的数百个应用有数万个非 K8s 容器,蚂蚁团队最终选择通过大规模扩缩容的方式,将其全部更换成了 K8s Pods。

经过这两轮改造,蚂蚁团队在基础设施层面同步完成了面向云原生的改造。

对资源模型的挑战

Sidecar 模式带来的一个重要的问题是:如何分配资源。

理想比例的假设

最初的资源设计基于内存无法超卖的现实。蚂蚁做了一个假设:MOSN 的基本资源占用与业务选择的规格同比例。即 CPU 和 Memory 申请的额外资源与业务容器成相应比例,这一比例最后设定在了 CPU 1/4,Memory 1/16。

此时一个典型 Pod 的资源分配如下图示:

运维2.png

理想比例的缺陷

理想比例的假设带来了两个问题:

  • 蚂蚁集团已经实现了业务资源的 Quota 管控,但 Sidecar 并不在业务容器内,Service Mesh 容器成为了一个资源泄漏点。

  • 由于业务多样性,部分高流量应用的 Service Mesh 容器出现了严重的内存不足和 OOM 情况。

为了快速支撑 Service Mesh 在非云环境的铺开,上线了原地接入 Service Mesh。而原地接入 Service Mesh 的资源无法额外分配,在内存不能超卖的情况下,采取了二次分割的分配方式。此时的 Pod 内存资源分配方式为:

  • 1/16 内存给 Sidecar。

  • 15/16 内存给业务容器。

还有一些新的问题:

  • 业务可见内存不一致。

  • 业务监控偏差。

  • 业务进程 OOM 风险。

解决方案

为了解决上述问题,蚂蚁团队追加了一个假设:在接入 Service Mesh 之前,业务已使用的资源,才是 Service Mesh 容器占用的资源。接入 Service Mesh 的过程,同时也是一次资源置换。

基于这个假设,推进了调度层面支持 Pod 内的资源超卖。Service Mesh 容器的 CPU、MEM 都从 Pod 中超卖出来,业务容器内仍然可以看到全部的资源。

新的资源分配方案,示例如下:

运维3.png

新的分配方案考虑了下述因素:

  • 内存超卖

  • 引入了 Pod OOM 的风险

因此,对于 Sidecar 容器还调整了 OOM Score,保证在内存不足时,通过 Service Mesh 进程比 Java 业务进程启动更快,从而更降低影响。

同时,新的分配方案还解决了以上两个问题,并且平稳支持了大促前的多轮压测。

重建

新的分配方案上线时,Service Mesh 已经在弹性建站时同步上线。同时,蚂蚁团队还发现:在一些场景下,Service Mesh 容器无法抢占到 CPU 资源,导致业务 RT 出现了大幅抖动。原因是:在 CPU Share 模式下,Pod 内默认并没有将等额的CPU Quota 分配给 Sidecar。

于是又产生了两个新问题:

  • 存量的已分配 Sidecar 仍有 OOM 风险。

  • Sidecar 无法抢占到 CPU。

蚂蚁已经无法承受更换全部 Pod 的代价。最终在调度的支持下,通过手动对 Pod Annotation 进行重新计算及修改,在 Pod 内进行了全部资源的重分配,来修复这两个风险。最终修复的容器总数约为 25 w 个。

大规模场景下运维设施的演进

Service Mesh 的变更包括了接入与升级,所有变更底层都是由 Operator 组件 来接受上层写入到 Pod annotation 上的标识,然后通过对相应 Pod Spec 进行修改来完成,这是典型的云原生的方式。由于蚂蚁集团的资源现状与运维需要,又发展出了原地接入与平滑升级。

接入

有 2 种接入方式:

  • 创建接入:最初 Service Mesh 接入只提供了创建时注入 Sidecar。

  • 原地接入:后来引入了原地接入,主要是为了支撑大规模的快速接入与回滚。

2 种接入方式的优缺点如下:

  • 创建接入:

    • 资源替换过程需要大量 Buffer。

    • 回滚困难。

  • 原地接入:

    • 不需要重新分配资源。

    • 可原地回滚。

原地接入/回滚需要对 Pod Spec 进行精细化的修改,实践中发现了很多问题,当前能力只做了小范围的测试。

升级

Service Mesh 是深度参与业务流量的,因此最初的 Sidecar 的升级方式也需要业务伴随重启。这个过程看似简单,蚂蚁却遇到了 2 个严重问题:

  • Pod 内的容器启动顺序随机,导致业务无法启动。这个问题最终通过调度层修改启动逻辑来解决:Pod 内需要优先等待所有 Sidecar 启动完成。但是,这导致了下述第二所述的新问题。

  • Sidecar 启动慢了,上层超时。此问题仍在解决中。

Sidecar 中,MOSN 提供了更为灵活的平滑升级机制:由 Operator 控制启动第二个 MOSN Sidecar,完成连接迁移,再退出旧的 Sidecar。小规模测试显示,整个过程业务可以做到流量不中断,几近无感。目前平滑升级同样涉及到 Pod Spec 的大量操作,考虑到大促前的稳定性,目前此方式未做大规模应用。

规模化的问题

在逐渐达到大促状态的过程中,接入 Service Mesh 的容器数量开始大爆炸式增加。容器数量从千级别迅速膨胀到10 w +,最终达到全站数十万容器规模,并在膨胀后还经历了数次版本变更。

快速奔跑的同时,缺少相应的平台能力也给大规模的 Sidecar 运维带来了极大挑战:

  • 版本管理混乱:

    • Sidecar 的版本与应用 / Zone 的映射关系维护在内部元数据平台的配置中。大量应用接入后,全局版本、实验版本、特殊 Bugfix 版本等混杂在多个配置项中,统一基线被打破,难于维护。

  • 元数据不一致:

    • 元数据平台维护了 Pod 粒度的 Sidecar 版本信息,但是由于 Operator 是面向终态的,会出现元数据与底层实际不一致的情况,当前仍依赖巡检发现。

  • 缺少完善的 Sidecar ops 支撑平台:

    • 缺少多维度的全局视图。

    • 缺少固化的灰度发布流程。

    • 依赖于人工经验配置管理变更。

  • 监控噪声巨大。

目前,Service Mesh 与 PaaS 的开发团队都正在建设相应的能力,这些问题正得到逐步的缓解。

周边技术风险能力的建设

监控能力

蚂蚁的监控平台为 Service Mesh 提供了基础的监控能力和大盘,以及应用维度的 Sidecar 监控情况,包括:

  • 系统监控:

    • CPU

    • MEM

    • LOAD

  • 业务监控:

    • RT

    • RPC 流量

    • MSG 流量

    • Error 日志监控

Service Mesh 进程还提供了相应的 Metrics 接口,提供服务粒度的数据采集与计算。

巡检

在 Service Mesh 上线后,巡检也陆续被加入:

  • 日志 Volume 检查

  • 版本一致性检查

  • 分时调度状态一致性检查

预案与应急

Service Mesh 自身具备按需关闭部分功能的能力,当前通过配置中心实现下述功能:

  • 日志分级降级

  • Tracelog 日志分级降级

  • 控制面(Pilot)依赖降级

  • 软负载均衡长轮询降级

对于 Service Mesh 依赖的服务,为了防止潜在的抖动风险,也增加了相应的预案:

  • 软负载均衡列表停止变更。

  • 服务注册中心高峰期关闭推送。

Service Mesh 是非常基础的组件,目前的应急手段主要是下述重启方式:

  • Sidecar 单独重启

  • Pod 重启

变更风险防控

除了传统的变更三板斧之外,蚂蚁还引入了无人值守变更,对 Service Mesh 变更做了自动检测、自动分析与变更熔断。

无人值守变更防控主要关注变更后对系统和业务和影响,串联了多层检测,主要包括:

  • 系统指标:机器内存、磁盘、CPU。

  • 业务指标:业务和 Service Mesh 的 RT、QPS 等。

  • 业务关联链路:业务上下游的异常情况。

  • 全局的业务指标。

经过这一系列防控设施,可以在单一批次变更内,发现和阻断全站性的 Service Mesh 变更风险,避免了风险放大。

未来展望

Service Mesh 在快速落地的过程中,遇到并解决了一系列的问题,但同时也要看到还有更多的问题亟待解决。做为下一代云原生化中间件的核心组件之一,Service Mesh 的技术风险能力还需要持续的建议与完善。

未来需要在下述领域持续建设:

  • 大规模高效接入与回滚能力支撑。

  • 更灵活的变更能力,包括业务无感的平滑/非平滑变更能力。

  • 更精准的变更防控能力。

  • 更高效,低噪声的监控。

  • 更完善的控制面支持。

  • 应用维度的参数定制能力。