关于golang:基于-Golang-构建高可扩展的云原生-PaaS附-PPT-下载

3次阅读

共计 7883 个字符,预计需要花费 20 分钟才能阅读完成。


作者|刘浩杨
起源|尔达 Erda 公众号

本文整顿自刘浩杨在 GopherChina 2021 北京站主会场的演讲,微信增加:Erda202106,分割小助手即可获取讲师 PPT。

前言

当今时代,数字化转型概念在 ToB 畛域十分炽热,越来越多的企业须要数字化转型,因而越来越多的厂商涌入了 ToB 市场,端点就是其中一员。

端点的外围业务是给企业提供从洽购、交易、履约、仓储到批发全链路的数字化转型解决方案。围绕这个目标,咱们建设了一整套面向云原生的企业数字化软件产品,其中:

  • PaaS 平台 Erda 是技术底座。
  • Trantor 是具备 HPAPaaS 能力的研发底座,运行在 Erda 之上,提供低代码和高效开发的能力。
  • Gaia 是残缺的业务能力平台,笼罩打算、寻源、洽购、营销、服务、销售、交易、履约、结算等企业供应链业务畛域,提供会员营销、全渠道经营、SRM 洽购和在线销售平台等业务产品。

通过这几层能力的组合,使咱们具备了生产可定制 SaaS 化产品的能力,为企业客户提供端到端的解决方案,满足各行业不同客户的各类需要。所以能够看到在这个分层的企业数字化研发体系中,咱们通过 PaaS 平台向下屏蔽简单的基础设施,使整个业务零碎领有架构多云之上的能力;同时,PaaS 平台也向上提供微服务研发和治理的技术中台能力,让下层用户可能更专一于业务零碎本身的构建。

接下来,简略介绍一下咱们在构建 Erda 过程中的思考,文章后半局部将回到技术自身,来分享一下咱们如何应用 Golang 实现云原生的 PaaS 平台。

软件交付面临的问题和挑战

端点从 2012 年成立到当初,始终聚焦在企业级软件开发和交付上,咱们也从最开始的软件定制交付,到明天应用规范软件 + 二开机制解决定制需要的形式交付。在这个过程中,咱们遇到的问题能够总结为以下 4 点:

  1. 随着交付规模的快速增长,开发和交付团队要如何提效?
  2. 业务软件系统如何适配简单的客户部署环境?
  3. 大规模交付的部署过程须要可被标准化。
  4. 交付上线后须要继续保障业务稳定性。

现在,麻利开发是一个绝对遍及的概念,咱们在做软件交付的时候,也须要把开发流程从传统的瀑布式开发转变为麻利开发,比方一个现实的开发方式是:应用我的项目协同工具来治理研发过程的需要、工作、缺点;应用 gitflow 来治理性能需要的开发;应用自动化的流水线实现继续集成;而后基于容器化来部署咱们的软件;部署之后触发自动化测试来验证性能的正确性。同时,像 API 网关、微服务治理、容器服务、流计算等这些在互联网公司风行的技术,也逐步开始受到大型传统企业的青眼,这对咱们的要求也是进一步提高。

为了解决这些问题,咱们就须要一个残缺的 DevOps 平台来撑持整个研发交付的流程,来达到进步研发效力的目标。

方才讲了在研发过程中的问题,接下来聊一下在需要开发实现后,去企业提供的环境进行交付的环节。

在咱们做过的客户外面,有自建机房用 zstack 来提供虚拟化,也有洽购阿里云、腾讯云、或者微软云 azure 的 ECS,还有的会提供现成的容器环境但治理接口不同,比方 Rancher 和 OpenShift,这些状况咱们都碰到过。甚至最近的一个我的项目里,客户提供的是 arm 架构的运行环境。

因为这些企业提供的环境千差万别,所以交付就变成了一件很苦楚的事件。

回顾计算机软件的倒退历史,咱们晓得 java 是当初很风行的一个开发语言和平台,java 能风行的很大一个起因是因为它提出了 Java 虚拟机,通过编译 Java 代码到通用的字节码,再由运行时去即时编译字节码到不同平台的汇编形式来实现“一次编写,到处运行”。那么,咱们构建的软件系统是否也能够像 java 一样“一次打包,到处运行”?说到这里,可能很多人都会想到:基于 Docker 和 Kubernetes 作为软件的运行时也能够让咱们的软件制品屏蔽掉不同的部署环境。然而,治理不同环境下的 Kubernetes 也是一件很简单的事件,咱们须要一个平台来向上承载不同的业务零碎,向下治理资源和利用调度。

咱们明天的做法是通过一个多云治理平台来解决这个问题。

很多软件系统在验收交付上线后,如果没有一个残缺的平台实时监控、洞察零碎的衰弱状态,将会导致各种问题(稳定性、异样、谬误、攻打)时有发生,重大影响业务的失常运行。保障业务稳定性也是咱们能够提供给客户的外围服务之一。

在之前的案例里,咱们利用 PaaS 上监控的高度扩展性,帮忙一家排名世界 500 强的外企搭建了一套云上的对立监控运维平台,真正实现了从云产品,比方 SLB、WAF、ECS、RDS,到平台层、再到 PaaS 上运行的业务零碎的全链路监控和日志数据的对立剖析,再通过 PaaS 内置的可视化和告警入口,使得客户只须要投入很少的 IT 运维人员就可能保证系统的稳定性。

另一个场景是咱们的 PaaS 平台本身。咱们当初同时在运维着 100+ 的 Kubernetes 集群,但全职负责运维的共事大略只有三四人,而且可预感规模扩充的同时,也不须要在运维上投入更多的人力,这也得益于咱们对平台可观测性的全面笼罩。

所以能够看到,研发、交付、运维遇到的很多问题,咱们都是通过 PaaS 很好地解决了。

端点一站式 PaaS : Erda

后面提到,咱们构建 PaaS 很大一部分是来自端点本身的需要。早在 2016 年咱们就开始搭建端点的部署和利用监控平台,过后的抉择是应用 Docker 和 Jenkins 等开源工具、让业务利用手写 dockerfile 的形式来进行公布;在监控的选型上,应用 Zipkin 作为分布式应用的追踪零碎、应用 ELK 作为日志平台,这可能也是很多公司常见的做法。这套零碎搭建起来当前,在一段时间里满足了公司外部的开发应用,然而随着业务对平台要求越来越多,咱们也引入了更多的开源组件,保护这套零碎的老本也越来越高。同时,有客户心愿咱们能把技术平台也一起对外输入,很显然应用开源组件混搭的这台零碎并不能满足咱们的要求。

在 2017 年,咱们想要从新设计一个以利用为核心的研发平台产品,于是抉择了以 DC/OS 为底座,在下层应用 Java 构建 DevOps 和服务治理平台,并且在 2018 年初交付了第一个客户。当初来看,抉择 mesos 而不是 K8s,过后是走了弯路的,所以从 2018 年下半年开始,咱们也全面拥抱 K8s 生态。同时因为 Java 的性能和资源占用问题,咱们做了第二次的 PaaS 架构降级,开始应用 Golang 重写了大部分的平台组件,也因为要同时反对 DC/OS 和 K8s 两个容器平台,咱们拆分出了异构的调度器模块和流水线模块。时至今日,咱们正在交付的所有客户都曾经在应用 K8s 架构。

越往后走,咱们开发的性能就越多,平台笼罩的范畴也越大。咱们陆陆续续在平台上实现了微服务治理、快数据、挪动开发、边缘计算等诸多平台级利用,演变成了明天 Erda 的一站式 PaaS 产品矩阵。


上图是 Erda 现今的产品大图,其中以多云治理、DevOps、微服务治理和快数据四个平台为外围。咱们在多云治理平台外面实现了两个比拟重要的能力:

  • 一个是对异构资源环境的反对,反对治理物理机、虚拟机、反对原生的 K8s 集群、DC/OS 集群等。
  • 另一个能力是原生的多集群架构,能够通过不同的集群对环境进行物理隔离,比方实现开发、测试和生产环境的资源互不影响。基于容器化,咱们也能够很容易地实现对资源池的精密治理,按 CPU 和内存的粒度准确管制不同利用的资源分配等。

在多云平台之上,DevOps、微服务和快数据平台别离来治理业务和数据。在业务侧提供软件开发的需要、开发、测试、部署、运维全生命周期的性能,在数据侧也通过批流一体实现真正快数据治理能力。除此之外,业务和数据的对立协同,业务能够更大程度地通过数字进行形容,从而实现更为精细化的经营。

Erda 架构的思考

后面介绍了 Erda 提供的的一站式能力,那么咱们是怎么去实现在 PaaS 上实现构建不同的平台服务,实现同一个内核反对微服务开发和数据治理的能力呢?首先来看咱们对 PaaS 扩大架构的思考。

在最后的版本里,咱们只有简略的利用部署性能,把所有的代码放在一起构建了一个单体服务。随着平台性能逐步增多,咱们也开始把零碎拆分成更多的微服务,在拆分的过程中,严格遵守一些设计准则,进行正当的架构分层来防止服务爆炸。在 Erda 以后的零碎架构中,咱们把零碎分为三层:平台应用层,服务层和 PaaS 的内核层,并且约定每一层之间不容许产生横向调用,只容许调用下一层服务提供的接口。

内核层 提供了 PaaS 和基础设施交互的能力 它蕴含三个外围组件和绝对独立的监控零碎:

  • cluster manager 通过和每个集群的 cluster agent 通信,实现多集群治理的能力。
  • pipeline 服务实现了 workflow 的编排和 job 调度能力,包含短时工作、数据的批工作、流工作等。
  • orchestrator 服务实现了 workload 的编排和有状态 / 无状态的服务调度能力。
  • 监控零碎负责收集、计算和展现每个集群上报的可察看性数据。

服务层 相似于业务零碎中提到的中台概念,提供平台中的公共功能模块的能力,如用户、租户、权限、告诉、报表、事件、审计、版本控制、项目管理等。

应用层 则是每个平台调用上层的能力进行本身的业务逻辑封装,同时提供和前端交互的接口。

通过这样一个分层架构,能够很容易地去实现一个新的平台利用。例如在实现挪动开发平台时,代码治理、构建流水线、审计能够复用 DevOps 原有的能力,用户行为剖析、异样剖析等性能依赖监控零碎的能力得以实现。

家喻户晓,Kubernetes 作为云原生利用的最佳部署平台,凋谢了容器运行时接口(CRI)、容器网络接口(CNI)和容器存储接口(CSI),这些接口让 Kubernetes 的开放性变得最大化,而 Kubernetes 自身则专一于容器调度。同样,在以利用为核心的 DevOps 平台中,CI/CD 是最为外围的能力,而咱们也认为 CI/CD 的外围是对 workflow 和 workload 的治理,所以咱们也凋谢了 workflow 接口和 workload 接口,让 DevOps 平台专一于利用开发治理,而不用关注 JOB 和利用被部署到何种平台上。

这里咱们也在实际基础设施即代码的思维。在 Erda 上,你能够应用 pipeline.yaml 来定义利用的 CI/CD 全流程,比方代码拉取、品质扫描、单测执行、利用编译、构建和部署。

一个 pipeline.yaml 的示例如下:

stages:
  stage:
  - git-checkout:
  stage:
  - buildpack:
      params:
        context: ${git-checkout}
  stage:
  - release:
      params:
        services:
          trade-server: ${buildpack:image}
          erda_yaml: ${git-checkout}/erda.yaml
  stage:
  - deploy:
      params:
        release_id: ${release:id}

同时,还能够应用申明式的 erda.yaml 来形容你的利用微服务架构,包含微服务之间的依赖关系、对中间件的依赖等,任何规范的 erda.yml 都能够被 DevOps 平台所部署。一个 erda.yaml 的示例如下:

services:
  trade-server:
    resources:
      cpu: 2
      mem: 2048
    deployments:
      replicas: 2
    ports:
     - port: 8080
    envs:
      ENABLE_ALIPAY: true
addons:
  mysql:
    plan: mysql:basic
    options:
      version: 5.7.23
      create_dbs: trade_db 

值得一提的是,基于 pipeline(流水线)和 erda(部署)两个定义之上,咱们构建了丰盛的 addon 和 action 市场,你能够把本人的服务打包成一个开箱即用的 addon,也能够来实现本人的流水线 action,这些机制让 DevOps 平台的扩展性失去极大的加强。

咱们再来看一下 Erda 微服务平台的设计。共分为管制面和微服务引擎两个局部,它们之间通过咱们设计的协定进行通信。通常,咱们会应用 Erda 内置的微服务引擎,这里的选型是应用了 Spring Cloud Alibaba 组件作为内置实现,能够兼容企业原有的 Spring Cloud & Dubbo 的业务利用,不须要改变任何代码即可接入。同时,对于有非凡需要应用云服务的用户,也反对间接对接云厂商的微服务引擎,咱们曾经实现了阿里云 MSE 的可选实现。在这样的设计下,当初很风行的 ServiceMesh 零碎比方 Istio 也能够很容易的作为 Erda 微服务引擎的一种实现被接入。

最初,咱们再来讲一下监控零碎的设计。在 Erda 的场景里,监控零碎同时撑持根底监控、APM 和浏览器端的监控,所以咱们没有间接应用社区风行的监控零碎,比方 Prometheus 或者 Skywalking,而是抉择了自研一套监控零碎,在采集端适配社区的标准化协定。

首先咱们在每个集群中装置基于 Telegraf 深度定制的 Cluster Agent,负责采集 Kubernetes、Erda 在集群中部署组件的可察看性数据,同时这个 Agent 也能够模仿成一个 Prometheus Server,拉取集群中被主动发现的 Exporters 数据。

那么在每个节点上,也会部署一个 Node Agent,能够主动发现节点上的 Pod,并把 Pod 辨认为 Erda 平台定义的 Service、Job 或者 Addon 组件。同时 Node Agent 也会作为一个本地 Proxy,接管 Pod 中的业务利用 Java Agent 探针和 NodeJS 探针上报的利用申请和 Trace 数据,转发给后端的 Metrics Gateway 组件。
在将来,咱们打算反对更多的第三方协定,如 SkyWalking 和 OpenTelemetry,来更多地进步 Erda 在可察看性上的扩大。

Erda Infra 模块化开发框架

后面从架构的角度讲了咱们对 PaaS 扩大的一些思考,也提到通过微服务的形式来构建整个平台,实现微服务化的重点就是要对系统性能进行正当拆解,把零碎拆解成诸多边界清晰、能够内聚的业务模块。

尽管在 golang 社区中有很多 web 开发框架,如 gin、go-zero、beego,但三思而行后,咱们发现须要的不仅仅是一个 Web 框架和微服务框架,而且还须要一个以模块化开发为外围,能够通过接口对系统进行扩大的开发体系。基于此咱们设计了 Erda Infra,一套轻量级 Go 微服务框架,蕴含大量现成的模块和工具,可能疾速构建起以模块化驱动的应用程序。

Erda-Infra 的外围个性包含:

  • 以模块化设计形式来驱动利用零碎实现,反对模块可插拔。
  • 对立配置读取,反对默认值、反对从文件、环境变量、命令行参数读取。
  • 对立模块的初始化、启动、敞开。
  • 对立治理模块间的依赖关系。
  • 反对模块间的依赖注入。
  • 蕴含大量现成的微模块 Provider,包含 etcd、docker、cassandra、es 的 sdk、Http Server、gRPC Server 等。
  • 应用 Protocol Buffer 定义接口,反对主动生成 gRPC 和 HTTP 接口和客户端调用代码。
  • 提供疾速构建模块的代码生成工具。


Erda 当初有数千个性能点蕴含在几十个服务外面,一旦服务性能拆分设计的不合理,很容易引发整个我的项目的保护老本问题。咱们在从架构层面扫视模块拆分的同时,也冀望应用开发框架来对开发进行一些束缚。

第一个准则 是对模块的拆分粒度要尽可能小,让每个模块的逻辑能高度内聚,对外的依赖能够松耦合。拿利用监控这个子系统来说,咱们拆解成了拓扑、服务列表、服务监控、浏览器监控、谬误剖析、链路追踪等绝对独立的模块,而后应用 Erda Infra 提供的能力拼装到一起组成监控的服务。

第二个准则 是模块的开发者须要面向接口开发,而不是面向实现;模块之间依赖接口,而不是具体的实现类。这样做的益处是须要对模块进行扩大的时候,能够不须要批改已有的代码。咱们也在 Erda Infra 中实现了依赖注入容器,通过相似 Spring 中 IoC 的形式,让开发模块的人更关注本人负责的逻辑单元。

上面来看一个 Erda Infra 中最简略的模块示例,咱们把模块定义为 provider 构造,能够把须要注入的接口申明在 provider 的字段中,同时还须要实现 Init、Run 函数来管制模块的生命周期,最初把定义好的模块注册到全局的服务容器中,即可实现一个微模块的实现。


那么咱们如何在服务容器中定位到实现的接口呢?Erda Infra 提供了一个 Provide 接口,在这个接口中咱们能够显示申明接口的具体实现,上面是 mysql-client 模块的申明示例:


对于接口的获取,Erda Infra 提供了主动注入和应用服务定位器来解析两种形式。

主动注入和 Spring 的应用一样,通过在字段上标记 autowired 标签即可失效:


服务定位器模式则能够应用在后台任务中,通过框架的服务上下文来获取须要的接口具体实现:


最初再来聊一聊 Erda 中的 API 定义形式,咱们把 API 对立都定义在 Protobuf 文件中,这样能够对立生成 gRPC、HTTP、OpenAPI 接口,以及 Client 的代码。

假如零碎中有一个服务叫 Greeter,定义如下所示。其中:通过 google.api.http 选项,来定义 http 相干的信息,能够主动把申请的数据解析到 Path 参数和 Query 参数上。还能够通过在对应的接口上申明 +publish 非凡的正文,来示意公布该接口到 OpenAPI 上,如果想要把某个接口强制标记为外部接口,那么也能够通过 +private 正文来实现。

// +publish prefix:"/api/greeter" backend-prefix:"/api" service:"user-center"
service GreeterService {
    // say hello
    // +publish
    rpc SayHello (HelloRequest) returns (HelloResponse)  {option (google.api.http) = {get: "/api/hello/{name}",
      };
    }
  }
  
  message HelloRequest {string name = 1;}
  
  message HelloResponse {string data = 1;}

Erda Infra 作为咱们应用的根底框架,当初还有一些不欠缺的中央,咱们后续打算持续增加服务注册发现的反对,来实现运行时的服务模块治理等,以此继续加强 Erda 的平台扩展性。

总结

咱们从 3 月开始打算 Erda 的开源,到当初曾经构建了第一个稳固的开源版本,第二个版本也将在近期公布。

Erda 自身提供的一站式服务开发治理和数据治理性能曾经十分丰盛,咱们接下来将会重点对用户体验和性能细节进行打磨,对开源代码重构以进步代码品质,简化平台的装置部署形式等。欢送大家关注 Erda 开源我的项目,一起探讨、交换云原生 PaaS 相干的技术,共建开源社区。

  • Erda Github 地址:https://github.com/erda-project/erda
  • Erda Cloud 官网:https://www.erda.cloud/
正文完
 0