背景

一起长大服务端技术架构一直跟随着云原生的发展方向,云原生让我们适应了业务高弹性的场景,满足了业务高峰的需求。

但如何让云原生资源利用率更高,用更少的计算节点承载更多的实例,降低资源开销,提高服务的可用性,是我们一直在探索的。最近两年持续升温的 Serverless 具备弹性伸缩、按量计费、无需运维等优势,是解决上述问题非常好的方案之一。

公有云厂商有很多 Serverless 解决方案和相关产品,包括函数计算, Serverless 应用引擎,Serverless 容器服务,弹性容器实例等等。调研和试用以后发现,很多产品屏蔽了底层的 Kubernete,更适合于没有 Kubernetes 基础设施的团队来使用。一起长大从 2018 年就已经开始通过运用 Infrastructure As Code (IAC) 的方式使用云厂商的 Kubernetes 基础设施,所以云厂商的上述 Serverless 解决方案产品对我们没有太多的帮助和价值。

选择

因为一起长大的业务有着明显的波峰和波谷,我们选择了 Kubernetes Serverless 虚拟节点的方案,阿里云 ECI 就是一种典型 Kubernetes 虚拟节点方案,对已经运行在 Kubernetes 上的服务其实没有实际差异,在高峰期弹性调度到 Serverless 虚拟节点会带来巨大的收益。

Kubernetes Serverless 虚拟节点

虚拟节点并不是真实的节点,而是一种调度能力,它将标准 Kubernetes 集群中的 pod 调度到集群服务器节点之外的资源中。部署在虚拟节点上的 pod 具备一致的安全隔离性、网络隔离性、网络连通性,又具有无需预留资源,按量计费的特性,架构如下图:

2022-06-10-eci.png

成本试算

一起长大所有服务都是容器化部署,业务有着典型的高峰期,且高峰期持续时间不长(6 个小时 / 每天),全部使用包年包月服务器,低峰期负载只有 30% 左右。所以一起长大的场景本身就非常适合 Serverless 的弹性伸缩落地。

做一个简单且粗略的计算:假如全部使用传统节点单位规格时间成本为 C,平均每天高峰期的时间为 6 小时,使用同规格 Serverless 的单位规格时间成本为 1.5C,那么:

  1. 全部使用传统节点的总成本为每天 24C
  2. 保留 60% 的传统服务器,高峰期增加 40% 的 Serverless 来应对,此时的总成本为:24C * 0.6 + 1.5C * 6 * 0.4 = 18C

理论上高峰期波峰部分使用 Serverless 可降低的成本为:(24C - 18C) / 24C = 25%,成本降低的效果是很明显的。

调度、扩容与缩容

使用 Kubernetes Serverless 虚拟节点,调度主要存在两个问题:一是扩容时创建 pod 基于何种调度策略调度到虚拟节点,二是缩容时应优先缩虚拟节点上的 pod。

阿里云支持添加 Annotations 来声明只使用普通节点的资源或者虚拟节点的 ECI 资源,或者在普通节点的资源不足时自动使用 ECI 资源,这已经可以满足大部分场景对弹性资源的需求了。

除了调度到虚拟节点的能力外,我们还配合了 Kubernetes 本身的 hpa 及 cronhpa 同时使用,来满足业务更灵活的需求。

缩容时应优先缩虚拟节点上的 pod,这个是需要修改调度器的调度算法才能实现的。

TODO

扩容:修改调度器,设置阀值,将超过阈值的 pod 调度到虚拟节点上,而不是资源不足的时候才到虚拟节点。这样既能满足集群节点的利用率,也能满足性能的要求。阈值太低可能会造成资源浪费,阈值太高可能造成资源利用率过高,甚至影响业务。

缩容:缩容时优先缩 serverless 虚拟节点上的 pod 很好理解,因为包年包月的节点单价更低,虚拟节点上的资源是按量计费的,单价较高,优先缩虚拟节点上的 pod 可以达到成本的最优。

附图,通过 k9s 工具看到的集群中的传统节点和虚拟节点状态。

2022-06-10-k9s.png