• 云原生领域的一些技术展望


    云原生的由来

    云原生(Cloud Native)的概念最早出现于2010年,Paul Fremantle的一篇博客中提出“云原生”应用应该具有的一些特性。其中包括:分布式、动态插拔、弹性、多租户、自服务、精确计量及计费、增量部署和测试。后来,Pivotal的Matt Stine于2013年在其推特上推广云原生的概念。但彼时虽然云原生的意义很丰富,其概念并不清晰,直到CNCF(云原生计算基金会)对其进行了重新定义。

    阅读CNCF对云原生的定义,我们大致可以这样理解云原生:以容器、服务网格、微服务、不可变基础设施和声明式API为代表的,有助于各组织在公有云、私有云等动态环境中构建可弹性扩展应用的技术体系。其中不可变基础设施我这里解释一下,即对于应用依赖的基础设施或者环境,如果不符合要求,那么我们不是去修改它,而是整体部署或者启动一整个新的。那么具体的有代表性的云原生技术有哪些呢?这里例举一下常见的。基础容器编排及环境的kubernets、minikube、kind等,分布式强一致性数据库etcd,消息队列nats、pulsar、kafka等,监控告警prometheus、datadog等,服务网格istio、linkerd等,无服务架构knative、openfaas等这些都是。cncf致力于云原生技术的普及和可持续发展,该社区维护了大量相关项目,如果对这些技术体系感兴趣可以看一下cncf的项目全景图

    本篇文章主要想跟大家聊聊云原生环境下架构相关的一些技术体系,接下来我们来看一些跟架构关系较大的paas平台项目、微服务框架、中间件相关的项目或者趋势。

    paas平台

    kubernets向上对应用程序暴露基础设施能力的数据抽象并提供编排能力,向下提供基础设施能力接入的标准接口,管理着物理机、虚拟机、网络带宽、存储资源等;可以看做是云原生时代的操作系统内核。为什么说是内核而不是操作系统呢,因为从使用的角度来看paas平台更像是一个操作系统的角色,而k8s则是各家发行版操作系统共同依赖的内核。据cncf2021年四月底进行的2020中国云原生调查,在生产环境中使用kubernets的比例已经达到惊人的82%。这说明kubernets已经成为容器编排领域的事实标准。如果对技术发展趋势有兴趣,这个调查报告非常值得一看。

    各家企业应用也都有基于kubernets构建的paas平台去满足企业内部的容器编排、多云管理等需求。其中可能大家比较熟悉的开源项目有rancher、kubeSphere、openshift等。他们都是基于kubernets去实现,继承且扩展了kubernets的能力。我们来看一下rancherkubesphere他们的系统架构:

    虽然二者图示的侧重点不同,rancher更多的在描述整体宏观的架构,而kubesphere则更侧重于表达涵盖了哪些能力。过我们仍然可以看出他们的模式是类似的:构建一个中心的管理service,下面链接多个k8s集群,在此基础上再逐步的扩展出丰富的特性,比如cicd、弹性伸缩、监控告警等。目前大多数的企业也都是这么做的,这么做对于企业内的业务研发同学来说,屏蔽掉了内部kubernets、cicd、持久化等系统的复杂度,加速了研发过程,促进了企业业务迭代速度。

    对于企业来说,这么做可以满足需求,当然是没什么问题的。但是如果我们把视角提升到整个技术领域、技术社区,则可以发现一些能够做的更好的地方。首先是扩展性,基于以上的模式开构建paas平台,每当我们想要新引入一个功能特性,都需要一些开发工作,如果要集成到现有的平台中,或者权限系统等,可能工作量并不小。这样就不利于引入或者快速试错社区的工具或者平台等,也就限制了paas平台功能的丰富程度。另外是不同平台入口的统一性,举个例子,假如自家企业的软件基础设施建设的比较全面,既有paas平台又有servless平台,还有一个任务平台。那么业务研发的同学要上线不同种类的应用时,是不是要到不同的平台中去发布或者管理呢,当然有可能负责平台项目的同学把他们集成到同一个项目中了,但大概率还是在不同的模块中。这样还是会让整体的技术体系变得比较复杂。

    其实如果都是基于kubernets实现的,那么这些不同的服务、任务、functions到了实际运行的时候很可能都是kubernets中的一个pod,对于kubernets来说都是工作负载,只不过其类型不同。这样的话,我们可不可以再做一层上层抽象,给这些不同的工作负载提供一个统一的入口呢?kubevela项目正是这样做的。kubevela通过定义统一的组件(component)和特征(trait)来抽象。组件可以根据类型的不同,具体渲染成不同的kubernets工作负载资源,比如说deployment、job、pod等。而特征也是按照类别区分,特征可以渲染成类似ingress、hpa、sidcar等工作负载的附加属性。那么从用户定义的组件,到底层渲染的deployment(假定它是deployment类型)这一步是如何实现的呢?这一步是由平台维护人员定义一个WorkloadDefinition来描述特定类型的组件渲染为何种资源类型,及如何去渲染。由于kubernets都是声明式api的设计,而声明可以被文本描述,所以这种渲染其实都是文本间的转化,WorkloadDefinition定义的其实也是一个文本的转化规则。有了文本、余下的生成具体资源类型的实现工作kubevela就可以比较容易的完成了。

    这样的话,它就会有另一个优点:会很容易的扩展社区新的工具或者平台。比如说在vela项目中引入argo的功能应该怎么做呢?首先在集群中安装argo,其次由平台维护者定义出argo-workflow的WorkloadDefinition,然后用户就可以愉快的使用了。在使用组件的时候就声明负载类型为argo-workflow的的类型即可。当然了,全部功能资源类型的统一化管理并不好做,可能一些特殊功能的管理还是需要做兼容性处理,甚至是单独的管理模块。最后我们来看一下kubevela的架构,如下图:

    可以看到中上层是它的组件和特征处理层,中间是一些kubevela的controller,负责把用户定义的组件和特征渲染为具体的资源类型等功能。下层左侧是边缘计算和物联网支持、中间是多个云环境的支持、右侧则是可以集成其他工具或者平台的功能到kubevela中。

    kubevela有一些下一代paas平台的感觉,其开发人员也是这么说的。但是它的优势是否足以取代现有的paas平台构建模式还是个未知数。

    service mesh 与 mesh

    在久远的以前,计算机与计算机之间通信是需要程序开发者自己实现通信协议的。也即是说现在的网络协议栈中的一部分以前是在程序开发者的代码中实现并维护的,后来随着计算机的增多,慢慢出现了统一的标准协议,对应的实现也下沉到操作系统层面了。再后来随着软件规模的膨胀、软件架构的演进,出现了soa(面向服务的架构)、微服务、service messh(服务网格)这样的架构设计。由单体应用程序逐步到service mesh的设计,也类似于网络协议的下沉,把服务发现、流量控制、依赖控制等下沉到一个跟程序自身分离的较小的服务(sidecar)中。对这个演进过程感兴趣的同学可以浏览下这篇service mesh设计模式

    istio是开源service mesh框架中被采用率最高的项目之一,据cncf的调查,目前已有至少38%的单位在生产环境中使用service mesh,42%的单位在评估中。可见service mesh的设计模式已经得到了市场的验证。我们来看一下istio的架构,如下图:

    istio

    图中,control plane为一个控制面板,中心化的服务;envoy proxy则为服务发现、流量控制等逻辑所在之处,每个服务都会存在一个与之对应、为之服务的envoy实例。其中控制面板服务为istiod,其中包含galley、pilot、citadel等模块,分别管理配置及其验证、配置下发、安全策略等功能。关于istio还有一个值得玩味的小故事,istio的控制面板曾经是一个有多个组件的分布式应用,现在istiod中的模块多为不同的独立部署的组件。那么为什么合并为单体应用了呢?“复杂是万恶之源,停止焦虑,学会爱上单体”istio开发团队是这么说的。直白的说,这是他们做的一个取舍:为了易用性、性能放弃了更为解耦、健壮的架构。由此可见、做架构抉择时不可盲目的选择看起来“高大上”的,适合的才是最好的,当鱼与熊掌不可兼得的时候,找出我们更看重的方面,做出取舍。

    与service mesh十分相似还有一个database mesh 的概念。顾名思义,database mesh即是把存储能力也网格化。业界已有相关的案例实践(规划中),我们来看一下Sharding-JDBC的的mesh化设计,如下图:

    图中的下方,是一个管理平台,类似于istio的控制面板;上方则是我们的服务节点,其中有service mesh的sidecar、database mesh的sidecar;中间则是数据库集群和一个注册中心。与service mesh不同的是,下方的server也会是一个流量入口,因为数据库存在许多需要人工管理的场景,而人工管理是没有sidecar可用的。

    那么,除了database的mesh化设计,还有其他的服务于程序的能力可以mesh化吗?我们来看一下微软的微服务框架dapr的设计,其说明图示如下:

    图中,最上层指明支持很多种语言;最下层指明支持很多云环境。中间层则说明了dapr可以提供哪些能力,其中包括服务间访问、状态管理、发布订阅、资源绑定和触发器等等。而dapr提供这些能力,也是以sidecar的方式提示共的(也提供了sdk方式)。如此一来,dapr的服务间访问能力是不是和service mesh有些许相似了。而其于sidecar中提供状态管理、发布订阅消息队列等能力,也可以看做是更多基础能力下沉到sidecar中的一个类似于service mesh设计的架构演进。service mesh的定位是针对流量的治理,而dapr则是各种分布式应用所需能力的聚合;dapr的设计可以看做是service mesh的扩展和延伸。

    我们可以结合蚂蚁金服基于mosn的应用运行时框架和dapr一起来看看这个方向的软件设计的架构演进。mosn在2018最初也是service mesh的形式,在2019年则逐步的加入了message mesh和database mesh,并在当年支持了618促销活动。可以看到mosn从service mesh到multi mesh再到云原生运行时(或者也可以叫做all mesh?)的一个演进过程。dapr其实也称自己为一个运行时,它跟mosn的最终形态还是十分相似的。我们来看一下mosn的架构图,可以将两者对比一下:

    我个人还有另外一个思路:以node节点守护进程的方式提供中间件的服务,再将其映射到容器内。这样考虑到pod漂移,可能会需要会引入另外一些的同步数据的复杂度。但是有的场景还是很适合这样的设计的。比如这样一个使用database的场景,企业内部不同的业务线使用不同的机器节点资源池,一个业务线内的服务使用相同的一批账号。此时如果以守护进程的方式提供database的服务,既有database mesh的优点,又避免了database mesh可能带来的连接数过多的问题。此外,日志收集服务天生适合这个场景,因为日志收集在不同的服务间没有差异性,不需要考虑pod漂移的问题。

    综上,虽然目前只有service mesh有一定的市场采用率,但是service mesh才仅仅是一个开始。mesh模式是云原生领域的关键技术,消息队列、database、cache、servless等的mesh化已是可见的趋势。以sidecar或者守护进程来提供服务,应该是中间件技术提供服务的未来形态。

    低代码

    低代码是一种方便产生应用程序的平台型软件及开发环境,这个软件会开发环境让用户以图形化接口以及配置编写程序,而不是用传统的程序设计方法。为什么提到这个呢?如果低代码开发被推广开来,之前一些需要专业开发人员开发的软件可以由非软件开发专业人士来完成,比如说图书管理系统、报销流程审批系统等等,这会让更多的人成为应用开发者,甚至如阿里云开发者所说:“人人都是开发者”。微软已经在这个领域做了大量的布局,阿里更是已经在这个领域取得了一定的成果、有了一定的用户量。阿里内部,使用宜搭搭建的月活应用达3000多个,每天活跃在这些应用的用户已达10w的量级。钉钉上现在已经有宜搭的入口,打开之后可以看到已经有约80个应用模板。据2021年五月底举办的阿里云开发者大会,有一名乡村数学老师,花费了2000多的费用,开发了43款低代码应用,让整个校园基本实现了数字化。

    由此可见低代码也是一个软件开发分化的方向,越来越多的非专业人员会成为开发者,越来越多的软件实现过程逐渐的不需要专业的开发人员来完成。但目前来看,低代码开发可能更擅长于数据采集、数据统计、流程审批这些功能相对简单的系统。所以,影响也不会特别的大。

    云上开发vs本地开发

    在线开发环境(online-ide,也叫做云开发环境)是指部署在远端服务器的开发环境,用户在浏览器上就可以使用ide进行软件开发。在线开发环境可以跟测试环境更好的契合,微服务场景下这个优点会更加突出些。但云端开发环境使用体验上要比本地开发环境差不少,且大多模式单一不灵活(至少我的体验如此),比如只能用一种ide、无法配合shell使用等。也许你还没太注意到它的存在,不过很多公有云已经提供了云端开发环境,比如华为云、腾讯云、AWS、Azure等。开源的在线开发环境也有不少,其中也有高达8k、10k收藏数的项目。但是从我个人的日常工作、同事们和同学们之间的交流来看,在线开发环境的普及率还是相当低的。但是随着faas(Functions as a Service)的发展,可能会给在线开发环境带来一个契机。轻量级的functions,开发起来不需要太复杂的操作,直接在云端迅速开发、发布,这样的体验就比较不错。现有的openfaas项目也确实提供了一个简单的在线编辑代码的环境。个人觉得faas即使发展良好,给在线开发环境的发展带来的促进作用也有限。如此,在线开发环境何时会有大的发展机会呢?可能会很久远,直到在线开发环境的体验优于本地环境、用户的成本又低于本地环境。

    最后

    软件架构的发展过程,其实也是一个复杂度转移的过程;由应用程序中转移到操作系统中、框架中、基础平台中。复杂度的转移,让基础的软件开发越来越方便、迅速、简单;也让承接复杂度的基础软件越来越成熟、统一、标准化。顺着这个思路极端化一些来思考,也许我们现在做的很多软件方面的事情,在未来会变成少数企业提供服务其他企业直接使用的、赢者通吃的模式。但是也不必悲观,届时科技的发展肯定会带来更新鲜的事物需要我们去贡献自己的聪明才智。

    最后引用一下Eric Raymond惋惜Plan9的言论:“九号项目会失败单纯只是因为它的改进程度没大到能取代Unix。与九号项目相比较,虽然UNIX看来破破烂烂又有明显缺失,但是它还是能好好的把工作完成,这就足以保住它的地位了。这件事情给那些有雄心壮志的系统架构师上了一课:更佳解决方案所面临的最危险的敌人,是那些已经能能把事情做好的程序(方案)。”

    所有参考资料已经以连接形式置于文中。另外,本人知识、水平有限,如有遗漏、疏误之处欢迎补充和指正。

  • 相关阅读:
    自定义镜像流程
    go语言中go+select的理解
    go语言中var声明chan、map、指针,注意的情况
    docker SDK 的基本学习
    ubuntu上安装postgres以及在远程连接上的坑
    go语言模板中的os.Stdout标准输出转化为string
    angular7升级到angular8
    sudo不用在输入密码
    go语言简单的执行shell命令
    Ubuntu上面安装docker
  • 原文地址:https://www.cnblogs.com/mingbai/p/cloudnative.html
Copyright © 2020-2023  润新知