Service Mesh:探索分布式系统的幻觉与未来
在现代的微服务架构中,应用程序网络是实现微服务之间分布式通信的关键。无论是在单个 Kubernetes 集群中部署还是跨多个集群和不同基础设施环境中部署,都需要建立一个强大的应用程序网络,让微服务能够相互交流。这种通信不仅需要高效可靠,还需要具备适应各种逆境的韧性。
除了建立应用程序网络,我们还需要监控微服务之间的通信,即可观察性(observability)。在微服务通信中,可观察性非常重要,可以了解微服务之间的相互作用方式。此外,微服务之间的通信也需要安全保护,通信应当进行加密,防止中间人攻击。每个微服务应具有身份标识,并能够证明其与其他微服务之间的授权通信。
那么,为什么需要服务网格(Service Mesh)呢?为什么这些需求不能在 Kubernetes 中满足?答案在于 Kubernetes 的架构和设计目标。正如之前提到的,Kubernetes 是应用程序生命周期管理软件,它提供了基本级别的应用程序网络、可观察性和安全性支持,但无法满足现代动态微服务架构的需求。这并不意味着 Kubernetes 不是现代化的软件,它确实是一项非常先进和前沿的技术,但它主要用于容器编排。
在 Kubernetes 中,流量管理由 Kubernetes 网络代理(kube-proxy)负责。kube-proxy 在每个节点上运行,并与 Kubernetes API 服务器通信,获取关于 Kubernetes 服务的信息。Kubernetes 服务是一种将一组 Pod 作为网络服务公开的抽象层。kube-proxy 通过设置 iptables 规则,定义了如何将流量路由到对应的端点(实际上是承载应用程序的底层 Pod)。
这就是服务网格发挥作用的地方。服务网格通过提供高级流量管理、可观察性和安全性功能,弥补了 Kubernetes 的不足。服务网格位于应用程序层,并与微服务并行工作,拦截和管理它们之间的通信。借助服务网格,您可以实现细粒度的流量控制、收集丰富的遥测数据以实现可观察性,并强制实施微服务之间的安全通信。
服务网格,例如 Istio、FloMesh、和 Linkerd,与 Kubernetes 紧密集成,并增强其功能,以满足现代微服务架构的要求。通过采用服务网格,组织可以实现微服务部署的增强韧性、可观察性和安全性。
服务网格技术填补了 Kubernetes 在微服务架构中先进的应用程序网络、可观察性和安全性方面的不足。它提供了一个强大且灵活的基础设施层,与 Kubernetes 互补,使组织能够构建和运行具备韧性和安全性的分布式系统。通过采用服务网格,组织可以实现微服务部署的增强韧性、可观察性和安全性。
当设计分布式应用程序时,软件开发人员经常会犯一些错误的假设,这些假设被称为"分布式系统的谬论"(Fallacies of a distributed system)。这些谬论最初由 L Peter Deutsch 和其他 Sun Microsystems 的工程师提出,并被广泛接受。它们揭示了关于分布式系统性质和挑战的常见误解。下面是这些谬论的总结:
1. 网络是可靠的:这个假设认为网络始终可用且没有故障。然而,在现实中,网络可能会出现中断、故障或间歇性的连接问题。
2. 延迟为零:这个谬论假设网络传输数据时没有延迟。然而,在实际情况下,网络延迟受到距离、拥塞和处理时间等因素的影响,会有不同程度的延迟。
3. 带宽是无限的:这个假设认为网络传输的数据量没有限制。然而,在现实中,网络带宽是有限的,会存在拥塞和性能降低的情况。
4. 网络是安全的:这个谬论认为网络本身是安全的,能够防止未经授权的访问或数据泄漏。实际上,网络需要强大的安全措施来确保机密性、完整性和可用性。
5. 拓扑结构不会改变:这个假设认为网络的结构和配置在时间上保持静态不变。然而,网络是动态的,节点可能加入、离开或改变连接,应用程序需要对此进行适应。
6. 只有一个管理员:这个谬论认为单个实体对整个网络具有完全的控制和管理权。实际上,分布式系统通常涉及多个管理员,他们拥有不同的控制权和责任。
7. 传输成本为零:这个假设认为在网络中传输数据没有任何成本。然而,在现实中,网络基础设施、带宽使用等因素都会带来成本。
8. 网络是同质的:这个谬论认为网络的各个组件具有相同的特性和统一的行为。实际上,网络可能由不同类型的设备、操作系统、协议和能力组成。
微服务架构中,团队可能使用不同的编程语言和技术栈来开发微服务。这导致了多语言和多技术栈的挑战,需要找到一种统一的方式来协调不同语言的微服务之间的通信和交互。这涉及到如何选择合适的通信协议、数据格式以及寻找跨语言的解决方案。
传统的服务治理解决方案可能需要对现有的微服务代码进行侵入性的修改或添加额外的依赖库,以实现服务发现、负载均衡、故障转移等功能。这样的侵入性可能增加了开发团队的工作量,并且可能引入不必要的复杂性和风险。
在大规模微服务架构中,可能存在大量的微服务实例需要进行服务治理。在传统的方式下,每个微服务都需要重复构建和维护自己的服务发现、负载均衡、故障转移等功能,导致了重复建设的问题。这不仅浪费了开发资源,还增加了系统的复杂性和维护成本。
当微服务通过共享的 SDK 进行通信时,不同微服务可能使用不同版本的 SDK。这导致了 SDK 版本碎片化的问题,可能会导致兼容性和一致性方面的挑战。当需要更新 SDK 版本或解决 SDK 中的漏洞时,需要协调和管理各个微服务的 SDK 版本,这增加了额外的复杂性和风险。
在分布式系统中,微服务可能部署在不同的机房或地域中。在进行跨机房或跨地域的调度时,需要考虑网络延迟、带宽限制等因素,以确保微服务之间的通信效率和质量。这需要一种灵活而智能的调度策略,能够根据实际情况进行动态的负载均衡和故障转移。
Service Mesh 提供了一系列的功能来增强微服务的扩展性。这包括熔断、限流、超时控制、灰度发布和故障注入等机制,以确保微服务在面对高负载、异常情况或部分故障时能够保持稳定和可靠。Service Mesh 支持多种通信协议,如 HTTP、gRPC、Dubbo、Thrift 等,使得这些功能可以适用于不同类型的微服务。
Service Mesh 提供了强大的连接管理功能,确保微服务之间的连通性。它通过服务发现和负载均衡机制,使得微服务能够自动发现和定位其他微服务,并能够实现跨不同语言和技术栈的通信。Service Mesh 还提供了智能路由和流量控制功能,以便在微服务之间实现灵活的流量转发和负载均衡策略。
Service Mesh 关注微服务架构的性能和资源管理。它通过优化网络通信、请求处理和数据传输等方面的性能,提高微服务的响应速度和吞吐量。同时,Service Mesh 还提供了对微服务的监控、追踪和日志记录功能,以便进行性能分析、故障排查和容量规划等任务。通过对资源的细粒度管理和调控,Service Mesh 可以有效地提高微服务架构的资源利用率和效率。
Service Mesh 设计了一套简洁易用的接口和控制平面,使得开发人员和运维人员可以轻松地配置、管理和监控微服务。它提供了可视化的管理界面和命令行工具,简化了配置和部署的流程。同时,Service Mesh 还支持自动化的服务注册和发现,减轻了手动管理的负担。通过这些易用性的特点,Service Mesh 提供了一种简单而高效的方式来管理和维护微服务架构。
Istio 和 FloMesh 都使用了 sidecar 模型,它们具有这些优点:解耦服务逻辑和网络治理、统一的通信层、动态的网络治理、安全性和可观测性增强、无侵入性。
但是在使用的同时也增加了一些损耗,具体可以从下面的示例图中看出:sidecar 模型在服务之间进行通讯的时候有三个 connection 需要维护。
Istio 固有地支持诸如断路、速率限制、超时控制、金丝雀部署和故障注入等机制。一旦正确安装了 Istio,这些特性就可以开箱即用了。而 FloMesh 采取了不同的方法。它提供了一个基于 JavaScript 的可扩展性模型,允许开发人员根据他们的具体需求定制和扩展这些功能。通过编写 JavaScript 代码,FloMesh 实现了对这些机制的细粒度控制,给予开发人员更多的灵活性,并使其能够根据自己的独特需求进行调整。
在 Istio 和 FloMesh 之间的选择应该基于你的具体需求和优先事项。Istio 提供了具有广泛内置特性的健壮和成熟的服务网格解决方案,而 FloMesh 为那些寻求对其服务网格功能进行细粒度控制的人提供了更可定制的方法。考虑诸如易用性、开发灵活性。
看看下面的图或许就能够理解了设计的区别:
采用 WebAssembly (Wasm) sidecar 形式相对于传统的 sidecar 具有以下优势:
跨平台兼容性:Wasm 是一种可移植的二进制格式,可以在不同的操作系统和架构上运行。使用 Wasm sidecar 可以轻松实现跨平台部署,而无需担心依赖于特定环境的问题。
轻量高效:Wasm 代码通常比传统的 sidecar 容器更小、更轻量,因为它是一种二进制指令格式。这使得 Wasm sidecar 在启动时间和资源消耗方面表现更加高效,提供更快的响应和更低的延迟。
安全性:Wasm 提供了一种沙箱环境,在其中运行代码可以被有效地隔离和限制。使用 Wasm sidecar 可以增加安全性,因为它可以将应用程序与主机环境隔离开来,防止恶意代码的影响。
可扩展性:由于 Wasm 的灵活性,可以使用多种编程语言编写 Wasm 模块,而不仅仅局限于特定的编程语言或框架。这使得开发人员能够选择最适合他们需求的语言和工具,并提供更大的灵活性和可扩展性。
通过采用每个节点的代理模型,我们能够摆脱其中一个代理的需求,因为我们不再依赖于在每个工作负载内运行一个附属容器。这种转变带来了 ambient mesh 相对于 sidecar 模型的几个显著优势。
首先,使用 ambient mesh,我们可以减少运行在每个工作负载内的附属容器数量,从而减轻了系统的负担和复杂性。
其次,ambient mesh 不再依赖于每个工作负载的 sidecar 容器,这意味着我们不再需要为每个工作负载额外的连接。虽然仍然需要一些额外的连接,但这比始终需要两个额外连接要好得多。
最重要的是,ambient mesh 提供了更灵活的部署选项。由于不再需要在每个工作负载内运行附属容器,我们可以更轻松地将应用程序部署到不同的环境中,而无需过多的修改。
在每个工作负载中运行附属容器会导致大量的代理实例,即使每个代理实例的内存占用已经进行了优化,但实例数量的增加仍会对整体系统造成重大影响。此外,每个代理还要维护诸如路由和终端点表等数据结构,随着集群规模的增长,这些数据结构也会增加,导致每个代理所消耗的内存随着集群规模的扩大而增加。为了解决这个问题,一些服务网格尝试将部分路由表推送到各个代理中,以限制它们的路由范围。
eBPF 是一种灵活的内核扩展框架,它允许在内核空间中执行自定义的网络过滤和处理逻辑。相比于运行在用户空间的附属容器,eBPF 的运行开销更低,因为它直接在内核中执行,避免了用户态和内核态之间的频繁切换。
采用 eBPF 而不使用附属容器具有轻量高效、低延迟、强大的可编程性、节省系统资源以及简化部署和管理的优势。这使得 eBPF 成为一种强大的工具,在现代网络环境中实现高性能和灵活的网络处理和功能成为可能。
微服务架构中的应用程序网络是实现微服务之间分布式通信的关键。为了建立高效可靠的通信,需要具备适应各种逆境的韧性。此外,可观察性和安全性也是微服务通信中的重要方面。
服务网格位于应用程序层,与微服务并行工作,拦截和管理微服务之间的通信。它能实现细粒度的流量控制、收集丰富的遥测数据以实现可观察性,并强制实施微服务之间的安全通信。一些常见的服务网格技术包括 Istio、FloMesh 和 Linkerd,它们与 Kubernetes 紧密集成,增强其功能,满足现代微服务架构的要求。
陈章朝,政采云有限公司运维开发工程师,一个热爱生活的编程爱好者,热于参与开源社区共建以及分享知识。
点击底部阅读原文访问 InfoQ 官网,获取更多精彩内容!
对话贾扬清、关涛、张伯翰:AI 平民化趋势下,数据架构将被彻底颠覆?
对话开源泰斗陆首群教授:中国开源发展应追求0到1的爆发性创新,而不是0到0的假创新
离职员工窃取源代码,半年狂赚1.5 亿;美团“1元现金”火速收购光年之外;53岁周鸿祎清华读博:重新学习做一个工程师|Q 资讯
微信扫码关注该文公众号作者