美国西部时间 2020 年 5 月 27 日,阿里云和微软云共同宣布,Open Application Model (OAM) 社区携手知名混合云管理项目 Crossplane,联合发布了 OAM 在 Kubernetes 平台上的标准实现与核心依赖库项目。新版的 OAM 核心依赖库以 Go 语言编写,由来自阿里、微软和 Crossplane 三方的工程师共同维护,能够以 Kubernetes 插件或者 Go 语言依赖库的方式被社区所使用。在内置了 OAM 核心依赖库之后,Crossplane 项目也实现了“华丽升级”,从原先的混合云管理项目一跃成为了一个能够面向所有云环境、提供“应用 + 云服务”一站式管理与交付体验的 OAM 标准实现平台。
- OAM 核心依赖库项目:https://github.com/crossplane/oam-kubernetes-runtime
- Crossplane 项目:https://github.com/crossplane/crossplane
OAM 是阿里云与微软云在 2019 年末联合推出的标准化云原生应用管理模型。相比于传统 PaaS 封闭、不能同“以 Operator 为基础的云原生生态”衔接的现状,基于 OAM 和 Kubernetes 构建的现代云原生应用管理平台,本质上是一个“以应用为中心”的 Kubernetes ,保证了这个应用平台在能够无缝接入整个云原生生态。同时,OAM 可以进一步屏蔽掉容器基础设施的复杂性和差异性,为平台的使用者带来低心智负担的、标准化的、一致的应用管理与交付体验。
OAM 项目:https://github.com/oam-dev/spec
“Cloud 2.0”时代的应用定义模型
应用容器技术自诞生开始,就以“彻底改变了软件打包与分发方式”的魅力迅速征服了几乎所有的云厂商与数据中心。 不过,软件打包与分发方式的革新,并没有能够让软件本身的定义与描述发生本质的变化,基于 K8s 的应用管理体验,也没有让业务研发与运维的工作变得更简单。
实际上,Kubernetes 带来的云原生技术革命,在于实现了基础设施层的标准化和抽象,但这一层抽象距离业务研发与运维还是太过遥远了。一个最典型的例子,直到今天,Kubernetes 里面始终都没有“应用”这个概念,它提供的是更细粒度的“工作负载”原语,比如 Deployment 或者 DaemonSet。而在实际环境中,一个应用往往是由一系列独立组件的组合,比如一个“PHP 应用容器”和一个“数据库实例”组成的电商网站;一个“参数服务节点”和一个“工作节点”组成的机器学习训练任务;一个由“Deployment + StatefulSet + HPA + Service + Ingress”组成的 Kubernetes 应用。
而 OAM 项目,是一个基于 Kubernetes API 资源模型(Kubernetes Resource Model)的标准应用定义规范。在 OAM 中,它强调一个现代应用是多个组件的集合,而非一个简单的工作负载或者 K8s Operator。所以在 OAM 的语境中,一个 PHP 容器和它所依赖的数据库,以及它所需要使用的各种云服务,都是一个“电商网站”应用的组成部分。更进一步的,OAM 把这个应用所需的“运维策略”也认为是一个应用的一部分,比如这个 PHP 容器所需的 HPA(水平自动扩展策略):
与此同时,OAM 模型依据“关注点分离”的思想,对上述应用的组成部分进行了分类。其中,应用研发所关注的部分被称作“Component”,应用运维所关注的运维策略等被称作“Traits” 和 “Scope”,如下所示:
自发布 6 个月以来,OAM 模型正在迅速成为了阿里和微软内部进行应用定义的事实标准,并且已经成为了阿里云企业级分布式应用服务 EDAS 等云端应用管理产品的核心架构。在 2020 年 4 月,国外知名技术媒体 TheNewStack 提出了一个《为什么 Kubernetes 时代的应用如此与众不同》的疑问,引发了巨大的反响。TheNewStack 在文中把 OAM 称作“Cloud 2.0 时代的应用定义模型”,并在最后讲到:
“OAM 的核心思想是,业务研发人员的工作以从编写源代码开始,到构建完容器镜像结束。而应用运维人员或者应用管理平台会负责将这个应用所需的所有组件配置和部署为一个完整的应用程序。而我们已经能够看到,在以 Kubernetes 为代表的 Cloud 2.0 时代,一个现代化应用程序是由许多对象组成的,其中一些对象已经超出了业务研发人员的认知范围。 这可能是互联网历史上第一次研发人员不再完全控制自己开发制品的完整生命周期。”
解读:OAM Kubernetes 核心依赖库
社区在落地 OAM 模型的过程中,提出了很多关于 OAM 统一实现库的诉求。一方面,一个统一的实现库能够更好的对规范进行诠释,增强复用性;另一方面,大量共性需求比如依赖管理、参数传递、冲突管理、编排等,也可以在这个核心依赖库构建。
所以在本次发布中,三方工程师使用 Go 语言开发了一个 OAM Kubernetes 核心依赖库。这个项目的名字叫做 oam-kubernetes-runtime ,它的主要功能包括:
1. 稳定且统一的 OAM 内核:所有基于 OAM 的应用交付平台的构建者都将基于这个依赖库开始构建,OAM 内核将会是统一的。同时该依赖库也由三方的顶级工程师共同维护,确保其具备生产级的稳定性。
- 可漂移的 Workload/Trait 能力:基于这个依赖库构建的 OAM 平台,上面新增的所有 Workload 和 Trait,都可以复用和漂移到其他同样基于该依赖库的平台,像插件一样可以轻松插拔,不需要做代码的变动。
- 通用逻辑内置:所有公共的逻辑,如依赖管理等,也将内置到这个依赖库中,使得大家使用 OAM 基于 K8s 构建以“应用为中心”的管理平台更加容易。
而 OAM 核心依赖库最大的使用场景,就是构建开放、用户友好、标准化的应用管理平台。这样一个管理平台的核心架构如下图所示。
在这样的平台中,平台构建者可以基于 OAM 模块化添加 Workload 和 Trait,而这些模块也可以在不同的 OAM 平台复用。比如,Workload 可以包括函数、容器、云资源、虚拟机等多种不同形态的工作负载;Trait 则可以包含流量管理、发布策略、弹性策略、可观测性策略等多种不同的运维能力。最终,平台本身可以通过不同 Workload 和 Trait 组合,来对最终用户提供差异化的场景。
oam-kubernetes-runtime 使用起来非常便利,可以直接按照样例代码中所描述的那样,通过一个 main 函数把这个依赖库运行起来。OAM Kubernetes 核心依赖库本身是一个 Kubernetes Controller ,通过响应 ApplicationConfiguration 的变化来创建和管理 Workload 和 Trait。具体来说,OAM Kubernetes 核心依赖库会提供两个非常重要的功能:
功能一:无缝对接现有 K8s API 资源
oam-kubernetes-runtime 支持将任何现有的 CRD 被声明为 Workload 或者 Trait 而不需要做任何改动。当然,这也意味着任何 K8s 原生的 API 资源也可以被声明为 Workload 或者 Trait。通过这种设计,现有 Kubernetes 集群里的所有能力进行 OAM 化变得就”易如反掌“了。这也使得 OAM 成为了结构化管理当前集群中的各种 Operator 的不二之选。
功能二:Workload 与 Trait 标准化交互机制
前面的例子告诉我们,OAM 可以模块式的接入、部署和管理任何 Kubernetes 工作负载和运维能力。而这些工作负载和运维能力之间的交互,则需要通过第二个功能来实现标准化和统一化。
这个交互关系在 Kubernetes 里非常常见,比如一个 Deployment 和 HPA(自动水平扩展控制器) 的协作关系。这里 Deployment 在 OAM 模型中就属于 Workload,而 HPA 则属于 Trait。所以说在 OAM 当中,一个 ApplicationConfiguration 里引用的 Workload 和 Trait 也必须通过协作的方式来操作具体的 k8s 资源。举个例子,一个 HPA Trait 该如何去水平扩展上述 OpenFaaS 的 Function Workload 呢?这个协作关系就得依靠 OAM 插件来去管理了。
在 OAM Kubernetes 核心依赖库中,它会通过一种叫做 DuckTyping (鸭子类型)的机制,在 Trait 对象上自动记录与之绑定的 Workload 关系,从而实现了工作负载(Workload)和运维能力(Trait)之间的双向记录关系:
- 给定任何一工作负载(Workload) ,系统可以直接获取到同它绑定的所有运维能力(Trait);
- 给定任何一个运维能力(Trait),系统可以直接获取到它所要作用于的所有工作负载(Workload)。
这种双向记录关系,对于在一个大规模的生产环境中保证运维能力的可管理性、可发现性和应用的稳定性,是至关重要的。
除此之外,OAM 社区还 Kubernetes 核心依赖库中目前还有几个非常重要的基础功能同大家见面,包括:
- Component 版本管理:对于任何一次 Component 的变更,OAM 平台都可以记录下来它对于的变更历史,从而允许运维通过 Trait 来进行回滚、蓝绿发布等运维操作。
- Component 间依赖关系与参数传递:该功能将解决大家亟需的组件间依赖问题,包括 Component 之间的依赖和传输传递,以及 Trait 与 Component 之间的依赖和参数传递。
- Component 运维策略:该功能将允许研发在 Component 中声明对运维能力的诉求,指导运维人员或者系统给这个 Component 绑定和配置合理的运维能力。
OAM + Crossplane:定义云原生应用的下一阶段
可能大家会有这样一个疑问,为什么这一次 OAM 会选择 Crossplane 社区来作为 OAM Kubernetes 核心依赖库的合作团队呢?
我们知道,OAM 的主要思想是以 Kubernetes API 资源模型为核心、以结构化和平台无关的方式,对应用进行定义和管理。这里的“应用”,既包括待运行的程序本身(比如一个容器),也包括它需要的所有其他依赖(比如云资源和运维能力的描述)。而如果你熟悉 Kubernetes 生态的话,就会知道这种通过 Kubernetes API 模型“定义一切”的思想,也正是 Crossplane 项目的设计理念。
只不过,作为 Kubernetes 混合云场景中的佼佼者,Crossplane 项目以前的关注点是以结构化和平台无关的方式对云服务进行定义和管理而已。而在经过 OAM 化之后,今天的 Crossplane 项目,已经成为了 OAM 的标准实现,使用 OAM 作为其应用定义的入口,并且直接通过 OAM Component 的方式来为使用者暴露出平台无关的云服务定义。这样,一个符合 OAM 规范的待运行程序、运维能力和它所依赖的云服务,就可以组成一个整体,在不同的平台之间无缝漂移了。
这种平台无关的应用定义范式,使得应用研发人员只需要通过 OAM 规范来描述他们的应用程序,那么该应用程序就可以在任何 Kubernetes 群集或者 Serverless 应用平台甚至边缘环境上运行而无需对应用描述做任何修改。 这种体验,一直是阿里云和微软云在努力的构建“云、边、端”一致性体验的核心思想。 而此次 OAM 与 Crossplane 的深度协作,也终于将标准应用定义和标准化的云服务管理能力统一起来,从而使“云端应用交付”的故事真正成为了现实。
在未来,这两个社区将进一步紧密协作,在 OAM Kubernetes 标准实现中提供更好的 Component 和 Trait 可移植性、互操作性,在 OAM 生态中上线更加丰富的应用运维能力,共同建立一个专注于标准应用程序与基础设施管理的开放社区。
本文转自<阿里巴巴云原生技术圈>——阿里巴巴云原生小助手