SpringCloud 应用在 Kubernetes 上的最佳实践 —— 高可用(弹性伸缩)

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
可观测可视化 Grafana 版,10个用户账号 1个月
性能测试 PTS,5000VUM额度
简介: 关于如何用好弹性伸缩,一直是用户非常关心的问题,本文尝试围绕这个话题,给出一些相关的思考和优化实践。有两种实现弹性伸缩方法,一种是“垂直弹性”,即“Scale Up”,另一种是“水平弹性”,也就是“Scale Out”。

929头图.png

作者 | 三未

前言

弹性伸缩是一种为了满足业务需求、保证服务质量、平衡服务成本的重要应用管理策略。弹性伸缩让应用的部署规模能够根据实时的业务量产生动态调整,在业务高峰期扩大部署规模,保证服务不被业务冲垮;在业务低谷期缩减部署规模,避免资源浪费。

由于大部分云资源是按需取用,按量计费模式,相比使用 IDC,使用云的用户从弹性伸缩获得的成本优势是非常明显的,弹性伸缩也是大多数云上用户的选择。而关于如何用好弹性伸缩,一直是用户非常关心的问题,本文尝试围绕这个话题,给出一些相关的思考和优化实践。

有两种实现弹性伸缩方法,一种是“垂直弹性”,即“Scale Up”,另一种是“水平弹性”,也就是“Scale Out”。

1. 垂直弹性伸缩

垂直弹性伸缩一般是指通过升降服务器的规格来实现的弹性伸缩。这种伸缩方式对应用本身几乎没有约束,可以被大部分应用或组件使用,它的问题主要在两个方面:

  • 动态调整服务器的规格而不影响上层部署的应用,对基础设施要求比较高,对于许多云厂商而言是个难题,并不能实现业务完全无感的动态变配;
  • 垂直弹性无法突破单台物理设备的规格限制,面向巨量的突发业务增长,垂直弹性的应对能力是有上限的。

2. 水平弹性伸缩

而水平弹性伸缩恰恰相反,它依靠增减服务器的数量来实现弹性伸缩,对基础设施的要求不高,水平弹性除了可以解决容量上限的问题,多副本部署还能带来更高的可靠性,因为被广泛的使用在生产系统中,很多时候水平弹性也成了弹性伸缩的代名词,所以我们后文的讲述的主要也是水平弹性。

微服务与弹性伸缩

水平弹性虽然存在诸多优势,但它对于应用本身的要求相比垂直弹性是更高的,开发者在使用前需要要考虑好以下的问题:

  • 多副本部署要求应用本身无状态化,如何抽离应用中的状态信息并保持配置同步?
  • 弹性伸缩导致应用实例本身是不稳定的,如何保证应用实例之间能实现可靠的相互调用?

这些恰好也是微服务架构要解决的问题,而 SpringCloud 作为广泛使用的微服务框架自然不例外,拿问题对号入座的来看:

  • 其一,通过 SpringCloud,开发者可以将原先单体应用中无状态的部分拆解出来,以服务的形式来组织业务逻辑,无状态的服务本身是可以进行水平伸缩的,另外 SpringCloud 提供了很易用的集中式配置管理能力,确保了配置信息可以被高效的分发和同步;
  • 其二,SpringCloud 的服务注册和发现机制,使得服务可以动态的增加或移除实例,通过熔断等服务治理机制可以进一步提升远程调用的可靠性。

换个角度看,催生微服务的驱动力之一,就是开发者希望利用云的弹性伸缩能力来实现运营成本和服务质量的平衡,因此微服务从设计上就考虑到了要利用弹性伸缩的能力,它们之间是本来就是相辅相成,紧密相关的。

原生的弹性伸缩

应用架构支持只是使用弹性伸缩的必要条件之一,想用好弹性伸缩,另外还有两个关键点需要考虑:在什么时机触发弹性伸缩,以及弹性伸缩产生出来的应用如何部署,即规则触发实例调度

在云原生的体系中,K8s 控制了应用的生命周期管理,在弹性规则触发与实例调度方面,K8s 也提供了相关的能力,足够完成应用弹性伸缩的整个过程。

K8s 中,无状态应用通常以 Deployment 的形式进行部署,弹性伸缩过程由 Horizontal Pod Autoscaler(HPA)来进行控制,开发者设定 CPU 或内存的目标使用率与 Deployment 的副本数区间,由 HPA 负责定时从监控数据中计算并设定目标的副本数,至于实例的调度过程则交由 K8s 的 Scheduler 来控制。

参考:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ 

1.png

如何优化弹性伸缩?

看起来借助 K8s 的 HPA 机制就可以很轻易的给微服务应用提供弹性伸缩能力,但这样真的就足够了吗?没有那么简单,在弹性伸缩上,目前 SpringCloud 和 K8s 的默认机制仍然存在诸多不足,如果缺少完备而健壮的方案,将其直接用于生产系统,其实是很容易踩坑的。怎么做才能保证弹性伸缩精准到位,过程如丝般顺滑,这是我们写作本文,提供最佳实践的意义。

EDAS 作为一站式的分布式应用管理平台,对于弹性伸缩这样涉及应用监、管、控全方位的场景,在对弹性伸缩的支持上做了系统的设计,打磨出许多功能点,目的是为用户使用弹性伸缩的“减负”,使其能真正落地到用户生产系统中。

顺着刚提到的两个关键点,规则触发与实例调度,我们来看 EDAS 在优化弹性伸缩方面是如何思考与实现的。

1. 规则触发

常用的弹性伸缩规则是基于监控数据来进行触发的,K8s 也自带了基于 CPU 和内存监控来触发弹性伸缩的功能。但仅有这两种指标并不够,相比基础监控数据,应用指标数据对于业务量的反馈更为直接和敏感,可以说是适合弹性伸缩参考的“黄金指标”。

但由于 K8s 无法获取到应用的监控信息,这些信息只能通过自定义扩展 API 的方式来实现,对于用户来说,需要理解 K8s 的扩展机制,有一定的学习成本;而且,基于监控数据的规则无法实现实例数从 0 到 1 的扩容,这也不利于实现极致的成本控制。

1)KEDA

针对这些痛点,开源社区发展了很多项目,其中最为典型的是 KEDA(Kubernetes Event-driven Autoscaling),通过事件流来辅助 K8s 进行弹性伸缩,架构如下:

2.png

KEDA 项目地址:https://keda.sh/

KEDA 可以被方便地安装到任意的 K8s 集群,它的 Controller(Operator)提供了将应用从 0 副本扩缩的能力,KEDA 也提供了监控指标服务,通过不同的 Scaler 来对接各种开源与供应商的监控指标,并将这些指标提供给 HPA 控制器,来完成多副本的弹性伸缩。

2)EDAS 的应用弹性策略

KEDA 的功能很强大,但对于一般用户而言使用的门槛比较高,为了解决这一问题,EDAS 结合 ARMS 提供的应用监控能力,在保留 KEDA 核心功能同时对其做了增强,使得弹性的规则配置更为易用。

EDAS 的弹性伸缩既支持 K8s 原生的 HPA 规则的配置能力:

3.png

还能使用应用黄金指标,如服务每秒请求量(QPS)和平均响应时间(RT):

4.png

此外,EDAS 不仅支持指标弹性,还支持定时弹性,通过为不同时段设置合理的副本数区间,定时弹性能最大程度的保证用户体验:

5.png

2. 实例调度

弹性伸缩的规则触发将产生实例调度的请求,但如何将这些请求分配到节点,并在节点部署应用实例,调度是必经的流程,也是 K8s 的核心能力。对于弹性伸缩这一场景,由于涉及大量新实例创建和旧实例的替换,实例调度的动作非常频繁,首先选择合适的调度策略就非常重要。

1)调度策略

K8s 提供了丰富配置项供开发者设定调度策略,比如节点选择,节点亲和,污点和容忍等。但如何搭配所需的调度规则并没有放之四海而皆准的做法,需要根据业务实际情况来进行制定,这里列举一些设置调度规则时,常见的考虑:

  • 弹性伸缩发生时系统往往处于比较繁忙状态,尽可能将新增实例发布到不同节点,可以有效避免集群压力分布不均带来的服务质量受损或资源浪费;
  • 将节点分开并均衡部署到多个可用区能有效提升系统的可用性;
  • 对于具有密切关联性的应用实例,可以考虑部署到同样的节点或可用区,可以减少调用开销,提升稳定性。

对于第 3 点,仅靠调整调度规则还不够,还要依赖微服务治理的能力,使得关联实例能完成就近的服务路由,这也是 EDAS 正在解决的问题之一,而对同应用分节点或者可用区部署 EDAS 已经提供了直接的支持,用户只需要部署时勾选即可:

6.png

弹性伸缩时另一个常见的问题是集群节点资源被用尽,因为 K8s 不会主动扩展节点,此时即使弹性伸缩产生了准确的调度请求,K8s 也无法分配出新的应用实例。考虑到这种可能性,这要求用户预留一部分节点资源以应对弹性的需求,但由于资源池的存在,导致用户付出的成本并非是完全的按用量计费,这又与弹性伸缩的初衷相悖,我们不禁会想,怎么做能让节点资源既能物尽其用又能取之不竭?

2)Cluster AutoScaler

社区的 Cluster AutoScaler 项目提供了集群节点的自动扩缩,一定程度上解决了资源的按需申请问题,各容器服务提供商也提供了对应的 Cluster AutoScaler 实现,阿里云也不例外,在 ACK 的管控台可以直接配置集群的自动伸缩:

7.png

但 Cluster AutoScaler 也有其不足的地方,比如:

  • 首先,Cluster AutoScaler 是在产生了无法满足的实例调度请求之后才开始介入的,而购买新实例的时间比较长(可能在分钟级),远大于 Pod 的启动时间,这等于降低了弹性伸缩的灵敏度,增加了服务受损的风险;
  • 其次,在缩容时,由于应用实例是随机释放的,因此会产生一些遗留的应用实例分散在不同节点上,变成碎片,Cluster AutoScaler 在缩容节点前会尝试迁移这些实例,需要消耗时间甚至引发稳定性问题,也不利于成本控制。

3)Serverless Kubernetes

问题的根本还是出在调度上,K8s 需要匹配实例与节点,在这个过程中有太多的复杂度需要用户去考虑和处理。那是否消除掉 K8s 集群的节点,去掉调度的过程,就是通往极致的弹性的方向?答案是肯定的,而且阿里云的 Serverless Kubernetes 服务(ASK)在这个方向上提供了一条现成的途径。

使用 ASK 服务,用户不用关心节点资源是否充足,应用实例秒级调度,按量计费,完美的契合了弹性伸缩的需求:

8.png

EDAS 也支持了 ASK 集群的接管,用户可以直接在 EDAS 创建 Serverless 应用,就能得到“彻底”的弹性伸缩能力:

9.png

结语

本文介绍了微服务应用在云原生体系下的弹性伸缩的用法,并尝试从弹性伸缩的两个关键点来探讨优化的方向和做法,以及 EDAS 是如何看待并解决这些问题的。

弹性伸缩包含了应用生命周期的整个过程,这过程中就涉及到多项应用管理能力的联动,举个例子,如应用实例缩容时如何进行节点的无损下线,这在弹性伸缩过程中就是非常重要的功能,类似的场景非常多,受限于篇幅,本文不做展开。

对于 EDAS 来说,弹性伸缩就是一场综合的能力测验,只有在每个环节都做到位,才能更好的用户业务保驾护航。而我们也相信 EDAS 通过与云原生技术和云产品的全面融合,能带给用户更佳的体验,助用户“躺着”用好弹性伸缩,享受到云的福利。

相关文章推荐:

课程推荐

去年,CNCF 与 阿里云联合发布了《云原生技术公开课》已经成为了 Kubernetes 开发者的一门“必修课”。

今天,阿里云再次集结多位具有丰富云原生实践经验的技术专家,正式推出《云原生技术实践公开课》。课程内容由浅入深,专注讲解“ 落地实践”。还为学习者打造了真实、可操作的实验场景,方便验证学习成果,也为之后的实践应用打下坚实基础。点击链接查看课程:https://developer.aliyun.com/learning/roadmap/cloudnative2020

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
5天前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
|
15天前
|
Kubernetes 监控 Cloud Native
云原生入门:从传统应用到容器化部署的旅程
【9月更文挑战第19天】在数字化浪潮中,企业正迅速将目光投向云原生技术,以实现更快的应用开发和更灵活的资源管理。本文将通过一个简单示例引导读者理解如何将传统应用转变为云原生应用,并部署至云端。我们将探索容器化技术的基础,以及它如何帮助企业解锁现代软件交付的速度和效率。准备好让你的应用乘上云原生的快车了吗?让我们开始这段令人兴奋的旅程吧!
|
1月前
|
Kubernetes 负载均衡 前端开发
二进制部署Kubernetes 1.23.15版本高可用集群实战
使用二进制文件部署Kubernetes 1.23.15版本高可用集群的详细教程,涵盖了从环境准备到网络插件部署的完整流程。
53 2
二进制部署Kubernetes 1.23.15版本高可用集群实战
|
17天前
|
Kubernetes Cloud Native Linux
云原生入门:Kubernetes的简易部署与应用
【8月更文挑战第49天】在云原生的世界里,Kubernetes(K8s)是一颗璀璨的星。本文将带你走进K8s的世界,从安装到简单应用,轻松驾驭这个强大的容器编排工具。让我们一起探索云原生的奥秘,解锁新技能!
|
22天前
|
Kubernetes Docker 微服务
构建高效的微服务架构:基于Docker和Kubernetes的最佳实践
在现代软件开发中,微服务架构因其灵活性和可扩展性而受到广泛青睐。本文探讨了如何利用Docker和Kubernetes来构建高效的微服务架构。我们将深入分析Docker容器的优势、Kubernetes的编排能力,以及它们如何结合实现高可用性、自动扩展和持续部署。通过具体的最佳实践和实际案例,读者将能够理解如何优化微服务的管理和部署过程,从而提高开发效率和系统稳定性。
|
28天前
|
Kubernetes Docker Python
如何在K8s中使用Python应用
一文带你了解如何在K8s中使用Python应用
21 4
|
1月前
|
Kubernetes 负载均衡 应用服务中间件
kubeadm快速构建K8S1.28.1高可用集群
关于如何使用kubeadm快速构建Kubernetes 1.28.1高可用集群的详细教程。
49 2
|
16天前
|
Kubernetes Cloud Native Java
探索未来编程新纪元:Quarkus带你秒建高性能Kubernetes原生Java应用,云原生时代的技术狂欢!
Quarkus 是专为 Kubernetes 设计的全栈云原生 Java 框架,凭借其轻量级、快速启动及高效执行特性,在 Java 社区脱颖而出。通过编译时优化与原生镜像支持,Quarkus 提升了应用性能,同时保持了 Java 的熟悉度与灵活性。本文将指导你从创建项目、编写 REST 控制器到构建与部署 Kubernetes 原生镜像的全过程,让你快速上手 Quarkus,体验高效开发与部署的乐趣。
15 0
|
2月前
|
Kubernetes Cloud Native Linux
云原生入门:Kubernetes的简易部署与应用
【8月更文挑战第31天】在云原生的世界里,Kubernetes(K8s)是一颗璀璨的星。本文将带你走进K8s的世界,从安装到简单应用,轻松驾驭这个强大的容器编排工具。让我们一起探索云原生的奥秘,解锁新技能!
|
2月前
|
容器 Kubernetes Docker
云原生JSF:在Kubernetes的星辰大海中,让JSF应用乘风破浪!
【8月更文挑战第31天】在本指南中,您将学会如何在Kubernetes上部署JavaServer Faces (JSF)应用,享受容器化带来的灵活性与可扩展性。文章详细介绍了从构建Docker镜像到配置Kubernetes部署全流程,涵盖Dockerfile编写、Kubernetes资源配置及应用验证。通过这些步骤,您的JSF应用将充分利用Kubernetes的优势,实现自动化管理和高效运行,开启Java Web开发的新篇章。
46 0

相关产品

  • 容器服务Kubernetes版
  • 下一篇
    无影云桌面