cover_image

RTA从ECS转向容器化架构演进

Norman 拍码场
2025年01月02日 02:45

图片

前言

在数字化转型的浪潮中,技术的进步不断推动着企业架构的革新。随着云计算的兴起,Elastic Compute Service(ECS)以其灵活、可伸缩的特性,成为了众多企业部署和管理应用的首选。然而,技术的边界总是在不断扩展,容器化技术的兴起,特别是以Docker和Kubernetes为代表的容器生态系统,为应用的部署、扩展和管理带来了革命性的变化。

本文将带领读者走进一次技术迁徙之旅,探讨一个业务从传统的ECS发布方式转变为现代化的容器化发布的过程。通过实际案例的分析,我们将展示容器化如何为业务带来更高的灵活性、更好的可移植性和更强的扩展性。

背景

RTA业务在多个云上都有相关的服务, 不过云上是直接使用的ECS服务器, 然后部署的时候通过jar包部署. 如下图图片

ECS上面直接部署服务, 服务通过Jar包的形式进行启动, 并且对外暴露端口

LB直连ECS, 并且绑定ECS对应的端口

外部流量会打到LB上, LB转到ECS对应的服务端口上.

Jar包部署改进

问题点 : ECS上通过Jar包部署服务, 那么就会带来一个问题, 同一服务对外暴露端口都是一样的, 这样就限定了一个ECS上只能部署一个服务; 如果要部署多个服务, 那么每个服务就需要通过命令行来指定不同的端口, 这样的话就又会带来后续维护的难度

解决方案 : 解决Jar包部署的问题就可以使用容器化部署, 容器化部署不仅可以解决单台机器端口的问题, 还可以在单台机器上部署多个实例, 我们只需要定义一个Service对外就可以了 同时, 容器部署还可以屏蔽服务器层面的差异, 可移植性会比Jar包部署好很多

容器化部署后, 整体架构如下 :图片

  • LB连接Ingress, ingress将请求转发到Service
  • Service下面挂的是所有的Pod, 将请求交给Pod来处理
  • 发布的时候通过Deployment进行发布, Deployment会定义要发多少个Pod

这套架构的优点有 :

  • 添加和减少实例数很方便, 只需要修改Deployment的副本数就可以了
  • 实例数添加和减少之后, Service能直接感知到, 添加出来的实例不需要额外在LB上配置就能直接开始接流量
  • 单台服务器可以部署多个服务实例, 从而不需要受同一端口号的限制, 这样可以大大减少我们的服务器数量, 从而减轻运维压力

负载感知优化

容器化改造完之后, 增减服务实例已经没有问题了, 接下来我们再思考下一个问题 :

碰到流量突涨的时候, 单个Pod实例的承载能力是有上限的, 一旦我们现存的这些Pod实例都满负载之后, 就有流量丢失的风险, 这个时候就需要依靠告警, 告警后我们人为介入添加实例

有没有一种办法能够让服务自己知道自己的负载, 然后根据自己的负载来扩缩容呢?

kubernetes的HPA

kubernetes在1.2版本开始引入了一个Horizontal Pod AutoScaler(HPA)功能, 它能够根据Pod自身的CPU使用率, 内存使用率, 或其他资源的使用情况, 来自动调整Pod的数量

我们可以设置Pod实例的CPU使用率超过80%的时候, 来进行自动扩容.

这样, 在面对流量突涨的时候, Pod在达到80%水位线之后开始触发扩容. Pod水位线下去之后又能自动给它缩容回去

引入HPA之后, 容器集群的架构如下 :图片

弹性资源引入

有了上面的HPA,那是不是就已经万事大吉了呢?我们来思考这样一个问题:

集群里面一共有20台32C64G的节点,每个Pod需要的资源是4C8G,那么一台机器满打满也只能部署8个实例。算上节点本身的预留资源和DaemonSet的话,一台节点上最多部署7个服务实例

这样,20台机器最多能部署的实例数量就是140个,日常情况下,需要的资源最多也就130个。也就是我们有10个实例的Buffer

假设在流量高峰的时候,10个实例的Buffer都已经用满了,但是还是不够接收高峰流量。这个时候,就算我们有HPA,我们的实例也会因为资源不足没办法扩容出来图片

这个时候简单的解决办法就是加节点,提前预留多一点的资源,以防止出现流量高峰期间现有资源没办法承接所有流量的情况。

但是这样我们的成本会变高,我们为了短时间的流量高峰预留了太多的资源。那么有没有更好的解决办法呢?

超级节点

现在各个云厂商在容器相关产品上都有一个弹性资源的概念,叫做超级节点。超级节点本身不是一个实际的节点,它是一个虚拟的节点定义。超级节点本身不占任何的资源,只会在我们需要使用的时候才会开始分配资源出来

就好比这个超级节点是一个很大的资源池,池子里面的资源不用不收费,要用的时候到池子里申请,申请之后开始收费,然后当一段时间后,资源用完不需要了之后,我们再把资源还到池子里面。还资源的同时计费截止。

弹性资源的超级节点就很符合我们资源不足这个需求的场景。并且成本也不会有大幅的增加

引入超级节点后,我们就可以做到:日常流量都使用普通节点,流量高峰的时候,先用普通节点的10个Buffer开始扩容,如果扩容的10个Buffer还不够,那么用超级节点来创建不够的实例。然后等流量高峰过去之后,超级节点实例相关的资源就被HPA回缩掉。

引入弹性资源之后的架构如下:图片

最终架构

经过上面几轮的演进,我们最终的容器化架构如下:图片

这套架构的优点有:

  1. 解决ECS上部署Jar包, 同一个服务只能绑定一个端口的问题
  2. 能够随着业务的发展演进按需添加或修改服务实例数
  3. 能自动感知外部流量增长, 并且根据流量来调整副本数, 无需我们人为介入
  4. 能应对流量突发增长,并且可以在无预留资源的情况下承接外部流量
  5. 大大减少服务器数量,从而减轻运维压力

改进空间

快速启停

目前,超级节点上的容器实例从发起Pod到Pod完全就绪,需要3~5分钟。这个时间相对来说还是太长了,对流量的快速反应不够及时,需要看一下还有没有优化的空间

成本优化

有了上面这套最终架构,我们就可以来实现一些压缩资源来节省成本的方案。比如一天之内流量有波峰低谷。普通节点只保留最低谷需要的资源。其他的高峰流量都用弹性资源来支撑。以此来减少资源浪费,节约成本

作者简介

Norman 基础框架研发专家

招聘信息


RTA · 目录
上一篇【预告】百亿流量系统RTA的探索与实践
继续滑动看下一个
拍码场
向上滑动看下一个