1 - 规范概述

OAM规范(v0.3.0)

https://github.com/oam-dev/spec/blob/master/SPEC.md

文档

  1. Purpose and Goals
  2. Overview and Terminology
  3. Component Model
  4. Workload Types
  5. Application Scopes
  6. Traits
  7. Application
  8. Practical Considerations
  9. Design Principles

模型实体

Category API Version
ComponentDefiniton core v1beta1
WorkloadDefiniton core v1beta1
TraitDefinition core v1beta1
Application Scope core v1beta1
Application core v1beta1

版本

对于模型对象,Open Application Model采用了 Kubernetes API资源惯例

模型的发布是根据 语义化版本2.0 进行的,并在OAM发布页中进行了描述。该模型的实现需要指定它们实现的版本。

对API对象的更改

本模型中的API对象的变化遵循 Kubernetes API资源公约中定义的兼容和不兼容的api变化。它不与该模型的发布版本相联系。

对变更过程(如治理模型、审查/批准过程等)本身的变更目前没有版本,但将来可能会独立地进行版本。

2 - 目的和目标

目标是定义一种标准的、与基础设施无关的方式来描述跨混合环境、云甚至是边缘设备的应用部署

https://github.com/oam-dev/spec/blob/master/1.purpose_and_goals.md

开放应用模型的目标是定义一种标准的、与基础设施无关的方式来描述跨混合环境、云甚至是边缘设备的应用部署。

这个模型试图解决的核心问题是如何组成分布式应用,然后成功地移交给负责运维它们的人。问题不在于如何编写程序,而在于如何采用面向服务(或面向微服务)架构的组件,并简化围绕此类应用的工作流程。

例如,一个当代的云计算应用可能是由几十个微服务组成的,每个微服务负责一个离散的块,广义上讲,就是 “一个应用”。这些应用需要被配置、部署、审计、更新和删除。有时,应用程序必须作为一个整体来处理,有时则需要更精细的粒度。而且最重要的是,这种应用往往不是由一个人或一个团队管理,而是由多个团队管理,他们必须合作以实现可靠性、稳定性和及时性。

这个模型提供了对这种工作流程的描述,其中描述本身是陈述性的、可扩展的,并且具有最佳的清晰度。此外,它还提出了操作此类应用的模式和流程。该模型将专注于云原生(即高度分布式)应用,包含公共云技术、内部解决方案和物联网/边缘技术。这为现代应用交付系统奠定了坚实的基础,为云原生应用部署提供了标准但更高层次的描述。

非目标包括:

  • 定义或规定具体的编排工具

  • 定义运维资源的模式,例如(但不限于):

    • 秘密(安全、加密的值)。
    • 网络
    • 卷(Volumes)
  • 描述或定义运行时基础设施本身。

3 - 概述和术语

应用程序是具有一组运维特性的组件的集合,并将其范围扩大到一个或多个应用程序边界

https://github.com/oam-dev/spec/blob/master/2.overview_and_terminology.md

本节概述了开放应用模式(OAM)及其术语。它首先确定运行云原生应用过程中涉及的组织角色。从这里开始,它阐述了本文件中使用的具体术语。

模型概述

本文档提出了一个定义云原生应用的模型,如下所示:

云原生应用是一系列相互关联但互不相干的组件(服务、任务、工作者)的集合,当它们与配置结合并在合适的运行时基础设施中实例化时,共同完成一个统一的功能目的。

在目前的版本中,这个应用模型定义了以下内容:

  • 组件(Component)代表一个可运行的单元,同时还带有描述(description)(示意图)。
  • 工作负载(Workload)类型确定组件可以执行的不同工作负载。
  • 特质(Trait)是覆盖物,用额外的运维特定的功能来增强组件。特质代表运维人员的关注,而不是开发者/软件所有者的关注。
  • 应用范围(Application scope)通过对具有共同属性或依赖关系的组件进行分组来代表应用的边界。
  • 应用配置(application configuration)集合了一组组件实例、它们的特性以及它们所处的应用范围,并与配置参数和元数据相结合。

因此,应用程序是具有一组运维特性的组件的集合,并将其范围扩大到一个或多个应用程序边界。

overview

4 - 组件模型

组件描述了可以作为更大的分布式应用的一部分的被实例化的功能单元

https://github.com/oam-dev/spec/blob/master/3.component_model.md

本节定义了组件模型。

组件描述了可以作为更大的分布式应用的一部分的被实例化的功能单元。应用部分将描述组件如何被分组,以及这些组件的实例如何被配置,而本节将重点讨论组件模型本身。

modern_app

组件定义

ComponentDefinition 实体的作用是允许组件提供者以基础设施中立的格式声明这种执行单元的运行时特性。

例如,应用程序中的每个微服务都被描述为一个组件。请注意,ComponentDefinition 本身不是该微服务的实例,而是对该微服务的可配置属性的声明。这些可配置的属性应该作为参数列表公开,允许应用团队在以后部署时设置和实例化这个组件。

在实践中,简单的容器化工作负载、Helm图表或云数据库都可以被建模为一个组件。

顶层属性

以下是提供组件定义的顶层信息的属性。

Attribute Type Required Default Value Description
apiVersion string Y 用于标识对象应该具有的模式版本的字符串。核心类型在这个版本的模式中使用core.oam.dev/v1beta1
kind string Y 必须是 ComponentDefinition
metadata Metadata Y 实体元数据.
spec Spec Y 组件定义的规范

Spec

Attribute Type Required Default Value Description
workload WorkloadTypeDescriptor Y 对该组件的工作负载类型 的标识符。
schematic Schematic Y 该组件的原理图信息。

WorkloadTypeDescriptor

Attribute Type Required Default Value Description
type string Y 通过名称对 WorkloadDefinition 的引用。
definition WorkloadGVK Y type相互排斥,通过group, version和kind对WorkloadDefinition的引用。

WorkloadGVK

Attribute Type Required Default Value Description
apiVersion string Y 工作负载类型的API版本。
kind string Y 工作负载类型的API种类。

Schematic

本节声明了组件的示意图,该组件可以在以后的部署工作流程中作为应用程序的一部分被实例化。请注意,OAM本身对如何实现该示意图没有强制要求,只要它能做到。

  1. 建立一个可部署单元的模型。
  2. 暴露一个JSON模式或同等的参数列表。

在KubeVela中,目前支持以下模式的实现(cuehelmkube)。

示例

下面是一个基于CUE的组件定义的完整例子,名为webserver。

apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
  name: webserver
  annotations:
    definition.oam.dev/description: "webserver is a combo of Deployment + Service"
spec:
  workload:
    definition:
      apiVersion: apps/v1
      kind: Deployment
  schematic:
    cue:
      template: |
        output: {
            apiVersion: "apps/v1"
            kind:       "Deployment"
            spec: {
                selector: matchLabels: {
                    "app.oam.dev/component": context.name
                }
                template: {
                    metadata: labels: {
                        "app.oam.dev/component": context.name
                    }
                    spec: {
                        containers: [{
                            name:  context.name
                            image: parameter.image

                            if parameter["cmd"] != _|_ {
                                command: parameter.cmd
                            }

                            if parameter["env"] != _|_ {
                                env: parameter.env
                            }

                            if context["config"] != _|_ {
                                env: context.config
                            }

                            ports: [{
                                containerPort: parameter.port
                            }]

                            if parameter["cpu"] != _|_ {
                                resources: {
                                    limits:
                                        cpu: parameter.cpu
                                    requests:
                                        cpu: parameter.cpu
                                }
                            }
                        }]
                }
                }
            }
        }
        // an extra template
        outputs: service: {
            apiVersion: "v1"
            kind:       "Service"
            spec: {
                selector: {
                    "app.oam.dev/component": context.name
                }
                ports: [
                    {
                        port:       parameter.port
                        targetPort: parameter.port
                    },
                ]
            }
        }
        parameter: {
            image: string
            cmd?: [...string]
            port: *80 | int
            env?: [...{
                name:   string
                value?: string
                valueFrom?: {
                    secretKeyRef: {
                        name: string
                        key:  string
                    }
                }
            }]
            cpu?: string
        }        

在平台上安装了上述网络服务器后,用户将能够在一个应用程序中部署这个组件,如下所示。

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: webserver-demo
spec:
  components:
    - name: hello-world
      type: webserver               # claim to deploy webserver component definition
      properties:                   # setting parameter values
        image: crccheck/hello-world
        port: 8000                  # this port will be automatically exposed to public
        env:
        - name: "foo"
          value: "bar"
        cpu: "100m"

其他原理图格式的例子。

  • Helm组件:示例
  • 原始Kubernetes API资源作为组件:样本

5 - 工作负载类型

工作负载类型由平台提供,以便用户可以检查平台并了解有哪些工作负载类型可供使用。

https://github.com/oam-dev/spec/blob/master/4.workload_types.md

使用工作负载类型在组件模型部分有所涉及,但这里要描述工作负载类型的定义。

工作负载类型是特定组件定义的关键特征。工作负载类型由平台提供,以便用户可以检查平台并了解有哪些工作负载类型可供使用。请注意,工作负载类型对终端用户是不可扩展的(只对平台运营商)。因此,不允许终端用户创建新的工作负载类型。

工作负载的定义

工作负载类型以 WorkloadDefinition 的形式呈现,除了可发现性的目的,工作负载定义还带有特征信息,提示平台如何将特征附加到引用该工作负载类型的特定组件上(即适用于特征系统的特性)。

顶层属性

以下是提供工作负载定义顶层信息的属性。

Attribute Type Required Default Value Description
apiVersion string Y A string that identifies the version of the schema the object should have. The core types uses core.oam.dev/v1beta1 in this version of model
kind string Y 必须是 WorkloadDefinition
metadata Metadata Y 实体元数据。
spec Spec Y 工作负载定义的规范。

Spec

Attribute Type Required Default Value Description
definitionRef DefinitionRef Y 平台中工作负载能力的标识符。

DefinitionRef

Attribute Type Required Default Value Description
name string N 工作负载能力的名称标识符。与 apiVersionkind 相互排斥。
apiVersion string N 工作负载能力的API版本。
kind string N 工作负载能力的类型

工作负载类型的特点

在工作负载定义中保留的 metadata.labels 是用来表示工作负载类型的区别特征的。

这些特征将被应用于特征系统(traits system)的特性。

Label Type Explain
workload.oam.dev/replicable boolean 它们是否可以复制(replicable)。如果不是,则不可以指定复制或扩展的特征。
workload.oam.dev/daemonized boolean 它们是否是守护型的(daemonized)。对于守护进程类型,如果工作负载退出,这被认为是一个故障,系统必须修复它。对于非daemonized类型,如果没有报告错误,退出被认为是成功。
workload.oam.dev/exposed boolean 它们是否被暴露,即有一个具有稳定名称的网络流量的服务端点。拥有服务端点的工作负载类型需要一个带有DNS名称的虚拟IP地址(VIP),以代表组件的整体,可在其网络范围内寻址,并可以分配流量路由特征。
workload.oam.dev/podspecable boolean 该工作负载是否可以由Kubernetes PodSpec解决。如果是,实现可以通过利用PodSpec结构来操纵工作负载,而不是对工作负载的模式不闻不问。

工作负载类型的分类

工作量类型有几个类别。

官方维护的工作负载类型

官方维护的工作负载类型必须是在 oam.dev 组中。

下面是一个官方维护的工作负载类型的例子:

kind: WorkloadDefinition
metadata:
  name: Server
spec:
  definitionRef:
    name: containerizedworkloads.core.oam.dev

该工作负载类型的规范:

Name Category Schema Exposed Replicable Daemonized
Server Core ContainerizedWorkload Yes Yes Yes

扩展工作负载类型

每个OAM运行时都可以在这个分组之外定义自己的工作负载类型,它们将被视为一种扩展的工作负载类型。扩展工作负载类型的名称和模式完全由OAM的实施者决定。

下面是一个扩展工作负载的例子:

kind: WorkloadDefinition
metadata:
  name: redis.cache.aliyun.com
spec:
  definitionRef:
    name: redis.cache.aliyun.com # this is an extended workload type

对于扩展的工作负载类型,建议采用以下约定:

  • 使用 Group/Version/Kind 来唯一地识别工作负载能力。
  • 该名称遵循 Group, Version, Kind 中描述的格式。
  • WorkloadDefinition 的 name 与它所指向的 name 相同。

比如说:

kind: WorkloadDefinition
metadata:
  name: schema.example.com
spec:
  definitionRef:
    name: schema.example.com

组件和工作负载类型的关系

简而言之,组件是对工作负载类型的封装,预先定义了面向用户的示意图。组件需要明确声明其工作负载类型,以便OAM系统正常工作,也就是说,OAM特性系统将检查这个工作负载类型信息,以验证某个特性是否可以附加到这个组件。

下面的例子可能也有助于更好地解释它们之间的关系。

  • 一个Web服务组件,封装了一个Kubernetes Deployment +一个Service。

    • 在这种情况下,app/v1.Deployment是这个组件的工作负载类型。
  • 一个封装了Kubernetes Deployment的后端工作者组件。

    • 在这种情况下,apps/v1.Deployment仍然是该组件的工作负载类型。
  • 模板化 Kubernetes Deployment的Helm图+Ingress也是一个组件。

    • apps/v1.Deployment是该组件的工作负载类型。

concepts

从另一个角度来看,ComponentDefinition 总是由某些组件提供者或软件构建者定义,而 WorkloadDefinition 作为一种平台能力,总是由基础设施运营商维护。因此,OAM平台通常拥有数量非常有限的工作负载定义,而且它们不会有很大的变化,但总是有无数的组件定义由不同的供应商和用户维护。

6 - 应用作用域

应用作用域是通过提供不同形式的应用边界和共同的组行为,将组件组合成逻辑应用。

https://github.com/oam-dev/spec/blob/master/5.application_scopes.md

应用作用域是通过提供不同形式的应用边界和共同的组行为,将组件组合成逻辑应用。

应用程序作用域具有以下通用特征:

  • 当定义一组组件实例所共有的行为或元数据时,应该使用应用作用域。
  • 组件可以同时被部署到不同类型的多个应用作用域中。
  • 应用作用域类型可以决定组件是否可以被同时部署到同一应用作用域类型的多个实例中。
  • 应用作用域可被用作组件组与基础设施(如网络)或外部能力(如身份提供者)所提供的能力之间的连接机制。

下图说明了组件如何被分组到重叠的应用作用域中以创建不同的应用边界:

scopes-diagram-1

这个例子显示了两种作用域类型,有四个组件分布在它们之间。

组件A、B和C被部署到同一个健康作用域。健康作用域将收集在组件升级操作中被评估的关于其组成组件的聚合健康信息。健康作用域提供的查询信息可以被需要根据一组组件的聚合健康状况进行评估和/或执行行动的特征或组件进一步使用。这是应用程序的基本分组构造,它提供了组件之间依赖关系的松散定义。

组件A在自己的网络作用域内与组件B、C和D隔离。这允许基础设施运营商为不同的组件组提供不同的SDN设置,如后端组件上更多的限制性入站/出站规则。

定义应用作用域

应用作用域由 ScopeDefinition 实体表示。

顶层属性

这些属性提供关于应用作用域的顶层信息。

Attribute Type Required Default Value Description
apiVersion string Y A string that identifies the version of the schema the object should have. The core types uses core.oam.dev/v1beta1 in this version of model.
kind string Y Must end with ScopeDefinition.
metadata Metadata Y 实体元数据
spec Spec Y 作用域属性的规范。

Spec

spec 定义了作用月的构成部分。

Attribute Type Required Default Value Description
allowComponentOverlap bool N true 确定是否允许一个组件同时出现在这个作用域类型的多个实例中。如果是false,那么如果试图把一个组件同时放到这个作用域类型的一个以上的实例中,运行时实现必须产生一个错误并停止部署。
definitionRef DefinitionRef Y 平台中作用域能力的标识符。

DefinitionRef

Attribute Type Required Default Value Description
name string N 作用域能力的名称标识符。与apiVersionkind相互排斥。
apiVersion string N 作用域能力的API版本。
kind string N 作用域能力的类型。

示例

apiVersion: core.oam.dev/v1beta1
kind: ScopeDefinition
metadata:
  name: healthscopes.core.oam.dev
spec:
  allowComponentOverlap: true
  definitionRef:
    name: healthscopes.core.oam.dev

本文档中定义了以下示例作用域能力。

健康作用域

健康作用域将组件分组到一个综合健康组。该组中的组成部件的总体健康状况为升级和回滚机制提供信息。

网络作用域

网络作用域将组件归入网络子网边界,并定义了一般运行时网络模型。网络定义、规则和政策由基础设施的网络或SDN描述。

7 - 特质

特质用运维功能增强了组件工作负载实例。

https://github.com/oam-dev/spec/blob/master/6.traits.md

特质(trait)是一种随意的运行时覆盖物,它用运维功能增强了组件工作负载实例。它为应用程序运维人员提供了一个机会,使他们能够对组件的配置做出具体的决定,而不必让组件提供者参与其中或破坏组件的封装。

例如, WordPress Helm 图表中向工作负载注入一个 sidecar 容器的 sidecar 特性。

特质可以是适用于单个组件的分布式应用的任何配置,如流量路由规则(例如,负载平衡策略、网络入口路由、中断、速率限制)、自动扩展策略、升级策略等。

特质定义

本节是规范性的,因为特征是系统的可检查(可能是可共享)部分。所有特质必须可以用以下格式表示。

特征的定义与组件一样,都是用示意图(schematics)来定义的。与工作负载定义一样,每个特征定义都有一个 definitionRef,它是对定义该特征的配置选项的模式的引用。

顶层属性

特质的顶级属性定义了它的元数据、版本、种类和规格。

Attribute Type Required Default Value Description
apiVersion string Y A string that identifies the version of the schema the object should have. The core types uses core.oam.dev/v1beta1 in this version of documentation.
kind string Y Must be TraitDefinition
metadata Metadata Y Information about the trait.
spec Spec Y A specification for trait attributes.

Spec

Attribute Type Required Default Value Description
appliesToWorkloads []string * 该特征所适用的工作负载类型特征的集合。如果该字段为空或未指定或指定为 "*",则表示适用任何工作负载类型。特征必须至少适用于一个工作负载类型。这个属性必须至少包含一个值。
conflictsWith []string N 当应用于同一工作负载类型时,将与该特性冲突的特性列表。例如,“autoscaling” 可能与 “cron-autoscaling” 冲突。
definitionRef DefinitionRef Y 特质能力的标识符。

DefinitionRef

DefinitionRef identifies the trait capability, i.e. the trait implementation.

Attribute Type Required Default Value Description
name string N 特质的名称标识符。与apiVersionkind相互排斥。
apiVersion string N API version of the trait.
kind string N Kind of trait.

建议使用 Group/Version/Kind 来唯一地识别特征能力。如果使用definitionRef.name,它必须包含可用于唯一标识的信息。

应用部分将详细描述用户如何将特征附加到组件上。

实现特性系统

警告:本节只针对OAM平台的实现者(即KubVela),如果你只对OAM的概念感兴趣,请随意跳过本节。

特质系统在本文档中被定义为运行时通过特质对组件实例应用和管理运维行为的方式。

该模型的运行时实现必须提供特性系统,以便将运维行为附加到组件实例上。

特征系统的规则和特性

特征应该在安装/升级时被应用到运行时中。特征不应该被 “懒惰地/lazily” 检查,而应该在持有特征的组件被创建时被检查。

当组件附加了一个以上的特性时,它必须:

  • 按照定义的顺序应用特征
  • 确定兼容性,如果特性的组合不能被满足,则失败。

特质是按顺序应用的,这样,如果某些特质集表达了依赖性(例如,在SSL之前必须设置ingress),这可以通过设置一个显式顺序来解决。

一个组件实例只能有一个任何给定特性类型的配置。

在所有特征配置完成之前,部署不应该被标记为完成。例如,如果Web服务器组件被部署为自动缩放器特性,那么在(a)Web服务器本身运行(由健康检查决定)和(b)自动缩放器特性运行(由底层平台决定)之前,Web服务器不应该被视为 “运行”。

组件可以指定多个特性;因此,运行时必须支持将零个或多个特性应用于一个组件。如果底层运行时不能满足所请求的特征,则运行时必须产生错误并停止部署。

没有机制可以明确地要求特性的组合。例如,一个特征(ssl)不能指定它要求另一个特征(ingress)应用于一个对象。然而,如果一个特征在没有另一个特征存在的情况下不能履行其契约,那么特征的实现就应该失败。一个系统可能支持这样一种机制,即一个特征(sslIngress)被两个独立的特征实现(ssl和ingress)不透明地支持着。

任何在运行时中可用的特性都必须在该运行时中实现。例如,在一个运行时中不能有一个用于自动缩放的特性,但没有实现该特性。

特质的类别

特质系统被设计成作为运行时运维能力的扩展点,同时也为组件提供通用的,在某些情况下是必要的运维功能。

特质的实现细节超出了本文档的范围。然而,为了使运行时能够实现任意特征,同时保持一定程度的通用性,以便在不同的运行时之间进行应用移植,特征被分为以下几类。

  • 核心特质。该类别定义了一组类型名称为 core.oam.dev 组的特性定义。这些特征提供了某些工作负载类型和组件特性运行所需的运维功能。运行时必须实现本模型中定义的这些特征。

  • 标准特质。该类别定义了一组特征定义,其类型名称在 standard.oam.dev 组中。这些特征提供了应用程序运维人员常用的运维功能,并由大多数运行时实现。建议运行时在提供与标准特性定义中所列功能相当的运维功能时,使用本模型中定义的标准特性定义。换句话说,如果运行时正在实现具有行为foo的特质,并且存在行为foo的标准特质定义,那么运行时应该使用标准foo特质定义。计划最大限度地提高其应用程序的可移植性的应用程序运营商应该在可用时使用这些特性定义。尽管这并不保证应用程序的可移植性,但它旨在提高跨运行时的可移植性。

  • 扩展特质。该类别允许运行时定义自己的特质定义集,这些特质定义是该运行时在核心和标准特质定义之外所特有的。运行时可以选择用任何定义来实现这个类别中的任何一组特质。扩展特性类型的名称不得在 core.oam.devstandard.oam.dev 组中。

特质特征

一个单独的特质可以与特定的工作负载相联系(也可以适用于所有工作负载)。特质可以声明它适用于哪个工作负载。

本模型没有对特质的简单或复杂程度做出要求。有些特质可能会暴露出一组广泛的可配置的选项,而其他特质可能没有暴露出可配置的选项。也不要求特质像其基础技术那样详尽。例如,一个自动缩放技术的实现可以提供许多方法来确定一个组件何时应该缩放。但该特质可能只显示其中的几个。同样地,可以定义多个自动缩放特质(每个都有唯一的名称),每个特质暴露不同的可配置选项子集。或者一个大的特质可以暴露所有可能的自动缩放配置。

OAM平台的实现应使所有支持的特质都能以下面解释的格式被发现。

8 - 应用程序

Application实体定义了一旦应用被部署就会被实例化的组件列表。

https://github.com/oam-dev/spec/blob/master/7.application.md

本节描述了应用程序如何被设计和部署。

直到当前模型的v0.3.0,Application 被称为ApplicationConfiguration。

应用

Application实体定义了一旦应用被部署就会被实例化的组件列表。

用户将指定每个组件的最终参数化以及应用于增强其功能或改变其行为的特性。此外,还可以指定一组范围,将不同的组件子集分组。

顶层属性

应用程序的顶级属性定义了它的元数据、版本、种类和规格。

Attribute Type Required Default Value Description
apiVersion string Y A string that identifies the version of the schema the object should have. The core types uses core.oam.dev/v1beta1 in this version of documentation.
kind string Y Must be Application
metadata Metadata Y Information about the application.
spec Spec Y A specification for application attributes.

Spec

应用程序的规范定义了要创建的组件、附着在每个组件上的特征以及组件所投放的一组作用域。

Attribute Type Required Default Value Description
components [\]Component Y Component specification.

Component

Attribute Type Required Default Value Description
name string Y The name of the component instance.
type string Y 对将被应用程序实例化的组件定义的引用。可以选择以<namespace>/<component_name> 的形式来引用一个被命名的组件。命名空间的含义是具体实施的,取决于正在使用的运行时和创建实体的目标平台。在Kubernetes的情况下,“namespace” 的概念与Kubernetes的现有概念相匹配。
properties Properties Y 一组分配给组件示意图中暴露的参数的值。
traits [\]Trait N 要附加到这个组件实例的特性。
scopes map[string]string N 包含组件所属的作用域的映射。该映射使用限定的作用域定义名称作为键(例如,“scope.company.com”),而作用域的名称作为值(例如,“myscope”)。注意,这个引用意味着目标作用域的一个具有特定名称的实体存在。

name 必须遵循这些命名规则:

name字段是必需的,必须是63个字符或更少,以字母数字字符([a-z0-9A-Z])开头和结尾,中间有破折号(-)、下划线(_)、点(.)和字母数字。

Trait

Attribute Type Required Default Value Description
type string N 对特质定义名称的引用。对于一种类型的特质,一个组件中可能只有一个配置。
properties Properties Y 使用该特性的属性值。

请注意,Traits不需要名字,因为是OAM运行时负责实例化traits。组件的名称被期望用于相关的特征。

Properties

属性(Properties)指定与实体属性相关的值。

当与组件关联时,设置的值将覆盖组件的参数,遵循组件原理图中定义的原理图。

当属性被用于特质或作用域时,它们会设置这些实体所需的值,以便被实例化。结构是由定义引用决定的。它可能是一个简单的值,也可能是一个复杂的对象。属性会根据适合于特质或作用域的模式进行验证。

示例

下面是一个完整的YAML文件的例子,它表达了组件、特性和作用域。这个例子说明了一个组件的四个可配置元素:它的类型、属性、特征和作用域。

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: my-example-app
  annotations:
    version: v1.0.0
    description: "Brief description of the application"
spec:
  components:
    - name: publicweb
      type: web-ui
      properties: # properties targeting component parameters.
        image: example/web-ui:v1.0.2@sha256:verytrustworthyhash
        param_1: "enabled" # param_1 is defined on the web-ui component
      traits:
        - type: ingress # ingress trait providing a public endpoint for the publicweb component of the application.
          properties: # properties are defined by the trait CRD spec. This example assumes path and port.
            path: /
            port: 8080
      scopes:
        "healthscopes.core.oam.dev": "app-health" # An application level health scope including both components.
    - name: backend
      type: company/test-backend # test-backend is referenced from other namespace
      properties:
        debug: "true" # debug is a parameter defined in the test-backend component.
      traits:
        - type: scaler # scaler trait to specify the number of replicas for the backend component
          properties:
            replicas: 4
      scopes:
        "healthscopes.core.oam.dev": "app-health" # An application level health scope including both components.

上面的例子说明了一个完整的应用程序,包括它的作用域、组件和它们的特质。这个应用程序假定存在两个组件定义,分别代表网络用户界面和一个假想的应用程序的后台。两个特性被用来增强组件的功能。首先是后端设置复制因子的扩展器,以及将应用程序暴露给外部世界的入口器。此外,HealthScope被用来有一个共同点来检查网络和后端组件的状态。这是一个任意的组件集,不一定需要所有的组件。

在应用实例化时,运行时有望根据目标系统(如Kubernetes)生成所需的实体,并强制执行与每个实体(如trait)相关的模式。由于特质可以作为扩展添加到现有环境中,运行时必须能够创建任何通过特质定义(TraitDefinition)在系统上注册的特质实体。

组件实例

组件实例是在应用程序的部署过程中创建的。它是在一个组件与配置一起部署时创建的。

  • 每次部署一个组件时,它必须与一个应用程序一起部署。本规范的这一部分描述了配置。
  • 组件的每一次后续升级都会修改给定的实例,或者如果有任何修订意识的特征附加到组件上,则会产生一个新的修订实例。
  • 当一个实例第一次被创建时,它处于初始修订状态。每次发生升级操作时,我们就说该实例发生了新的修订。(然而,并没有假设一定有一个相应的修订对象存储在某个地方)。

发布

在十二因素应用中,发布(release)被定义为 构建加上一组配置。也就是说,对构建或配置的任何改变都会产生一个新的版本。在开放应用模型中,类似的情况是,组件、特质和作用域对象与应用相结合,共同构成一个发布。

对于OAM应用程序,发布是这样定义的:

发布是一个命名的应用程序,连同其相关的组件、作用域和特性的描述。

此外,当一个应用程序被发布时,它的组件实例也被发布。

为了适应这个发布的定义,OAM平台应该做出以下假设:

  • 应用程序是可变的。

  • 对应用程序的任何改变都会导致(从概念上讲)一个新的发布,取代旧的发布。

    • 如果应用程序被更新,并且新版本包括原始应用程序中不存在的组件,则必须创建组件实例。
    • 如果应用程序被更新,而新版本中没有以前的应用程序所包含的组件的记录,那么该组件实例必须被删除。
    • 同样,特性也应该根据同样的准则被附加和分离。
    • 组件与应用范围的关系应根据同样的准则来应用或删除。

9 - 实用考虑因素

就实现者的实际考虑提供了额外的指导

https://github.com/oam-dev/spec/blob/master/8.practical_considerations.md

本节就实现者的实际考虑提供了额外的指导。

提案阶段和规范的成熟度

该模型目前处于粗略草案(Rough Draft)阶段,正在向工作草案(Working Draft)方向努力。在工作草案之后,该规范将成为最终规范(例如,1.0)。

  • 在粗略草案期间,模型的任何部分都不被认为是稳定的。
  • 在工作草案期间,可能会增加功能,并修复问题。破坏性的变化可能会发生,但是作为一种不规则的现象
  • 在最终规范期间,模型将只更新勘误表、语法修正和明确标明的 “澄清性文本”

一旦最终规范发布(例如,1.0),新版本的规范(例如,1.1)可能会在粗略的草案阶段开始。

媒体类型

示意图的媒体类型将在模型进入工作草案状态时被定义。初步来说,媒体类型将是以下形式:

  • application/oam.TYPE.v1+json,其中 TYPE 由类型的名称(如组件component)代替。

安全性

这个模型在其目前的形式下,并不强制要求一套特定的安全策略。然而,它确实提供了关于安全的某些方面的指导:

  • OCI/Docker图像必须尽可能通过SHA来引用
  • 文件格式必须被转换为标准格式,以便它们可以被哈希

当这两个条件得到满足时,可以构建系统,其中原理图的摘要验证将保持系统所有组件的不可更改性。也就是说,如果一个原理图用哈希值引用一个图像,那么验证原理图摘要的过程也会确保所拉出的图像具有用于生成原理图的相同引用。

其他安全细节,如网络传输安全或确保静态数据的安全,被认为超出了本模型的范围。

10 - 设计原则

开放应用模式遵循一套设计原则,以确保该模式的清晰性、丰富性和可扩展性。

https://github.com/oam-dev/spec/blob/master/9.design_principles.md

开放应用模式遵循一套设计原则,以确保该模式的清晰性、丰富性和可扩展性。

关心点分离

关心点分离是一种设计理念,在这种理念中,架构的选择是参照正在解决的离散问题来进行的。像 “组件” 和 “应用”,或者 “原理图” 和 “配置” 这样的人工制品的划分是按照功能或行为线划分的。通过确定各种用户群体的角色和责任,规范被划分为与问题空间相匹配的概念。

运行时中立性

开放应用模式是运行时无关的。它不假设任何运行时的特定功能。相反,它的目的是为应用程序的所有者和运维人员提供一个通用的词汇表,以描述所需的拓扑结构和行为,不受任何特定平台的影响。

平衡(优雅)

在确保关注点分离的同时,OAM试图避免对在小型团队中承担多种角色的用户造成不必要的复杂性。简单的方案应该可以用最少的时间和精力投入来实现,但复杂的方案应该在不需要重新平台化的情况下得到满足。

OAM提供了多个抽象层,因此可以独立于开发人员的关注点来捕捉运维上的问题。

可重用性

OAM示意图中的组件被设计为可重复使用和可共享。此外,它们保持独立于它们所描述的代码,使得有可能重新使用代码(容器),并防止 “锁定” 条件。

该模型作为一个整体被设计用来提供应用程序的 “分布(distributions)",在这种情况下,同一个应用程序可以在不同的平台上执行而不被改变。应用程序的这种可移植性旨在使以下情况不仅是可能的,而且是容易的:

  • 将应用程序从开发者工作站转移到生产集群或服务中
  • 在不改变代码的情况下从一个实施方案迁移到另一个实施方案
  • 创建类似市场的环境,使应用程序可以部署到客户平台上。

应用模型不是编程模型

应用模型和编程模型之间有明显的区别。应用模型描述了一个应用程序的组成和其组件的拓扑结构。它不关心每个组件是如何实现的(语言、设计模式等)。

另一方面,编程模型描述了单独的软件是如何组成的。它被开发者用来实现应用组件。开放应用模型提供了一个没有任何编程模型要求的应用模型。