一、微服务及服务治理
在微服务之前的软件开发中,往往通过一个应用的方式将所有的模块都包括进去,并一起编译、打包、部署、运维。这种方式存在很多问题,由于单个应用包含的东西太多,其中某个模块出现问题或者需要更新那么整个应用就需要重新部署。这种方式给开发和运维带来了很大的麻烦。随着应用的逐渐复杂,单个应用涉及的东西就会越来越多,慢慢地大家发现了其中很多的缺点,开始对服务进行划分,将一个大的应用按照不同的维度进行划分从而产生很多个小的应用,各应用之间会形成一个调用关系,每个小的应用由不同的开发负责,大家各自部署和运维,这样微服务就出现了。
由于微服务中各应用部署在不同的机器上,服务之间需要进行通信和协调,相比单个应用来说会麻烦很多。在同一个应用内不同方法之间的调用由于在相同的内存中,在代码编译打包时已经进行了链接,因此调用是可寻址且快速的。微服务下不同服务之间的调用涉及到不同进程或者机器之间的通信,一般需要通过第三方中间件的方式作为中介和协调,由于种种这些,面向微服务出现了很多中间件包括服务治理的框架。通过服务治理工具可以管理其接入的所有应用,使得服务之间的通信和协调更加简单高效。
二、容器及容器编排
最初容器技术是为了解决应用运行环境不一致的问题而出现的,避免在本地环境或者测试环境能够跑通,等发到生产环境却出现问题。通过容器将程序及其依赖一起打包到镜像中去,将程序的镜像在任何安装并运行了容器软件的机器上启动若干的容器,每个容器就是应用运行时的实例,这些实例一般拥有完全相同的运行环境和参数。使得不管在任何机器上应用都可以表现出一样的效果。这给开发、测试、运维带来了极大的便利,不再需要为不同机器上构建相同的运行环境而头大。且镜像可以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,这就是云原生。云原生可以方便的构建应用,并对应用进行完整的监控,以及在应用针对不同流量时能进行快速的扩容和缩容。
云原生主要包括四个部分:微服务、容器、持续集成和交付
四、ServiceMesh的定义
前面讲了微服务、容器、容器编排、云原生等,其实就是为了得出什么是ServiceMesh,自己总结了一下:SeviceMesh是云原生下的微服务治理方案。
当我们通过微服务的方式将应用以容器的形式部署在K8S上后,服务之间调用和治理其实有新的方案,可以不需要依赖传统的微服务治理框架。ServiceMesh通过对每个应用在其Pod中启动一个Sidecar(边车)实现对应用的透明代理,所有出入应用的流量都先经过该应用的Sidecar,服务之间的调用转变成了Sidecar之间的调用,服务的治理转变成了对Sidecar的治理。
在ServiceMesh中Sidecar是透明的,开发无感知的,之前一直觉得奇怪,总觉得一个应用要让别人发现它从而调用它,总得引入一些库然后进行主动的服务注册,不然啥都不做,别人咋知道这个应用的存在,为什么在ServiceMesh中就可以省去这些,做到对开发者完全地透明呢?这个的实现依赖于容器编排工具,通过K8S进行应用的持续集成和交付时,在启动应用Pod后,其实已经通过Yaml文件的形式向K8S注册了自己的服务以及声明了服务之间的关系,ServiceMesh通过和K8S进行通信获取集群上所有的服务信息,通过K8S这个中间者实现了对开发者的透明。
这种方式存在很多好处,我们可以发现在这种模式下应用的语言其实不会对整个服务治理过程有什么影响,对于ServiceMesh来说,它只关心Pod或者说是Pod中的容器实例,并不需要在乎容器中应用的实现语言是啥,Sidecar和其负责的容器在同一个Pod中。这样ServiceMesh就可以实现跨语言,这也是目前很多传统的服务治理框架的一大缺点,而且采用传统的服务治理,需要对应用引入大量的依赖,这样就会造成依赖之间的各种冲突,集团通过Pandora对应用的各种依赖进行隔离。再者传统的服务治理门槛较高,需要开发者对整个架构有一定的了解,且发现问题排查较为麻烦。这也造成了开发和运维之间的界限不清,在ServiceMesh中开发只需要交付代码,运维可以基于K8S去维护整个容器集群。