查看原文
其他

技术开放日PPT大放送 | 五星级的云原生开发体验

王炜 腾讯云原生 2021-07-14

王炜,腾讯云 CODING DevOps 高级架构师,Nocalhost 研发负责人,CNCF 大使。

本文根据 2021 年 4 月 10 日深圳站举办的【腾讯云原生技术开放日】 线下活动中,腾讯云 CODING DevOps 高级架构师 王炜 关于“Nocalhost - 五星级的云原生开发体验”的演讲整理而成。

腾讯云原生公众号后台回复【云原生技术】,即可获得4月10日云原生开放日所有讲师的演讲PPT。

背景

大家好,今天跟大家分享的话题是云原生开发环境 Nocalhost。之前已经分享过了在应用上的 K8s 或者容器化之后给我们带来了一些在运维层面或者发布层面的收益,比如像滚动、灰度、A/B Test 之类的,一些运维方面的能力。其实我们会发现在业务应用上了 K8s 容器化、拥抱了微服务之后,我们会遇到一个非常棘手的问题,就是我们在本地怎么去开发它?

相信大部分一线开发同学应该是比较深有体会的,所以今天我们分享的话题就是跟云原生开发息息相关的。

这次分享主要会以这几个模块跟大家做主要的介绍:第一个是 Nocalhost 因何而生,我们为什么要做这个项目?第二个是目前主流的云原生背景下开发方式。第三个是我们做开源产品当然要知道我们最终想把它做成什么样的效果,比如像 K8s 目前是云原生的一个标准。第四个是 Nocalhost 的实现原理。第五个是组件构成,Nocalhost 由哪些组件构成。第六个是我们现场会演示用 Nocalhost 怎么来开发 Istio 官方的 demo Bookinfo。

Nocalhost 因何而生

第一个是 Nocalhost 因何而生,为什么云原生、微服务、分布式的应用开发很难?首先看左边的图,左边的图从基础的单体架构上来说,本地的开发体验是非常好的,比如像以前流行的 PHP,我们在开发 PHP 的时候要在本地修改完代码、刷新页面就能立即看到效果了,这是以前传统的开发方式或者单体开发方式。它是组件少,人员或者规模也比较小,环境搭建或者运维相对来说多比较简单。

随着规模或者应用场景越来越复杂,我们拥抱了微服务以及 K8s 容器化,所以这个时候我们把单体应用拆成了巨大的微服务应用,它的微服务组件可能是由几十个、数百个组成的。从右边这张图,我们就会发现微服务和微服务之间的调用是非常复杂,意味着本地怎么开发某一个微服务组件呢?常见的痛点是我需要在本地把我所有的微服务给 run 起来,如果微服务特别巨大,可能需要准备一台非常强的本地开发机,可能是 64G 内存,I7或者I9之类的,才能搞定业务系统开发。

拥抱微服务最大的问题可能还是处于开发环境的搭建以及整个开发和调试是比较困难的。

从单体架构的开发自测来说,我们每写一行代码或者几行代码、十几行代码,我们想看一下效果,在单体的架构下是很简单、快速的,但是在容器化、K8s 这种环境下,其实整个开发自测循环是很慢的,我们常见的一些开发方式可能是我写一行代码之后,然后我来运行 docker build,重新构建一个镜像,可能还要 docker push 把镜像推到我的仓库里,再修改集群工作的负载版本,再等 pod 重启,才能看到最新的效果。整个开发自测循环是非常慢,可能是五分钟、十分钟甚至更久的时间。

在开发环境上的管理,同时也会有遇到一些问题,就是在单体架构这种开发环境下是很简单的,准备一个配置不需要那么高的开发机,我就能搞定业务开发。但是在微服务这种背景下,可能有些团队会采用本地和远端组合的形式,可能会遇到不同版本的环境管理混乱的问题,甚至是需要等其他开发用完之前的环境,然后我下一个才能去用,出现这种排队的情况。

云原生环境下一般的开发方式

刚才提到了我们目前主流的开发方式,基于目前主流的开发方式整理了一张简易的图,重点关注最左边的开发方式,所有服务运行在本地的情况。可以发现,它的编码和自测反馈循环体验是最好的。开发测试环境、维护成本、横向扩容能力,这些其实都是非常弱的。当然,我们使用 K8s 和容器化之后,最右边的所有服务都运行在云端,除了编码自测返回、循环反馈体验不好以外,其他这些给我们带来的能力或者收益其实是非常棒的,特别是前面我们提到的在运维层面的基本可以实现服务这种自愈以及自动扩缩容等等能力。

我们讲到最右边的图,对 Nocalhost 项目来说,我们希望有没有可能找到一种方法可以在集合对右边开发方式所有优点的同时,然后把最左边所有服务运行在本地的编码自测反馈循环体验的五颗星这个优点也放在为右边的模式下,这是希望 Nocalhost 想解决或者希望解决的问题。

Nocalhost 的愿景

Nocalhost 的愿景,我们产品的愿景是让云原生的开发回归原始而简单。也就是说,跟你在本地开发一个单体应用一样这么简单,你不需要考虑一些复杂的背景知识以及应用方面的背景知识。

刚才我们所说,我在传统的云原生开发可能需要五分钟甚至十分钟的体验,那对 Nocalhost 来说,整个过程我们是可以做到秒级。从原来这种开发环境混乱的状态,到现在 Nocalhost 提供的一个有序的环境管理。Nocalhost 提供的开发环境,本身是不提供计算资源,也就是说 Nocalhost 本身不提供K8s集群,它是用现有的集群资源,通过 Namespace 的方式分配给每个开发者去做开发,如果结合一些云计算弹性方面的能力,甚至可以做到按需分配以及用完销毁的。

Nocalhost 实现原理

第四个跟大家分享 Nocalhost 的原理,为什么它能够做到在容器化的开发场景可以做到这么高效的开发,它主要的核心点在于 Nocalhost 可以让业务容器进入一个开发模式。

Nocalhost 有几个核心的概念,第一个是应用,可能是由很多个微服务组成的,比如 Bookinfo 是一个 Kubernetes 应用。我们公司的服务是由一百多个接近两百多个微服务组成的,所以这也是一个 Kubernetes 应用。其实在 Kubernetes 体系下是没有应用这个概念的,所以现在应用领域,比如大家所熟知的 OAM 标准以及 Kubevela,它们是有重新封装一个应用的概念,这是对 K8s 能力的补充,因为我们都知道应用是几个工作负载组合成成的,其实这个只有我们才知道,K8s 集群是不知道的,所以这是应用。当然,应用有很多种类型,可以用 Manifest 组成应用,可以 Helm 组成,也可以用 Kustomize 组成的应用,这在 Nocalhost 里面都支持的。

第二个就是集群,也就是计算资源需要用户来提供。其实这个提供可以说是只需要提供一个集群资源就好了。至于分配给每个开发者,它是基于 Namespace 隔离的,用于部署每个开发者的开发环境以及开发时候用的。

第三个是开发者,开发者在 Nocalhost 里面也是有一个概念的,我这个企业下面可能有很多开发者,我只需给你分配一个开发账号,你登录就能进行所有的开发工作了。

最后一个是开发空间,前面已经讲过了。

在讲下一个的话题之前,我们先把 Nocalhost 的环境一键初始化起来。Nocalhost 提供了一个 CLI 工具,用来快速初始化整个开发环境,并且会内置一些应用,比如像 bookinfo 快速体验。只要这一条命令就可以了。

通过插件端,开发者可以一键拉起自己的开发环境,就是点右边的小火箭就可以开发,就可以拉起完整的一套开发环境了。

实现原理是,让某一个业务容器进入开发模式,甚至是不同的开发者之间在相同一个开发环境里共同来协作开发,比如我开发的业务代码需要依赖于你的新接口,所以会有一个协同开发的过程。对于 Nocalhost 来说,在同一个 Namespace 可能会有两个开发者共享开发者,并且去做协同的开发工作。

进入开发模式会发生什么呢?首先我们会替换整个业务容器的镜像,比如我们会 disable 跟生产、运维有关的东西,HPA、Liveness & Readiness,以及让它的实例副本数到 1。最重要的一点,我们在开发的时候也会给这个业务容器加一个 Sidecar。这样,整个 POD 会有两个容器,第一个是为业务代码提供 Runtime 能力支持的容器,第二个是文件同步的容器,它们两个会通过共享卷来共享存储。

实现了这一步之后,我们本地的代码其实就是可以通过经由 Sidecar 的能力,同步到远端开发环境的 POD 里面。再结合 Nocalhost 提供很便捷的获取远端容器的 Terminal 的机制,就可以实现在容器里面直接运行业务代码。

为什么业务代码能在容器里运行?因为这个容器是真正的业务容器,保留了所有你之前给它设定的 ENV,不管你是通过 configMap 挂载,还是在 Deployment 里声明的 ENV,这些东西都是有保留的,可能有一些业务会在 InitContainer 里做一些魔法的操作。这就意味着在容器里面 RUN 业务代码是完全OK的,并且是走整个集群的网络,在网络层面以及在流量层面也都是OK的。

Nocalhost 除了提供对业务容器直接进入开发以外,我们还会做一个依赖处理的逻辑。打比方,在 Kubernetes 环境下,如果部署一个应用,这个应用可能是由两百个微服务组成的,你发现很多应用在业务逻辑是有依赖关系的,但是 K8s 并没有为我们提供这种依赖关系处理,部署完之后很多 POD 会不断重启,因为可能有些业务是依赖于 DB、MQ、基础组件。如果它找不到这些服务,它自己会挂掉,意味着很庞大的微服务真正被拉起来的时候,POD 会被重启 N 次,由于 K8s 对这些 POD 重启的时间频率,它是一个越来越慢的算法,所以这就导致了你拉起整个开发环境的时间是非常久的,像我们内部的系统两百个微服务左右,如果仅仅用很粗暴的方式去部署大概三十分钟才能把整个业务全部 RUN 起来,会发现里面很多 POD 重启次数已经达到几十次。

这是 Nocalhost 提供的另外一个能力,也就是业务方可以给 Nocalhost 提供一些依赖的声明式的配置,在部署的时候,Nocalhost会有一个准入控制器。我们会把进集群的所有工作负载拦截,根据声明的服务依赖信息给这些服务注入 InitContainer,InitContainer 等待被依赖的服务启动后,再启动,其实是一个等待的过程。这是由Nocalhost Agent 拦截,并且自动注入的,所以这是 Nocalhost 提供的第二方面大的能力。

Nocalhost 的组件构成

Nocalhost 的组件,一个是 CLI 工具,这个工具是给开发者用的,也就是本地电脑装这个工具就好了。当然它的命令有很多,你完全可以使用 CLI 工具对你的工作负载进行开发,但是命令非常复杂。

还有一个 Sever 端,它有几个大的功能,一个是我可以创建我的应用,以及开发者、用户,就是所有开发人员。

刚才所说到 CLI 工具用起来是比较麻烦的,所以提供了一个 Plugin,也就是 IDE 的插件,现在都是可以直接用的,所以,对开发者来说只需要安装 CLI 工具和 IDE 插件就可以实现非常简单的云原生的开发体验。插件的好处在于,因为 IDE 是对接近开发人员的,在插件进行开发环境的操作是最简便的。

最后一个是 Agent,它也是以 Deployment 的形式布局在集群的,当然这些都是自动的。

前面的讲解,我们实现了像在本地开发单体应用一样,在 Nocalhost 下的开发体验集合了所有的应用所有开发环境运行在远端,并且编码和自测反馈循环是一个非常好的体验。

在我们 CODING DevOps 内部目前已经全部使用了,实现的效果是新员工入职当天,就能够独立提交业务代码。这在以前可能是比较难的,也就是说一个新员工入职可能需要一周左右的时间了解开发环境、业务系统、如何搭建开发环境等。在真正搭建的时候,可能从第二周真正开始,过程中会遇到各种各样的问题,可能会有自己的师兄或者自己的导师来协助解决。在原来的业务开发模式下,从效率上来说是不高效的。

在 CODING 内部,所有应用都是按照业务线分的,像 CI 运行自己最小化的 CI应用、微服务这些整合起来的应用,最小化的应用。CD 也是运行自己最小化的微服务开发环境。

比如我现在接到一个需求,我需要去开发登录或者是整个消息通知的组件,对于新员工来说,他唯一需要知道的是需要开发哪个组件就好了。点了开发之后,它会自动帮你克隆代码,自动打开,甚至你这个应用是怎么运行的,在 Nocalhost 里面都是可以配置的。也就是说,它甚至不需要你这个应用的运行命令是什么样的。在我们内部使用目前 Nocalhost 支撑了近百名开发人员日常的开发工作,所以我们采用的是一个集中式的开发环境的管理。也就是说,一个运维团队管了所有这些开发资源,这个集群是一个巨大的资源池。

开源和社区共建

目前 Nocalhost 是开源的,并且采用 Apache 的开源协议,在 GitHub 上是可以找到我们的项目。

整体的 RodaMap,目前 0.1.0 版本在 K8s 环境下非常好的开发体验。当然,也不排除以后会支持其他的环境。

依赖分析、按需启动,目前对开发来说,其实也是一个非常大的痛点。Nocalhost 目前的缺点在于每个开发人员都要运行一套完整的开发环境,也就是说它包含了所有的微服务组件,但实际上你如果要开发某一个微服务组件,它可能是不需要启动完整开发环境的,所以我们接下来会做依赖分析以及按需去启动你要开发的微服务组件所依赖的组件。

最后我们会实现共享开发环境,这是什么意思呢?这个共享指的是我可能会共享一些基础组件,打比方,我们现在每一个开发同学都全量拉起了所有的微服务组件,有一些基础组件平时是不怎么被更新的或者基本上是稳定的状态。Nocalhost 接下来想实现的目标是对于这些组件,大家一起去共用,结合 Service Mesh 的技术做一些流量转发甚至实现基础组件是共享的,可以大大减少整个开发环境所需要的一些资源。

QA环节

提问:我想问一下,在一个上百人的研发团队里,因为有些人对 Docker、K8s 这些知识不熟悉,如何从零开始推广这种开发模式?
王炜:Nocalhost 要解决的核心问题,其实这也算是一个。你会看到刚才我在对 Bookinfo 微服务组件做开发的时候,我是没有运行任何的 kubectl 或者是 Docker 相关的命令的,意味着这些知识已经对开发人员屏蔽了。比如你需要看一个工作负载具体的情况,你可能用 kubectl get deploment 的命令去查看,如果你是传统的开发方式,你可能需要用 kubectl edit 来修改你工作负载的镜像版本。如果是传统的开发方式,你需要具备非常多的至少是入门级的或者知道怎么去使用 kubectl 以及 Docker 常见的这些命令。如果你用 Nocalhost 来开发,你会发现全程几乎不涉及到这些知识的,你所需要做的就是点一下那个锤子,然后去开发它就OK了。

提问:基础环境中,比如涉及到K8s还有一些 Helm 的编写,这些是由运维团队来负责的吗?

王炜:实际上不是运维团队,在我们内部会有一个基础架构的业务团队来维护这些基础环境。当然,涉及到每一个微服务你要去更新,就是更新基准环境的时候,这是由每一个业务团队负责的。其实这个问题痛点我们公司之前也遇到过,你想要维护一套统一的 Helm 或者 Manifest 是非常难的。比如我的微服务,它有可能被任何一个部门更新了,导致我要把它拉起来的时候,我发现各种报错,完全拉不起来,或者它是旧的版本。这里的核心问题,你们维护的那套东西不是被高频使用的,所以它即便是出现问题了,它也很难被人发现或者很久才被人发现,慢慢这套东西就不被维护。如果采用 Nocalhost 集中式应用管理,这个问题就会被解决掉。因为拉起部署环境以及进入开发这些动作都是非常高频的。在一个团队来说,我们发现只要有了工具化的帮助,你会发现团队内会形成良性的循环。也就是说,我在用 Nocalhost 开发的时候,我会发现我有一个组件 RUN 不起来,这个组件可能是我负责的或者我维护的,我就会把它更新掉,或者有一些新的 feature,我会把它更新上去,因为我也要依赖于这套东西开发。

提问:假设我们现在搭建这么一套环境,新人进来了,Nocalhost 服务挂了,会不会导致公司整套用不了?容错方案有没有?

王炜:没错。首先这个答案是肯定的,就像公司采用了 K8s,这个集群挂了,它会导致你的业务没办法 RUN,会停止的状态。实际来说,整个 Nocalhost 是部署在 K8s 环境下的,所以你可以为 Nocalhost 配置一些 HPA 之类的。当然,从 Nocalhost 本身来讲是高可用的,但是依赖于你提供的 K8s 集群稳定性。如果是自建集群,那稳定性可能从概率上来讲应该没有 TKE 高。

提问:假如我有ABC服务,要开发两个服务,AB 两个服务依赖 C 服务,我在线上会不会导致有这些问题?

王炜:你刚才提到的有这些问题,开发模式是部分运行在本地,部分运行在远端的开发模式。但是 Nocalhost 的开发模式是在你自己开发空间里部署完整一套你所有的业务应用以及微服务组件,所以这是不会的,因为你个人用的就是一套独立的开发环境或者是跟别人完全不冲突的。

提问:假设一个 AB 服务,A 服务在迭代,B 服务迭代,可不可以做到跨 Namespace 相互联调的功能?如果能达到未来所说的,一个是共享资源能够不要出现复制多份的问题,你们那边 Namespace 会不会出现膨胀的情况?

王炜:第一个问题又分两个问题,一是你刚刚问到能不能跨 Namespace,这个目前已经在实施了,已经在做了,马上会支持这种集群级的开发。不管几个 Namespace,在 Nocalhost 下都可以开发。这位同学非常敏锐发现了 Nocalhost 现在比较不好的一个点,比如我要开发 Prometheus 组件,它是在固定的 Namespace 下面这种组件,用 Nocalhost 开发也是可以的,你需要用 Nocalhost 的 CLI 工具,但它的使用门槛太高了,所以我们接下来会在插件层面支持这种集群级的。不管你提供的是什么样的权限,可能是管理员或者是具有多个 Namespace 的权限,你可以在不同的 Namespace 下面开发。

提问:能不能通过未来服务网格的问题彻底解决第一个问题,达到像你说的每个人到时候就是一个 K8s 集群,并行迭代开发也能相互联调的问题得到解决。

王炜:是的,用服务网格的方案是可以实现的,完全可以解决的,但从目前实现方面的技术难度来说,可能 Nocalhost 需要自己做一个独立的控制面,所以它的实现难度非常大,基本上可能要基于 Istio 做二次开发。这方面我们有长期的规划,但是从目前来讲,可能我们团队认为云资源未来会越来越便宜。在环境资源上看,现有能提供这种方案或者是现有这些资源能满足开发条件,其实暂时还没有必要在节省资源方面投入太多的精力。




  往期精选推荐  

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存