4 个概念,1 个动作,让应用管理变得更简单
作者:
劉洋(炎尋) EDAS-OAM 架構(gòu)與開發(fā)負(fù)責(zé)人
鄧洪超 OAM spec maintainer
孫健波(天元) OAM spec maintainer
隨著以 K8s 為主的云原生基礎(chǔ)架構(gòu)遍地生根,越來越多的團(tuán)隊(duì)開始基于 K8s 搭建持續(xù)部署、自助式發(fā)布體驗(yàn)的應(yīng)用管理平臺。然而,在 K8s 交付和管理應(yīng)用方面,目前還缺乏一個(gè)統(tǒng)一的標(biāo)準(zhǔn),這最終促使我們與微軟聯(lián)合推出了首個(gè)云原生應(yīng)用標(biāo)準(zhǔn)定義與架構(gòu)模型 - OAM。本文作者將從基本概念以及各個(gè)模塊的封裝設(shè)計(jì)與用法等角度出發(fā)來詳細(xì)解讀 OAM。
OAM 主要有三個(gè)特點(diǎn):
- 開發(fā)和運(yùn)維關(guān)注點(diǎn)分離:開發(fā)者關(guān)注業(yè)務(wù)邏輯,運(yùn)維人員關(guān)注運(yùn)維能力,讓不同角色更專注于領(lǐng)域知識和能力;
- 平臺無關(guān)與高可擴(kuò)展:應(yīng)用定義與平臺實(shí)現(xiàn)解耦,應(yīng)用描述支持跨平臺實(shí)現(xiàn)和可擴(kuò)展性;
- 模塊化應(yīng)用部署和運(yùn)維特征:應(yīng)用部署和運(yùn)維能力可以描述成高層抽象模塊,開發(fā)和運(yùn)維可以自由組合和支持模塊化實(shí)現(xiàn)。
OAM 綜合考慮了在公有云、私有云以及邊緣云上應(yīng)用交付的解決方案,提出了通用的模型,讓各平臺可以在統(tǒng)一的高層抽象上透出應(yīng)用部署和運(yùn)維能力,解決跨平臺的應(yīng)用交付問題。同時(shí),OAM 以標(biāo)準(zhǔn)化的方式溝通和連接應(yīng)用開發(fā)者、運(yùn)維人員、應(yīng)用基礎(chǔ)設(shè)施,讓云原生應(yīng)用交付和管理流程更加連貫、一致。
角色分類
OAM 將應(yīng)用相關(guān)的人員劃分為 3 個(gè)角色:
-
應(yīng)用開發(fā):關(guān)注應(yīng)用代碼開發(fā)和運(yùn)行配置,是應(yīng)用代碼的領(lǐng)域?qū)<?#xff0c;應(yīng)用開發(fā)完成后打包(比如鏡像)交給應(yīng)用運(yùn)維;
-
應(yīng)用運(yùn)維:關(guān)注配置和運(yùn)行應(yīng)用實(shí)例的生命周期,比如灰度發(fā)布、監(jiān)控、報(bào)警等操作,是應(yīng)用運(yùn)維專家;
-
平臺運(yùn)維:關(guān)注應(yīng)用運(yùn)行平臺的能力和穩(wěn)定性,是底層(比如 Kubernetes 運(yùn)維/優(yōu)化,OS 等)的領(lǐng)域?qū)<摇?/p>
核心概念
OAM 包含以下核心概念:
服務(wù)組件(Component Schematics)
應(yīng)用開發(fā)使用服務(wù)組件來聲明應(yīng)用的屬性(配置項(xiàng)),運(yùn)維人員定義這些屬性之后就能按照組件聲明得到運(yùn)行的組件實(shí)例,組件聲明包含以下信息:
- 工作負(fù)載類型(Workload type):表明該組件運(yùn)行時(shí)的工作負(fù)載依賴;
- 元數(shù)據(jù)(Metadata):面向組件用戶的一些描述性信息;
- 資源需求(Resource requirements):組件運(yùn)行的最小資源需求,比如最小內(nèi)存,CPU 和文件掛載需求;
- 參數(shù)(Parameters):可以被運(yùn)維人員配置的參數(shù);
- 工作負(fù)載定義(Workload definition):工作負(fù)載運(yùn)行的一些定義,比如可運(yùn)行包定義(ICO images, Function等)。
應(yīng)用邊界(Application Scopes)
運(yùn)維人員使用應(yīng)用邊界將組件組成松耦合的應(yīng)用,可以賦予這組組件一些共用的屬性和依賴,應(yīng)用邊界聲明包含以下信息:
- 元數(shù)據(jù)(Metadata):面向應(yīng)用邊界用戶的一些描述性信息。
- 類型(Type):邊界類型,不同類型提供不同的能力;
- 參數(shù)(Parameters):可以被運(yùn)維人員配置的參數(shù)。
運(yùn)維特征(Traits)
運(yùn)維人員使用運(yùn)維特征賦予組件實(shí)例特定的運(yùn)維能力,比如自動擴(kuò)縮容,一個(gè) Trait 可能僅限特定的工作負(fù)載類型,它們代表了系統(tǒng)運(yùn)維方面的特性,而不是開發(fā)的特性,比如開發(fā)者知道自己的組件是否可以擴(kuò)縮容,但是運(yùn)維可以決定是手動擴(kuò)縮容還是自動擴(kuò)縮容,特征聲明包含以下信息:
- 元數(shù)據(jù)(Metadata):面向特征用戶的一些描述性信息;
- 適用工作負(fù)載列表(Applies-to list):該特征可以應(yīng)用的工作負(fù)載列表;
- 屬性(Properties):可以被運(yùn)維人員配置的屬性。
工作負(fù)載類型和配置(Workload types and configurations)
描述特定工作負(fù)載的底層運(yùn)行時(shí),平臺需要能夠提供對應(yīng)工作負(fù)載的運(yùn)行時(shí),工作負(fù)載聲明包含以下信息:
- 元數(shù)據(jù)(Metadata):面向工作負(fù)載用戶的一些描述性信息;
- 工作負(fù)載設(shè)置(Workload Setting):可以被運(yùn)維人員配置的設(shè)置。
應(yīng)用配置(Application configuration)
運(yùn)維人員使用應(yīng)用配置將組件、特征和應(yīng)用邊界的組合在一起實(shí)例化部署,應(yīng)用配置聲明包含以下信息:
- 元數(shù)據(jù)(Metadata):面向應(yīng)用配置用戶的一些描述性信息;
- 參數(shù)覆蓋(Parameter overrides):可以理解為變量定義,可以被組件、特征、應(yīng)用邊界的參數(shù)引用;
- 組件設(shè)置(Component):構(gòu)成應(yīng)用的全部組件都在這里設(shè)置;
- 綁定組件的運(yùn)維特征配置(Trait Configuration):綁定的特征列表及其參數(shù)。
OAM 認(rèn)為:
一個(gè)云原生應(yīng)用由一組相互關(guān)聯(lián)但又離散獨(dú)立的組件構(gòu)成,這些組件實(shí)例化在合適的運(yùn)行時(shí)上,由配置來控制行為并共同協(xié)作提供統(tǒng)一的功能。
更加具體的說:
一個(gè) Application 由一組 Components 構(gòu)成,每個(gè) Component 的運(yùn)行時(shí)由 Workload 描述,每個(gè) Component 可以施加 Traits 來獲取額外的運(yùn)維能力,同時(shí)我們可以使用 Application scopes 將 Components 劃分到 1 或者多個(gè)應(yīng)用邊界中,便于統(tǒng)一做配置、限制、管理。
整體的運(yùn)行模式如下所示:
組件、運(yùn)維特征、應(yīng)用邊界通過應(yīng)用配置(Application Configuration)實(shí)例化,然后再通過 OAM 的實(shí)現(xiàn)層翻譯為真實(shí)的資源。
怎么用?
使用 OAM 來管理云原生應(yīng)用,其核心主要是圍繞著“四個(gè)概念,一個(gè)動作”。
四個(gè)概念
- 應(yīng)用組件(包含對工作負(fù)載的依賴聲明);【開發(fā)人員關(guān)心】
- 工作負(fù)載;【平臺關(guān)心】
- 運(yùn)維特征;【平臺關(guān)心】
- 應(yīng)用邊界;【平臺關(guān)心】
一個(gè)動作
- 下發(fā)應(yīng)用配置;【運(yùn)維人員關(guān)心】
下發(fā)應(yīng)用配置之后 OAM 平臺將會實(shí)例化四個(gè)概念得到運(yùn)行的應(yīng)用。
一個(gè) OAM 平臺在對外提供 OAM 應(yīng)用管理界面時(shí),一定是預(yù)先已經(jīng)準(zhǔn)備好了“運(yùn)維特征,應(yīng)用邊界”供運(yùn)維人員使用,準(zhǔn)備好了“工作負(fù)載”供開發(fā)者使用,同時(shí)開發(fā)者準(zhǔn)備“組件”供運(yùn)維人員使用。因此角色劃分就很明了:
- 開發(fā)者提供組件,使用平臺的工作負(fù)載;
- 運(yùn)維人員關(guān)注一個(gè)動作實(shí)例化四個(gè)概念;
- 平臺方需要提供工作負(fù)載,運(yùn)維特征,應(yīng)用邊界,并且托管用戶的應(yīng)用組件;
例子
如何使用上面“四個(gè)概念,一個(gè)動作”來部署一個(gè) OAM 應(yīng)用呢?
我們假想一個(gè)場景,用戶的應(yīng)用有兩個(gè)組件:frontend 和 backend,其中 frontend 組件需要域名訪問、自動擴(kuò)縮容能力,并且 frontend 要訪問 backend,兩者應(yīng)該在同一個(gè) vpc 內(nèi),基于這個(gè)場景我們需要有:
- 開發(fā)者創(chuàng)建 2 個(gè)組件
frontend 的 workload 類型是 Server 容器服務(wù)(OAM 平臺提供該工作負(fù)載):
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata:name: frontendannotations:version: v1.0.0description: "A simple webserver" spec:workloadType: core.oam.dev/v1.Serverparameters:- name: messagedescription: The message to display in the web app.type: stringvalue: "Hello from my app, too"containers:- name: webenv:- name: MESSAGEfromParam: messageimage:name: example/charybdis-single:latestbackend 的 workload 是 Cassandra(OAM 平臺提供該工作負(fù)載):
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata:name: backendannotations:version: v1.0.0description: "Cassandra database" spec:workloadType: data.oam.dev/v1.Cassandraparameters:- name: maxStalenessPrefixdescription: Max stale requests.type: intvalue: 100000- name: defaultConsistencyLeveldescription: The default consistency leveltype: stringvalue: "Eventual"workloadSettings:- name: maxStalenessPrefixfromParam: maxStalenessPrefix- name: defaultConsistencyLevelfromParam: defaultConsistencyLevel- OAM 平臺提供 Ingress Trait
- OAM 平臺提供網(wǎng)絡(luò)應(yīng)用邊界
- 應(yīng)用運(yùn)維部署整個(gè)應(yīng)用
使用應(yīng)用配置將上面的組件、邊界、特征組合起來即可部署一個(gè)應(yīng)用,這個(gè)由應(yīng)用的運(yùn)維人員提供:
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationConfiguration metadata:name: custom-single-appannotations:version: v1.0.0description: "Customized version of single-app" spec:variables:- name: messagevalue: "Well hello there"- name: domainNamevalue: "www.example.com"components:- componentName: frontendinstanceName: web-front-endparameterValues:- name: messagevalue: "[fromVariable(message)]"traits:- name: Ingressproperties:- name: hostvalue: "[fromVaraible(domainName)]"- name: pathvalue: "/"applicationScopes:- my-vpc-network- componentName: backendinstanceName: databaseapplicationScopes:- my-vpc-network通過以上完整的使用流程我們可以看到:應(yīng)用配置是真正部署應(yīng)用的起點(diǎn),在使用該配置的時(shí)候,對應(yīng)的組件、應(yīng)用邊界、特征都要提前部署好,運(yùn)維人員只需做一個(gè)組合即可。
服務(wù)組件(Component Schematic)
服務(wù)組件的意義是讓開發(fā)者聲明離散執(zhí)行單元的運(yùn)行時(shí)特性,可以用 JSON/YAML 格式來表示,其聲明遵循 Kubernetes API 規(guī)范,區(qū)別在于:
- 定義字段是 Kubernetes 的子集,因?yàn)?OAM 是更高的抽象;
- OAM Spec 的底層運(yùn)行時(shí)可以不是 Kubernetes
下面我們來看看具體的組件聲明如何定義。
定義
頂層屬性
| apiVersion | string | Y | 特定oam spec版本,比如core.oam.dev/v1 | |
| kind | string | Y | 類型,對于組件來說就是 ComponentSchematic | |
| metadata | Metadata | Y | 組件元數(shù)據(jù) | |
| spec | Spec | Y | 組件特定的定義屬性 |
Metadata
| name | string | Y | ||
| labels | map[string]string | N | k/v對作為組件的lebels | |
| annotations | map[string]string | N | k/v對作為組件的描述信息 |
Spec
| parameters | []Parameter | N | 組件的可配置項(xiàng) | |
| workloadType | string | Y | 簡明語義化的組件運(yùn)行時(shí)描述,以K8s為例就是指定底層使用StatefulSet還是Deployment這樣 | |
| osType | string | N | linux | 組件容器運(yùn)行時(shí)依賴的操作系統(tǒng)類型,可選值: - linux - windows |
| arch | string | N | amd64 | 組件容器運(yùn)行時(shí)依賴的CPU架構(gòu),可選值: - i386 - amd64 - arm - arm64 |
| containers | []Container | N | 實(shí)現(xiàn)組件的OCI容器們 | |
| workloadSettings | []WorkloadSettings | N | 需要傳給工作負(fù)載運(yùn)行時(shí)的非容器配置聲明 |
上面的 workloadType 后面會有詳細(xì)說明,這里簡要來說就是開發(fā)者可以指定該 field 告訴運(yùn)行時(shí)該組件如何被執(zhí)行。工作負(fù)載命名的規(guī)范是 GROUP/VERSION.KIND,和 K8s 資源類型坐標(biāo)一致,比如:
- core.oam.dev/v1alpha1.Singleton
core.oam.dev 表示是 oam 內(nèi)置的分組,oam 內(nèi)置的表示任何 OAM 實(shí)現(xiàn)都支持該類型的工作負(fù)載,v1alpha1 表示依舊是 alpha 狀態(tài),類型是 Singleton,這表示運(yùn)行時(shí)應(yīng)該只運(yùn)行一個(gè)組件實(shí)例,無論誰提供。
- alibabacloud.com/v1.Function
alibabacloud.com 表示該對象是一個(gè)運(yùn)營商特定的實(shí)現(xiàn),不一定所有平臺都實(shí)現(xiàn),版本 v1 表示實(shí)現(xiàn)已經(jīng)穩(wěn)定,類型是 Function 表示運(yùn)行時(shí)是 Alibaba Functions 提供的。
- streams.oam.io/v1beta2.Kafka
表示該對象是一個(gè)第三方組織實(shí)現(xiàn),不一定所有平臺都實(shí)現(xiàn),版本 v1beta2 表示實(shí)現(xiàn)已經(jīng)趨于穩(wěn)定,類型是 Kafka 表示運(yùn)行時(shí)是開源組件 Kafka 提供的。
工作負(fù)載主要分為兩類:
- 核心工作負(fù)載類型
屬于 core.oam.dev 分組,所有對象都需要 oam 平臺實(shí)現(xiàn),都是容器運(yùn)行時(shí),該 Spec 目前定義了如下核心工作負(fù)載類型:
| 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:定義了容器運(yùn)行時(shí)可以運(yùn)行 0 或多個(gè)容器實(shí)例,該工作負(fù)載提供了冗余的可擴(kuò)縮容的多副本常駐服務(wù),在 K8s 平臺可以使用 Deployment 或者 Statefulset 加上 Service 來實(shí)現(xiàn);
-
Singleton Server:定義了容器運(yùn)行時(shí)只能運(yùn)行一個(gè)容器實(shí)例,該工作負(fù)載提供了無法冗余的單副本常駐服務(wù),在 K8s 平臺可以使用副本為 1 的 Statefulset 加上 Service 來實(shí)現(xiàn);
-
Worker:定義了容器運(yùn)行時(shí)可以運(yùn)行 0 或多個(gè)容器實(shí)例,該工作負(fù)載提供了冗余的可擴(kuò)縮容的多副本常駐實(shí)例但是不提供服務(wù),在 K8s 平臺可以使用 Deployment 或者 Statefulset 來實(shí)現(xiàn);
-
Singleton Worker:定義了容器運(yùn)行時(shí)只能運(yùn)行一個(gè)容器實(shí)例,該工作負(fù)載提供了無法冗余的單副本常駐實(shí)例但是不提供服務(wù),在 K8s 平臺可以使用副本為 1 的 Statefulset 來實(shí)現(xiàn);
-
Task:定義了非常駐可冗余的容器運(yùn)行時(shí),運(yùn)行完就退出,可以賦予擴(kuò)縮容特性,在 K8s 平臺可以使用 Job 來實(shí)現(xiàn);
-
Singleton Task:定義了非常駐非冗余的容器運(yùn)行時(shí),運(yùn)行完就退出,在 K8s 平臺可以使用 completions=1 的 Job 來實(shí)現(xiàn)。
核心工作負(fù)載必須給定 container 部分,實(shí)現(xiàn)核心工作負(fù)載的 OAM 平臺必須不依賴 workloadSettings。
- 擴(kuò)展工作負(fù)載類型
擴(kuò)展工作負(fù)載類型是平臺運(yùn)行時(shí)特定的,由各個(gè) OAM 平臺自定提供,當(dāng)前版本的 Spec 不支持用戶自定義工作負(fù)載類型,只能是平臺方提供,擴(kuò)展工作負(fù)載可以使用非容器運(yùn)行時(shí),workloadSettings 的目的就是為了擴(kuò)展工作負(fù)載類型的配置。
工作負(fù)載的定義是包羅萬象的,他允許任何部署的服務(wù)作為工作負(fù)載,無論是容器化還是虛擬機(jī),基于此,我們可以將緩存,數(shù)據(jù)庫,消息隊(duì)列都作為工作負(fù)載,如果組件指定的工作負(fù)載在平臺沒有提供,應(yīng)該快速失敗將信息返回給用戶。
除了 WorkloadType,可以看到組件 Spec 內(nèi)嵌了 3 種結(jié)構(gòu)體,下面來看看它們的定義:
1.Parameter
定義了該組件的所有可配置項(xiàng),其定義如下:
| name | string | Y | ||
| description | string | N | 組件的簡短描述 | |
| type | string | Y | 參數(shù)類型,JSON定義的boolean, number, … | |
| required | boolean | N | false | 參數(shù)值是否必須提供 |
| default | 同上面的type | N | 參數(shù)的默認(rèn)值 |
2.Container
| name | string | Y | 容器名字,在組件內(nèi)必須唯一 | |
| iamge | string | Y | 鏡像地址 | |
| resources | Resources | Y | 鏡像運(yùn)行最小資源需求 | |
| env | []Env | N | 環(huán)境變量 | |
| ports | []Port | N | 暴露端口 | |
| livenessProde | HealthProbe | N | 健康狀態(tài)檢查指令 | |
| readinessProbe | HealthProbe | N | 流量可服務(wù)狀態(tài)檢查指令 | |
| cmd | []string | N | 容器運(yùn)行入口 | |
| args | []string | N | 容器運(yùn)行參數(shù) | |
| config | []ConfigFile | N | 容器內(nèi)可以訪問的配置文件 | |
| imagePullSecrets | string | N | 拉取容器的憑證 |
其中 Resources 的定義如下:
| cpu | CPU | Y | 容器運(yùn)行所需的cpu資源 | |
| memory | Memory | Y | 容器運(yùn)行所需的memory資源 | |
| gpu | GPU | N | 容器運(yùn)行所需的gpu資源 | |
| volumes | []Volume | N | 容器運(yùn)行所需的存儲資源 | |
| extended | []ExtendedResource | N | 容器運(yùn)行所需的外部資源 |
其中 CPU/Memory/GPU 都是數(shù)值型,不贅述,Volume 的定義如下:
| name | string | Y | 數(shù)據(jù)卷的名字,引用的時(shí)候使用 | |
| mountPath | string | Y | 實(shí)際在文件系統(tǒng)的掛載路徑 | |
| accessMode | string | N | RW | 訪問模式,RW或RO |
| sharingPolicy | string | N | Exclusive | 掛載共享策略,Exclusive或者Shared |
| disk | Disk | N | 該數(shù)據(jù)卷使用底層磁盤資源的屬性 |
Disk 指定存儲是否需要持久化,最小的空間需求,定義如下:
| required | string | Y | 最小磁盤大小需求 | |
| ephemeral | boolean | N | 是否需要掛載外部磁盤 |
ExtendedResource 描述特定實(shí)現(xiàn)的資源需求,比如 OAM 運(yùn)行時(shí)平臺可能提供特殊的硬件,這個(gè)字段允許容器聲明需要這個(gè)特定的 offering:
| required | string | Y | 需要的條件 | |
| name | string | Y | 資源名字,比如GV.K |
Env,Port,HealthProbe 和 K8s 類似,這里不再贅述。
3.WorkloadSetting
工作負(fù)載的附加配置,用于非容器運(yùn)行時(shí)(當(dāng)然,也可以用于容器運(yùn)行時(shí)工作負(fù)載的附加字段)。
| name | string | Y | 參數(shù)名 | |
| type | string | N | string | 參數(shù)類型,用于實(shí)現(xiàn)的hint |
| value | any | N | 參數(shù)值,如果沒有fromParam則用該值 | |
| fromParam | string | N | 參數(shù)引用,覆蓋value |
這組配置會傳給運(yùn)行時(shí),一個(gè)運(yùn)行時(shí)可以返回錯(cuò)誤,如果特定的限制沒有滿足,比如:
- 丟失了期望的 k/v 對;
- 不認(rèn)識的 k/v 對;
例子
使用核心工作負(fù)載 Server 的組件聲明
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata:name: frontendannotations:version: v1.0.0description: >Sample component schematic that describes the administrative interface for our Twitter bot. spec:workloadType: core.oam.dev/v1alpha1.ServerosType: linuxparameters:- name: usernamedescription: Basic auth username for accessing the administrative interfacetype: stringrequired: true- name: passworddescription: Basic auth password for accessing the administrative interfacetype: stringrequired: true- name: backend-addressdescription: Host name or IP of the backendtype: stringrequired: truecontainers:- name: my-twitter-bot-frontendimage:name: example/my-twitter-bot-frontend:1.0.0digest: sha256:6c3c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3bresources:cpu:required: 1.0memory:required: 100MBports:- name: httpvalue: 8080env:- name: USERNAMEfromParam: 'username'- name: PASSWORDfromParam: 'password'- name: BACKEND_ADDRESSfromParam: 'backend-address'livenessProbe:httpGet:port: 8080path: /healthzreadinessProbe:httpGet:port: 8080path: /healthz使用擴(kuò)展工作負(fù)載的組件聲明
apiVersion: core.oam.dev/v1alpha1 kind: ComponentSchematic metadata:name: alibabacloudFunctionsannotations:version: v1.0.0description: "Extended workflow example" spec:workloadType: alibabacloud.com/v1.Functionparameters:- name: github-tokendescription: GitHub API session keytype: stringrequired: trueworkloadSettings:- name: sourcevalue: git://git.example.com/function/myfunction.git- name: github_tokenfromParam: github-token總結(jié)
組件聲明是由開發(fā)者或者 OAM 平臺給出,透出應(yīng)用運(yùn)行的可配置項(xiàng)、依賴的平臺和工作負(fù)載,可以看成是一個(gè)聲明了運(yùn)行環(huán)境的函數(shù)定義,運(yùn)維人員填寫函數(shù)參數(shù)之后,組件就會按照聲明的功能運(yùn)行起來。
應(yīng)用邊界(Application scopes)
應(yīng)用邊界通過提供不同形式的應(yīng)用邊界以及共有的分組行為來將組件組成邏輯的應(yīng)用,應(yīng)用邊界具備以下通用的特征:
- 應(yīng)用邊界應(yīng)該描述該組組件實(shí)例的共有行為和元數(shù)據(jù);
- 一個(gè)組件可以同時(shí)部署到多個(gè)不同類型的應(yīng)用邊界中;
- 應(yīng)用邊界類型可以決定組件是否可以部署到多個(gè)相同的應(yīng)用邊界類型實(shí)例;
- 應(yīng)用邊界可以用于不同組件分組以及不同 infra 能力之間的連接機(jī)制,比如 networking 或者外部能力(如驗(yàn)證服務(wù));
下圖說明了組件可以屬于多個(gè)重疊的應(yīng)用分組,最終創(chuàng)建出不同的應(yīng)用邊界。
上圖有兩種應(yīng)用邊界類型:Network 與 Health,有四個(gè)組件分布在不同的應(yīng)用邊界實(shí)例中:
- A、B、C 三個(gè)組件部署到了相同的 Health scope,該 scope 會收集所有屬于這個(gè)邊界的組件狀態(tài)和信息,可以給 Traits 或者其他組件使用;
- 組件 A 和 B、C、D 的網(wǎng)絡(luò)邊界是隔離的,這允許 infra 運(yùn)維提供不同的 SDN 設(shè)置,控制不同分組的流量流入/流出規(guī)則;
類型
主要是有兩種應(yīng)用邊界類型:
- 核心應(yīng)用邊界類型
- 擴(kuò)展應(yīng)用邊界類型
核心應(yīng)用邊界類型
定義基本運(yùn)行時(shí)行為的分組結(jié)構(gòu),它們擁有如下特征:
- 必須是 core.oam.dev 命名空間;
- 必須被全部實(shí)現(xiàn);
- 核心工作負(fù)載類型實(shí)例必須部署到所有核心應(yīng)用邊界類型實(shí)例中;
- 運(yùn)行時(shí)必須為每種應(yīng)用邊界類型提供默認(rèn)的應(yīng)用邊界實(shí)例;
- 運(yùn)行時(shí)如果組件實(shí)例沒有指定特定的應(yīng)用邊界,必須將該組件實(shí)例部署到默認(rèn)應(yīng)用邊界實(shí)例上;
當(dāng)前 Spec 定義的應(yīng)用邊界類型有:
| Network | core.oam.dev/v1alpha1.Network | 該邊界將組件組織到一個(gè)子網(wǎng)邊界并且定義統(tǒng)一的運(yùn)行時(shí)網(wǎng)絡(luò)模型,以及infra網(wǎng)絡(luò)描述的定義和規(guī)則 |
| Health | core.oam.dev/v1alpha1.Health | 該邊界將組件組織到一個(gè)聚合的健康組中,信息可以用于回滾和升級 |
擴(kuò)展應(yīng)用邊界類型
對于運(yùn)行時(shí)來說是 optional 的,可以自定義。
定義
apiVersion,kind,metadata 和前面組件一致,不贅述,主要描述 Spec:
| type | string | Y | 應(yīng)用邊界類型 | |
| allowComponentOverlap | bool | Y | 決定是否允許一個(gè)組件同時(shí)出現(xiàn)在多個(gè)該類型應(yīng)用邊界實(shí)例中 | |
| parameters | []Parameter | N | 邊界的可配置參數(shù) |
例子
Network scope(core)
用于將組件劃分到一個(gè)網(wǎng)絡(luò)或者 SDN 中,網(wǎng)絡(luò)本身必須被 infra 定義和運(yùn)維,也可以被流量管理 Traits 查詢,用于發(fā)現(xiàn) service mesh 的可發(fā)現(xiàn)邊界或者 API 網(wǎng)關(guān)的 API 邊界:
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationScope metadata:name: networkannotations:version: v1.0.0description: "network boundary that a group components reside in" spec:type: core.oam.dev/v1.NetworkScopeallowComponentOverlap: falseparameters:- name: network-iddescription: The id of the network, e.g. vpc-id, VNet name.type: stringrequired: Y- name: subnet-iddescription: The id of the subnet within the network.type: stringrequired: Y- name: internet-gateway-typedescription: The type of the gateway, options are 'public', 'nat'. Empty string means no gateway.type: stringrequired: NHealth scope(core)
用于聚合組件的健康狀態(tài),可以設(shè)計(jì)的參數(shù)有健康閾值(超過該閾值的組件不健康則認(rèn)為整個(gè)邊界不健康),健康邊界實(shí)例本身不會用健康狀態(tài)做任何操作,它只是分組健康聚合器,其信息可以被查詢并用于其他地方,比如:
- 應(yīng)用的變更 Traits 可以監(jiān)控健康狀態(tài)來決定何時(shí)回滾;
- 監(jiān)控 Traits 可以監(jiān)控健康狀態(tài)來觸發(fā)報(bào)警。
resource quota scope(extended)
限制分組內(nèi)所有組件的資源使用總量上限。
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationScope metadata:name: myResourceQuotasannotations:version: v1.0.0description: "The production configuration for Corp CMS" spec:type: resources.oam.dev/v1.ResourceQuotaScopeallowComponentOverlap: falseparameters:- name: CPUdescription: maximum CPU to be consumed by this scopetype: doublerequired: Y- name: Memorydescription: maximum memory to be consumed by this scopetype: doublerequired: Y總結(jié)
應(yīng)用邊界聲明由 OAM 平臺提供,透出應(yīng)用邊界實(shí)例運(yùn)行的可配置項(xiàng),可以看成是一個(gè)函數(shù)定義,運(yùn)維人員或者平臺填寫函數(shù)參數(shù)之后,應(yīng)用邊界就會按照聲明的功能運(yùn)行起來,對該邊界內(nèi)的組件們起作用。
應(yīng)用特征(Traits)
OAM Spec 的實(shí)現(xiàn)平臺應(yīng)該提供 Traits 給組件工作負(fù)載增強(qiáng)運(yùn)維操作,一個(gè) Trait 是一種自由的運(yùn)行時(shí),增強(qiáng)工作負(fù)載提供額外的功能,比如流量路由規(guī)則、自動擴(kuò)縮容規(guī)則、升級策略等,這讓應(yīng)用運(yùn)維具備根據(jù)需求配置組件,不需要開發(fā)者參與的能力。一個(gè)獨(dú)立的 Trait 可以綁定 1 或多個(gè)工作負(fù)載類型,它可以聲明哪些工作負(fù)載類型才能使用該Trait。
規(guī)則
- 目前并沒有機(jī)制來顯示約定組件的多個(gè) Traits 組合,也就是一個(gè)組件應(yīng)用了 Trait A 無法要求 Trait B 必須應(yīng)用于該組件,如果在運(yùn)行時(shí)發(fā)生存在 Trait A 但是 Trait B 不存在,應(yīng)該標(biāo)記 Trait A 失敗;
- Traits 應(yīng)該按照定義的順序施加到組件上;
- 應(yīng)用部署只有當(dāng)所有組件和其 Traits 都正常運(yùn)行起來才能標(biāo)記為部署成功;
- OAM 平臺應(yīng)該支持組件施加多個(gè) Traits,這些 Traits 可能是相同的類型;
- OAM 對 Trait 的實(shí)現(xiàn)沒有任何限制,Trait 一般作用于應(yīng)用的安裝和升級時(shí);
分類
目前 Traits 主要分為三類:
- Core Traits: core Traits 屬于 core.oam.dev 分組,是一些必要的運(yùn)維特征,所有 OAM 平臺必須實(shí)現(xiàn);
- Standard Traits: standard Traits 屬于 standard.oam.dev 分組里面,是一些常用的運(yùn)維特征,推薦 OAM 平臺實(shí)現(xiàn);
- Extensions Traits: extension Traits 是自定義 Traits,其分組也是自定義,是平臺特定的運(yùn)維特征(通常是特定 OAM 平臺差異性)的體現(xiàn)。
定義
apiVersion,kind,metadata 和前面組件一致,不贅述,主要描述 Spec:
| appliesTo | []string | N | ["*"] | 該Trait可以應(yīng)用的工作負(fù)載類型 |
| properties | []Properties | N | Trait的可配置參數(shù),使用JSON Schema來表達(dá)。 |
例子
Manual Scaler(core)
apiVersion: core.oam.dev/v1alpha1 kind: Trait metadata:name: ManualScalerannotations:version: v1.0.0description: "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.Taskproperties: |{"$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}}}上面是一個(gè)手動擴(kuò)縮容服務(wù)的 Trait,只有一個(gè)參數(shù)就是 replicaCount。
總結(jié)
應(yīng)用特征聲明由 OAM 平臺提供,透出應(yīng)用特征的可配置項(xiàng),標(biāo)明了可作用于的工作負(fù)載,可以看成函數(shù)定義,運(yùn)維人員或者平臺填寫實(shí)參之后,應(yīng)用特征就會按照聲明的功能運(yùn)行起來,對綁定的組件起作用。
應(yīng)用配置(Application Configuration)
應(yīng)用配置主要是描述應(yīng)用如何被部署的,一個(gè)組件可以部署到任意的運(yùn)行時(shí),我們稱一個(gè)組件的一次部署為實(shí)例,每次組件部署的時(shí)候必須有應(yīng)用配置。
應(yīng)用配置由應(yīng)用運(yùn)維管理,提供當(dāng)前組件實(shí)例的信息:
- 特定組件的基本信息:名字、版本、描述;
- 組件及其相關(guān)組件定義 parameters 的賦值;
- 組件要施加的 Trait 以及 Trait 的配置。
概念
實(shí)例與升級(Instances and upgrades)
一個(gè)實(shí)例是組件的可追溯部署,當(dāng)組件部署時(shí)創(chuàng)建,后續(xù)該組件的升級都是修改該實(shí)例,回滾/重新部署都屬于升級,實(shí)例都會有名字方便引用。當(dāng)一個(gè)實(shí)例首次創(chuàng)建時(shí),處于初始發(fā)行 (release) 狀態(tài),每次升級操作之后,一個(gè)新的發(fā)行就會創(chuàng)建。
發(fā)行(Releases)
任何對組件本身或者其配置的變更都會創(chuàng)建一個(gè)新的發(fā)行,一個(gè)發(fā)行就是應(yīng)用配置以及它對組件、應(yīng)用特征、應(yīng)用邊界的定義,當(dāng)一個(gè)發(fā)行被部署,對應(yīng)的組件、應(yīng)用特征和應(yīng)用邊界也會被部署。
基于該定義,平臺需要保證以下變更語義:
- 如果新的發(fā)行包含了舊發(fā)行不存在的組件,平臺需要?jiǎng)?chuàng)建該組件;
- 如果新的發(fā)行不包含舊發(fā)行存在的組件,平臺需要?jiǎng)h除該組件;
- 應(yīng)用特征和應(yīng)用邊界與組件的變更語義一致。
運(yùn)行時(shí)與應(yīng)用配置(Runtime and Application Configuration)
一個(gè)組件可以部署到多個(gè)不同的運(yùn)行時(shí),在每個(gè)運(yùn)行時(shí)中應(yīng)用配置的實(shí)例與應(yīng)用配置之間是 1:1 的關(guān)系,應(yīng)用配置由應(yīng)用運(yùn)維管理,包含 3 個(gè)主要部分:
-
參數(shù):運(yùn)維人員在部署時(shí)可以定義的參數(shù);
-
應(yīng)用邊界列表:一組應(yīng)用邊界列表,每個(gè)應(yīng)用邊界定義對應(yīng)的參數(shù);
-
組件實(shí)例定義:定義一個(gè)組件實(shí)例如何部署,這個(gè)定義本身有 3 個(gè)部分:
- 組件參數(shù)的定義;
- Traits 列表:每個(gè) Trait 定義對應(yīng)的參數(shù);
- 應(yīng)用邊界列表:該組件應(yīng)該部署到的應(yīng)用邊界列表。
定義
apiVersion,kind,metadata 和前面組件一致,不贅述,主要描述 Spec:
| variables | []Variable | N | 可以在參數(shù)值和屬性中引用的變量 | |
| scopes | []Scope | N | 應(yīng)用邊界定義 | |
| components | []Component | N | 組件實(shí)例定義 |
variables 就是一個(gè) k/v 對,一個(gè)集中的地方定義運(yùn)維的變量,在運(yùn)維配置的其他地方都可以用 fromVariable(VARNAME) 引用:
| name | string | Y | 變量名字 | |
| value | string | Y | 標(biāo)量值 |
scopes 定義該運(yùn)維配置將要?jiǎng)?chuàng)建的應(yīng)用邊界,其定義為:
| name | string | Y | 應(yīng)用邊界名字 | |
| type | string | Y | 應(yīng)用邊界的GROUP/VERSION.KIND | |
| properties | Properties | N | 覆蓋邊界的參數(shù) |
components 是組件實(shí)例定義,而不是組件定義:
| componentName | string | Y | 組件名 | |
| instanceName | string | Y | 組件實(shí)例名 | |
| parameterValues | []ParameterValue | N | 覆蓋組件的參數(shù) | |
| Traits | []Trait | N | 指定組件實(shí)例綁定的Traits | |
| applicationScopes | []string | N | 指定組件運(yùn)行的應(yīng)用邊界 |
Trait 在這里的定義是:
| name | string | Y | Trait實(shí)例名 | |
| properties | Properties | N | 覆蓋Trait的參數(shù) |
例子
apiVersion: core.oam.dev/v1alpha1 kind: ApplicationConfiguration metadata:name: my-app-deploymentannotations:version: v1.0.0description: "Description of this deployment" spec:variables:- name: VAR_NAMEvalue: SUPPLIED_VALUEscopes:- name: core.oam.dev/v1alpha1.NetworkparameterValues:- name: PARAM_NAMEvalue: SUPPLIED_VALUEcomponents:- componentName: my-web-app-componentinstanceName: my-app-frontentparameterValues:- name: PARAMETER_NAMEvalue: SUPPLIED_VALUE- name: ANOTHER_PARAMETERvalue: "[fromVariable(VAR_NAME)]"traits:- name: Ingressproperties:CUSTOM_OBJECT:DATA: "[fromVariable(VAR_NAME)]"總結(jié)
應(yīng)用配置定義由運(yùn)維人員或者 OAM 平臺提供,描述應(yīng)用的部署,可以看成是一個(gè)函數(shù)調(diào)用,運(yùn)維人員或者 OAM 平臺填寫實(shí)參之后,調(diào)用之前定義的組件、應(yīng)用特征、應(yīng)用邊界等函數(shù),這些實(shí)例一起作用對外提供應(yīng)用服務(wù)。
工作負(fù)載類型(Workload Types)
Workload 類型和 Trait 一樣由平臺提供,所以用戶可以查看平臺提供哪些工作負(fù)載,對于平臺用戶來說工作負(fù)載類型無法擴(kuò)展,只能由平臺開發(fā)者擴(kuò)展提供,因此平臺一定不允許用戶創(chuàng)建自定義的工作負(fù)載類型。
定義
apiVersion,kind,metadata 和前面組件類似,不贅述,這里主要描述 Spec,定義組件如何使用工作負(fù)載類型,除此之外暴露了底層工作負(fù)載運(yùn)行時(shí)的可配置參數(shù):
| group | string | Y | 該工作負(fù)載類型所屬的group | |
| names | Names | Y | 該工作負(fù)載類型的關(guān)聯(lián)名字信息 | |
| settings | []Setting | N | 該工作負(fù)載的設(shè)置選項(xiàng) |
Names 就是描述了對應(yīng)類型的不同形式名字引用:
| kind | string | Y | 工作負(fù)載類型的正確引用名字,比如Singleton | |
| singular | string | N | 單數(shù)形式的可讀名字,比如singleton | |
| plural | string | N | 復(fù)數(shù)形式的可讀名字,比如singletons |
Setting 描述工作負(fù)載可配置部分,類似前面組件的 Parameters,都是 schema:
| name | string | Y | 配置名,每個(gè)workload類型必須唯一 | |
| description | string | N | 配置說明 | |
| type | string | Y | 配置類型 | |
| required | bool | N | false | 是否必須提供 |
| default | indicated by type | N | 默認(rèn)值 |
價(jià)值
通過上面的介紹,我們了解了 OAM Spec 里面的基本概念和定義,以及如何使用它們來描述應(yīng)用交付和運(yùn)維流程。然而,OAM 能給我們帶來什么樣的價(jià)值呢?我們評判一個(gè)好的架構(gòu)體系,不僅是因?yàn)樗诩夹g(shù)上更先進(jìn),更主要的是它能夠解決一些實(shí)際問題,為用戶帶來價(jià)值。所以,接下來我們將總結(jié)一下這方面的內(nèi)容。
OAM 的價(jià)值要從下往上三個(gè)層面來說起。
1. 從基礎(chǔ)設(shè)施層面
基礎(chǔ)設(shè)施,指的是像 K8s 這類的提供基礎(chǔ)服務(wù)能力與抽象的一層服務(wù)體系。拿 K8s 來說,它提供了許多種類的基礎(chǔ)服務(wù)和強(qiáng)大的擴(kuò)展能力來靈活擴(kuò)展其他基礎(chǔ)服務(wù)。
但是,使用基礎(chǔ)設(shè)施的運(yùn)維人員很快就發(fā)現(xiàn) K8s 存在一個(gè)問題:缺乏統(tǒng)一的機(jī)制來注冊和管理自定義擴(kuò)展能力。這些擴(kuò)展能力的表達(dá)方式不夠統(tǒng)一,有些是 CRD、有些是 annotation、有些是 Config…
這種亂象使得基礎(chǔ)設(shè)施用戶不知道平臺上都提供了哪些能力,不知道怎么使用這些能力,更不知道這些能力互相之間的兼容組合關(guān)系。
OAM 提供了抽象(如 Workload/Trait 等)來統(tǒng)一定義和管理這些能力。有了 OAM,各平臺實(shí)現(xiàn)就有了統(tǒng)一的標(biāo)準(zhǔn)規(guī)范去透出公共的或差異化的能力:公共的基礎(chǔ)服務(wù)像容器部署、監(jiān)控、日志、灰度發(fā)布;差異化的、高級復(fù)雜的能力像 CronHPA(周期性定時(shí)變化的強(qiáng)化版 HPA)。
2. 從應(yīng)用運(yùn)維者層面
應(yīng)用運(yùn)維,指的是像給應(yīng)用加上網(wǎng)絡(luò)接入、復(fù)雜均衡、彈性伸縮、甚至是建站等運(yùn)維操作。但是,運(yùn)維的一個(gè)痛點(diǎn)就是原來這些能力并不是跨平臺的:這導(dǎo)致在不同平臺、不同環(huán)境下去部署和運(yùn)維應(yīng)用的操作,是不互通和不兼容的。
上面這個(gè)問題,是客戶應(yīng)用、尤其是傳統(tǒng) ERP 應(yīng)用上云的一大阻礙。我們做 OAM 的一個(gè)初衷,就是通過一套標(biāo)準(zhǔn)定義,讓不同的平臺實(shí)現(xiàn)也通過統(tǒng)一的方式透出。我們希望:哪怕一個(gè)應(yīng)用不是生在云上、長在云上,也能夠趕上這趟通往云原生未來的列車,擁抱云帶來的變化和紅利!
OAM 提供的抽象和模型,是我們通往統(tǒng)一、標(biāo)準(zhǔn)的應(yīng)用架構(gòu)的強(qiáng)有力工具。這些標(biāo)準(zhǔn)能力以后都會通過 OAM 輸出,讓運(yùn)維人員輕易去實(shí)現(xiàn)跨平臺部署。
3. 從應(yīng)用開發(fā)者層面
應(yīng)用開發(fā),指的就是業(yè)務(wù)邏輯開發(fā),這是業(yè)務(wù)產(chǎn)生價(jià)值的核心位置。
也正因如此,我們希望,應(yīng)用開發(fā)者能夠?qū)W⒂跇I(yè)務(wù)開發(fā),而不需要關(guān)心運(yùn)維細(xì)節(jié)。但是,K8s 提供的 API,并沒有很好地分離開發(fā)和運(yùn)維的關(guān)注點(diǎn),開發(fā)和運(yùn)維之間需要來回溝通以避免產(chǎn)生誤解和沖突。
OAM 分離了開發(fā)和運(yùn)維的關(guān)注點(diǎn),很好地解決了以上問題,讓整個(gè)發(fā)布流程更加連貫、高效。
下一步
目前,OAM 已經(jīng)在阿里云 EDAS 等多個(gè)項(xiàng)目中進(jìn)行了數(shù)月的內(nèi)部落地嘗試。我們希望通過一套統(tǒng)一、標(biāo)準(zhǔn)的應(yīng)用定義體系,承載云應(yīng)用管理項(xiàng)目產(chǎn)品與外部資源關(guān)系的高效管理體驗(yàn),并將這種體驗(yàn)統(tǒng)一帶給了基于 Function、ECS、Kubernetes 等不同運(yùn)行時(shí)的應(yīng)用管理流程;通過應(yīng)用特征系統(tǒng),將多個(gè)阿里云獨(dú)有的能力進(jìn)行了模塊化,大大提高了阿里云基礎(chǔ)設(shè)施能力的交付效率。
經(jīng)過了前一段努力的鋪墊,我們也慢慢明確了接下來的工作方向:
- 將接入更多的云產(chǎn)品服務(wù),為用戶將跨平臺應(yīng)用交付的能力最大化;
- 提供 OAM framework 等工具和框架,幫助新的 OAM 平臺開發(fā)者去快速、簡單地搭建 OAM 服務(wù),接入 OAM 標(biāo)準(zhǔn);
- 推動開源生態(tài)建設(shè),以標(biāo)準(zhǔn)化的方式幫助“應(yīng)用”高效和高質(zhì)量地交付到任何平臺上去。
社區(qū)共建
為了能夠讓社區(qū)更加高效、健康的運(yùn)轉(zhuǎn)下去,我們非常期待得到您的反饋,并與大家密切協(xié)作,針對 Kubernetes 和任意云環(huán)境打造一個(gè)簡單、可移植、可復(fù)用的應(yīng)用模型。參與方式:
- 通過 Gitter 直接參與討論:https://gitter.im/oam-dev/;
- 選擇釘釘掃碼進(jìn)入 OAM 項(xiàng)目中文討論群。
歡迎你與我們一起共建這個(gè)全新的應(yīng)用管理生態(tài)!
“ 阿里巴巴云原生微信公眾號(ID:Alicloudnative)關(guān)注微服務(wù)、Serverless、容器、Service Mesh等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢、云原生大規(guī)模的落地實(shí)踐,做最懂云原生開發(fā)者的技術(shù)公眾號。”
更多相關(guān)信息,請關(guān)注“阿里巴巴云原生”。
總結(jié)
以上是生活随笔為你收集整理的4 个概念,1 个动作,让应用管理变得更简单的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从零开始入门 | Kubernetes
- 下一篇: KubeCon 2019 北美会议完美落