自定义 OAM 模板

应用商店支持从根据 OAM 模型定义的应用模板一键生成应用服务(CafeDeployment),您可以通过自定义 OAM 模板来快速创建应用服务。本文以示例模板为例阐释如何编写符合 OAM 规范的产品模板。

背景介绍

OAM 是阿里巴巴联合微软在社区推出的一款用于构建和交付云原生应用的标准规范,旨在通过全新的应用定义、运维、分发与交付模型,推动应用管理技术向轻运维的方向迈进。对于 Kubernetes 来说,OAM 既是一个标准的应用定义项目(类比已经不再活跃的 Kubernetes Application CRD 项目),同时也是一个专注于封装、组织和管理 Kubernetes 中各种运维能力、以及连接运维能力与应用的平台层项目。而通过同时提供定义应用和组织管理应用的运维能力这两大核心功能,OAM 项目自然成为了阿里巴巴进行统一应用架构升级和构建下一代 PaaS/Serverless 过程中的关键路径。

在 OAM 中,一个应用程序包含三个核心概念:

  • Component:组成应用程序的 组件,它可能包含微服务集合、数据库和云负载均衡器。

  • Trait:描述应用程序 运维特征 的集合,例如,弹性伸缩和 Ingress 等功能。它们对应用程序的运行至关重要,但在不同环境中其实现方式各不相同。

  • Application Configuration:最后,为了将这些描述转化为具体的应用程序,运维人员使用 应用配置 来组合组件和相应的特征,以构建应部署的应用程序的具体实例。

更多关于 OAM 的介绍,请参考 官方文档

准备工作

下载以下任意模板,并将模板上传至 AKS 应用商店 > 产品模板 > 私有模板 中。

目录说明

上传模板后,模板中的配置文件目录如下:

目录结构

您需要关注的配置文件如下:

  • templates

    • AppConfig.yaml:应用配置文件,一般由运维人员编写。

    • Component.yaml:组件配置文件,一般由研发人员编写。

  • values.yaml: 应用名称、用户的登录名以及访问中间件服务的四元组信息。

    说明
    必须填写 app(应用名称)、access(访问控制键)、secret(访问控制密钥),请参考 创建AccessKey 获取 access 及 secret。
    values
  • Charts.yaml:描述产品模板的元数据信息,包含模板名称、模板版本、应用版本等。

    说明

    除 type 的值固定为 application 不可以修改,其他参数值可自定义。

    chart信息

模板参数说明

模板的参数说明,请参考示例模板中的注释内容,您可以根据实际情况去修改。

sofaboot-helloworld 模板

Component

apiVersion: core.oam.dev/v1alpha2
kind:Component# 组件类型: 必须为Component
metadata:
  name:"{{ .Release.Name }}-component"# 组件名称:用于在appconfig中component[].componentName处选择组件
spec:
# 参数列表:包含组件所有可配置的参数,可在appconfig中component[].parameterValues处通过name和value进行配置
  parameters:
- name: imageName    # 参数名称:每个组件内必须唯一
      required:false# 在appconfig中配置该组件时是否必须提供value
      fieldPaths:# workload中的对应字段会被该参数覆盖
-"/spec/containers/0/image"
- name: sofa_instanceid
      required:true
      fieldPaths:
-"/spec/containers/0/env/2/value"
- name: sofa_anvip_endpoint
      required:true
      fieldPaths:
-"/spec/containers/0/env/3/value"
- name: sofa_ak
      required:true
      fieldPaths:
-"/spec/containers/0/env/4/value"
- name: sofa_sk
      required:true
      fieldPaths:
-"/spec/containers/0/env/5/value"
  workload:
    apiVersion: oam.cafe.cloud.alipay.com/v1alpha1
    kind:CafeContainerizedworkload# 现有工作负载类型:CafeContainerizedworkload
    spec:
      containers:
- name: sofaboot-helloworld
          image: registry-vpc.cn-shanghai.aliyuncs.com/sofastackcafe/sofaboot-helloworld:v0.0.1
          resources:
            limits:
              memory:"700Mi"
              cpu:"700m"
            requests:
              memory:"500Mi"
              cpu:"500m"
          ports:
- containerPort:8080
              protocol: TCP
- containerPort:8341
              protocol: TCP
          env:
- name: run.mode
              value: NORMAL
- name: logging.path
              value:/home/admin/logs
- name: SOFA_INSTANCE_ID
              value:""
- name: SOFA_ANTVIP_ENDPOINT
              value:""
- name: SOFA_ACCESS_KEY
              value:""
- name: SOFA_SECRET_KEY
              value:""

Application Configuration

apiVersion: core.oam.dev/v1alpha2
kind:ApplicationConfiguration
metadata:
    name:"{{ .Release.Name }}"# 安装模板时输入的发布名称
    annotations:
        app.kubernetes.io/name:"{{ .Values.sofastack.app}}"# 所属应用名(必填)
        app.kubernetes.io/description:"{{ .Release.Name }} from OAM Chart"
        cafe.sofastack.io/loginName:"{{ .Values.sofastack.loginName }}"# 负责人/操作人 登录名(非必填)
        cafe.sofastack.io/userId:"{{ .Values.sofastack.userId }}"# 负责人/操作人 用户ID(非必填)
spec:
    components:
- componentName:"{{ .Release.Name }}-component"# 组件名称:应与组件.metadata.name一致
          parameterValues:# 覆盖组件.spec.parameters相应参数
- name: sofa_instanceid
            value:"{{ .Values.sofastack.instanceid }}"
- name: sofa_anvip_endpoint
            value:"{{ .Values.sofastack.endpoint }}"
- name: sofa_ak
            value:"{{ .Values.sofastack.access }}"
- name: sofa_sk
            value:"{{ .Values.sofastack.secret }}"
          traits:
- trait:
                    apiVersion: core.oam.dev/v1alpha2
                    kind:Strategy# 现有运维特征类型:Strategy、CafeService
                    metadata:
                        annotations:
                            groupStrategy: QUICK        # 分组策略:QUICK(快速分组)、EACH_ONE(每个POD一组)或ALL_ONE(共分一组)
                            groupCount:1# 每组Pod数
                            enableSofaMesh:false# enableSofaMesh:是否开启 Mesh,true 或 false(默认)
                    spec:
                        replicas:1# Pod 副本数
                        strategy:
                            upgradeType:Beta# beta分组
                        needWaitingForConfirm:true# 批量发布时,是否每批都需要等待用户确认

sofaboot-helloworld-service 模板

Component

apiVersion: core.oam.dev/v1alpha2
kind:Component# 组件类型: 必须为Component
metadata:
  name:"{{ .Release.Name }}-component"# 组件名称:用于在appconfig中component[].componentName处选择组件
spec:
# 参数列表:包含组件所有可配置的参数,可在appconfig中component[].parameterValues处通过name和value进行配置
  parameters:
- name: imageName    # 参数名称:每个组件内必须唯一
      required:false# 在appconfig中配置该组件时是否必须提供value
      fieldPaths:# workload中的对应字段会被该参数覆盖
-"/spec/containers/0/image"
- name: sofa_instanceid
      required:true
      fieldPaths:
-"/spec/containers/0/env/2/value"
- name: sofa_anvip_endpoint
      required:true
      fieldPaths:
-"/spec/containers/0/env/3/value"
- name: sofa_ak
      required:true
      fieldPaths:
-"/spec/containers/0/env/4/value"
- name: sofa_sk
      required:true
      fieldPaths:
-"/spec/containers/0/env/5/value"
  workload:
    apiVersion: oam.cafe.cloud.alipay.com/v1alpha1
    kind:CafeContainerizedworkload# 现有工作负载类型:CafeContainerizedworkload
    spec:
      containers:
- name: sofaboot-helloworld
          image: registry-vpc.cn-shanghai.aliyuncs.com/sofastackcafe/sofaboot-helloworld:v0.0.1
          resources:
            limits:
              memory:"700Mi"
              cpu:"700m"
            requests:
              memory:"500Mi"
              cpu:"500m"
          ports:
- containerPort:8080
              protocol: TCP
- containerPort:8341
              protocol: TCP
          env:
- name: run.mode
              value: NORMAL
- name: logging.path
              value:/home/admin/logs
- name: SOFA_INSTANCE_ID
              value:""
- name: SOFA_ANTVIP_ENDPOINT
              value:""
- name: SOFA_ACCESS_KEY
              value:""
- name: SOFA_SECRET_KEY
              value:""

Application Configuration

apiVersion: core.oam.dev/v1alpha2
kind:ApplicationConfiguration
metadata:
    name:"{{ .Release.Name }}"
    annotations:
        app.kubernetes.io/name:"{{ .Values.sofastack.app}}"# 所属应用名(必填)
        app.kubernetes.io/description:"{{ .Release.Name }} from OAM Chart"
        cafe.sofastack.io/loginName:"{{ .Values.sofastack.loginName }}"# 负责人/操作人 登录名(必填)
        cafe.sofastack.io/userId:"{{ .Values.sofastack.userId }}"
spec:
    components:
- componentName:"{{ .Release.Name }}-component"# 组件名称:应与组件.metadata.name一致
          parameterValues:# 覆盖组件.spec.parameters相应参数
- name: sofa_instanceid
            value:"{{ .Values.sofastack.instanceid }}"
- name: sofa_anvip_endpoint
            value:"{{ .Values.sofastack.endpoint }}"
- name: sofa_ak
            value:"{{ .Values.sofastack.access }}"
- name: sofa_sk
            value:"{{ .Values.sofastack.secret }}"
          traits:
- trait:
                    apiVersion: core.oam.dev/v1alpha2
                    kind:Strategy# 现有运维特征类型:Strategy、CafeService
                    metadata:
                        annotations:
                            groupStrategy: EACH_ONE     # 分组策略:QUICK(快速分组)、EACH_ONE(每个POD一组)或ALL_ONE(共分一组)
                            groupCount:2# BatchSize 每组pod数
# enableSofaMesh: true        # enableSofaMesh:true或false(默认)
                    spec:
                        replicas:1# pod总数
                        strategy:
                            batchSize:1# 升级时每批的pod更新数
                            upgradeType:Beta# beta分组
                        needWaitingForConfirm:true# 批量发布时,是否每批都需要等待用户确认
                        topology:
                            unitType:Cell
                            values:# 部署单元
-CellA
# podSetType: InPlaceSet          # 升级策略:InPlaceSet(原地)或ReplicaSet(替换,默认)
- trait:
                  apiVersion: core.oam.dev/v1alpha2
                  kind:CafeService
                  metadata:
                      name: sofaboot-helloworld-service
                      annotations:
                          service.beta.kubernetes.io/antcloud-loadbalancer-address-type: INTERNET                           # 负载均衡类型(非集群内访问必填): INTRANET(内网)或INTERNET(外网)
                          service.beta.kubernetes.io/antcloud-loadbalancer-internet-charge-type: PAY_BY_TRAFFIC
                          service.beta.kubernetes.io/antcloud-loadbalancer-listener-healthcheck:8080:ON;8341:ON
                          service.beta.kubernetes.io/antcloud-loadbalancer-listener-healthcheck-interval:"8080:2;8341:2"# 健康检查间隔时间(非集群内访问必填):针对每个端口要单独指定间隔时间,如8341:3,以英文分号分隔(阿里云默认:45;金融云默认:5)
                          service.beta.kubernetes.io/antcloud-loadbalancer-listener-healthcheck-timeout:"8080:5;8341:5"# 健康检查超时时间(非集群内访问必填):针对每个端口要单独指定超时时间,如8341:3,以英文分号分隔
                          service.beta.kubernetes.io/antcloud-loadbalancer-listener-scheduler:8080:WRR;8341:WRR            # 转发规则(非集群内访问必填):WRR或WLC
                          service.beta.kubernetes.io/antcloud-loadbalancer-port-protocol:8080:TCP;8341:TCP
                          service.beta.kubernetes.io/antcloud-loadbalancer-lb-name: sofaboot                                # 负载均衡名称(非集群内访问必填)
# service.beta.kubernetes.io/antcloud-loadbalancer-listener-healthcheck-uri: 8080:/actuator/readiness;8341:/actuator/readiness     # 健康检查路径(非集群内访问且协议类型为http/https必填):针对每个端口单独设置检查路径,以英文分号分隔
# service.beta.kubernetes.io/antcloud-loadbalancer-listener-healthcheck-domain: 8080:www.alipay.net       # 健康检查域名(可选)
                  spec:
                      type:'LoadBalancer'# 访问方式:"ClusterIP"(集群内访问)、"LoadBalancer"(VPC内网访问)、'LoadBalancer'(公网访问)
                      ports:
- protocol: TCP               # 协议类型(必填):TCP、UDP、HTTP或HTTPS
                            port:8080# 前端端口
                            targetPort:8080# 后端端口
# name: helloworld-conn       # 服务名称
- protocol: TCP
                            port:8341
                            targetPort:8341