vlambda博客
学习文章列表

读书摘要之十五------Istio服务网格技术解析与实践(上)

    最初接触微服务,是因为项目用到Spring Cloud框架,奇奇怪怪的组件名花好大力气才记住,后来在B站看别人如何用类库写代码,就觉得没啥特别了。            也许,越好的理念,实现起来越不复杂,毕竟前边有那么多聪明人在铺路,就是为后来人方便走吧。

     下边这本书是讲“服务网格”的,对云原生架构的介绍很深入,其中有一句话:“在新技术迭起的今天,我们既要拥抱新技术带来的架构变化,更要加关注其背后的演进逻辑和核心价值,系统化地控制复杂性”,喜欢这种通过演变来介绍技术进化的方式,从学习的角度,也能学到更多内容。


------------分隔线--------------



《Istio服务网格技术解析与实践》-----------王夕宁
现代软件架构的核心任务之一就是定义基础设施与应用的边界,合理切分复杂性,减少应用开发者需要面对的复杂性。换句话说,就是让开发者专注于核心价值创新上,而把一些问题交给更合适的人和系统来解决。
SOA提出了一系列构建分布式系统的原则,这些原则直到今天也依然适用:1)服务具备明确定义的标准化的接口,通过服务定义描述,将服务消费者(consumer)和服务提供者(provider)的实现进行解耦。并且服务应该采用contract-first而非code-first方式进行开发。服务间通信采用面向文档的消息而非特定语言RPC协议,一方面可以解决服务与实现语言的解耦,另一方面可以灵活选择同步或者异步的通信实现,提升系统可用性和可伸缩性。
2)服务应该是松耦合的,服务之间不应存在时间、空间、技术、团队上的依赖。3)服务应该是无状态的,使得服务调用与会话上下文状态实现解耦。4)服务应该是可复用的,业务逻辑切分为一系列可复用服务。5)服务应该是自治和自包含的,服务的实现可以独立进行部署、版本控制、自我管理和恢复。6)服务是可发现、可组合的。比如可以通过Service Registry进行服务发现,实现了服务消费者和服务提供者的动态绑定。业务流程中可以对来自不同系统的的业务服务进行编排组装。在初始构建SOA系统的时候,大多数系统采用点对点的通信连接,服务调用和集成逻辑被内嵌在应用实现中。这种方式在服务数量比较少的时候,确实是一种简单和高效的开发方式。但其最大的问题是,随着服务规模的增长,服务之间通信愈发复杂,连接路径和复杂性会剧增,给服务治理带来巨大的挑战。
为了解决上述挑战,企业服务总线(Enterprise Service Bus,ESB)开始被引入,企业服务总线提供了服务之间的连接、转换以及中介处理的能力。可以将企业内部和各种服务连接到服务总线上,实现信息系统之间的松耦合架构,屏蔽了系统集成的复杂性,提高了IT系统架构的灵活性,降低企业内部信息共享的成本。
任何IT架构的成功,都离不开与业务目标、技术基础和组织能力的相互配合
1)由于过度强调业务系统的可复用性,而不是对企业IT架构的治理和重构。大量服务集成的实现逻辑被下沉到ESB内部,从而导致ESB滥用,这些逻辑非常难以维护,难以移植和扩展,成为ESB不可承受之重。我们必须在合适的地点合理地处理复杂性,而非将其简单转移。2)ESB是基于一个中心化的消息处理系统,随着互联网的高速发展,ESB已经无法应对企业IT规模化成长的挑战。3)ESB这样的“智能管道,哑端点”的系统架构是一个无法适应快速变化和大众创新的架构。
这些系统需要能够应对互联网规模的快速增长,并且能够快速迭代,低成本试错。
微服务的核心思想便是应用功能拆分与解耦,降低业务系统实现复杂性。微服务强调将应用功能拆解为一组松耦合服务,每个服务遵守单一责任原则。微服务架构解决了传统单体式架构存在的几个固有问题:每个服务可以独立部署和交付,大大提升了业务敏捷性;每个服务可以独立横向扩展、收缩,应对互联网规模的挑战
微服务架构继承了SOA的架构原则,但是在实现层面,它倾向于通过构造“智能端点,哑管道”的去中心化分布式架构来替代ESB,把所有的服务治理逻辑包括服务发现、路由、消息解析等放在服务内部,去掉大一统的ESB,服务间通信采用简单的协议,是比SOA更彻底的分布式的、去中心化的架构。
将大型的单体应用拆解为多个微服务,也一定会增加IT系统研发协同、交付、运维的复杂性。随着容器技术的广泛应用,容器已经成为应用分发和交付的标准,可以将应用与底层运行环境解耦;Kubernetes成为资源调度和编排的标准,屏蔽了底层架构的差异性,帮助应用平滑运行在不同的基础设施上,可以帮助应用从数据中心平滑迁移到云端等不同环境。这时候微服务架构与DevOps和容器自然走到了一起,构成了云原生应用架构的雏形。
微服务框架需要能够解决服务通信和服务治理的复杂性,比如服务发现、熔断、限流、全链路追踪等挑战。微服务框架,如HSF、Dubbo或Spring Cloud以代码库的方式来封装这些能力。这些代码库被构建在应用程序本身中,随着应用一起发布和维护,服务通信和治理本质是横向的系统级关注,是与业务逻辑正交的。但在微服务架构中,其实现方式和生命周期与业务逻辑耦合在一起。微服务框架的升级会导致整个服务应用的重新构建和部署。此外由于代码库通常与特定语言所绑定,难以支持企业应用的多语言(polyglot)实现。
微服务架构回归了去中心化的点对点调用方式,在提升敏捷性和可伸缩性的同时,也牺牲了业务逻辑和服务治理逻辑解耦所带来的灵活性
服务网格(service mesh)架构。它重新将服务治理能力下沉到基础设施,在服务的消费者和提供者两侧以独立进程的方式部署。这样既达到了去中心化的目的,保障了系统的可伸缩性;也实现了服务治理和业务逻辑的解耦,二者可以独立演进不相互干扰,提升了整体架构演进的灵活性;同时服务网格架构减少了对业务逻辑的侵入性,降低了多语言支持的复杂性,
Istio的复杂性,一方面来源于其丰富的功能,譬如说它支持多种协议的流量控制,支持多语言,无需修改应用程序的情况下可以支持启用双向TLS认证等等;另一方面则来源于分布式架构的部署、运维本身就很复杂。
托管的服务网格模式可能是一个较为合理的方案。在托管模式下,控制平面的组件被托管,降低用户使用的复杂度,用户只需要专注于数据平面中业务应用的开发部署。同时,仍然保持与Istio的兼容,支持声明式的方式来定义灵活的路由规则,支持多个Kubernetes集群的统一流量管理。
在新技术迭起的今天,我们既要拥抱新技术带来的架构变化,更要加关注其背后的演进逻辑和核心价值,系统化地控制复杂性。
Kubernetes在这个基础基础上,提供了面向容器的自动化管理、运维、编排能力。通过更为优异的架构设计、拓展和集成能力,Kubernetes也快速成为这个领域被用户认可的标准和基石。
云原生技术的出发点是解决运维域的标准化、自动化、云集成化问题,渗透点主要是基于新应用或者新领域的容器技术。
把之前复杂、繁琐的开发流程中的工作,转移到基础设施层自动完成,提高开发人员工作效率,降低人员成本
服务网格是微服务领域在云原生时代的重要发展方向,它在传输层对服务进行统一的管理,确保服务的互通性,提高服务的弹性、可用性,保障通信的安全性与可靠性等
对于分布式应用来说,快速演进主要包含软件架构和工程方法两大内容,前者追求合理的概念切分和松耦合的关系,后者则依赖单元测试、持续集成等工程手段去确保质量。
微服务软件架构并非银弹,在解决发布效率低的同时将复杂度“藏”到了微服务之间。解决好链路跟踪、安全、服务发现、负载均衡、限流等内容都具有相当的挑战,当服务规模变大时尤为如此。
云原生(cloud native)技术的出现尝试着以体系化的方式去解决分布试计算所面临的诸多挑战,其本质是以分层的方式解决分布式应用的弹性、易用性和可移植性。服务网格(service mesh)作为云原生的关键技术,提出以平台思维去探索微服务软件架构的全新解决方案,背后的原则变成了“智能管道,哑端点”。服务网格的核心思路是将框架中易变、与环境相关的内容下沉到平台而使整个应用变轻,借助无缝升级等具体的技术能力实现应用与平台彼此无感独立演进。
Istio使得开发人员能使用自己喜欢的编程语言构建服务功能,这有效提升了开发人员的生产力,同时免于将解决分布式系统问题的代码糅合到业务代码中。
每个服务运行在其独立的进程中,服务和服务之间采用轻量级的通信机制并且相互沟通(通常是基于HTTP的Restful API)。每个服务都围绕着具体的业务进行构建,并且能够被独立地部署到预发布环境或者生产环境等。另外,应尽量避免统一的、集中的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。
微服务是一种小型、可独立部署的且可独立扩展的软件服务,目的是将特定语义功能封装在更大的应用程序中。
最近软件架构的趋势主要围绕如何扩展团队和技术来实现这种敏捷性。云改变了我们消费基础设施的方式,并改变了我们构建应用程序的条件。微服务、DevOps和云服务等技术能带来开发的灵活性
“服务网格”是一个相对较新的术语,用于描述分布式应用程序的网络基础架构,通过它使得应用程序更加安全、更加有弹性,并且可观测性以及灵活可控。服务网格描述了一种由控制平面和数据平面组成的体系架构,其中,数据平面使用应用程序级的代理来管理网络流量,而控制平面用于管理代理。这种架构允许我们在应用程序之外构建这些重要功能,几乎不需要应用程序的干预或太多修改。
Istio的数据平面由基于Envoy代理的服务代理组成,控制平面实现了API来管理和配置这些Envoy代理。服务代理与应用程序一起用于控制服务网络行为。
由于服务代理服务于应用程序之外,因此任何架构的任何应用程序都是服务网格中受欢迎的一等公民
为使用的每种语言或者框架投入大量时间和资源,以便在特定于语言或框架中实现类似的功能,这不应该是最佳的解决方法。我们真正想要的是以一种技术无关的方式来解决这些问题,并减轻特定于应用程序本身来实现。
在微服务环境中,可将单一应用程序分解为独立的多个组件,并作为分布式服务进行部署,这些服务通常是无状态的、短暂的、动态可扩展的,运行在容器编排系统(如Kubernetes)中。服务网格一般由控制平面和数据平面组成。具体来说,控制平面是一组在一个专用的命名空间中运行的服务。这些服务完成一些控制管理的功能,
而数据平面则是由一系列运行在每个服务实例旁边的透明代理构成。这些代理自动处理进出服务的所有流量,因为它们是透明的,所以这些代理充当了一个进程外网络堆栈,向控制平面发送遥测数据并从控制平面接收控制信号。
服务实例可以根据需要进行启动、停止、销毁、重建或替换。因此,这些服务需要一个通信中间件来支持服务的动态发现和自我修复连接能力,从而使得这些服务之间能够以安全、动态和可靠的方式相互通信,这就是服务网格所支持的功能,
服务网格已成为云原生程序的关键组件,它通过包含现代云原生应用程序的复杂服务拓扑来可靠地传递请求。
服务网格是一种网络模型,位于TCP/IP之上的抽象层。它假定底层的三四层网络存在并且能够从一点到另一点传送字节。它还假设该网络与环境的其他方面一样不可靠,因此服务网络也必须能够处理网络故障。在某些方面,服务网格类似于TCP/IP。正如TCP协议栈抽象了在网络端点之间可靠地传递字节的机制一样,服务网格抽象了在服务之间可靠地传递请求的机制。与TCP一样,服务网格不关心实际有效负载或其编码方式,只负责完成从服务A发送到服务B,并且在处理任何故障的同时实现这一目标。但是,与TCP不同的是,服务网格不仅仅具备“使其工作”的能力,还提供了一个统一的应用程序控制点,用于将可见性和控制引入应用程序运行时。服务网格的明确目标是将服务通信从不可见的基础设施领域移出,并转变为生态系统的一部分,可以对其进行监控、管理和控制。
当通过一个服务网格向服务发出请求时,其交互过程可以大致简化为如下步骤(如图1-5所示):1)服务网格组件通过应用动态路由规则来确定请求者想要的服务。
2)找到正确的目的地后,服务网格组件从相关的服务发现端点检索相应的实例池,可能有多个实例。如果这些信息与服务网格组件在实践中观察到的信息不同,那么它会决定要信任哪些信息来源。3)服务网格组件根据各种因素选择最有可能返回快速响应的实例,包括观察到的最近请求的延迟数据。4)服务网格组件尝试将请求发送到选择的实例,记录响应结果的延迟和响应类型。5)如果实例已经由于各种原因宕机,或者请求根本没有响应,或者由于其他任何原因而无法处理请求,服务网格组件则会根据需要在另一个实例上重试该请求,前提是它知道请求是幂等的。6)如果实例始终返回错误,则服务网格组件会将其从负载均衡池中逐出,以便稍后定期重试。
7)如果请求的超时点已过,服务网格组件则会主动使请求失败,而不是通过进一步重试来添加负载,以防雪崩发生。
8)与此同时,服务网格组件以度量指标和分布式跟踪的形式捕获上述行为的各个方面,并将这些数据发送到集中式的度量系统或者链路跟踪系统。
大规模分布式系统(无论如何构建)都有一个明确的特征:任何小型本地化故障都有可能升级为系统范围的灾难性故障。服务网格必须设计成在基础系统接近其极限时通过减少负载和快速失败来防止这些故障升级。
进入云原生时代之后,云原生模型有两个重要因素:容器(例如Docker)提供资源隔离和依赖管理,编排层(例如Kubernetes)将底层硬件抽象为同质的资源池。
尽管这些代码库组件在一定程度上允许应用程序具备一定的负载扩展能力,并处理云环境中始终存在的部分故障,但是,随着数百个服务或数千个实例的增加,以及存在不时重新调度实例的业务流程层,单个请求通过服务拓扑所遵循的路径可能非常复杂。同时随着容器技术的普及,且容器使每个服务都易于用另一种语言编写运行,程序库式方法在此时此刻就变得捉襟见肘了。这种复杂性和关键性的诉求,使得应用越来越需要一个服务间通信的专用层,该专用层与应用程序代码分离并且能够捕获底层环境的高度动态弹性能力。该层就是我们需要的服务网格。
服务代理形成一个网状的数据平面,通过该数据平面处理和观察所有服务间的流量。数据平面负责建立、保护和控制通过网格的流量。负责数据平面如何执行的管理组件称为控制平面。控制平面是网格的大脑,并为网格使用人员提供公开API,以便操纵网络行为。
Istio是一个用于连接/管理以及安全化微服务的开放平台,提供了一种简单的方式用于创建微服务网格,并提供负载均衡、服务间认证以及监控等能力,关键的一点是并不需要修改太多服务就可以实现上述功能。
Istio主要提供以下功能:·流量管理,
·可观测性,
·策略执行,
·服务身份和安全
Istio的数据平面默认使用Envoy代理,开箱即用,
Istio的控制平面由一些组件组成,这些组件为最终用户和运维人员提供运维API、代理的配置API、安全设置、策略声明以及其他更多功能。
通过每个应用程序实例旁边的服务代理,应用程序不再需要具有特定于语言的弹性库来实现熔断、超时、重试、服务发现、负载均衡等功能。此外,服务代理还处理度量标准收集、分布式跟踪和日志收集等。
由于服务网格中的流量流经Istio服务代理,因此Istio在每个应用程序中都有控制点来影响和指导其网络行为。这允许服务运维人员可以控制路由流量,并通过金丝雀部署、暗启动(Dark Launch)、分级滚动和A/B测试来实现细粒度部署。