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包。
部署组顺序讨论
- 为什么要分组,并按照组序部署?
应用和应用之前存在部署依赖问题,也就是存在这样情况,部署应用B时,必须要确认应用A已经部署完成,否则部署会失败。所以应用A的组必要在应用B的所在组之前。
- 是否存在应用A依赖B,应用B又依赖A的情况?
有可能。这时候有两种解法:
- 一是具体分析应用A依赖B什么,应用B又依赖A什么,将被依赖的部分与本应用分割出来,例如从A中分割出B依赖的a,从B中分割出A依赖的b,然后将a的组排在B前面,b的组排在A前面即可;
-
如果上种解法麻烦,那就只能把A,B放在同一个组里面,然后如果应用部署失败了,那就自动重新部署,一般情况,重启若干次后,A和B都会部署成功;
-
是否存在应用依赖另一个产品的某个应用的情况?
有可能,而且很常见。这是需要将被依赖的产品,部署在当前产品之前。
- 是否存在产品P的应用A,依赖产品Q的应用B;且产品Q的应用C,同时也依赖产品P的应用D?
期望不存在。如果发现存在这种情况,应该是能调整应用的产品归属,解决跨产品的应用间循环依赖的问题。例如将应用C从产品Q移出来,放到产品P里面,或者放到部署在产品P之前产品中。
上面所有的概念,都是围绕着应用构建出来的。也就是这样"积木",统一了私有化世界的架(构师)-产(品)-研(发)-交(付)-(运)维 岗位人员意识,让所有人言之有物,提高了交流和交付的效率。