做者:
刘洋(炎寻) EDAS-OAM 架构与开发负责人
邓洪超 OAM spec maintainer
孙健波(天元) OAM spec maintainerlinux
随着以 K8s 为主的云原生基础架构遍地生根,愈来愈多的团队开始基于 K8s 搭建持续部署、自助式发布体验的应用管理平台。然而,在 K8s 交付和管理应用方面,目前还缺少一个统一的标准,这最终促使咱们与微软联合推出了首个云原生应用标准定义与架构模型 - OAM。本文做者将从基本概念以及各个模块的封装设计与用法等角度出发来详细解读 OAM。git
OAM 主要有三个特色:github
OAM 综合考虑了在公有云、私有云以及边缘云上应用交付的解决方案,提出了通用的模型,让各平台能够在统一的高层抽象上透出应用部署和运维能力,解决跨平台的应用交付问题。同时,OAM 以标准化的方式沟通和链接应用开发者、运维人员、应用基础设施,让云原生应用交付和管理流程更加连贯、一致。web
OAM 将应用相关的人员划分为 3 个角色:数据库
应用开发:关注应用代码开发和运行配置,是应用代码的领域专家,应用开发完成后打包(好比镜像)交给应用运维;json
应用运维:关注配置和运行应用实例的生命周期,好比灰度发布、监控、报警等操做,是应用运维专家;windows
平台运维:关注应用运行平台的能力和稳定性,是底层(好比 Kubernetes 运维/优化,OS 等)的领域专家。api
OAM 包含如下核心概念:缓存
应用开发使用服务组件来声明应用的属性(配置项),运维人员定义这些属性以后就能按照组件声明获得运行的组件实例,组件声明包含如下信息:微信
运维人员使用应用边界将组件组成松耦合的应用,能够赋予这组组件一些共用的属性和依赖,应用边界声明包含如下信息:
运维人员使用运维特征赋予组件实例特定的运维能力,好比自动扩缩容,一个 Trait 可能仅限特定的工做负载类型,它们表明了系统运维方面的特性,而不是开发的特性,好比开发者知道本身的组件是否能够扩缩容,可是运维能够决定是手动扩缩容仍是自动扩缩容,特征声明包含如下信息:
描述特定工做负载的底层运行时,平台须要可以提供对应工做负载的运行时,工做负载声明包含如下信息:
运维人员使用应用配置将组件、特征和应用边界的组合在一块儿实例化部署,应用配置声明包含如下信息:
OAM 认为:
一个云原生应用由一组相互关联但又离散独立的组件构成,这些组件实例化在合适的运行时上,由配置来控制行为并共同协做提供统一的功能。
更加具体的说:
一个 Application 由一组 Components 构成,每一个 Component 的运行时由 Workload 描述,每一个 Component 能够施加 Traits 来获取额外的运维能力,同时咱们可使用 Application scopes 将 Components 划分到 1 或者多个应用边界中,便于统一作配置、限制、管理。
总体的运行模式以下所示:
组件、运维特征、应用边界经过应用配置(Application Configuration)实例化,而后再经过 OAM 的实现层翻译为真实的资源。
使用 OAM 来管理云原生应用,其核心主要是围绕着“四个概念,一个动做”。
下发应用配置以后 OAM 平台将会实例化四个概念获得运行的应用。
一个 OAM 平台在对外提供 OAM 应用管理界面时,必定是预先已经准备好了“运维特征,应用边界”供运维人员使用,准备好了“工做负载”供开发者使用,同时开发者准备“组件”供运维人员使用。所以角色划分就很明了:
如何使用上面“四个概念,一个动做”来部署一个 OAM 应用呢?
咱们假想一个场景,用户的应用有两个组件:frontend 和 backend,其中 frontend 组件须要域名访问、自动扩缩容能力,而且 frontend 要访问 backend,二者应该在同一个 vpc 内,基于这个场景咱们须要有:
frontend 的 workload 类型是 Server 容器服务(OAM 平台提供该工做负载):
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata: name: frontend annotations: version: v1.0.0 description: "A simple webserver" spec: workloadType: core.oam.dev/v1.Server parameters: - name: message description: The message to display in the web app. type: string value: "Hello from my app, too" containers: - name: web env: - name: MESSAGE fromParam: message image: name: example/charybdis-single:latest
backend 的 workload 是 Cassandra(OAM 平台提供该工做负载):
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata: name: backend annotations: version: v1.0.0 description: "Cassandra database" spec: workloadType: data.oam.dev/v1.Cassandra parameters: - name: maxStalenessPrefix description: Max stale requests. type: int value: 100000 - name: defaultConsistencyLevel description: The default consistency level type: string value: "Eventual" workloadSettings: - name: maxStalenessPrefix fromParam: maxStalenessPrefix - name: defaultConsistencyLevel fromParam: defaultConsistencyLevel
apiVersion: core.oam.dev/v1alpha1 kind: Trait metadata: name: Ingress spec: type: core.oam.dev/v1beta1.Ingress appliesTo: - core.oam.dev/v1alpha1.Server parameters: properties: | { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "host": { "type": "string", "description": "ingress hosts", }, "path": { "type": "string", "description": "ingress path", } } }
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationScope metadata: name: network annotations: version: v1.0.0 description: "network boundary that a group components reside in" spec: type: core.oam.dev/v1.NetworkScope allowComponentOverlap: false parameters: - name: network-id description: The id of the network, e.g. vpc-id, VNet name. type: string required: Y - name: subnet-ids description: > A comma separated list of IDs of the subnets within the network. For example, "vsw-123" or ""vsw-123,vsw-456". There could be more than one subnet because there is a limit in the number of IPs in a subnet. If IPs are taken up, operators need to add another subnet into this network. type: string required: Y - name: internet-gateway-type description: The type of the gateway, options are 'public', 'nat'. Empty string means no gateway. type: string required: N
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationConfiguration metadata: name: my-vpc-network spec: variables: - name: networkName value: "my-vpc" scopes: - name: network type: core.oam.dev/v1alpha1.Network properties: - name: network-id value: "[fromVariable(networkName)]" - name: subnet-ids value: "my-subnet1, my-subnet2"
使用应用配置将上面的组件、边界、特征组合起来便可部署一个应用,这个由应用的运维人员提供:
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationConfiguration metadata: name: custom-single-app annotations: version: v1.0.0 description: "Customized version of single-app" spec: variables: - name: message value: "Well hello there" - name: domainName value: "www.example.com" components: - componentName: frontend instanceName: web-front-end parameterValues: - name: message value: "[fromVariable(message)]" traits: - name: Ingress properties: - name: host value: "[fromVaraible(domainName)]" - name: path value: "/" applicationScopes: - my-vpc-network - componentName: backend instanceName: database applicationScopes: - my-vpc-network
经过以上完整的使用流程咱们能够看到:应用配置是真正部署应用的起点,在使用该配置的时候,对应的组件、应用边界、特征都要提早部署好,运维人员只需作一个组合便可。
服务组件的意义是让开发者声明离散执行单元的运行时特性,能够用 JSON/YAML 格式来表示,其声明遵循 Kubernetes API 规范,区别在于:
下面咱们来看看具体的组件声明如何定义。
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
apiVersion | string | Y | 特定oam spec版本,好比core.oam.dev/v1 | |
kind | string | Y | 类型,对于组件来讲就是 ComponentSchematic |
|
metadata | Metadata | Y | 组件元数据 | |
spec | Spec | Y | 组件特定的定义属性 |
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | ||
labels | map[string]string | N | k/v对做为组件的lebels | |
annotations | map[string]string | N | k/v对做为组件的描述信息 |
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
parameters | []Parameter | N | 组件的可配置项 | |
workloadType | string | Y | 简明语义化的组件运行时描述,以K8s为例就是指定底层使用StatefulSet仍是Deployment这样 | |
osType | string | N | linux | 组件容器运行时依赖的操做系统类型,可选值: - linux - windows |
arch | string | N | amd64 | 组件容器运行时依赖的CPU架构,可选值: - i386 - amd64 - arm - arm64 |
containers | []Container | N | 实现组件的OCI容器们 | |
workloadSettings | []WorkloadSettings | N | 须要传给工做负载运行时的非容器配置声明 |
上面的 workloadType 后面会有详细说明,这里简要来讲就是开发者能够指定该 field 告诉运行时该组件如何被执行。工做负载命名的规范是 GROUP/VERSION.KIND,和 K8s 资源类型坐标一致,好比:
core.oam.dev 表示是 oam 内置的分组,oam 内置的表示任何 OAM 实现都支持该类型的工做负载,v1alpha1 表示依旧是 alpha 状态,类型是 Singleton,这表示运行时应该只运行一个组件实例,不管谁提供。
alibabacloud.com 表示该对象是一个运营商特定的实现,不必定全部平台都实现,版本 v1 表示实现已经稳定,类型是 Function 表示运行时是 Alibaba Functions 提供的。
表示该对象是一个第三方组织实现,不必定全部平台都实现,版本 v1beta2 表示实现已经趋于稳定,类型是 Kafka 表示运行时是开源组件 Kafka 提供的。
工做负载主要分为两类:
属于 core.oam.dev 分组,全部对象都须要 oam 平台实现,都是容器运行时,该 Spec 目前定义了以下核心工做负载类型:
名字 | 类型 | 是否对外提供服务 | 是否能够多副本运行 | 是否常驻 |
---|---|---|---|---|
Server | core.oam.dev/v1alpha1.Server | Y | Y | Y |
Singleton Server | core.oam.dev/v1alpha1.SingletonServer | Y | N | Y |
Worker | core.oam.dev/v1alpha1.Worker | N | Y | Y |
Singleton Worker |
core.oam.dev/v1alpha1.SingletonWorker | N | N | Y |
Task | core.oam.dev/v1alpha1.Task | N | Y | N |
Singleton Task | core.oam.dev/v1alpha1.SingletonTask | N | N | N |
Server:定义了容器运行时能够运行 0 或多个容器实例,该工做负载提供了冗余的可扩缩容的多副本常驻服务,在 K8s 平台可使用 Deployment 或者 Statefulset 加上 Service 来实现;
Singleton Server:定义了容器运行时只能运行一个容器实例,该工做负载提供了没法冗余的单副本常驻服务,在 K8s 平台可使用副本为 1 的 Statefulset 加上 Service 来实现;
Worker:定义了容器运行时能够运行 0 或多个容器实例,该工做负载提供了冗余的可扩缩容的多副本常驻实例可是不提供服务,在 K8s 平台可使用 Deployment 或者 Statefulset 来实现;
Singleton Worker:定义了容器运行时只能运行一个容器实例,该工做负载提供了没法冗余的单副本常驻实例可是不提供服务,在 K8s 平台可使用副本为 1 的 Statefulset 来实现;
Task:定义了很是驻可冗余的容器运行时,运行完就退出,能够赋予扩缩容特性,在 K8s 平台可使用 Job 来实现;
Singleton Task:定义了很是驻非冗余的容器运行时,运行完就退出,在 K8s 平台可使用 completions=1 的 Job 来实现。
核心工做负载必须给定 container 部分,实现核心工做负载的 OAM 平台必须不依赖 workloadSettings。
扩展工做负载类型是平台运行时特定的,由各个 OAM 平台自定提供,当前版本的 Spec 不支持用户自定义工做负载类型,只能是平台方提供,扩展工做负载可使用非容器运行时,workloadSettings 的目的就是为了扩展工做负载类型的配置。
工做负载的定义是一应俱全的,他容许任何部署的服务做为工做负载,不管是容器化仍是虚拟机,基于此,咱们能够将缓存,数据库,消息队列都做为工做负载,若是组件指定的工做负载在平台没有提供,应该快速失败将信息返回给用户。
除了 WorkloadType,能够看到组件 Spec 内嵌了 3 种结构体,下面来看看它们的定义:
1.Parameter
定义了该组件的全部可配置项,其定义以下:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | ||
description | string | N | 组件的简短描述 | |
type | string | Y | 参数类型,JSON定义的boolean, number, ... | |
required | boolean | N | false | 参数值是否必须提供 |
default | 同上面的type | N | 参数的默认值 |
2.Container
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | 容器名字,在组件内必须惟一 | |
iamge | string | Y | 镜像地址 | |
resources | Resources | Y | 镜像运行最小资源需求 | |
env | []Env | N | 环境变量 | |
ports | []Port | N | 暴露端口 | |
livenessProde | HealthProbe | N | 健康状态检查指令 | |
readinessProbe | HealthProbe | N | 流量可服务状态检查指令 | |
cmd | []string | N | 容器运行入口 | |
args | []string | N | 容器运行参数 | |
config | []ConfigFile | N | 容器内能够访问的配置文件 | |
imagePullSecrets | string | N | 拉取容器的凭证 |
其中 Resources 的定义以下:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
cpu | CPU | Y | 容器运行所需的cpu资源 | |
memory | Memory | Y | 容器运行所需的memory资源 | |
gpu | GPU | N | 容器运行所需的gpu资源 | |
volumes | []Volume | N | 容器运行所需的存储资源 | |
extended | []ExtendedResource | N | 容器运行所需的外部资源 |
其中 CPU/Memory/GPU 都是数值型,不赘述,Volume 的定义以下:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | 数据卷的名字,引用的时候使用 | |
mountPath | string | Y | 实际在文件系统的挂载路径 | |
accessMode | string | N | RW | 访问模式,RW或RO |
sharingPolicy | string | N | Exclusive | 挂载共享策略,Exclusive或者Shared |
disk | Disk | N | 该数据卷使用底层磁盘资源的属性 |
Disk 指定存储是否须要持久化,最小的空间需求,定义以下:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
required | string | Y | 最小磁盘大小需求 | |
ephemeral | boolean | N | 是否须要挂载外部磁盘 |
ExtendedResource 描述特定实现的资源需求,好比 OAM 运行时平台可能提供特殊的硬件,这个字段容许容器声明须要这个特定的 offering:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
required | string | Y | 须要的条件 | |
name | string | Y | 资源名字,好比GV.K |
Env,Port,HealthProbe 和 K8s 相似,这里再也不赘述。
3.WorkloadSetting
工做负载的附加配置,用于非容器运行时(固然,也能够用于容器运行时工做负载的附加字段)。
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | 参数名 | |
type | string | N | string | 参数类型,用于实现的hint |
value | any | N | 参数值,若是没有fromParam则用该值 | |
fromParam | string | N | 参数引用,覆盖value |
这组配置会传给运行时,一个运行时能够返回错误,若是特定的限制没有知足,好比:
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata: name: frontend annotations: version: v1.0.0 description: > Sample component schematic that describes the administrative interface for our Twitter bot. spec: workloadType: core.oam.dev/v1alpha1.Server osType: linux parameters: - name: username description: Basic auth username for accessing the administrative interface type: string required: true - name: password description: Basic auth password for accessing the administrative interface type: string required: true - name: backend-address description: Host name or IP of the backend type: string required: true containers: - name: my-twitter-bot-frontend image: name: example/my-twitter-bot-frontend:1.0.0 digest: sha256:6c3c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3b resources: cpu: required: 1.0 memory: required: 100MB ports: - name: http value: 8080 env: - name: USERNAME fromParam: 'username' - name: PASSWORD fromParam: 'password' - name: BACKEND_ADDRESS fromParam: 'backend-address' livenessProbe: httpGet: port: 8080 path: /healthz readinessProbe: httpGet: port: 8080 path: /healthz
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata: name: alibabacloudFunctions annotations: version: v1.0.0 description: "Extended workflow example" spec: workloadType: alibabacloud.com/v1.Function parameters: - name: github-token description: GitHub API session key type: string required: true workloadSettings: - name: source value: git://git.example.com/function/myfunction.git - name: github_token fromParam: github-token
组件声明是由开发者或者 OAM 平台给出,透出应用运行的可配置项、依赖的平台和工做负载,能够当作是一个声明了运行环境的函数定义,运维人员填写函数参数以后,组件就会按照声明的功能运行起来。
应用边界经过提供不一样形式的应用边界以及共有的分组行为来将组件组成逻辑的应用,应用边界具有如下通用的特征:
下图说明了组件能够属于多个重叠的应用分组,最终建立出不一样的应用边界。
上图有两种应用边界类型:Network 与 Health,有四个组件分布在不一样的应用边界实例中:
主要是有两种应用边界类型:
定义基本运行时行为的分组结构,它们拥有以下特征:
当前 Spec 定义的应用边界类型有:
Name | Type | Description |
---|---|---|
Network | core.oam.dev/v1alpha1.Network | 该边界将组件组织到一个子网边界而且定义统一的运行时网络模型,以及infra网络描述的定义和规则 |
Health | core.oam.dev/v1alpha1.Health | 该边界将组件组织到一个聚合的健康组中,信息能够用于回滚和升级 |
对于运行时来讲是 optional 的,能够自定义。
apiVersion,kind,metadata 和前面组件一致,不赘述,主要描述 Spec:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
type | string | Y | 应用边界类型 | |
allowComponentOverlap | bool | Y | 决定是否容许一个组件同时出如今多个该类型应用边界实例中 | |
parameters | []Parameter | N | 边界的可配置参数 |
用于将组件划分到一个网络或者 SDN 中,网络自己必须被 infra 定义和运维,也能够被流量管理 Traits 查询,用于发现 service mesh 的可发现边界或者 API 网关的 API 边界:
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationScope metadata: name: network annotations: version: v1.0.0 description: "network boundary that a group components reside in" spec: type: core.oam.dev/v1.NetworkScope allowComponentOverlap: false parameters: - name: network-id description: The id of the network, e.g. vpc-id, VNet name. type: string required: Y - name: subnet-id description: The id of the subnet within the network. type: string required: Y - name: internet-gateway-type description: The type of the gateway, options are 'public', 'nat'. Empty string means no gateway. type: string required: N
用于聚合组件的健康状态,能够设计的参数有健康阈值(超过该阈值的组件不健康则认为整个边界不健康),健康边界实例自己不会用健康状态作任何操做,它只是分组健康聚合器,其信息能够被查询并用于其余地方,好比:
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationScope metadata: name: health annotations: version: v1.0.0 description: "aggregated health state for a group of components." spec: type: core.oam.dev/v1alpha1.HealthScope allowComponentOverlap: true parameters: - name: probe-method description: The method to probe the components, e.g. 'httpGet'. type: string required: true - name: probe-endpoint description: The endpoint to probe from the components, e.g. '/v1/health'. type: string required: true - name: probe-timeout description: The amount of time in seconds to wait when receiving a response before marked failure. type: integer required: false - name: probe-interval description: The amount of time in seconds between probing tries. type: integer required: false - name: failure-rate-threshold description: If the rate of failure of total probe results is above this threshold, declared 'failed'. type: double required: false - name: healthy-rate-threshold description: If the rate of healthy of total probe results is above this threshold, declared 'healthy'. type: double required: false - name: health-threshold-percentage description: The % of healthy components required to upgrade scope type: double required: false - name: required-healthy-components description: Comma-separated list of names of the components required to be healthy for the scope to be health. type: []string required: false
限制分组内全部组件的资源使用总量上限。
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationScope metadata: name: myResourceQuotas annotations: version: v1.0.0 description: "The production configuration for Corp CMS" spec: type: resources.oam.dev/v1.ResourceQuotaScope allowComponentOverlap: false parameters: - name: CPU description: maximum CPU to be consumed by this scope type: double required: Y - name: Memory description: maximum memory to be consumed by this scope type: double required: Y
应用边界声明由 OAM 平台提供,透出应用边界实例运行的可配置项,能够当作是一个函数定义,运维人员或者平台填写函数参数以后,应用边界就会按照声明的功能运行起来,对该边界内的组件们起做用。
OAM Spec 的实现平台应该提供 Traits 给组件工做负载加强运维操做,一个 Trait 是一种自由的运行时,加强工做负载提供额外的功能,好比流量路由规则、自动扩缩容规则、升级策略等,这让应用运维具有根据需求配置组件,不须要开发者参与的能力。一个独立的 Trait 能够绑定 1 或多个工做负载类型,它能够声明哪些工做负载类型才能使用该Trait。
目前 Traits 主要分为三类:
apiVersion,kind,metadata 和前面组件一致,不赘述,主要描述 Spec:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
appliesTo | []string | N | ["*"] | 该Trait能够应用的工做负载类型 |
properties | []Properties | N | Trait的可配置参数,使用JSON Schema来表达。 |
apiVersion: core.oam.dev/v1alpha1 kind: Trait metadata: name: ManualScaler annotations: version: v1.0.0 description: "Allow operators to manually scale a workloads that allow multiple replicas." spec: appliesTo: - core.oam.dev/v1alpha1.Server - core.oam.dev/v1alpha1.Worker - core.oam.dev/v1alpha1.Task properties: | { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "required": ["replicaCount], "properties": { "replicaCount": { "type": "integer", "description": "the target number of replicas to scale a component to.", "minimum": 0 } } }
上面是一个手动扩缩容服务的 Trait,只有一个参数就是 replicaCount。
应用特征声明由 OAM 平台提供,透出应用特征的可配置项,标明了可做用于的工做负载,能够当作函数定义,运维人员或者平台填写实参以后,应用特征就会按照声明的功能运行起来,对绑定的组件起做用。
应用配置主要是描述应用如何被部署的,一个组件能够部署到任意的运行时,咱们称一个组件的一次部署为实例,每次组件部署的时候必须有应用配置。
应用配置由应用运维管理,提供当前组件实例的信息:
一个实例是组件的可追溯部署,当组件部署时建立,后续该组件的升级都是修改该实例,回滚/从新部署都属于升级,实例都会有名字方便引用。当一个实例首次建立时,处于初始发行 (release) 状态,每次升级操做以后,一个新的发行就会建立。
任何对组件自己或者其配置的变动都会建立一个新的发行,一个发行就是应用配置以及它对组件、应用特征、应用边界的定义,当一个发行被部署,对应的组件、应用特征和应用边界也会被部署。
基于该定义,平台须要保证如下变动语义:
一个组件能够部署到多个不一样的运行时,在每一个运行时中应用配置的实例与应用配置之间是 1:1 的关系,应用配置由应用运维管理,包含 3 个主要部分:
组件实例定义:定义一个组件实例如何部署,这个定义自己有 3 个部分:
apiVersion,kind,metadata 和前面组件一致,不赘述,主要描述 Spec:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
variables | []Variable | N | 能够在参数值和属性中引用的变量 | |
scopes | []Scope | N | 应用边界定义 | |
components | []Component | N | 组件实例定义 |
variables 就是一个 k/v 对,一个集中的地方定义运维的变量,在运维配置的其余地方均可以用 fromVariable(VARNAME) 引用:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | 变量名字 | |
value | string | Y | 标量值 |
scopes 定义该运维配置将要建立的应用边界,其定义为:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | 应用边界名字 | |
type | string | Y | 应用边界的GROUP/VERSION.KIND | |
properties | Properties | N | 覆盖边界的参数 |
components 是组件实例定义,而不是组件定义:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
componentName | string | Y | 组件名 | |
instanceName | string | Y | 组件实例名 | |
parameterValues | []ParameterValue | N | 覆盖组件的参数 | |
Traits | []Trait | N | 指定组件实例绑定的Traits | |
applicationScopes | []string | N | 指定组件运行的应用边界 |
Trait 在这里的定义是:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | Trait实例名 | |
properties | Properties | N | 覆盖Trait的参数 |
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationConfiguration metadata: name: my-app-deployment annotations: version: v1.0.0 description: "Description of this deployment" spec: variables: - name: VAR_NAME value: SUPPLIED_VALUE scopes: - name: core.oam.dev/v1alpha1.Network parameterValues: - name: PARAM_NAME value: SUPPLIED_VALUE components: - componentName: my-web-app-component instanceName: my-app-frontent parameterValues: - name: PARAMETER_NAME value: SUPPLIED_VALUE - name: ANOTHER_PARAMETER value: "[fromVariable(VAR_NAME)]" traits: - name: Ingress properties: CUSTOM_OBJECT: DATA: "[fromVariable(VAR_NAME)]"
应用配置定义由运维人员或者 OAM 平台提供,描述应用的部署,能够当作是一个函数调用,运维人员或者 OAM 平台填写实参以后,调用以前定义的组件、应用特征、应用边界等函数,这些实例一块儿做用对外提供应用服务。
Workload 类型和 Trait 同样由平台提供,因此用户能够查看平台提供哪些工做负载,对于平台用户来讲工做负载类型没法扩展,只能由平台开发者扩展提供,所以平台必定不容许用户建立自定义的工做负载类型。
apiVersion,kind,metadata 和前面组件相似,不赘述,这里主要描述 Spec,定义组件如何使用工做负载类型,除此以外暴露了底层工做负载运行时的可配置参数:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
group | string | Y | 该工做负载类型所属的group | |
names | Names | Y | 该工做负载类型的关联名字信息 | |
settings | []Setting | N | 该工做负载的设置选项 |
Names 就是描述了对应类型的不一样形式名字引用:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
kind | string | Y | 工做负载类型的正确引用名字,好比Singleton | |
singular | string | N | 单数形式的可读名字,好比singleton | |
plural | string | N | 复数形式的可读名字,好比singletons |
Setting 描述工做负载可配置部分,相似前面组件的 Parameters,都是 schema:
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
name | string | Y | 配置名,每一个workload类型必须惟一 | |
description | string | N | 配置说明 | |
type | string | Y | 配置类型 | |
required | bool | N | false | 是否必须提供 |
default | indicated by type | N | 默认值 |
经过上面的介绍,咱们了解了 OAM Spec 里面的基本概念和定义,以及如何使用它们来描述应用交付和运维流程。然而,OAM 能给咱们带来什么样的价值呢?咱们评判一个好的架构体系,不只是由于它在技术上更先进,更主要的是它可以解决一些实际问题,为用户带来价值。因此,接下来咱们将总结一下这方面的内容。
OAM 的价值要从下往上三个层面来讲起。
基础设施,指的是像 K8s 这类的提供基础服务能力与抽象的一层服务体系。拿 K8s 来讲,它提供了许多种类的基础服务和强大的扩展能力来灵活扩展其余基础服务。
可是,使用基础设施的运维人员很快就发现 K8s 存在一个问题:缺少统一的机制来注册和管理自定义扩展能力。这些扩展能力的表达方式不够统一,有些是 CRD、有些是 annotation、有些是 Config...
这种乱象使得基础设施用户不知道平台上都提供了哪些能力,不知道怎么使用这些能力,更不知道这些能力互相之间的兼容组合关系。
OAM 提供了抽象(如 Workload/Trait 等)来统必定义和管理这些能力。有了 OAM,各平台实现就有了统一的标准规范去透出公共的或差别化的能力:公共的基础服务像容器部署、监控、日志、灰度发布;差别化的、高级复杂的能力像 CronHPA(周期性定时变化的强化版 HPA)。
应用运维,指的是像给应用加上网络接入、复杂均衡、弹性伸缩、甚至是建站等运维操做。可是,运维的一个痛点就是原来这些能力并非跨平台的:这致使在不一样平台、不一样环境下去部署和运维应用的操做,是不互通和不兼容的。
上面这个问题,是客户应用、尤为是传统 ERP 应用上云的一大阻碍。咱们作 OAM 的一个初衷,就是经过一套标准定义,让不一样的平台实现也经过统一的方式透出。咱们但愿:哪怕一个应用不是生在云上、长在云上,也可以遇上这趟通往云原生将来的列车,拥抱云带来的变化和红利!
OAM 提供的抽象和模型,是咱们通往统1、标准的应用架构的强有力工具。这些标准能力之后都会经过 OAM 输出,让运维人员轻易去实现跨平台部署。
应用开发,指的就是业务逻辑开发,这是业务产生价值的核心位置。
也正因如此,咱们但愿,应用开发者可以专一于业务开发,而不须要关心运维细节。可是,K8s 提供的 API,并无很好地分离开发和运维的关注点,开发和运维之间须要来回沟通以免产生误解和冲突。
OAM 分离了开发和运维的关注点,很好地解决了以上问题,让整个发布流程更加连贯、高效。
目前,OAM 已经在阿里云 EDAS 等多个项目中进行了数月的内部落地尝试。咱们但愿经过一套统1、标准的应用定义体系,承载云应用管理项目产品与外部资源关系的高效管理体验,并将这种体验统一带给了基于 Function、ECS、Kubernetes 等不一样运行时的应用管理流程;经过应用特征系统,将多个阿里云独有的能力进行了模块化,大大提升了阿里云基础设施能力的交付效率。
通过了前一段努力的铺垫,咱们也慢慢明确了接下来的工做方向:
为了可以让社区更加高效、健康的运转下去,咱们很是期待获得您的反馈,并与你们密切协做,针对 Kubernetes 和任意云环境打造一个简单、可移植、可复用的应用模型。参与方式:
(****钉钉扫码加入交流群****)
欢迎你与咱们一块儿共建这个全新的应用管理生态!
“ 阿里巴巴云原生微信公众号(ID:Alicloudnative)关注微服务、Serverless、容器、Service Mesh等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,作最懂云原生开发者的技术公众号。”
更多相关信息,请关注“阿里巴巴云原生”。