Skip to content

Simplicity in practice globally aligned private cloud for applications

2025-02-10

为什么是“应用”

说到“应用”,就不得不提到赵成著的《进化-运维技术变革与实践探索》,文中1.2.3 “微服务架构时代下为什么要以应用为核心”节中:在软件架构上引入了微服务,但是后续的一系列运维措施和管理手段没跟上,主要还是思路没有转变过来。虽然说要做DevOps,但实际的执行还是把开发和运维分裂对待了。

上一段话简单来说,就是以应用的粒度,组建成一个产品,是在微服务时代及以后的云原生时代,让研发和运维能够清晰地对齐,在80%时间的运维阶段得到极大的提效。

在公有云上,研发只需要关注当前若干个(总是确定的)Region的应用的稳定性,而且私有云,交付的局点数是不断地上升的。回过头来,从私有化的领域来说,最难的不是产品的研发,也不是产品的交付,而且在已经有许多局点交付的情况下,怎么把产品运维好,不出故障,是非常考验 架(构师)-产(品)-研(发)-交(付)-(运)维 团队齐心和高效合作的。而在当前的云原生的时代,用互联网的黑话讲,“应用”已经是这几个岗位人员高度认同的颗粒度了 :)

玩过乐高的人知道,一个漂亮的“世界”就是由一个个小的积木构建而成的。另一个例子是现在比较流行的低代码平台,让一些普通人都能搭建出功能强大的系统,或者世界。而在私有化的世界,这些小小的积木就是“应用”。

怎样定义“应用”

随着Google开源kubernetes引起了业界大火后,互联网也从之前的微服务时代进化到了云原生时代(Cloud-Native)。在云原生时代,OAM的模型对“应用”做了最好的解释。

什么是 OAM

Open Application Model (OAM) 是一个用于定义云原生应用的标准规范,旨在将应用开发与基础设施管理解耦。OAM 通过定义清晰的组件、运维特征和工作流,帮助开发者和运维团队更好地协作,同时提高应用的可移植性和可管理性。

OAM 的核心思想是将应用描述为三个部分:

组件(Component):定义应用的核心功能模块,如微服务、数据库等。

运维特征(Trait):描述组件的运维需求,如自动扩缩容、监控等。

应用配置(Application Configuration):将组件和运维特征组合成一个完整的应用。

OAM 的核心概念

组件(Component)

组件是应用的基本构建块,通常对应一个微服务或一个功能模块。示例:一个 Web 服务、一个数据库服务。

apiVersion: core.oam.dev/v1beta1
kind: Component
metadata:
  name: web-service
spec:
  workload:
    apiVersion: apps/v1
    kind: Deployment
    spec:
      containers:
        - name: web
          image: my-web-app:latest

运维特征(Trait)

运维特征描述组件的非功能性需求,如自动扩缩容、监控、日志等。示例:为 Web 服务添加自动扩缩容。

apiVersion: core.oam.dev/v1beta1
kind: Trait
metadata:
  name: autoscaler
spec:
  appliesTo:
    - web-service
  properties:
    minReplicas: 2
    maxReplicas: 10

应用配置(Application Configuration)

将组件和运维特征组合成一个完整的应用。示例:定义一个包含 Web 服务和自动扩缩容的应用。

# 定义组件
Component:
  name: web-service
  workload:
    type: Deployment
    containers:
      - name: web
        image: my-web-app:latest

# 定义运维特征
Trait:
  name: autoscaler
  appliesTo: web-service
  properties:
    minReplicas: 2
    maxReplicas: 10

# 定义应用配置
ApplicationConfiguration:
  name: my-app
  components:
    - componentName: web-service
      traits:
        - traitName: autoscaler

OAM 的工作流程

开发者定义组件:开发者编写组件的定义,描述应用的功能模块。

运维团队定义运维特征:运维团队根据需求为组件添加运维特征,如自动扩缩容、监控等。

应用配置组合:将组件和运维特征组合成一个完整的应用配置。

平台执行:OAM 平台(如 KubeVela)根据应用配置生成 Kubernetes 资源,并部署应用。

OAM 的优势

开发与运维解耦:开发者专注于业务逻辑,运维团队专注于非功能性需求。

可移植性:OAM 定义的应用可以在不同的云平台和 Kubernetes 集群上运行。

标准化:提供统一的应用定义规范,减少团队间的沟通成本。

扩展性:支持自定义组件和运维特征,适应不同的业务需求。

如下图,OAM有效的将开发和运维解耦,开发主要关注容器申明、资源使用,而运维则更关注trait(特征),比如流量管控,蓝绿发布,A/B测试,以及扩缩容。

KubeVela

目前来看,KubeVela是实现OAM模型最好开源软件系统分发平台,它面对今天私有云、混合云、多云的环境,能够简单、快速、可靠的将系统部署到这些场景中。它以应用为中心,可配置的方式活跃在软件系统的CI/CD阶段中,有兴趣的可以移步:https://kubevela.io/

怎么对齐私有化世界

构建一个以应用为中心的世界,以及各岗位关注的视角。接下来详细说明下图中的含义,并会给出适当的例子。

画板

应用

研发人员和运维人员特别需要关心应用的申明,它主要由两方面组成,一个是镜像,代表的是docker技术,两一个是OAM,典型的是KubeVela。这两部分通过协议好的方式,可以在代码仓库里面申明。例如仓库的目录结构:

some-example-repo
|-.oam
    |-applications
    |     |-app1
    |     |   |-templates
    |     |   |    |-Application.yaml
    |     |   |-Chart.yaml 
    |     |   |-values.yaml
    |     |-app2
    |        |-templates
    |        |    |-Application.yaml
    |        |-Chart.yaml 
    |        |-values.yaml
    |-devops.yaml
    |-builds
        |-app1
        |  |-comp1
        |  |   |-Dockerfile.amd
        |  |   |-Dockerfile.arm
        |  |-comp2
        |      |-Dockerfile.amd
        |      |-Dockerfile.arm
        |-app2
           ...

其中.oam是大家协议的固定目录格式,如果没有则表示该仓库没有应用引用。

第一个在.oam/applications中,可以理解为oam(或者kubevela)概念的体现。有多个app,例如app1,app2,则表示有2个应用引用了该仓库。每个应用里面是一个chart包(chart包,是通过helm工具的一种部署方式,详见 https://helm.sh/),它使用了oam的概念,例如templates/Application.yaml的内容中会有Application,Trait,Comp。

第二个是devops.yaml的文件。devops.yaml里面可以配置很多关于流水线打包的各种配置参数,例如 docker build构建命令的参数、流水线的构建机器(操作系统)选择等等。

第三个是builds文件夹,可以理解为镜像构建体现。它和.oam/application类似,里面包含了多个app。app由多个comp组成,组件里面包含了多种CPU架构的Dockerfile.{arch},常见的架构有amd,arm。

子模块

子模块是由多个相互联系的应用组合而成的。应用组合完成后,它能够具有一个可以自闭环的功能,或者可以承诺外界提供一组稳定有效(详见约定的SLA)API。

例如OpenAPI网关子模块,它可能包含以下几个应用:

应用名 说明
api-gateway 接收所有前端或者SDK的流量,并路由到真正业务后端。技术竞品有ingress,traefik等
api-console 编辑api定义参数,例如入出参,业务后端地址。保存后,实时应用到api-gateway
api-doc 根据api的定义,导出API文档,提供给客户使用
api-sdk 根据api的定义,导出各语言的SDK,方便客户端接入

以上四个组件就可以合成一个OpenAPI网关子模块,它满足了客户对OpenAPI的自定义、接入和访问的需求。

产品

产品是由多个相互联系子模块组合而成的。子模块组合完成后,它能够具备一个相对自闭环的一类产品功能。

例如公共能力产品,它可能包含以下几个子模块:

子模块名 说明
OpenAPI网关 提供了产品对OpenAPI的自定义、接入和请求的能力
账号中心 提供了租户和子账号的创建、查询等生命周期管理的能力
登录和企业登录 提供了租户登录,登录态校验和续租,以及自助接入客户企业账号体系的能力
权限策略 提供了策略定义、用户关联策略,和用户操作鉴权的能力
授权管理 提供了整个平台或软件的授权,包括授权开通、配额定义以及非授权拦截等能力
客制化 提供了允许客户自定义产品的能力,如背景、Logo、配额参数、菜单可见性等
日志审计 提供了其他产品的日志接入、搜索、聚合、图表大盘等能力

这里所说的公共能力,是针对产品的公共能力。通俗的说,多个产品想要组合交付在一个系统平台中,以上这些子模块必不可少,而且产品都是需要统一接入的。否则,客户就无法真正在一个系统上,优雅的体验产品A,同时,转到该系统的另一个菜单后,也可以体验产品B了。

解决方案

解决方案是由多个产品组合而成。产品组合完成后,形成了产品矩阵,所以在这里,我们管解决方案也叫产品矩阵。

例如云原生套件解决方案,它可能包含以下几个产品:

产品 说明
公共能力产品 为解决方案中的其他产品,提供都需要使用的公共能力,如API、登录、鉴权等
微服务产品 为客户提供了容器应用创建、维护、服务发现、负载均衡、副本扩缩容的产品
数据库产品 在云原生底座上的PaaS的数据库产品,如Redis、MySQL、Mongodb等
消息队列产品 在云原生底座上的PaaS的消息队列产品,如Kafka、RocketMQ等
监控产品 基于Prometheous和Grafana的关键指标(性能指标后业务指标)的产品

架构师向客户推销、售卖的产品矩阵,也就是解决方案,所以架构师又称解决方案架构师。他可以与客户磋商,是否客户需求都落在了已提供的产品矩阵能力中,或者收集额外的需求,并给产品输入,然后产品判断是否为通用需求,并将需求落到某个产品迭代里面。研发同学将需求拆解为若干个子任务,在迭代中进行研发。

部署组和产品部署

在产品维度,将所有的应用罗列出来,然后分组,如group1, group2...,按照组序,即group1-->group2...部署下去,当前group的所有应用部署成功后,才能部署下一个group。group内的应用,可以并发启动部署。而应用的部署手段就是通过helm工具,使用应用构建出来的chart包。

部署组顺序讨论

  1. 为什么要分组,并按照组序部署?

应用和应用之前存在部署依赖问题,也就是存在这样情况,部署应用B时,必须要确认应用A已经部署完成,否则部署会失败。所以应用A的组必要在应用B的所在组之前。

  1. 是否存在应用A依赖B,应用B又依赖A的情况?

有可能。这时候有两种解法:

  • 一是具体分析应用A依赖B什么,应用B又依赖A什么,将被依赖的部分与本应用分割出来,例如从A中分割出B依赖的a,从B中分割出A依赖的b,然后将a的组排在B前面,b的组排在A前面即可;
  • 如果上种解法麻烦,那就只能把A,B放在同一个组里面,然后如果应用部署失败了,那就自动重新部署,一般情况,重启若干次后,A和B都会部署成功;

  • 是否存在应用依赖另一个产品的某个应用的情况?

有可能,而且很常见。这是需要将被依赖的产品,部署在当前产品之前。

  1. 是否存在产品P的应用A,依赖产品Q的应用B;且产品Q的应用C,同时也依赖产品P的应用D?

期望不存在。如果发现存在这种情况,应该是能调整应用的产品归属,解决跨产品的应用间循环依赖的问题。例如将应用C从产品Q移出来,放到产品P里面,或者放到部署在产品P之前产品中。

上面所有的概念,都是围绕着应用构建出来的。也就是这样"积木",统一了私有化世界的架(构师)-产(品)-研(发)-交(付)-(运)维 岗位人员意识,让所有人言之有物,提高了交流和交付的效率。