Service Mesh 初体验

前言
计算机软件技术发展到如今,软件架构的演进无不朝着让开发者可以更加轻松快捷地构建大型复杂应用的方向发展。容器技术最初是为了解决运行环境的不一致问题而产生的,随着不断地发展,围绕容器技术衍生出来愈来愈多的新方向。
最近几年,云计算领域不断地出现不少新的软件架构模式,其中有一些很热门的概念名词如:云原生、函数计算、Serverless、ServiceMesh等等,而本文将初窥一下ServiceMesh的面纱。下面结合本身的理解尽可能以通俗的话进行叙述。
背景和定义
微服务及服务治理
在微服务以前的软件开发中,每每经过一个应用的方式将全部的模块都包括进去,并一块儿编译、打包、部署、运维。这种方式存在不少问题,因为单个应用包含的东西太多,其中某个模块出现问题或者须要更新那么整个应用就须要从新部署。这种方式给开发和运维带来了很大的麻烦。随着应用的逐渐复杂,单个应用涉及的东西就会愈来愈多,慢慢地你们发现了其中不少的缺点,开始对服务进行划分,将一个大的应用按照不一样的维度进行划分从而产生不少个小的应用,各应用之间会造成一个调用关系,每一个小的应用由不一样的开发负责,你们各自部署和运维,这样微服务就出现了。
因为微服务中各应用部署在不一样的机器上,服务之间须要进行通讯和协调,相比单个应用来讲会麻烦不少。在同一个应用内不一样方法之间的调用因为在相同的内存中,在代码编译打包时已经进行了连接,所以调用是可寻址且快速的。微服务下不一样服务之间的调用涉及到不一样进程或者机器之间的通讯,通常须要经过第三方中间件的方式做为中介和协调,因为种种这些,面向微服务出现了不少中间件包括服务治理的框架。经过服务治理工具能够管理其接入的全部应用,使得服务之间的通讯和协调更加简单高效。
容器及容器编排
最初容器技术是为了解决应用运行环境不一致的问题而出现的,避免在本地环境或者测试环境可以跑通,等发到生产环境却出现问题。经过容器将程序及其依赖一块儿打包到镜像中去,将程序的镜像在任何安装并运行了容器软件的机器上启动若干的容器,每一个容器就是应用运行时的实例,这些实例通常拥有彻底相同的运行环境和参数。使得无论在任何机器上应用均可以表现出同样的效果。这给开发、测试、运维带来了极大的便利,再也不须要为不一样机器上构建相同的运行环境而头大。且镜像能够Push到镜像仓库,这使得应用能够进行很方便的迁移和部署。Docker就是一个应用普遍的容器技术。目前愈来愈多的应用以微服务的方式并经过容器进行部署,给了软件开发极大的活力。
与微服务和服务治理的关系相似,愈来愈多的应用经过容器进行部署,使得集群上的容器数量急剧增长,经过人工的管理和运维这些容器已经变得很艰难且低效,为了解决诸多容器及容器之间的关系出现了不少编排工具,容器编排工具可以管理容器的整个生命周期。如Docker官方出的docker-compose和docker swarm,这两个工具能实现批量容器的启动和编排,但功能较为简单,不足以支撑大型的容器集群。Google基于内部大量的容器管理经验,开源出了Kubernetes项目,Kubernetes(K8S)是针对Google集群上每周亿级别的容器而设计的,具备很强大的容器编排能力和丰富的功能。K8S经过定义了不少资源,这些资源以声明式的方式进行建立,能够经过JSON或者YAML文件表示一个资源,K8S支持多种容器,但主流的是Docker容器,K8S提供了容器接入的相关标准,只要容器实现了该标准就能够被K8S所编排。因为K8S的功能较多,不在此一一叙述,有兴趣能够参考官方文档或者ATA上搜索相关文章。
当某个公司的应用已经彻底微服务化后,选择以容器的方式部署应用,此时能够在集群上部署K8S,经过K8S提供的能力进行应用容器的管理,运维能够也能够面向K8S进行工做。因为K8S是目前使用最普遍的容器编排工具,所以成为了容器编排的一个标准了,目前集团内部也有本身的容器和容器编排工具。
面向以K8S为表明的容器管理方式衍生出了一些新的技术。
云原生
最近两年云原生被炒的很火,能够在各处看到不少大佬对云原生的高谈阔论,下面直接抛出CNCF对云原生的定义:
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的表明技术包括容器、服务网格、微服务、不可变基础设施和声明式API。 这些技术可以构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师可以轻松地对系统做出频繁和可预测的重大变动。
在我看来,经过微服务的方式开发应用,以容器进行部署,使用K8S等容器编排工具进行容器集群的管理,使得开发运维都面向K8S,这就是云原生。云原生能够方便的构建应用,并对应用进行完整的监控,以及在应用针对不一样流量时能进行快速的扩容和缩容。以下图:
 
 
云原生主要包括四个部分:
  • 微服务
  • 容器
  • 持续集成和交付
  • DevOps
PS:老是以为云原生这个叫法太抽象了,很难让人经过名字想到这是个啥东西。
ServiceMesh的定义
前面讲了微服务、容器、容器编排、云原生等,其实就是为了得出什么是ServiceMesh,本身总结了一下:SeviceMesh是云原生下的微服务治理方案
当咱们经过微服务的方式将应用以容器的形式部署在K8S上后,服务之间调用和治理其实有新的方案,能够不须要依赖传统的微服务治理框架。ServiceMesh经过对每一个应用在其Pod中启动一个Sidecar(边车)实现对应用的透明代理,全部出入应用的流量都先通过该应用的Sidecar,服务之间的调用转变成了Sidecar之间的调用,服务的治理转变成了对Sidecar的治理。在ServiceMesh中Sidecar是透明的,开发无感知的,以前一直以为奇怪,总以为一个应用要让别人发现它从而调用它,总得引入一些库而后进行主动的服务注册,否则啥都不作,别人咋知道这个应用的存在,为何在ServiceMesh中就能够省去这些,作到对开发者彻底地透明呢?这个的实现依赖于容器编排工具,经过K8S进行应用的持续集成和交付时,在启动应用Pod后,其实已经经过Yaml文件的形式向K8S注册了本身的服务以及声明了服务之间的关系,ServiceMesh经过和K8S进行通讯获取集群上全部的服务信息,经过K8S这个中间者实现了对开发者的透明。以下图所示,是ServiceMesh的一个基本结构,包括数据平面和控制平面。
 
 
这种方式存在不少好处,咱们能够发如今这种模式下应用的语言其实不会对整个服务治理过程有什么影响,对于ServiceMesh来讲,它只关心Pod或者说是Pod中的容器实例,并不须要在意容器中应用的实现语言是啥,Sidecar和其负责的容器在同一个Pod中。这样ServiceMesh就能够实现跨语言,这也是目前不少传统的服务治理框架的一大缺点,并且采用传统的服务治理,须要对应用引入大量的依赖,这样就会形成依赖之间的各类冲突,集团经过Pandora对应用的各类依赖进行隔离。再者传统的服务治理门槛较高,须要开发者对整个架构有必定的了解,且发现问题排查较为麻烦。这也形成了开发和运维之间的界限不清,在ServiceMesh中开发只须要交付代码,运维能够基于K8S去维护整个容器集群。
发展示状
经过目前查阅的资料来看,ServiceMesh一词最先出如今2016年,最近两年被炒的很火,蚂蚁金服已经有了本身的一套完整的ServiceMesh服务框架--SofaMesh,集团不少团队也在进行相应的跟进。
从历史发展的路线来看,程序的开发方式经历了不少的变化,但总的方向是变得愈来愈简单了,如今咱们在集团内进行开发,能够很简单的构建一个支撑较大QPS的服务,这得益于集团的整个技术体系的完整和丰富以及强大的技术积淀。
咱们下面来看看应用开发到底经历了啥?
发展历史
主机直接阶段
 
 
如上图,这一阶段应该是最古老的阶段,两台机器经过网线直接链接,一个应用包含了你能想到的全部的功能,包括两台机器的链接管理,这时尚未网络的概念,毕竟只能和经过网线直接链接在一块儿的机器进行通讯。
网络层的出现
 
 
如上图,随着技术的发展,网络层出现了,机器能够和经过网络链接的其余全部机器进行通讯,再也不限制于必需要网线直连两台机器。
集成到应用程序内部的流量控制
 
 
如上图,因为每一个应用所在环境和机器配置不同,接受流量的能力也不相同,当A应用发送的流量大于了B应用的接受能力时,那么没法接收的数据包一定会被丢弃,这时就须要对流量进行控制,最开始流量的控制须要应用本身去实现,网络层只负责接收应用下发的数据包并进行传输。
流量控制转移到网络层
 
 
如上图,慢慢地你们发应用中的网络流量控制是能够转移到网络层的,因此网络层中的流量控制出现了,我想大概就是指TCP的流量控制吧,这样还能保证可靠的网络通讯。
应用程序的中集成服务发现和断路器
 
 
如上图,开发者经过在本身的代码模块中实现服务发现和断路器。
专门用于服务发现和断路器的软件包/库
 
 
如上图,开发者经过引用第三方依赖去实现服务发现和断路器。
出现了专门用于服务发现和断路器的开源软件
 
 
如上图,基于各类中间件去实现服务发现和断路器。
ServiceMesh出现
 
 
最终到了如今,ServiceMesh大法诞生,进一步解放了生产力,提升了软件整个生命周期的效率。
ServiceMesh市场竞争
虽然直到2017年末,ServiceMesh才开始较大规模被世人了解,这场微服务市场之争也才显现,可是其实ServiceMesh这股微服务的新势力,早在 2016年初就开始萌芽: 2016年1月,离开Twitter的基础设施工程师William Morgan和Oliver Gould,在github上发布了Linkerd 0.0.7版本,业界第一个ServiceMesh项目就此诞生。Linkerd基于Twitter的Finagle开源项目,大量重用了Finagle的类库,可是实现了通用性,成为了业界第一个ServiceMesh项目。而Envoy是第二个ServiceMesh项目,二者的开发时间差很少,在2017年都相继成为CNCF项目。2017年5月24日,Istio 0.1 release版本发布,Google和IBM高调宣讲,社区反响热烈,不少公司在这时就纷纷站队表示支持Istio。Linkerd的风光瞬间被盖过,从意气风发的少年一晚上之间变成过气网红。固然,从产品成熟度上来讲,linkerd做为业界仅有的两个生产级ServiceMesh实现之一,暂时还能够在Istio成熟前继续保持市场。可是,随着Istio的稳步推动和日益成熟,外加第二代ServiceMesh的自然优点,Istio取代第一代的Linkerd只是个时间问题。自从在2016年决定委身于Istio以后,Envoy就开始了一条波澜不惊的平稳发展之路,和Linkerd的跌宕起伏彻底不一样。在功能方面,因为定位在数据平面,所以Envoy无需考虑太多,不少工做在Istio的控制平面完成就好,Envoy今后专心于将数据平面作好,完善各类细节。在市场方面,Envoy和Linkerd性质不一样,不存在生存和发展的战略选择,也没有正面对抗生死大敌的巨大压力。 从Google和IBM联手决定推出Istio开始,Istio就注定永远处于风头浪尖,不管成败,Istio面世以后,赞誉不断,尤为是ServiceMesh技术的爱好者,能够说是为之一振:以新一代ServiceMesh之名横空出世的Istio,对比Linkerd,优点明显。同时产品路线图上有一大堆使人眼花缭乱的功能。假以时日,若是Istio能顺利地完成开发,稳定可靠,那么这会是一个很是美好、值得憧憬的大事件,
 
 
Istio介绍
Istio是目前最热的ServiceMesh开源项目,Istio主要分为两个部分:数据平面和控制平面。Istio实现了云原生下的微服务治理,能实现服务发现,流量控制,监控安全等。Istio经过在一个Pod里启动一个应用和Sidecar方式实现透明代理。Istio是一个拓展性较高的框架,其不只能够支持K8S,还能够支持其余如Mesos等资源调度器。以下图所示,为Istio的总体架构:
 
 
  • 逻辑上分为数据平面(上图中的上半部分)和控制平面(上图中的下半部分)。
  • 数据平面由一组以 Sidecar 方式部署的智能代理(Envoy)组成。这些代理能够调节和控制微服务及 Mixer 之间全部的网络通讯。
  • 控制平面负责管理和配置代理来路由流量。此外控制平面配置 Mixer 以实施策略和收集遥测数据。
  • Pilot是整个架构中的抽象层,将对接K8S等资源调度器的步骤进行抽象并以适配器的形式展示,并和用户以及Sidecar交互。
  • Galley负责资源配置为验证。
  • Citadel用于生成身份,及密钥和证书管理
  • 核心功能包括流量控制、安全控制、可观测性、多平台支持、可定制化。
Mixer
Mixer一样是一个可拓展的模块,其负责遥感数据的采集以及集成了一些后端服务(BAAS),Sidecar会不断向Mixer报告本身的流量状况,Mixer对流量状况进行汇总,以可视化的形式展示,此外Sidecar能够调用Mixer提供的一些后端服务能力,例如鉴权、登陆、日志等等,Mixer经过适配器的方式对接各类后端服务。
 
 
In-process Adapter形式
以前版本的Isito采用这种将后端服务适配器集成在Mixer内部的形式,这种方式会有一个问题,就是某个后端服务适配器出现问题即会影响整个Mixer模块,但因为适配器和Mixer集成在一块儿,在同一个进程内,方法的调用会很快。
 
 
Out-of-process Adapter形式
目前版本的Istio将Adapter移到Mixer外部,这样能够实现Mixer与Adapter的解耦,当Adapter出现问题并不会影响Mixer,但这种方式一样也存在问题,即Adapter在Mixer外,是两个不一样的进程,两者之间的调用是经过RPC的方式,这种方式比同进程内部的方法调用会慢不少,所以性能会受到影响。
Pilot
 
 
  • Envoy API负责和Envoy的通信, 主要是发送服务发现信息和流量控制规则给Envoy。
  • Abstract Model 是 Pilot 定义的服务的抽象模型, 以从特定平台细节中解耦, 为跨平台提供基础。
  • Platform Adapter则是这个抽象模型的实现版本, 用于对接外部的不一样平台如k8s/mesos等。
  • Rules API提供接口给外部调用以管理 Pilot, 包括命令行工具Istioctl以及将来可能出现的第三方管理界面。
Galley
Galley 原来仅负责进行配置验证, 1.1 后升级为整个控制面的配置管理中心, 除了继续提供配置验证功能外, Galley还负责配置的管理和分发, Galley 使用 网格配置协议(Mesh Configuration Protocol) 和其余组件进行配置的交互.
Istio 创造了50多个CRD, 其复杂度可见一斑, 因此有人说面向k8s编程近似于面向yaml编程.早期的Galley 仅仅负责对配置进行运行时验证, Istio 控制面各个组件各自去list/watch 各自关注的配置。愈来愈多且复杂的配置给Istio用户带来了诸多不便, 主要体如今:
  • 配置的缺少统一管理, 组件各自订阅, 缺少统一回滚机制, 配置问题难以定位。
  • 配置可复用度低, 好比在1.1以前, 每一个Mixer adpater 就须要定义个新的CRD。
  • 配置的隔离, ACL 控制, 一致性, 抽象程度, 序列化等等问题都还不太使人满意
随着Istio功能的演进, 可预见的Istio CRD数量还会继续增长, 社区计划将Galley 强化为Istio配置控制层, Galley 除了继续提供配置验证功能外, 还将提供配置管理流水线, 包括输入, 转换, 分发, 以及适合Istio控制面的配置分发协议(MCP)。
Citadel
将服务拆分为微服务以后,在带来各类好处的同时,在安全方面也带来了比单体时代更多的需求,毕竟不一样功能模块之间的调用方式从原来单体架构中的方法调用变成了微服务之间的远程调用:
  • 加密:为了避免泄露信息,为了抵御中间人攻击,须要对服务间通信进行加密。
  • 访问控制:不是每一个服务都允许被任意访问,所以须要提供灵活的访问控制,如双向 TLS 和细粒度的访问策略。
  • 审计:若是须要审核系统中哪些用户作了什么,则须要提供审计功能。
Citadel 是 Istio 中负责安全性的组件,可是 Citadel 须要和其余多个组件配合才能完成工做:
  • Citadel:用于密钥管理和证书管理,下发到Envoy等负责通信转发的组件。
  • Envoy:使用从Citadel下发而来的密钥和证书,实现服务间通信的安全,注意在应用和Envoy之间是走Localhost,一般不用加密。
  • Pilot:将受权策略和安全命名信息分发给Envoy。
  • Mixer:负责管理受权,完成审计等。
Istio支持的安全类功能有:
  • 流量加密:加密服务间的通信流量。
  • 身份认证:经过内置身份和凭证管理能够提供强大的服务间和最终用户身份验证,包括传输身份认证和来源身份认证,支持双向TLS。
  • 受权和鉴权:提供基于角色的访问控制(RBAC),提供命名空间级别,服务级别和方法级别的访问控制。
做者信息:彭家浩,花名毅忻,阿里巴巴淘系技术部开发工程师,热爱云计算。
 
 
 
本文为云栖社区原创内容,未经容许不得转载
相关文章
相关标签/搜索