在云原生架构下,中间件管理方式和传统方式有较大差别。首先在 K8s 上如何管理中间件集群,其次云原生架构将运维能力下沉,如何高效利用云原生能力并实现中间件跨可用区高可用?在 10 月 18-19 日举办的 QCon 全球软件开发大会上,网易云信资深架构师裴明明为我们带来了精彩的专题演讲“云原生架构下中间件联邦高可用架构实践”,重点介绍了网易云信基于 K8s 的集群联邦能力实现中间件有状态应用跨可用区高可用的最佳实践,分享了网易云信在 K8s 中管理中间件遇到的难题和解决方案,并且会分享最终的落地效果和上云收益。 内容亮点利用云原生技术栈实现中间件集群的自动化管理,提升集群管理运维效率和自愈能力,增加中间件集群的弹性。利用 K8s 的集群联邦能力实现中间件这类有状态应用的跨可用高可用。以下是演讲实录(经 InfoQ 进行不改变原意的编辑整理)。本次演讲我与大家探讨的主题是“云原生架构下中间件联邦高可用架构实践”。首先,我会简要介绍中间件在云原生平台上的运维管理方式。接着,我们将深入探讨在云原生环境下实现中间件高可用性的实践方法。特别是联邦高可用性,这是中间件高可用性中的一个特殊场景。整个讨论将分为四个部分。概述云原生中间件的基本概念。探讨云原生中间件的管理策略,以寻求最佳实践。介绍如何在云原生架构中实现中间件的跨可用区高可用性,这是技术领域的一个热点话题。展望未来,探讨云原生中间件的发展方向。
云原生中间件
在传统的架构中,部署中间件可能需要编写大量脚本和应用管理,以确保其健康运行和故障恢复。例如,我们可能需要使用特定的命令或系统服务来重启失败的服务。如果需要更高级的健康检查和状态管理,传统架构下这些工作可能会变得相当复杂。在云原生架构中,这些任务变得简单许多。通过利用 Kubernetes(K8S)等技术,我们可以更容易地实现服务的自动恢复、健康检测和优雅退出。云原生架构的核心在于将应用层的运维特性与底层基础设施的运维能力分离,并将它们整合到一个中间层,从而封装运维的复杂性,让专业人员来处理。云原生生态主要包括几个部分:首先是容器技术,如 Kubernetes 和 Docker;其次是微服务领域的技术,如 Istio 和 HELM 等;此外,还有 Karmada 和 Operator Framework,这些技术共同构成了云原生生态的基础,使得我们可以更高效地部署和管理中间件,同时保持系统的高可用性和灵活性。
中间件的发展经历了几个阶段。最初,人们接触中间件时,通常是通过开源社区获取相关的软件包和部署方法,这是实现中间件的最基础方式。虽然这种方法能够实现中间件的基本功能,但其复杂度高,使用起来并不方便。随后,许多厂商开始提供基于虚拟机的中间件解决方案,这种方式已经能够满足大多数人的需求。用户可以通过图形界面轻松创建中间件集群,例如 Redis 等。这种模式虽然方便,但也存在一些弊端,比如数据安全性无法得到保证,以及对于特定功能的定制需求难以在短时间内得到满足。现在,随着云原生技术的发展,中间件的实现方式也在发生变化。我们更倾向于在云原生环境中,以私有化的方式交付中间件。这种方式能够充分利用云原生的运维特性,快速实现基础能力的部署,同时保证了资源的低消耗,提高了中间件的灵活性和安全性。云原生中间件的实现依赖于 Kubernetes 的核心特性。这些特性包括:声明式定义,基础设施即代码,标准统一,易于编排;构建于标准 Kubernetes 之上,利用其灵活调度、故障自愈、弹性伸缩等内置能力简化中间件的运维;自动化管控,资源统一调度,有效提升资源利用率,降低基础设施成本;更适合构建私有化部署的 PaaS 中间件服务。
云原生中间件管理
云原生中间件的管理涉及到将中间件有效地部署到云环境中,并确保其高效运行。实现这一目标,我们可以利用 K8S 提供的 operator 和相关能力。通过简单的命令如 kubectl apply,我们可以迅速在 K8S 集群中拉起容器,实现中间件的基本功能,至少在访问层面没有问题。然而,在实际使用过程中,我们会遇到一系列挑战。首先,K8S 的 Pod 网络是隔离的,我们需要考虑如何优雅地从外部访问这些中间件服务。由于中间件对流量和网络有依赖,网络配置变得尤为重要。此外,中间件通常是资源密集型的,比如对磁盘 IO 性能有高要求,我们需要考虑 K8S 提供的存储解决方案是否合适。在中间件部署到 K8S 之后,我们还需要确保其稳定性。这包括可观测性的建设,虽然 Prometheus 提供了基于 exporter 的监控采集框架,但我们还需要进一步强化监控能力,丰富监控指标。同时,我们要考虑中间件在云环境中是否能保持原有的特性,比如在主机或虚拟机上运行得很好的中间件,迁移到云后是否还能保持这些特性。另一个问题是中间件的发现机制。在传统的物理主机或虚拟机环境中,中间件可能基于 IP 进行服务发现,但在云环境中,IP 可能会变化,这就需要我们找到新的解决方案来处理这种变化。
网易云信云原生中间件实践
这是网易云信在云原生中间件基础架构图。我们基于 K8s 构建了一个支持各种类型的底层架构,无论是来自不同厂商的解决方案,我们都能在此基础上进行扩展。第二层是我们自研的云原生基础平台,它能够屏蔽多云、多集群和多版本的复杂性,方便管理底层资源。这一层支持节点亲和性、节点分配等特性,并提供一致的 API,使得用户可以从多个集群中聚合资源。在此之上是我们的中间件层,主要基于 API 和 Operator 实现。我们还提供了独特的 API 层来管理 Operator 的特性和自定义 CRD。中间件的种类相对集中,包括 Redis、Kafka、Nginx 等。我们内部已经部署了几十种中间件,依据其使用频率进行分类。在使用中间件时,我们也面临一些挑战,特别是如何满足企业级特性。为此,我们与平台集成,增强了审计、监控告警和日志采集等功能。最上层是网络层的管理,我们提供了基础的负载均衡(LB)、Nodeport 等解决方案,以确保访问的稳定性和可靠性。
高性能与高可靠
在将中间件迁移到云端并确保其高性能的过程中,我们面临几个关键挑战,包括网络瓶颈和磁盘管理。网络性能对吞吐量和响应时间有着直接影响。为了实现高效的网络,我们采用了多种策略。由于 K8S 的 Pod 网络默认是隔离的,集群外访问会多进行一次转发,影响性能。通常情况下,我们采用基于 BGP 的网络协议实现负载均衡,这样可以分散流量并减少转发跳数。此外,我们还基于 NodePort 提供了一种基础能力,即使在没有 BGP 支持的情况下,也能实现外部访问,通过 Operator 将节点 IP 暴露给用户,直接将流量路由到目标节点。磁盘管理对于依赖磁盘 IO 性能的中间件至关重要。我们发现本地磁盘更为可靠,并自研了一套基于 Linux 磁盘管理的系统,实现磁盘的动态管理,并与 PV 和 PVC 结合使用,快速完成生命周期管理。同时,我们还支持独占盘和共享盘,以满足不同业务需求。中间件容器化功能适配和优化也是我们关注的重点。我们对不适应云环境的中间件进行了优化,如服务发现适配 K8S 等。内核调优也是一个关键领域,我们通过软中断、CPU 绑定和网卡 IO 优化等措施,确保容器化中间件的性能至少不会低于主机或虚拟机上的性能。中间件的配置管理,将我们的经验和最佳实践整合到平台中,帮助用户快速部署和设置高性能中间件集群。
云原生中间件高可靠,我总结了两个方面:高可用和可观测。中间件高可用单中间件集群通过节点反亲和、拓扑分区调度实现节点的互斥;提供中间件实时备份和一键恢复能力;云原生生态的集群热备多活,实现故障自动检测,自动转移,快速切流;基于 Kubernetes 集群联邦的同城多机房高可用。云原生可观测增强Prometheus 技术体系建设的中间件监控告警系统;云原生日志自动化采集组件 Loggie (网易云信开源),对中间件集群进行无侵入日志采集;基于云原生事件建立中间件事件管理能力,实现事件监控告警;中间件运维中心,提供风险巡检、根因分析、自主诊断等能力,增强运维能力,提升集群稳定性。
运维自动化
云原生中间件的运维自动化主要依赖于 Operator 模式,其核心功能是监控中间件的状态,并在状态发生变化或出现问题时,迅速执行 Operator 中预设的逻辑来恢复服务。此外,我们还结合了 K8S 的监控和自动伸缩能力,实现了自动化伸缩,包括水平自动伸缩(HPA)等技术。在无状态服务的情况下,自动伸缩相对简单,只需增加副本数量即可。在有状态的服务中,自动伸缩就变得复杂得多,需要特别的处理。我们内部有一套实践方案,基于时间的 HPA 是一个比较可靠的方法。弹性伸缩在实际应用中较为困难,尤其是在有状态的服务中。此外,我们还在探索 Serverless 化中间件,这也是基于自动化伸缩的能力来实现的。通过这些自动化运维的实践,我们能够提高中间件的可用性和弹性,同时降低人工干预。
中间件上云确实带来了许多优势,但同时也伴随着一些挑战。如果能够妥善解决这些难点,我们不仅能够获得技术上的优势,还能构建起一个统一的能力平台,这将极大地方便未来的扩展。因此,我们坚信云原生技术是未来的发展方向。我们一直在内部以及与客户合作中推进云原生技术,并不断地进行优化和改进。这包括提升通用能力、高阶特性和统一运维等方面,我们持续不断地进行这些方面的工作,以期达到更好的效果。同时,我们也将自己的一些经验和成果,比如 Loggie 等项目,开源出来,与大家分享我们在这一领域的实践和探索。
中间件跨可用区高可用
实现中间件跨可用区的高可用性是一个复杂的问题,尤其是在需要多机房容灾能力的情况下。以 Elasticsearch(ES)为例,如果我们的业务架构设计得很好,业务本身是无状态的,而所有的状态和特性都依赖于中间件层,那么我们就需要确保在一个机房宕机时,ES 和业务都不受影响。面对这样的挑战,我们首先会考虑 ES 原生提供的能力,比如跨可用区数据同步的 CCR(Cross Cluster Replication)。但是,我们发现这种能力有限制,并且不是开源的。在深入研究 ES 的代码后,我们考虑是否可以基于 Translog 实现数据同步。但 Translog 的生命周期管理与我们的需求不符,因为它是一个快速的生命周期,使用后就会被删除。在探索了一圈之后,我们发现要实现 ES 的数据同步,可能需要修改内核,没有现成的好方案。这时,我们转而考虑另一种方案:既然 ES 已经有了主从同步的能力,为什么不将中间件部署在多个机房中呢?这样,即使一个机房出现问题,其他机房的 ES 实例仍然可以继续工作,保证业务的连续性。这种方法也是我们在传统架构中实现高可用性的基础能力。总结而言,如何实现中间件跨多个可用区的高可用性。最基本的方法是实现多个集群之间的数据同步。数据同步实现后,我们就可以进一步考虑流量切换的问题,这直接影响到整个解决方案的稳定性和可靠性。我们的构建方案如下:中间件集群高可用方式:多集群数据同步单集群跨可用区多集群数据同步:热备、双活、多活等高可用能力单集群跨可用区:联邦多活,依赖中间件自身高可用多数选主的分布式一致性协议:要求至少三个可用区来保证任意可用区故障中间件依然可用对底层基础设施要求较高:不同可用区集群节点间的网络连通性和网络质量要求
中间件集群联邦的问题与挑战
在云原生环境中使用集群联邦的方式部署有状态服务面临着一系列问题和挑战。首先,有状态服务的部署并不容易,因为这些服务之间存在着紧密的联系。例如,在进行有序的滚动更新时,服务实例之间的依赖关系使得状态管理变得复杂。以最简单的状态集(如 0、1、2、3)为例,它们的服务发现和数据关系都是相互关联的,这就要求我们在管理状态时必须非常谨慎。其次,中间件的联邦调度也是一个重要挑战。当中间件分布在多个 K8S 集群中时,我们需要考虑如何合理地分配节点和分片。合理的调度不仅能确保资源的有效利用,还能在节点宕机或进行滚动升级时,最小化变动带来的影响。最后,故障恢复能力同样至关重要。在一个由三个可用区组成的 K8S 集群中,如果其中一个集群出现故障,我们需要确保系统能够快速恢复。如果多个集群都出现问题,我们的体系是否能有效处理这些故障场景?这就是在设计联邦高可用性时必须考虑的关键因素。
云原生下跨可用区高可用
在业内,跨可用区高可用性的解决方案备受关注。我们很早就开始关注社区,并研究了许多开源项目是如何实现联邦高可用性的。其中,Federation 2.0 是社区早期开源的一个项目,而目前比较出名的是 Karmada,我们与这个项目有很多合作,并为社区做出了贡献。Karmada 是基于联邦高可用性理念自主研发的系统,它对中间件联邦高可用性提供了支持。然而 Karmada 本身有一些局限性,比如部署时需要依赖额外的 ETCD 集群和 API Server,所以我们在它的基础上做了许多优化和改进。例如,我们对有状态服务的状态聚合进行了优化;优化架构使得 Karmada 可以直接部署在管控的 K8S 集群中。此外,我们还实现了对 Kubernetes API Server 的直接兼容,并提供了面向用户的查询接口。在状态聚合、spec 下发以及 annotation 管理等方面,我们做了很多特殊处理,以适应中间件的下发和状态聚合,从而实现中间件跨可用区的部署。
中间件集群联邦实现
中间件的联邦高可用性实现是一个复杂的架构设计。在我们的设计中,至少需要五个 K8S 集群来实现联邦高可用性。这包括一个主管控集群和一个备用管控集群,以及三个计算集群。我们认为至少需要三个可用区来实现最佳的高可用能力。具体实现时,我们的架构包括三个计算集群和两个管控集群。在联邦调度组件方面,我们有联邦控制器和联邦分发组件,还有负责跨集群的流量治理组件,确保所有集群之间能够顺畅通信,并对外提供服务。同时,主备管控集群在中间件的生命周期管理和故障恢复能力方面也扮演着关键角色,它们依赖管控面的 Operator 进行统一调度。此外,我们还实现了跨集群选主高可用性能力。在发生故障时,系统能够自动进行故障恢复,确保服务的连续性和数据的一致性。
有状态服务联邦管控
状态服务的联邦管控是一个复杂的过程,涉及到资源的创建、分发和状态管理。当创建一个中间件资源时,首先需要在管控层面进行创建,然后通过我们的分发组件将资源分发到不同的可用区。这个过程会根据创建的拓扑结构来决定资源如何分配到各个可用区,比如将 20 个节点分布在 5 个可用区中。一旦确定了拓扑结构,资源就会被下发到各个子集群。子集群的控制器接收到资源后,就会根据这些信息来管理中间件在本集群中的形态和拓扑结构。子控制器只需要关注自己集群内的状态,并将其写入状态信息中即可。联邦控制器会进一步聚合这些状态信息,从而了解整个联邦集群的状态。接下来,联邦控制器会根据集群的组网情况和节点关系,告诉子控制器整个集群的配置和节点发现应该如何设置,以及下一步的状态应该是什么样子。整个过程是一个渐进式的交付流程,涉及到管控和计算之间的协作。通过几轮的迭代,服务最终会达到一致状态,实现集群的成功交付。此外,这个流程还确保了集群具备自愈能力,能够在出现问题时自动恢复,确保服务的高可用性。
有状态服务联邦调度算法
有状态服务的联邦调度算法的实现涉及几个关键方面。首先,在新建集群时,需要计算集群的初始状态和调度策略,决定资源如何在多个集群中分布,以及每个集群内的拓扑结构。其次,在执行滚动操作,如扩缩容或更新时,需要重新计算拓扑结构的变化,以确定最佳的资源分布。最后,在故障迁移时,需要确定如何处理故障转移,例如一个集群故障后无法恢复,或者需要将集群数量从三个扩展到五个。了应对这些场景,我们总结了如下核心规则。半数约束:部署中间件节点和 K8S 集群分布规则,约束任意 K8S 集群中节点数不超过半数,要求节点在 K8s 集群中尽可能均分。扩容约束:中间件集群扩缩容时,算法应该在满足上述约束的情况下,确保调度算法一致性,存量节点不会重新调度。故障 约束:集群故障时,中间件角色相对集中,会打破上述规则。故障恢复时,应重新满足上述约束。除了这些核心规则,还有许多细节逻辑,比如考虑节点资源是否满足需求,以及每个节点的资源是否能够支持最优化的调度。联邦调度算法与 K8S 的调度类似,但特点是所有调度都是上下文相关的,不能单独对一个节点进行调度,这增加了调度的复杂度。一旦调度算法计算出整个拓扑结构,结果会存储在相应的自定义资源(CR)中,并通知控制器继续下发拓扑。这样,控制器就知道如何根据计算出的拓扑结构进行下一步操作,确保有状态服务的联邦调度算法能够有效地管理和优化资源分布。
集群联邦网络管理
集群联邦网络管理的核心挑战在于处理不同可用区中的节点网络连通性问题。由于这些节点的网络本身可能不连通,或者相互之间难以发现,我们需要确保 Pod 网络是通畅的。然而当 Pod IP 发生变化时,服务发现就变得复杂,通常需要依赖域名来实现。为了解决这个问题,我们设计了一些方案。其中较为可靠的方案之一是利用 External DNS 服务器,通过改写 DNS 的能力,让我们的注册组件能够监控所有 Service 和 EP 的变更,并将对应的 DNS 解析信息更新到所有自建的 DNS 服务器中。这样,在 CoreDNS 进行域名解析请求时,能够转发到我们的外部 DNS 服务器进行解析,这是一个实现相对复杂的设计方案。此外,我们还有些更简化或轻量级的方法。例如,我们可以直接在 EP 中通过 Operator 监控对端资源的列表变化。一旦获取变化,我们在自己的集群中创建一个 EP,并将对应的 Hostname 和 IP 填入,从而实现在这个集群内部的访问。这种方法减少了对外部 DNS 服务器的依赖,简化了网络管理流程。
联邦组件高可用
联邦组件的高可用性对于整个联邦集群的稳定运行至关重要。我们需要确保联邦组件能够在计算集群或管控集群中的任何一个集群发生故障时,依然保持正常运行。为此,我们实现了管控集群的主备高可用方案,这个方案相对简单,基于分布式选举算法,类似于 Keepalived 的能力,通过分配不同的优先级值来确定哪个节点能够成为 leader。在启动时,如果发现数据不一致,我们会阻止服务恢复,以保证数据的一致性,尽管这可能会牺牲一些可用性。在网易云信的实践中,我们已经在许多中间件上实现了联邦高可用。其中,Redis 是一个相对复杂的案例,因为它不仅涉及拓扑结构,还包括分片、主从分片等。如果一个可用区发生故障,Redis 的分片需要重新分配,这可能导致不均衡。在集群恢复后,我们需要 operator 介入,重新调整以达到均衡状态,因为虽然节点数是均衡的,但角色分配可能不均衡,这增加了实现的复杂性。其他中间件,如 Elasticsearch 也会面临一些复杂性,对集群节点间通讯方式和证书管理要求较高;而 ZooKeeper 则因为配置方式对暴露 IP 的要求较高,但是相对来说是一个更简单的案例。通过这些实践,我们不断优化联邦组件的高可用性,以确保在各种故障情况下,联邦集群都能保持稳定运行。
未来展望
我们计划在云原生领域进一步利用其底座能力,以实现持续迭代、稳定提升和降本增效。我们将持续在云原生建设上投入,利用云原生的可观测性来完善我们的服务,同时在 FinOps 方面,我们在内部已经有所实践,并产生效果。云原生中间件的运维与人工智能的结合也是我们的核心方向。我们的目标是从故障发现到故障消除,实现根因分析和故障恢复的自动化。我们的探索从神经网络算法开始,已经积累了丰富的经验,尤其是在小型模型的应用上已经取得了良好的效果。现在,我们正在探索大型模型,并基于智能体技术进行分析能力和故障恢复的开发提升。我们希望将来能够借助人工智能技术,进一步提升中间件的稳定性,使云原生中间件的发展更加稳健。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。