Platform admin cue + comp system (#163)
* basic * advanced part * adding component system * fix broken link and deprecated docs * fixs * fix customize-trait * fix customize-trait part 2 * fix customize-trait part 3 Co-authored-by: 段少 <duanwei.duan@alibaba-inc.com>
This commit is contained in:
		
							parent
							
								
									b6fc0d7a91
								
							
						
					
					
						commit
						00ce8f376e
					
				|  | @ -49,6 +49,6 @@ By default, the two commands will retrieve capabilities from [repo](https://regi | |||
| Check below documentations about how to bring your own components to the system in various approaches. | ||||
| 
 | ||||
| - [Helm](../../platform-engineers/helm/component) - Helm chart is a natural form of component, note that you need to have a valid Helm repository (e.g. GitHub repo or a Helm hub) to host the chart in this case. | ||||
| - [CUE](../../platform-engineers/components/component-cue) - CUE is powerful approach to encapsulate a component and it doesn't require any repository. | ||||
| - [CUE](../../platform-engineers/components/custom-component) - CUE is powerful approach to encapsulate a component and it doesn't require any repository. | ||||
| - [Simple Template](../../platform-engineers/kube/component) - Not a Helm or CUE expert? A simple template approach is also provided to define any Kubernetes API resource as a component. Note that only key-value style parameters are supported in this case. | ||||
| - [Cloud Services](../../platform-engineers/cloud-services) - KubeVela allows you to declare cloud services as part of the application and provision them in consistent API. | ||||
| - [Cloud Services](../../platform-engineers/cloud-services) - KubeVela allows you to declare cloud services as part of the application and provision them in consistent API. | ||||
|  | @ -55,7 +55,6 @@ from [repo](https://registry.kubevela.net) maintained by KubeVela. | |||
| 
 | ||||
| ## 2. Designed by yourself | ||||
| 
 | ||||
| 
 | ||||
| Check [this documentation](../../platform-engineers/traits/customize-trait) about how to design and enable your own traits in | ||||
| 
 | ||||
| KubeVela platform. | ||||
|  | @ -1,4 +0,0 @@ | |||
| --- | ||||
| title: Built-in Component | ||||
| --- | ||||
| 
 | ||||
|  | @ -2,7 +2,7 @@ | |||
| title:  KEDA as Autoscaling Trait | ||||
| --- | ||||
| 
 | ||||
| > Before continue, make sure you have learned about the concepts of [Definition Objects](definition-and-templates) and [Defining Traits with CUE](./traits/customize-trait) section. | ||||
| > Before continue, make sure you have learned about the concepts of [Definition Objects](definition-and-templates) and [Defining Traits with CUE]((./traits/customize-trait) section. | ||||
| 
 | ||||
| In the following tutorial, you will learn to add [KEDA](https://keda.sh/) as a new autoscaling trait to your KubeVela based platform. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| --- | ||||
| title:  自定义运维特征 | ||||
| title:  How-to | ||||
| --- | ||||
| 
 | ||||
| In this section we will introduce how to define a trait. | ||||
|  | @ -18,7 +18,6 @@ spec: | |||
|     name: ingresses.networking.k8s.io | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| Let's attach this trait to a component instance in `Application`: | ||||
| 
 | ||||
| ```yaml | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ worker     	vela-system	deployments.apps                     	Describes long-run | |||
| 
 | ||||
| 作为用户的你,可以继续使用 [CUE 组件](../end-user/components/cue)、[Helm 组件](../end-user/components/helm)、[Kustomize 组件](../end-user/components/kustomize)和[云服务组件](../end-user/components/cloud-services/terraform/rds)来实现你需要的任何组件类型。 | ||||
| 
 | ||||
| 同时作为管理员的你,也可以使用 [自定义组件](../platform-engineers/components/component-cue)、[Terraform 组件](../platform-engineers/components/component-terraform) 来自定义你的用户所需要的任何组件类型。 | ||||
| 同时作为管理员的你,也可以使用 [自定义组件](../platform-engineers/components/custom-component)、[Terraform 组件](../platform-engineers/components/component-terraform) 来自定义你的用户所需要的任何组件类型。 | ||||
| 
 | ||||
| ### Traits 运维特征 | ||||
| 
 | ||||
|  |  | |||
|  | @ -47,9 +47,10 @@ cloneset     CloneSet        Describes long-running, scalable, containerized ser | |||
| 默认情况下,这两个命令将从 KubeVela 维护的 [repo](https://registry.kubevela.net) 中检索功能。 | ||||
| 
 | ||||
| ## 2. 自己设计 | ||||
| 
 | ||||
| 查看以下文档,了解如何以各种方法将你自己的组件引入系统。 | ||||
| 
 | ||||
| - [Helm](../../platform-engineers/helm/component) - Helm chart 是组件的一种自然形式,请注意,在这种情况下,你需要有一个有效的 Helm 存储库(例如 GitHub 存储库或 Helm 中心)来托管 chart。 | ||||
| - [CUE](../../platform-engineers/components/component-cue) - CUE 是封装组件的强大方法,它不需要任何存储库。 | ||||
| - [CUE](../../platform-engineers/components/custom-component) - CUE 是封装组件的强大方法,它不需要任何存储库。 | ||||
| - [Simple Template](../../platform-engineers/kube/component) - 不是 Helm 或 CUE 专家? 还提供了一种简单的模板方法来将任何 Kubernetes API 资源定义为一个组件。 请注意,在这种情况下仅支持键值样式参数。 | ||||
| - [Cloud Services](../../platform-engineers/cloud-services) - KubeVela 允许你将云服务声明为应用程序的一部分,并在一致的 API 中提供它们。 | ||||
| - [Cloud Services](../../platform-engineers/cloud-services) - KubeVela 允许你将云服务声明为应用程序的一部分,并在一致的 API 中提供它们。 | ||||
|  | @ -1,4 +0,0 @@ | |||
| --- | ||||
| title: 内置组件 | ||||
| --- | ||||
| 
 | ||||
|  | @ -2,15 +2,19 @@ | |||
| title:  Terraform 组件 | ||||
| --- | ||||
| 
 | ||||
| In this documentation, we will use Alibaba Cloud's RDS (Relational Database Service), and Alibaba Cloud's OSS (Object Storage System) as examples to show how to enable cloud services as part of the application deployment. | ||||
| 对云资源的集成需求往往是最频繁出现,比如你可能希望数据库、中间件等服务使用阿里云、AWS 等云厂商的,以获得生产级别的可用性并免去运维的麻烦。Terraform 是目前业内支持云资源最广泛也最受欢迎的组件,KubeVela 对 Terraform 进行了额外的支持,使得用户可以通过 Kubernetes CRD 的方式配合 Terraform 使用任意的云资源。 | ||||
| 
 | ||||
| These cloud services are provided by Terraform. | ||||
| 本章节,将专门为你介绍如何通过 KubeVela 以及 Terraform 来实现自定义的云资源组件。我们以阿里云的对象存储(OSS),作为例子来进行讲解。 | ||||
| 
 | ||||
| ## Prepare Terraform Controller | ||||
| 它的大致流程如下: | ||||
| 1. 熟悉各云服务商的鉴权机制,准备相关的 `secret` 和 `token` 等必要信息。 | ||||
| 2. Terraform 使用 `Provider` 对象,完成对应云服务商的权限校验过程。 | ||||
| 3. KubeVela 通过 Terraform 控制器来拉起对应的云资源。 | ||||
| 
 | ||||
| <details> | ||||
| 
 | ||||
| Download the latest chart, like `terraform-controller-chart-0.1.8.tgz`, from the latest [releases list](https://github.com/oam-dev/terraform-controller/releases) and install it. | ||||
| ### 安装 Terraform 控制器 | ||||
| 
 | ||||
| 从最新的 [发布列表](https://github.com/oam-dev/terraform-controller/releases) 里下载并安装,比如 `terraform-controller-chart-0.1.8.tgz`。 | ||||
| 
 | ||||
| ```shell | ||||
| $ helm install terraform-controller terraform-controller-0.1.8.tgz | ||||
|  | @ -22,85 +26,129 @@ REVISION: 1 | |||
| TEST SUITE: None | ||||
| ``` | ||||
| 
 | ||||
| ### Apply Provider Credentials | ||||
| 
 | ||||
| By applying Terraform Provider credentials, Terraform controller can be authenticated to deploy and manage cloud resources. | ||||
| 
 | ||||
| Please refer to [Terraform controller getting started](https://github.com/oam-dev/terraform-controller/blob/master/getting-started.md) on how to apply Provider for Alibaba Cloud or AWS. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### Register `alibaba-rds` Component | ||||
| 
 | ||||
| Register [alibaba-rds](https://github.com/oam-dev/kubevela/tree/master/docs/examples/terraform/cloud-resource-provision-and-consume/ComponentDefinition-alibaba-rds.yaml) to KubeVela. | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1alpha2 | ||||
| kind: ComponentDefinition | ||||
| metadata: | ||||
|   name: alibaba-rds | ||||
|   annotations: | ||||
|     definition.oam.dev/description: Terraform configuration for Alibaba Cloud RDS object | ||||
|     type: terraform | ||||
| spec: | ||||
|   workload: | ||||
|     definition: | ||||
|       apiVersion: terraform.core.oam.dev/v1beta1 | ||||
|       kind: Configuration | ||||
|   schematic: | ||||
|     terraform: | ||||
|       configuration: | | ||||
|         module "rds" { | ||||
|           source = "terraform-alicloud-modules/rds/alicloud" | ||||
|           engine = "MySQL" | ||||
|           engine_version = "8.0" | ||||
|           instance_type = "rds.mysql.c1.large" | ||||
|           instance_storage = "20" | ||||
|           instance_name = var.instance_name | ||||
|           account_name = var.account_name | ||||
|           password = var.password | ||||
|         } | ||||
| 
 | ||||
|         output "DB_NAME" { | ||||
|           value = module.rds.this_db_instance_name | ||||
|         } | ||||
|         output "DB_USER" { | ||||
|           value = module.rds.this_db_database_account | ||||
|         } | ||||
|         output "DB_PORT" { | ||||
|           value = module.rds.this_db_instance_port | ||||
|         } | ||||
|         output "DB_HOST" { | ||||
|           value = module.rds.this_db_instance_connection_string | ||||
|         } | ||||
|         output "DB_PASSWORD" { | ||||
|           value = module.rds.this_db_instance_port | ||||
|         } | ||||
| 
 | ||||
|         variable "instance_name" { | ||||
|           description = "RDS instance name" | ||||
|           type = string | ||||
|           default = "poc" | ||||
|         } | ||||
| 
 | ||||
|         variable "account_name" { | ||||
|           description = "RDS instance user account name" | ||||
|           type = "string" | ||||
|           default = "oam" | ||||
|         } | ||||
| 
 | ||||
|         variable "password" { | ||||
|           description = "RDS instance account password" | ||||
|           type = "string" | ||||
|           default = "Xyfff83jfewGGfaked" | ||||
|         } | ||||
| ### 配置阿里云鉴权 | ||||
| 以下是阿里云的鉴权相关步骤,其它云服务商同理: | ||||
| 
 | ||||
| ``` | ||||
| $ export ALICLOUD_ACCESS_KEY=xxx; export ALICLOUD_SECRET_KEY=yyy | ||||
| If you'd like to use Alicloud Security Token Service, also export ALICLOUD_SECURITY_TOKEN. | ||||
| 
 | ||||
| ### Register `alibaba-oss` Component | ||||
| $ export ALICLOUD_SECURITY_TOKEN=zzz | ||||
| $ sh hack/prepare-alibaba-credentials.sh | ||||
| 
 | ||||
| Register [alibaba-oss](https://github.com/oam-dev/kubevela/tree/master/docs/examples/terraform/cloud-resource-provision-and-consume/ComponentDefinition-alibaba-oss.yaml) to KubeVela. | ||||
| $ kubectl get secret -n vela-system | ||||
| NAME                                              TYPE                                  DATA   AGE | ||||
| alibaba-account-creds                             Opaque                                1      11s | ||||
| 
 | ||||
| $ kubectl apply -f examples/alibaba/provider.yaml | ||||
| provider.terraform.core.oam.dev/default created | ||||
| ``` | ||||
| 
 | ||||
| `provider.yaml` 请使用示例: | ||||
| 
 | ||||
| ``` | ||||
| apiVersion: terraform.core.oam.dev/v1beta1 | ||||
| kind: Provider | ||||
| metadata: | ||||
|   name: default | ||||
| spec: | ||||
|   provider: alibaba | ||||
|   region: cn-beijing | ||||
|   credentials: | ||||
|     source: Secret | ||||
|     secretRef: | ||||
|       namespace: vela-system | ||||
|       name: alibaba-account-creds | ||||
|       key: credentials | ||||
| ``` | ||||
| 
 | ||||
| ### 云资源关联 Provider | ||||
| 
 | ||||
| Terraform 可以编写、应用一个 configuration_hcl_oss.yaml 来配置阿里云的 OSS 存储 Bukcet。它会去自动关联 Kubernetes 集群里的默认 `Provider`,即上一步的 `name: default` YMAL 文件。 | ||||
| 
 | ||||
| ``` | ||||
| apiVersion: terraform.core.oam.dev/v1beta1 | ||||
| kind: Configuration | ||||
| metadata: | ||||
|   name: alibaba-oss | ||||
| spec: | ||||
|   hcl: | | ||||
|     resource "alicloud_oss_bucket" "bucket-acl" { | ||||
|       bucket = var.bucket | ||||
|       acl = var.acl | ||||
|     } | ||||
| 
 | ||||
|     output "BUCKET_NAME" { | ||||
|       value = "${alicloud_oss_bucket.bucket-acl.bucket}.${alicloud_oss_bucket.bucket-acl.extranet_endpoint}" | ||||
|     } | ||||
| 
 | ||||
|     variable "bucket" { | ||||
|       description = "OSS bucket name" | ||||
|       default = "vela-website" | ||||
|       type = string | ||||
|     } | ||||
| 
 | ||||
|     variable "acl" { | ||||
|       description = "OSS bucket ACL, supported 'private', 'public-read', 'public-read-write'" | ||||
|       default = "private" | ||||
|       type = string | ||||
|     } | ||||
| 
 | ||||
|   variable: | ||||
|     bucket: "vela-website" | ||||
|     acl: "private" | ||||
| 
 | ||||
|   writeConnectionSecretToRef: | ||||
|     name: oss-conn | ||||
|     namespace: default | ||||
| ``` | ||||
| 然后部署: | ||||
| 
 | ||||
| ``` | ||||
| $ kubectl apply -f configuration_hcl_oss.yaml | ||||
| 
 | ||||
| $ kubectl get configuration.terraform.core.oam.dev | ||||
| NAME         AGE | ||||
| alibaba-oss   1h | ||||
| 
 | ||||
| $ kubectl get configuration.terraform.core.oam.dev alibaba-oss -o yaml | ||||
| apiVersion: terraform.core.oam.dev/v1beta1 | ||||
| kind: Configuration | ||||
| metadata: | ||||
|   annotations: | ||||
|     kubectl.kubernetes.io/last-applied-configuration: | | ||||
|       {"apiVersion":"terraform.core.oam.dev/v1beta1","kind":"Configuration","metadata":{"annotations":{},"name":"alibaba-oss","namespace":"default"},"spec":{"JSON":"{\n  \"resource\": {\n    \"alicloud_oss_bucket\": {\n      \"bucket-acl\": {\n        \"bucket\": \"${var.bucket}\",\n        \"acl\": \"${var.acl}\"\n      }\n    }\n  },\n  \"output\": {\n    \"BUCKET_NAME\": {\n      \"value\": \"${alicloud_oss_bucket.bucket-acl.bucket}.${alicloud_oss_bucket.bucket-acl.extranet_endpoint}\"\n    }\n  },\n  \"variable\": {\n    \"bucket\": {\n      \"default\": \"poc\"\n    },\n    \"acl\": {\n      \"default\": \"private\"\n    }\n  }\n}\n","variable":{"acl":"private","bucket":"vela-website"},"writeConnectionSecretToRef":{"name":"oss-conn","namespace":"default"}}} | ||||
|   creationTimestamp: "2021-04-02T08:17:08Z" | ||||
|   generation: 2 | ||||
| spec: | ||||
|   ... | ||||
|   variable: | ||||
|     acl: private | ||||
|     bucket: vela-website | ||||
|   writeConnectionSecretToRef: | ||||
|     name: oss-conn | ||||
|     namespace: default | ||||
| status: | ||||
|   outputs: | ||||
|     BUCKET_NAME: | ||||
|       type: string | ||||
|       value: vela-website.oss-cn-beijing.aliyuncs.com | ||||
|   state: provisioned | ||||
| ``` | ||||
| 
 | ||||
| 可以看到 OSS bucket 已经被分配出来。 | ||||
| 
 | ||||
| ``` | ||||
| $ ossutil ls oss:// | ||||
| CreationTime                                 Region    StorageClass    BucketName | ||||
| 2021-04-10 00:42:09 +0800 CST        oss-cn-beijing        Standard    oss://vela-website | ||||
| Bucket Number is: 1 | ||||
| 
 | ||||
| 0.146789(s) elapsed | ||||
| ``` | ||||
| 
 | ||||
| ### 自定义 OSS 云资源组件 | ||||
| 当前面的步骤全部完成之后,最后我们只需要继续使用组件定义,将这个 `alibaba-oss` 引入,作为后续应用部署计划的内置能力即可。 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1alpha2 | ||||
|  | @ -138,6 +186,4 @@ spec: | |||
|           default = "private" | ||||
|           type = string | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| ``` | ||||
|  | @ -2,13 +2,15 @@ | |||
| title:  自定义组件 | ||||
| --- | ||||
| 
 | ||||
| In this section, it will introduce how to use [CUE](https://cuelang.org/) to declare app components via `ComponentDefinition`. | ||||
| > 在阅读本部分之前,请确保你已经学习了 KubeVela 中的[组件定义(ComponentDefinition)](../oam/x-definition.md##组件定义(ComponentDefinition)) 原理 | ||||
| 
 | ||||
| > Before reading this part, please make sure you've learned the [Definition CRD](../definition-and-templates) in KubeVela. | ||||
| > 学习掌握了 [CUE 的基本知识](../cue/basic) | ||||
| 
 | ||||
| ## Declare `ComponentDefinition` | ||||
| 本节将以组件定义的例子展开说明,介绍如何使用 [CUE](https://cuelang.org/) 通过组件定义 `ComponentDefinition` 来自定义应用部署计划的组件。 | ||||
| 
 | ||||
| Here is a CUE based `ComponentDefinition` example which provides a abstraction for stateless workload type: | ||||
| ### 交付一个简单的自定义组件 | ||||
| 
 | ||||
| 我们先编写一个基于 CUE 的组件定义,它想提供的是一个无状态工作负载类型的抽象: | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
|  | @ -24,37 +26,37 @@ spec: | |||
|     cue: | ||||
|       template: | | ||||
|         parameter: { | ||||
|         	name:  string | ||||
|         	image: string | ||||
|           name:  string | ||||
|           image: string | ||||
|         } | ||||
|         output: { | ||||
|         	apiVersion: "apps/v1" | ||||
|         	kind:       "Deployment" | ||||
|         	spec: { | ||||
|         		selector: matchLabels: { | ||||
|         			"app.oam.dev/component": parameter.name | ||||
|         		} | ||||
|         		template: { | ||||
|         			metadata: labels: { | ||||
|         				"app.oam.dev/component": parameter.name | ||||
|         			} | ||||
|         			spec: { | ||||
|         				containers: [{ | ||||
|         					name:  parameter.name | ||||
|         					image: parameter.image | ||||
|         				}] | ||||
|         			} | ||||
|         		} | ||||
|         	} | ||||
|           apiVersion: "apps/v1" | ||||
|           kind:       "Deployment" | ||||
|           spec: { | ||||
|             selector: matchLabels: { | ||||
|               "app.oam.dev/component": parameter.name | ||||
|             } | ||||
|             template: { | ||||
|               metadata: labels: { | ||||
|                 "app.oam.dev/component": parameter.name | ||||
|               } | ||||
|               spec: { | ||||
|                 containers: [{ | ||||
|                   name:  parameter.name | ||||
|                   image: parameter.image | ||||
|                 }] | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
| ``` | ||||
| In detail: | ||||
| - `.spec.workload` is required to indicate the workload type of this component. | ||||
| - `.spec.schematic.cue.template` is a CUE template, specifically: | ||||
|     * The `output` filed defines the template for the abstraction. | ||||
|     * The `parameter` filed defines the template parameters, i.e. the configurable properties exposed in the `Application`abstraction (and JSON schema will be automatically generated based on them). | ||||
| 详细来说: | ||||
| - 需要 `.spec.workload` 来指示该组件的工作负载类型。 | ||||
| - `.spec.schematic.cue.template` 是一个 CUE 模板: | ||||
|      * `output` 字段定义了 CUE 要输出的抽象模板。 | ||||
|      * `parameter` 字段定义了模板参数,即在应用部署计划(Application)中公开的可配置属性(KubeVela 将基于 `parameter` 字段自动生成 Json schema)。 | ||||
| 
 | ||||
| Let's declare another component named `task`, i.e. an abstraction for run-to-completion workload. | ||||
| 接着,让我们声明另一个名为 `task` 的组件。 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
|  | @ -96,11 +98,18 @@ spec: | |||
|         } | ||||
| ``` | ||||
| 
 | ||||
| Save above `ComponentDefinition` objects to files and install them to your Kubernetes cluster by `$ kubectl apply -f stateless-def.yaml task-def.yaml` | ||||
| 将上面的组件定义对象保存到 YAML 文件中,并通过 `$ kubectl apply -f stateless-def.yaml task-def.yaml` 将它们部署到你的 Kubernetes 集群。 | ||||
| 
 | ||||
| ## Declare an `Application` | ||||
| ``` | ||||
| $  kubectl apply -f stateless-def.yaml               | ||||
| componentdefinition.core.oam.dev/stateless created | ||||
| $  kubectl apply -f task-def.yaml  | ||||
| componentdefinition.core.oam.dev/task created | ||||
| ``` | ||||
| 
 | ||||
| The `ComponentDefinition` can be instantiated in `Application` abstraction as below: | ||||
| 这两个已经定义好的组件,最终会在应用部署计划中实例化,我们引用自定义的组件类型 `stateless`,命名为 `hello`。同样,我们也引用了自定义的第二个组件类型 `task`,并命令为 `countdown`。 | ||||
| 
 | ||||
| 然后把它们编写到应用部署计划中,如下所示: | ||||
| 
 | ||||
|   ```yaml | ||||
|   apiVersion: core.oam.dev/v1alpha2 | ||||
|  | @ -124,17 +133,17 @@ The `ComponentDefinition` can be instantiated in `Application` abstraction as be | |||
|             - "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done" | ||||
|   ``` | ||||
| 
 | ||||
| ### Under The Hood | ||||
| <details> | ||||
| 以上,我们就完成了一个自定义应用组件的应用交付全过程。值得注意的是,作为管理员的我们,可以通过 CUE 提供用户所需要的任何自定义组件类型,同时也为用户提供了模板参数 `parameter` 来灵活地指定对 Kubernetes 相关资源的要求。 | ||||
| 
 | ||||
| Above application resource will generate and manage following Kubernetes resources in your target cluster based on the `output` in CUE template and user input in `Application` properties. | ||||
| #### 查看 Kubernetes 最终资源信息 | ||||
| <details> | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: apps/v1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: backend | ||||
|   ... # skip tons of metadata info | ||||
|   ... # 隐藏一些与本小节讲解无关的信息 | ||||
| spec: | ||||
|   template: | ||||
|     spec: | ||||
|  | @ -152,7 +161,7 @@ apiVersion: batch/v1 | |||
| kind: Job | ||||
| metadata: | ||||
|   name: countdown | ||||
|   ... # skip tons of metadata info | ||||
|   ... # 隐藏一些与本小节讲解无关的信息 | ||||
| spec: | ||||
|   parallelism: 1 | ||||
|   completions: 1 | ||||
|  | @ -171,70 +180,19 @@ spec: | |||
| ```   | ||||
| </details> | ||||
| 
 | ||||
| ## CUE `Context` | ||||
| 
 | ||||
| KubeVela allows you to reference the runtime information of your application via `context` keyword. | ||||
| ### 交付一个复合的自定义组件 | ||||
| 
 | ||||
| The most widely used context is application name(`context.appName`) component name(`context.name`). | ||||
| 除了上面这个例子外,一个组件的定义通常也会由多个 Kubernetes API 资源组成。例如,一个由 `Deployment` 和 `Service` 组成的 `webserver` 组件。CUE 同样能很好的满足这种自定义复合组件的需求。 | ||||
| 
 | ||||
| ```cue | ||||
| context: { | ||||
|   appName: string | ||||
|   name: string | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| For example, let's say you want to use the component name filled in by users as the container name in the workload instance: | ||||
| 
 | ||||
| ```cue | ||||
| parameter: { | ||||
|     image: string | ||||
| } | ||||
| output: { | ||||
|   ... | ||||
|     spec: { | ||||
|         containers: [{ | ||||
|             name:  context.name | ||||
|             image: parameter.image | ||||
|         }] | ||||
|     } | ||||
|   ... | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| > Note that `context` information are auto-injected before resources are applied to target cluster. | ||||
| 
 | ||||
| ### Full available information in CUE `context` | ||||
| 
 | ||||
| | Context Variable  | Description | | ||||
| | :--: | :---------: | | ||||
| | `context.appRevision` | The revision of the application | | ||||
| | `context.appRevisionNum` | The revision number(`int` type) of the application, e.g., `context.appRevisionNum` will be `1` if `context.appRevision` is `app-v1`| | ||||
| | `context.appName` | The name of the application | | ||||
| | `context.name` | The name of the component of the application | | ||||
| | `context.namespace` | The namespace of the application | | ||||
| | `context.output` | The rendered workload API resource of the component, this usually used in trait | | ||||
| | `context.outputs.<resourceName>` | The rendered trait API resource of the component, this usually used in trait | | ||||
| 
 | ||||
| 
 | ||||
| ## Composition | ||||
| 
 | ||||
| It's common that a component definition is composed by multiple API resources, for example, a `webserver` component that is composed by a Deployment and a Service. CUE is a great solution to achieve this in simplified primitives. | ||||
| 
 | ||||
| > Another approach to do composition in KubeVela of course is [using Helm](../helm/component). | ||||
| 
 | ||||
| ## How-to | ||||
| 
 | ||||
| KubeVela requires you to define the template of workload type in `output` section, and leave all the other resource templates in `outputs` section with format as below: | ||||
| 我们会使用 `output` 这个字段来定义工作负载类型的模板,而其他剩下的资源模板,都在 `outputs` 这个字段里进行声明,格式如下: | ||||
| 
 | ||||
| ```cue | ||||
| outputs: <unique-name>:  | ||||
|   <full template data> | ||||
| ``` | ||||
| 
 | ||||
| > The reason for this requirement is KubeVela needs to know it is currently rendering a workload so it could do some "magic" like patching annotations/labels or other data during it. | ||||
| 
 | ||||
| Below is the example for `webserver` definition:  | ||||
| 回到 `webserver` 这个复合自定义组件上,它的 YAML 文件编写如下: | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
|  | @ -330,7 +288,31 @@ spec: | |||
|         } | ||||
| ``` | ||||
| 
 | ||||
| The user could now declare an `Application` with it: | ||||
| 可以看到: | ||||
| 1. 最核心的工作负载,我们按需要在 `output` 字段里,定义了一个要交付的 `Deployment` 类型的 Kubernetes 资源。 | ||||
| 2. `Service` 类型的资源,则放到 `outputs` 里定义。以此类推,如果你要复合第三个资源,只需要继续在后面以键值对的方式添加: | ||||
| 
 | ||||
| ``` | ||||
| outputs: service: { | ||||
|             apiVersion: "v1" | ||||
|             kind:       "Service" | ||||
|             spec: { | ||||
| ... | ||||
| outputs: third-resource: { | ||||
|             apiVersion: "v1" | ||||
|             kind:       "Service" | ||||
|             spec: {    | ||||
| ...                      | ||||
| ``` | ||||
| 
 | ||||
| 在理解这些之后,将上面的组件定义对象保存到 YAML 文件中,并通过 `$ kubectl apply -f webserver-def.yaml` 部署到你的 Kubernetes 集群。 | ||||
| 
 | ||||
| ``` | ||||
| $ kubectl apply -f webserver-def.yaml | ||||
| componentdefinition.core.oam.dev/webserver created | ||||
| ``` | ||||
| 
 | ||||
| 然后,我们使用它们,来编写一个应用部署计划: | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
|  | @ -351,24 +333,18 @@ spec: | |||
|         cpu: "100m" | ||||
| ``` | ||||
| 
 | ||||
| It will generate and manage below API resources in target cluster: | ||||
| 进行部署: | ||||
| ``` | ||||
| $ kubectl apply -f webserver.yaml | ||||
| ``` | ||||
| 最后,它将在运行时集群生成相关 Kubernetes 资源如下: | ||||
| 
 | ||||
| ```shell | ||||
| kubectl get deployment | ||||
| ``` | ||||
| ```console | ||||
| $ kubectl get deployment | ||||
| NAME             READY   UP-TO-DATE   AVAILABLE   AGE | ||||
| hello-world-v1   1/1     1            1           15s | ||||
| ``` | ||||
| 
 | ||||
| ```shell | ||||
| kubectl get svc | ||||
| ``` | ||||
| ```console | ||||
| $ kubectl get svc | ||||
| NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE | ||||
| hello-world-trait-7bdcff98f7   ClusterIP   <your ip>       <none>        8000/TCP   32s | ||||
| ``` | ||||
| 
 | ||||
| ## What's Next | ||||
| 
 | ||||
| Please check the [Learning CUE](../cue/basic) documentation about why we support CUE as first-class templating solution and more details about using CUE efficiently. | ||||
| ``` | ||||
|  | @ -2,608 +2,4 @@ | |||
| title:  开发与调试 | ||||
| --- | ||||
| 
 | ||||
| 本节将介绍如何使用 [CUE](https://cuelang.org/) 通过 `ComponentDefinition` 来声明 app 组件。 | ||||
| 
 | ||||
| > 在阅读本部分之前,请确保你已经学习了 KubeVela 中的 [Definition CRD](../definition-and-templates)。 | ||||
| 
 | ||||
| ## 声明 `ComponentDefinition` | ||||
| 
 | ||||
| 这是一个基于 CUE 的 `ComponentDefinition` 示例,它提供了无状态工作负载类型的抽象: | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: ComponentDefinition | ||||
| metadata: | ||||
|   name: stateless | ||||
| spec: | ||||
|   workload: | ||||
|     definition: | ||||
|       apiVersion: apps/v1 | ||||
|       kind: Deployment | ||||
|   schematic: | ||||
|     cue: | ||||
|       template: | | ||||
|         parameter: { | ||||
|           name:  string | ||||
|           image: string | ||||
|         } | ||||
|         output: { | ||||
|           apiVersion: "apps/v1" | ||||
|           kind:       "Deployment" | ||||
|           spec: { | ||||
|             selector: matchLabels: { | ||||
|               "app.oam.dev/component": parameter.name | ||||
|             } | ||||
|             template: { | ||||
|               metadata: labels: { | ||||
|                 "app.oam.dev/component": parameter.name | ||||
|               } | ||||
|               spec: { | ||||
|                 containers: [{ | ||||
|                   name:  parameter.name | ||||
|                   image: parameter.image | ||||
|                 }] | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
| ``` | ||||
| 详细来说: | ||||
| - 需要 `.spec.workload` 来指示该组件的工作负载类型。 | ||||
| - `.spec.schematic.cue.template` 是一个 CUE 模板,具体来说: | ||||
|      * `output` 字段定义了抽象模板。 | ||||
|      * `parameter` 字段定义了模板参数,即在 `Application` 抽象中公开的可配置属性(KubeVela 将基于parameter字段自动生成Json schema)。 | ||||
| 
 | ||||
| 让我们声明另一个名为 `task` 的组件,即  run-to-completion 负载的抽象。 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: ComponentDefinition | ||||
| metadata: | ||||
|   name: task | ||||
|   annotations: | ||||
|     definition.oam.dev/description: "Describes jobs that run code or a script to completion." | ||||
| spec: | ||||
|   workload: | ||||
|     definition: | ||||
|       apiVersion: batch/v1 | ||||
|       kind: Job | ||||
|   schematic: | ||||
|     cue: | ||||
|       template: | | ||||
|         output: { | ||||
|           apiVersion: "batch/v1" | ||||
|           kind:       "Job" | ||||
|           spec: { | ||||
|             parallelism: parameter.count | ||||
|             completions: parameter.count | ||||
|             template: spec: { | ||||
|               restartPolicy: parameter.restart | ||||
|               containers: [{ | ||||
|                 image: parameter.image | ||||
|                 if parameter["cmd"] != _|_ { | ||||
|                   command: parameter.cmd | ||||
|                 } | ||||
|               }] | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         parameter: { | ||||
|           count:   *1 | int | ||||
|           image:   string | ||||
|           restart: *"Never" | string | ||||
|           cmd?: [...string] | ||||
|         } | ||||
| ``` | ||||
| 
 | ||||
| 将上面的 `ComponentDefinition` 对象保存到文件中,并通过 `$ kubectl apply -f stateless-def.yaml task-def.yaml` 将它们安装到你的 Kubernetes 集群。 | ||||
| 
 | ||||
| ## 声明一个 `Application` | ||||
| 
 | ||||
| `ComponentDefinition` 可以在 `Application` 抽象中实例化,如下所示: | ||||
| 
 | ||||
|   ```yaml | ||||
|   apiVersion: core.oam.dev/v1alpha2 | ||||
|   kind: Application | ||||
|   metadata: | ||||
|     name: website | ||||
|   spec: | ||||
|     components: | ||||
|       - name: hello | ||||
|         type: stateless | ||||
|         properties: | ||||
|           image: crccheck/hello-world | ||||
|           name: mysvc | ||||
|       - name: countdown | ||||
|         type: task | ||||
|         properties: | ||||
|           image: centos:7 | ||||
|           cmd: | ||||
|             - "bin/bash" | ||||
|             - "-c" | ||||
|             - "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done" | ||||
|   ``` | ||||
| 
 | ||||
| ### 背后含义 | ||||
| <details> | ||||
| 
 | ||||
| 上述应用程序资源将根据 CUE 模板中的 `output` 和 `Application` 属性中的用户输入生成和管理目标集群中的以下 Kubernetes 资源。 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: apps/v1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: backend | ||||
|   ... # skip tons of metadata info | ||||
| spec: | ||||
|   template: | ||||
|     spec: | ||||
|       containers: | ||||
|         - name: mysvc | ||||
|           image: crccheck/hello-world | ||||
|     metadata: | ||||
|       labels: | ||||
|         app.oam.dev/component: mysvc | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app.oam.dev/component: mysvc | ||||
| --- | ||||
| apiVersion: batch/v1 | ||||
| kind: Job | ||||
| metadata: | ||||
|   name: countdown | ||||
|   ... # skip tons of metadata info | ||||
| spec: | ||||
|   parallelism: 1 | ||||
|   completions: 1 | ||||
|   template: | ||||
|     metadata: | ||||
|       name: countdown | ||||
|     spec: | ||||
|       containers: | ||||
|         - name: countdown | ||||
|           image: 'centos:7' | ||||
|           command: | ||||
|             - bin/bash | ||||
|             - '-c' | ||||
|             - for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done | ||||
|       restartPolicy: Never | ||||
| ```   | ||||
| </details> | ||||
| 
 | ||||
| ## CUE `Context` | ||||
| 
 | ||||
| KubeVela 允许你通过 `context` 关键字引用应用程序的运行时信息。 | ||||
| 
 | ||||
| 最广泛使用的上下文是应用程序名称(`context.appName`) 组件名称(`context.name`)。 | ||||
| 
 | ||||
| ```cue | ||||
| context: { | ||||
|   appName: string | ||||
|   name: string | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 例如,假设你要使用用户填写的组件名称作为工作负载实例中的容器名称: | ||||
| 
 | ||||
| ```cue | ||||
| parameter: { | ||||
|     image: string | ||||
| } | ||||
| output: { | ||||
|   ... | ||||
|     spec: { | ||||
|         containers: [{ | ||||
|             name:  context.name | ||||
|             image: parameter.image | ||||
|         }] | ||||
|     } | ||||
|   ... | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| > 请注意,在将资源应用于目标集群之前,会自动注入 `context` 信息。 | ||||
| 
 | ||||
| ### CUE `context` 包含的所有信息 | ||||
| 
 | ||||
| | Context Variable  | Description | | ||||
| | :--: | :---------: | | ||||
| | `context.appRevision` | The revision of the application | | ||||
| | `context.appName` | The name of the application | | ||||
| | `context.name` | The name of the component of the application | | ||||
| | `context.namespace` | The namespace of the application | | ||||
| | `context.output` | The rendered workload API resource of the component, this usually used in trait | | ||||
| | `context.outputs.<resourceName>` | The rendered trait API resource of the component, this usually used in trait | | ||||
| 
 | ||||
| 
 | ||||
| ## 构造 | ||||
| 
 | ||||
| 一个组件定义通常由多个 API 资源组成,例如,一个由 Deployment 和 Service 组成的 `webserver` 组件。 CUE 是一个很好的解决方案,可以在简化的原语中实现这一点。 | ||||
| 
 | ||||
| > 当然,另一种在 KubeVela 中进行组合的方法是 [使用 Helm](../helm/component)。 | ||||
| 
 | ||||
| ## 怎么做 | ||||
| 
 | ||||
| KubeVela 要求你在 `output` 部分定义工作负载类型的模板,并在 `outputs` 部分保留所有其他资源模板,格式如下: | ||||
| 
 | ||||
| ```cue | ||||
| outputs: <unique-name>:  | ||||
|   <full template data> | ||||
| ``` | ||||
| 
 | ||||
| > 此要求的原因是 KubeVela 需要知道它当前正在渲染工作负载,因此它可以执行一些“魔术”,例如在此期间修补注释/标签或其他数据。 | ||||
| 
 | ||||
| 下面是 `webserver` 定义的例子: | ||||
| 
 | ||||
| ```yaml | ||||
| 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 | ||||
|         } | ||||
| ``` | ||||
| 
 | ||||
| 用户现在可以用它声明一个 `Application`: | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: Application | ||||
| metadata: | ||||
|   name: webserver-demo | ||||
|   namespace: default | ||||
| spec: | ||||
|   components: | ||||
|     - name: hello-world | ||||
|       type: webserver | ||||
|       properties: | ||||
|         image: crccheck/hello-world | ||||
|         port: 8000 | ||||
|         env: | ||||
|         - name: "foo" | ||||
|           value: "bar" | ||||
|         cpu: "100m" | ||||
| ``` | ||||
| 
 | ||||
| 它将在目标集群中生成和管理以下 API 资源: | ||||
| 
 | ||||
| ```shell | ||||
| $ kubectl get deployment | ||||
| NAME             READY   UP-TO-DATE   AVAILABLE   AGE | ||||
| hello-world-v1   1/1     1            1           15s | ||||
| 
 | ||||
| $ kubectl get svc | ||||
| NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE | ||||
| hello-world-trait-7bdcff98f7   ClusterIP   <your ip>       <none>        8000/TCP   32s | ||||
| ``` | ||||
| 
 | ||||
| ## 使用 CLI 编辑管理 Definitions | ||||
| 
 | ||||
| 在 Vela CLI 工具中,`vela def` 命令组为开发者提供了一系列便捷的 Definition 编写工具,使得 Definition 的编写将全部在 CUE 文件中进行,避免将 Template CUE 与 Kubernetes 的 YAML 格式进行混合,方便进行格式化与校验。 | ||||
| 
 | ||||
| ### init | ||||
| 
 | ||||
| `vela def init` 是一个用来帮助用户初始化新的 Definition 的脚手架命令。用户可以通过 `vela def init my-trait -t trait --desc "My trait description."` 来创建一个新的空白 TraitDefinition ,如下 | ||||
| 
 | ||||
| ```json | ||||
| "my-trait": { | ||||
|         annotations: {} | ||||
|         attributes: { | ||||
|                 appliesToWorkloads: [] | ||||
|                 conflictsWith: [] | ||||
|                 definitionRef:   "" | ||||
|                 podDisruptive:   false | ||||
|                 workloadRefPath: "" | ||||
|         } | ||||
|         description: "My trait description." | ||||
|         labels: {} | ||||
|         type: "trait" | ||||
| } | ||||
| template: patch: {} | ||||
| ``` | ||||
| 
 | ||||
| 或者是采用 `vela def init my-comp --interactive` 来交互式地创建新的 Definition 。 | ||||
| 
 | ||||
| ```bash | ||||
| $ vela def init my-comp --interactive | ||||
| Please choose one definition type from the following values: component, trait, policy, workload, scope, workflow-step | ||||
| > Definition type: component | ||||
| > Definition description: My component definition. | ||||
| Please enter the location the template YAML file to build definition. Leave it empty to generate default template. | ||||
| > Definition template filename:  | ||||
| Please enter the output location of the generated definition. Leave it empty to print definition to stdout. | ||||
| > Definition output filename: my-component.cue | ||||
| Definition written to my-component.cue | ||||
| ``` | ||||
| 
 | ||||
| 除此之外,如果用户创建 ComponentDefinition 的目的是一个 Deployment(或者是其他的 Kubernetes Object ),而这个 Deployment 已经有了 YAML 格式的模版,用户还可以通过 `--template-yaml` 参数来完成从 YAML 到 CUE 的自动转换。例如如下的 `my-deployment.yaml` | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: apps/v1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: hello-world | ||||
| spec: | ||||
|   replicas: 1 | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app.kubernetes.io/name: hello-world | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app.kubernetes.io/name: hello-world | ||||
|     spec: | ||||
|       containers: | ||||
|       - name: hello-world | ||||
|         image: somefive/hello-world | ||||
|         ports:  | ||||
|         - name: http | ||||
|           containerPort: 80 | ||||
|           protocol: TCP | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: hello-world-service | ||||
| spec: | ||||
|   selector: | ||||
|     app: hello-world | ||||
|   ports: | ||||
|   - name: http | ||||
|     protocol: TCP | ||||
|     port: 80 | ||||
|     targetPort: 8080 | ||||
|   type: LoadBalancer | ||||
| ``` | ||||
| 
 | ||||
| 运行 `vela def init my-comp -t component --desc "My component." --template-yaml ./my-deployment.yaml` 可以得到 CUE 格式的 ComponentDefinition | ||||
| 
 | ||||
| ```json | ||||
| "my-comp": { | ||||
|         annotations: {} | ||||
|         attributes: workload: definition: { | ||||
|                 apiVersion: "<change me> apps/v1" | ||||
|                 kind:       "<change me> Deployment" | ||||
|         } | ||||
|         description: "My component." | ||||
|         labels: {} | ||||
|         type: "component" | ||||
| } | ||||
| template: { | ||||
|         output: { | ||||
|                 metadata: name: "hello-world" | ||||
|                 spec: { | ||||
|                         replicas: 1 | ||||
|                         selector: matchLabels: "app.kubernetes.io/name": "hello-world" | ||||
|                         template: { | ||||
|                                 metadata: labels: "app.kubernetes.io/name": "hello-world" | ||||
|                                 spec: containers: [{ | ||||
|                                         name:  "hello-world" | ||||
|                                         image: "somefive/hello-world" | ||||
|                                         ports: [{ | ||||
|                                                 name:          "http" | ||||
|                                                 containerPort: 80 | ||||
|                                                 protocol:      "TCP" | ||||
|                                         }] | ||||
|                                 }] | ||||
|                         } | ||||
|                 } | ||||
|                 apiVersion: "apps/v1" | ||||
|                 kind:       "Deployment" | ||||
|         } | ||||
|         outputs: "hello-world-service": { | ||||
|                 metadata: name: "hello-world-service" | ||||
|                 spec: { | ||||
|                         ports: [{ | ||||
|                                 name:       "http" | ||||
|                                 protocol:   "TCP" | ||||
|                                 port:       80 | ||||
|                                 targetPort: 8080 | ||||
|                         }] | ||||
|                         selector: app: "hello-world" | ||||
|                         type: "LoadBalancer" | ||||
|                 } | ||||
|                 apiVersion: "v1" | ||||
|                 kind:       "Service" | ||||
|         } | ||||
|         parameter: {} | ||||
| 
 | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 接下来,用户就可以在该文件的基础上进一步做进一步的修改了。比如将属性中对于 **workload.definition** 中的 *\<change me\>* 去掉。 | ||||
| 
 | ||||
| ### vet | ||||
| 
 | ||||
| 在初始化 Definition 文件之后,可以运行 `vela def vet my-comp.cue` 来校验 Definition 是否在语法上有错误。比如如果少写了一个括号,该命令能够帮助用户识别出来。 | ||||
| 
 | ||||
| ```bash | ||||
| $ vela def vet my-comp.cue | ||||
| Validation succeed. | ||||
| ``` | ||||
| 
 | ||||
| ### render / apply | ||||
| 
 | ||||
| 确认 Definition 撰写无误后,开发者可以运行 `vela def apply my-comp.cue --namespace my-namespace` 来将该 Definition 应用在 Kubernetes 的 my-namespace 命名空间中。如果想了解一下 CUE 格式的 Definition 文件会被渲染成什么样的 Kubernetes YAML 文件,可以使用 `vela def apply my-comp.cue --dry-run` 或者 `vela def render my-comp.cue -o my-comp.yaml` 来预先渲染一下 YAML 文件进行确认。 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: ComponentDefinition | ||||
| metadata: | ||||
|   annotations: | ||||
|     definition.oam.dev/description: My component. | ||||
|   labels: {} | ||||
|   name: my-comp | ||||
|   namespace: vela-system | ||||
| spec: | ||||
|   schematic: | ||||
|     cue: | ||||
|       template: | | ||||
|         output: { | ||||
|                 metadata: name: "hello-world" | ||||
|                 spec: { | ||||
|                         replicas: 1 | ||||
|                         selector: matchLabels: "app.kubernetes.io/name": "hello-world" | ||||
|                         template: { | ||||
|                                 metadata: labels: "app.kubernetes.io/name": "hello-world" | ||||
|                                 spec: containers: [{ | ||||
|                                         name:  "hello-world" | ||||
|                                         image: "somefive/hello-world" | ||||
|                                         ports: [{ | ||||
|                                                 name:          "http" | ||||
|                                                 containerPort: 80 | ||||
|                                                 protocol:      "TCP" | ||||
|                                         }] | ||||
|                                 }] | ||||
|                         } | ||||
|                 } | ||||
|                 apiVersion: "apps/v11" | ||||
|                 kind:       "Deployment" | ||||
|         } | ||||
|         outputs: "hello-world-service": { | ||||
|                 metadata: name: "hello-world-service" | ||||
|                 spec: { | ||||
|                         ports: [{ | ||||
|                                 name:       "http" | ||||
|                                 protocol:   "TCP" | ||||
|                                 port:       80 | ||||
|                                 targetPort: 8080 | ||||
|                         }] | ||||
|                         selector: app: "hello-world" | ||||
|                         type: "LoadBalancer" | ||||
|                 } | ||||
|                 apiVersion: "v1" | ||||
|                 kind:       "Service" | ||||
|         } | ||||
|         parameter: {} | ||||
|   workload: | ||||
|     definition: | ||||
|       apiVersion: apps/v1 | ||||
|       kind: Deployment | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| $ vela def apply my-comp.cue -n my-namespace | ||||
| ComponentDefinition my-comp created in namespace my-namespace. | ||||
| ``` | ||||
| 
 | ||||
| ### get / list / edit / del | ||||
| 
 | ||||
| 在 apply 命令后,开发者可以采用原生的 kubectl 来对结果进行确认,但是正如我们上文提到的,YAML 格式的结果会相对复杂。使用 `vela def get` 命令可以自动将其转换成 CUE 格式,方便用户查看。 | ||||
| 
 | ||||
| ```bash | ||||
| $ vela def get my-comp -t component | ||||
| ``` | ||||
| 
 | ||||
| 或者用户可以通过 `vela def list` 命令来查看当前系统中安装的所有 Definition(可以指定命名空间及类型)。 | ||||
| 
 | ||||
| ```bash | ||||
| $ vela def list -n my-namespace -t component | ||||
| NAME                    TYPE                    NAMESPACE       DESCRIPTION   | ||||
| my-comp                 ComponentDefinition     my-namespace    My component. | ||||
| ``` | ||||
| 
 | ||||
| 同样的,在使用 `vela def edit` 命令来编辑 Definition 时,用户也只需要对转换过的 CUE 格式 Definition 进行修改,该命令会自动完成格式转换。用户也可以通过设定环境变量 `EDITOR` 来使用自己想要使用的编辑器。 | ||||
| 
 | ||||
| ```bash | ||||
| $ EDITOR=vim vela def edit my-comp | ||||
| ``` | ||||
| 
 | ||||
| 类似的,用户可以运行 `vela def del` 来删除相应的 Definition。 | ||||
| 
 | ||||
| ```bash | ||||
| $ vela def del my-comp -n my-namespace   | ||||
| Are you sure to delete the following definition in namespace my-namespace? | ||||
| ComponentDefinition my-comp: My component. | ||||
| [yes|no] > yes | ||||
| ComponentDefinition my-comp in namespace my-namespace deleted. | ||||
| ``` | ||||
| 
 | ||||
| ## 下一步是什么 | ||||
| 
 | ||||
| 请查看 [Learning CUE](./basic) 文档,了解我们为什么支持 CUE 作为一流的模板解决方案,以及有关有效使用 CUE 的更多详细信息。 | ||||
| TBD | ||||
|  | @ -2,17 +2,15 @@ | |||
| title:  基础 | ||||
| --- | ||||
| 
 | ||||
| 本章节将详细介绍关于如何使用 CUE 封装和抽象 Kubernetes 中已有的能力。 | ||||
| 
 | ||||
| > 开始阅读本章节前,请确保已经了解 `Application` 资源。 | ||||
| CUE 是 KubeVela 的核心依赖,也是用户实现自定义扩展的主要方式。本章节将详细介绍 CUE 的基础知识,帮助你更好地使用 KubeVela。 | ||||
| 
 | ||||
| ## 概述 | ||||
| 
 | ||||
| KubeVela 将 CUE 作为抽象最优方案的主要原因如下: | ||||
| KubeVela 将 CUE 作为应用交付核心依赖和扩展方式的原因如下:: | ||||
| 
 | ||||
| - **CUE 本身就是为大规模配置而设计。** CUE 能够感知非常复杂的配置文件,并且能够安全地更改可修改配置中成千上万个对象的值。这非常符合 KubeVela 的最初目标,即以 web-scale 方式定义和交付生产级别的应用程序(web-scale,是一种软件设计方法,主要包含可扩展性、一致性、容忍度和版本控制等)。 | ||||
| -  **CUE 支持一流的代码生成和自动化。** CUE 原生支持与现有工具以及工作流进行集成,反观其他工具则需要自定义复杂的方案才能实现。例如,需要手动使用 Go 代码生成 OpenAPI 模式。KubeVela 也是依赖 CUE 该特性进行构建开发工具和GUI界面。 | ||||
| - **CUE与Go完美集成。** KubeVela 像 Kubernetes 系统中的大多数项目一样使用 GO 进行开发。CUE 已经在 Go 中实现并提供了丰富的 API 。 KubeVela 以 CUE 为核心实现 Kubernetes 控制器。 借助 CUE KubeVela 可以轻松处理数据约束问题。 | ||||
| - **CUE 本身就是为大规模配置而设计。** CUE 能够感知非常复杂的配置文件,并且能够安全地更改可修改配置中成千上万个对象的值。这非常符合 KubeVela 的目标,即以可编程的方式,去定义和交付生产级别的应用程序。 | ||||
| -  **CUE 支持一流的代码生成和自动化。** CUE 原生支持与现有工具以及工作流进行集成,反观其他工具则需要自定义复杂的方案才能实现。例如,需要手动使用 Go 代码生成 OpenAPI 模式。KubeVela 也是依赖 CUE 该特性进行构建开发工具和 GUI 界面的。 | ||||
| - **CUE 与 Go 完美集成。** KubeVela 像 Kubernetes 系统中的大多数项目一样使用 GO 进行开发。CUE 已经在 Go 中实现并提供了丰富的 API。KubeVela 以 CUE 为核心实现 Kubernetes 控制器。借助 CUE,KubeVela 可以轻松处理数据约束问题。 | ||||
| 
 | ||||
| > 更多细节请查看 [The Configuration Complexity Curse](https://blog.cedriccharly.com/post/20191109-the-configuration-complexity-curse/) 以及 [The Logic of CUE](https://cuelang.org/docs/concepts/logic/)。 | ||||
| 
 | ||||
|  | @ -20,10 +18,19 @@ KubeVela 将 CUE 作为抽象最优方案的主要原因如下: | |||
| 
 | ||||
| 请确保你的环境中已经安装如下命令行: | ||||
| * [`cue` >=v0.2.2](https://cuelang.org/docs/install/) | ||||
| * [`vela` >v1.0.0](../../getting-started/quick-install#3-get-kubevela-cli) 目前 KubeVela 暂时只支持 CUE v0.2.2 版本,将在后续迭代中升级支持新的 CUE 版本。 | ||||
| 
 | ||||
| ## CUE 命令行基础 | ||||
| ## 学习 CUE 命令行 | ||||
| 
 | ||||
| 我们可以使用几乎相同的格式在同一个文件中定义模型和数据,以下为 CUE 基础数据类型: | ||||
| CUE 是 JSON 的超集, 我们可以像使用 JSON 一样使用 CUE,并具备以下特性: | ||||
| 
 | ||||
| * C 语言风格的注释 | ||||
| * 字段名称可以用双引号括起来,注意字段名称中不可以带特殊字符 | ||||
| * 可选字段末尾是否有逗号 | ||||
| * 允许数组中最后一个元素末尾带逗号 | ||||
| * 外大括号可选 | ||||
| 
 | ||||
| 请先复制以下信息,保存为一个 `first.cue` 文件: | ||||
| 
 | ||||
| ``` | ||||
| a: 1.5 | ||||
|  | @ -37,29 +44,28 @@ g: { | |||
| e: string | ||||
| ``` | ||||
| 
 | ||||
| CUE 是 JSON 的超集, 我们可以像使用 json 一样使用 CUE,同时具备以下便利性: | ||||
| 接下来,我们以上面这个文件为例子,来学习 CUE 命令行的相关指令: | ||||
| 
 | ||||
| * C 样式的注释, | ||||
| * 字段名称可以省略引号且不带特殊字符, | ||||
| * 字段末尾逗号可选, | ||||
| * 允许列表中最后一个元素末尾带逗号, | ||||
| * 外花括号可选。 | ||||
| 
 | ||||
| CUE 拥有强大的命令行。请将数据保存到 `first.cue` 文件并尝试使用命令行。 | ||||
| 
 | ||||
| * 格式化 CUE 文件。如果你使用 Goland 或者类似 JetBrains IDE, | ||||
|   可以参考该文章配置自动格式化插件 [使用 Goland 设置 cuelang 的自动格式化](https://wonderflow.info/posts/2020-11-02-goland-cuelang-format/)。 | ||||
|   该命令不仅可以格式化 CUE 文件,还能指出错误的模型,相当好用的命令。 | ||||
| * 如何格式化 CUE 文件。(如果你使用 Goland 或者类似 JetBrains IDE, | ||||
|   可以参考该文章配置自动格式化插件 [使用 Goland 设置 cuelang 的自动格式化](https://wonderflow.info/posts/2020-11-02-goland-cuelang-format/)。) | ||||
|    | ||||
|   该命令不仅可以格式化 CUE 文件,还能提示错误的模型,相当好用的命令。 | ||||
|     ```shell | ||||
|     cue fmt first.cue | ||||
|     ``` | ||||
| 
 | ||||
| * 模型校验。 除了 `cue fmt`,你还可以使用 `vue vet` 来校验模型. | ||||
| * 如何校验模型。除了 `cue fmt`,你还可以使用 `cue vet` 来校验模型。 | ||||
|     ```shell | ||||
|     cue vet first.cue | ||||
|     ``` | ||||
|     $ cue vet first.cue | ||||
|     some instances are incomplete; use the -c flag to show errors or suppress this message | ||||
|      | ||||
|     $ cue vet first.cue -c | ||||
|     e: incomplete value string | ||||
| 
 | ||||
| * 计算/渲染结果。 `cue eval` 可以计算 CUE 文件并且渲染出最终结果。 | ||||
|     ``` | ||||
|   提示我们:这个文件里的 e 这个变量,有数据类型 `string` 但并没有赋值。 | ||||
| 
 | ||||
| * 如何计算/渲染结果。 `cue eval` 可以计算 CUE 文件并且渲染出最终结果。 | ||||
|   我们看到最终结果中并不包含 `a: float` 和 `b: int`,这是因为这两个变量已经被计算填充。 | ||||
|   其中 `e: string` 没有被明确的赋值, 故保持不变. | ||||
|     ```shell | ||||
|  | @ -73,23 +79,31 @@ CUE 拥有强大的命令行。请将数据保存到 `first.cue` 文件并尝试 | |||
|     e: string | ||||
|     ``` | ||||
| 
 | ||||
| * 渲染指定结果。例如,我们仅想知道文件中 `b` 的渲染结果,则可以使用该参数 `-e`。 | ||||
| * 如何指定渲染的结果。例如,我们仅想知道文件中 `b` 的渲染结果,则可以使用该参数 `-e`。 | ||||
|     ```shell | ||||
|     $ cue eval -e b first.cue | ||||
|     1 | ||||
|     ``` | ||||
| 
 | ||||
| * 导出渲染结果。 `cue export` 可以导出最终渲染结果。如果一些变量没有被定义执行该命令将会报错。 | ||||
| * 如何导出渲染结果。 `cue export` 可以导出最终渲染结果。如果一些变量没有被定义执行该命令将会报错。 | ||||
|     ```shell | ||||
|     $ cue export first.cue | ||||
|     e: cannot convert incomplete value "string" to JSON: | ||||
|         ./first.cue:9:4 | ||||
|     e: incomplete value string   | ||||
|     ``` | ||||
|   我们可以通过给 `e` 赋值来完成赋值,例如: | ||||
|   我们更新一下 `first.cue` 文件,给 `e` 赋值: | ||||
|     ```shell | ||||
|     echo "e: \"abc\"" >> first.cue | ||||
|     a: 1.5 | ||||
|     a: float | ||||
|     b: 1 | ||||
|     b: int | ||||
|     d: [1, 2, 3] | ||||
|     g: { | ||||
|       h: "abc" | ||||
|     } | ||||
|     e: string | ||||
|     e: "abc" | ||||
|     ``` | ||||
|   然后,该命令就可以正常工作。默认情况下, 渲染结果会被格式化为 json 格式。 | ||||
|   然后,该命令就可以正常工作。默认情况下, 渲染结果会被格式化为 JSON 格式。 | ||||
|     ```shell | ||||
|     $ cue export first.cue | ||||
|     { | ||||
|  | @ -107,7 +121,7 @@ CUE 拥有强大的命令行。请将数据保存到 `first.cue` 文件并尝试 | |||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| * 导出 YAML 格式渲染结果。 | ||||
| * 如何导出 YAML 格式的渲染结果。 | ||||
|     ```shell | ||||
|     $ cue export first.cue --out yaml | ||||
|     a: 1.5 | ||||
|  | @ -121,7 +135,7 @@ CUE 拥有强大的命令行。请将数据保存到 `first.cue` 文件并尝试 | |||
|     e: abc | ||||
|     ``` | ||||
| 
 | ||||
| * 导出指定变量的结果。 | ||||
| * 如何导出指定变量的结果。 | ||||
|     ```shell | ||||
|     $ cue export -e g first.cue | ||||
|     { | ||||
|  | @ -129,11 +143,13 @@ CUE 拥有强大的命令行。请将数据保存到 `first.cue` 文件并尝试 | |||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| 至此, 你已经学习完所有常用 CUE 命令行参数。 | ||||
| 以上, 你已经学习完所有常用的 CUE 命令行指令。 | ||||
| 
 | ||||
| ## CUE 语言基础 | ||||
| ## 学习 CUE 语言 | ||||
| 
 | ||||
| * 数据类型: 以下为 CUE 的基础数据类型。 | ||||
| 在熟悉完常用 CUE 命令行指令后,我们来进一步学习 CUE 语言。 | ||||
| 
 | ||||
| 先了解 CUE 的数据类型。以下是它的基础数据类型: | ||||
| 
 | ||||
| ```shell | ||||
| // float | ||||
|  | @ -165,7 +181,7 @@ f: { | |||
| j: null | ||||
| ``` | ||||
| 
 | ||||
| * 自定义 CUE 类型。你可以使用 `#` 符号来指定一些表示 CUE 类型的变量。 | ||||
| 如何自定义 CUE 类型?使用 `#` 符号来指定一些表示 CUE 类型的变量。 | ||||
| 
 | ||||
| ``` | ||||
| #abc: string | ||||
|  | @ -191,11 +207,11 @@ $ cue export second.cue | |||
| } | ||||
| ``` | ||||
| 
 | ||||
| 自定义结构在 KubeVela 中被广泛用于定义模板和进行验证。 | ||||
| 自定义结构在 KubeVela 中被广泛用于模块定义(X-Definitions)和进行验证。 | ||||
| 
 | ||||
| ## CUE 模板和引用 | ||||
| ## 定义一个 CUE 模板 | ||||
| 
 | ||||
| 我们开始尝试利用刚刚学习知识来定义 CUE 模版。 | ||||
| 下面,我们开始尝试利用刚刚学习到的知识,来定义 CUE 模版。 | ||||
| 
 | ||||
| 1. 定义结构体变量 `parameter`. | ||||
| 
 | ||||
|  | @ -231,11 +247,11 @@ template: { | |||
| } | ||||
| ``` | ||||
| 
 | ||||
| 熟悉 Kubernetes 的人可能已经知道,这是 Kubernetes Deployment 的模板。 `parameter` 为模版的参数部分。 | ||||
| 熟悉 Kubernetes 的你可能已经知道,这是 Kubernetes Deployment 的模板。 `parameter` 为模版的参数部分。 | ||||
| 
 | ||||
| 添加上述内容到文件 `deployment.cue`. | ||||
| 
 | ||||
| 4. 随后, 我们通过添加以下内容来完成变量赋值: | ||||
| 4. 随后, 我们通过更新以下内容来完成变量赋值: | ||||
| 
 | ||||
| ``` | ||||
| parameter:{ | ||||
|  | @ -244,31 +260,34 @@ parameter:{ | |||
| } | ||||
| ``` | ||||
| 
 | ||||
| 5. 最后, 导出渲染结果为 yaml 格式: | ||||
| 5. 最后, 导出渲染结果为 YAML 格式: | ||||
| 
 | ||||
| ```shell | ||||
| $ cue export deployment.cue -e template --out yaml | ||||
| 
 | ||||
| apiVersion: apps/v1 | ||||
| kind: Deployment | ||||
| spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app.oam.dev/component: mytest | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app.oam.dev/component: mytest | ||||
|     spec: | ||||
|       containers: | ||||
|       - name: mytest | ||||
|         image: nginx:v1 | ||||
|     metadata: | ||||
|       labels: | ||||
|         app.oam.dev/component: mytest | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app.oam.dev/component: mytest | ||||
| ``` | ||||
| 
 | ||||
| ## 高级 CUE 设计 | ||||
| 以上,你就得到了一个 Kubernetes Deployment 类型的模板。 | ||||
| 
 | ||||
| * 开放的结构体和列表。在列表或者结构体中使用 `...` 说明该对象为开放的。 | ||||
|    -  列表对象 `[...string]` ,说明该对象可以容纳多个字符串元素。 | ||||
|       如果不添加 `...`, 该对象 `[string]` 说明列表只能容纳一个类型为 `string` 的元素。 | ||||
| ## CUE 的更多用法 | ||||
| 
 | ||||
| * 设计开放的结构体和数组。如果在数组或者结构体中使用 `...`,则说明该对象为开放的。 | ||||
|    -  数组对象 `[...string]` ,说明该对象可以容纳多个字符串元素。 | ||||
|       如果不添加 `...`, 该对象 `[string]` 说明数组只能容纳一个类型为 `string` 的元素。 | ||||
|    -  如下所示的结构体说明可以包含未知字段。 | ||||
|       ``` | ||||
|       { | ||||
|  | @ -277,20 +296,20 @@ spec: | |||
|       } | ||||
|       ``` | ||||
| 
 | ||||
| * 运算符  `|`, 它可以表示两种类型的值。如下所示,变量 `a` 表示类型可以是字符串或者整数类型。 | ||||
| * 使用运算符  `|` 来表示两种类型的值。如下所示,变量 `a` 表示类型可以是字符串或者整数类型。 | ||||
| 
 | ||||
| ```shell | ||||
| a: string | int | ||||
| ``` | ||||
| 
 | ||||
| * 默认值, 我们可以使用符号 `*` 定义变量的默认值。通常与符号 `|` 配合使用, | ||||
| * 使用符号 `*` 定义变量的默认值。通常它与符号 `|` 配合使用, | ||||
|   代表某种类型的默认值。如下所示,变量 `a` 类型为 `int`,默认值为 `1`。 | ||||
| 
 | ||||
| ```shell | ||||
| a: *1 | int | ||||
| ``` | ||||
| 
 | ||||
| * 选填变量。 某些情况下,一些变量不一定被使用,这些变量就是可选变量,我们可以使用 `?:` 定义此类变量。 | ||||
| * 让一些变量可被选填。 某些情况下,一些变量不一定被使用,这些变量就是可选变量,我们可以使用 `?:` 定义此类变量。 | ||||
|   如下所示, `a` 是可选变量, 自定义 `#my` 对象中 `x` 和 `z` 为可选变量, 而 `y` 为必填字段。 | ||||
| 
 | ||||
| ``` | ||||
|  | @ -327,7 +346,7 @@ output: { | |||
| } | ||||
| ``` | ||||
| 
 | ||||
| * 运算符  `&`,该运算符用来运算两个变量。 | ||||
| * 使用运算符 `&` 来运算两个变量。 | ||||
| 
 | ||||
| ```shell | ||||
| a: *1 | int | ||||
|  | @ -346,7 +365,7 @@ b: 3 | |||
| c: 3 | ||||
| ``` | ||||
| 
 | ||||
| * 条件判断。 当你执行一些级联操作时,不同的值会影响不同的结果,条件判断就非常有用。 | ||||
| * 需要执行条件判断。当你执行一些级联操作时,不同的值会影响不同的结果,条件判断就非常有用。 | ||||
|   因此,你可以在模版中执行 `if..else` 的逻辑。 | ||||
| 
 | ||||
| ```shell | ||||
|  | @ -393,8 +412,8 @@ output: { | |||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| * For循环。 我们为了避免重复可以使用 for 循环。 | ||||
|   - Map 循环 | ||||
| * 使用 For 循环。 我们为了避免减少重复代码,常常使用 For 循环。 | ||||
|   - 映射遍历。 | ||||
|     ```cue | ||||
|     parameter: { | ||||
|         name:  string | ||||
|  | @ -416,7 +435,7 @@ output: { | |||
|         } | ||||
|     } | ||||
|     ``` | ||||
|   - 类型循环 | ||||
|   - 类型遍历。 | ||||
|     ``` | ||||
|     #a: { | ||||
|         "hello": "Barcelona" | ||||
|  | @ -430,7 +449,7 @@ output: { | |||
|         } | ||||
|     } | ||||
|     ``` | ||||
|   - 切片循环 | ||||
|   - 切片遍历。 | ||||
|     ```cue | ||||
|     parameter: { | ||||
|         name:  string | ||||
|  | @ -454,13 +473,13 @@ output: { | |||
|     } | ||||
|     ``` | ||||
| 
 | ||||
| 备注, 可以使用 `"\( _my-statement_ )"` 进行字符串内部计算,比如上面类型循环示例中,获取值的长度等等操作。 | ||||
| 另外,可以使用 `"\( _my-statement_ )"` 进行字符串内部计算,比如上面类型循环示例中,获取值的长度等等操作。 | ||||
| 
 | ||||
| ## 导入 CUE 内部包 | ||||
| 
 | ||||
| CUE 有很多 [internal packages](https://pkg.go.dev/cuelang.org/go@v0.2.2/pkg) 可以被 KubeVela 使用。 | ||||
| CUE 有很多 [internal packages](https://pkg.go.dev/cuelang.org/go@v0.2.2/pkg) 可以被 KubeVela 使用,这样可以满足更多的开发需求。 | ||||
| 
 | ||||
| 如下所示,使用 `strings.Join` 方法将字符串列表拼接成字符串。 | ||||
| 比如,使用 `strings.Join` 方法将字符串数组拼接成字符串。 | ||||
| 
 | ||||
| ```cue | ||||
| import ("strings") | ||||
|  | @ -482,7 +501,7 @@ output: { | |||
| 
 | ||||
| ## 导入 Kubernetes 包 | ||||
| 
 | ||||
| KubeVela 会从 Kubernetes 集群中读取 OpenApi,并将 Kubernetes 所有资源自动构建为内部包。 | ||||
| KubeVela 会从 Kubernetes 集群中读取 OpenAPI,并将 Kubernetes 所有资源自动构建为内部包。 | ||||
| 
 | ||||
| 你可以在 KubeVela 的 CUE 模版中通过 `kube/<apiVersion>` 导入这些包,就像使用 CUE 内部包一样。 | ||||
| 
 | ||||
|  | @ -521,7 +540,7 @@ parameter: { | |||
| } | ||||
| ``` | ||||
| 
 | ||||
| 甚至已经安装的 CRD 也可以正常使用: | ||||
| 甚至已经安装的 CRD 也可以导入使用: | ||||
| 
 | ||||
| ``` | ||||
| import ( | ||||
|  |  | |||
|  | @ -1,53 +0,0 @@ | |||
| --- | ||||
| title:  Define resources located in defferent namespace with application | ||||
| --- | ||||
| 
 | ||||
| In this section, we will introduce how to use cue template create resources (workload/trait) in different namespace with the application. | ||||
| 
 | ||||
| By default, the `metadata.namespace` of K8s resource in CuE template is automatically filled with the same namespace of the applicaiton. | ||||
| 
 | ||||
| If you want to create K8s resources running in a specific namespace witch is different with the application, you can set the `metadata.namespace` field. | ||||
| KubeVela will create the resources in the specified namespace, and create a resourceTracker object as owner of those resources. | ||||
| 
 | ||||
| 
 | ||||
| ## Usage | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: ComponentDefinition | ||||
| metadata: | ||||
|   name: worker | ||||
| spec: | ||||
|   definitionRef: | ||||
|     name: deployments.apps | ||||
|   schematic: | ||||
|     cue: | ||||
|       template: | | ||||
|         parameter: { | ||||
|         	name:  string | ||||
|         	image: string | ||||
|         	namespace: string  # make this parameter `namespace` as keyword which represents the resource maybe located in defferent namespace with application | ||||
|         } | ||||
|         output: { | ||||
|         	apiVersion: "apps/v1" | ||||
|         	kind:       "Deployment" | ||||
|                 metadata: { | ||||
|                    namespace: my-namespace | ||||
|                 } | ||||
|         	spec: { | ||||
|         		selector: matchLabels: { | ||||
|         			"app.oam.dev/component": parameter.name | ||||
|         		} | ||||
|         		template: { | ||||
|         			metadata: labels: { | ||||
|         				"app.oam.dev/component": parameter.name | ||||
|         			} | ||||
|         			spec: { | ||||
|         				containers: [{ | ||||
|         					name:  parameter.name | ||||
|         					image: parameter.image | ||||
|         				}] | ||||
|         			}}} | ||||
|         } | ||||
| ``` | ||||
| 
 | ||||
|  | @ -4,6 +4,7 @@ title:  KEDA 作为自动伸缩 Trait | |||
| 
 | ||||
| > 在继续之前,请确保你已了解 [Definition Objects](definition-and-templates) 和 [Defining Traits with CUE](./traits/customize-trait) 的概念。 | ||||
| 
 | ||||
| 
 | ||||
| 在下面的教程中,你将学习将 [KEDA](https://keda.sh/) 作为新的自动伸缩 trait 添加到基于 KubeVela 的平台中。 | ||||
| 
 | ||||
| > KEDA 是基于 Kubernetes 事件驱动的自动伸缩工具。使用 KEDA,你可以根据资源指标或需要处理的事件数来驱动任何容器的伸缩。 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| title:  自定义运维特征 | ||||
| --- | ||||
| 
 | ||||
| 
 | ||||
| 本节,我们将为作为平台管理员的你,介绍如何自定义运维特征,为用户的组件增添任何需要的运维特征能力。 | ||||
| 
 | ||||
| ### 开始之前 | ||||
|  | @ -12,6 +13,7 @@ title:  自定义运维特征 | |||
| 
 | ||||
| 我们首先为你展示一个简单的示例,比如直接引用已有的 Kubernetes API 资源 Ingress。来编写一个下面这样的 YAML 文件: | ||||
| 
 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: TraitDefinition | ||||
|  | @ -53,6 +55,7 @@ volumes          	vela-system	deployments.apps 	              	true          	Ad | |||
| 
 | ||||
| 最后用户只需要把这个自定义的运维特征,放入一个与之匹配的组件中进行使用即可: | ||||
| 
 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: Application | ||||
|  | @ -93,6 +96,7 @@ spec: | |||
| 
 | ||||
| 在用法上,你需要把所有的运维特征定义在 `outputs` 里(注意,不是 `output`),格式如下: | ||||
| 
 | ||||
| 
 | ||||
| ```cue | ||||
| outputs: <unique-name>:  | ||||
|   <full template data> | ||||
|  | @ -100,6 +104,7 @@ outputs: <unique-name>: | |||
| 
 | ||||
| 我们下面同样使用一个 `ingress` 和 `Service` 的示例进行讲解: | ||||
| 
 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: TraitDefinition | ||||
|  | @ -133,6 +138,7 @@ spec: | |||
|         				targetPort: v | ||||
|         			}, | ||||
|         		] | ||||
| 
 | ||||
|             type: "LoadBalancer" | ||||
|         	} | ||||
|         } | ||||
|  | @ -189,6 +195,7 @@ volumes        	vela-system	deployments.apps 	              	true          	Add | |||
| 
 | ||||
| 最后用户将这个运维特征放入对应组件,通过应用部署计划完成交付: | ||||
| 
 | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: core.oam.dev/v1beta1 | ||||
| kind: Application | ||||
|  | @ -212,4 +219,4 @@ spec: | |||
|               "/api": 8080 | ||||
| ``` | ||||
| 
 | ||||
| 基于 CUE 的运维特征定义方式,也提供了满足于更多业务场景的用法,比如给运维特征打补丁、传递数据等等。后面的文档将进一步介绍相关内容。 | ||||
| 基于 CUE 的运维特征定义方式,也提供了满足于更多业务场景的用法,比如给运维特征打补丁、传递数据等等。后面的文档将进一步介绍相关内容。 | ||||
|  |  | |||
|  | @ -107,7 +107,10 @@ module.exports = { | |||
|       items: [ | ||||
|         'platform-engineers/addon', | ||||
|         { | ||||
|           'Learning OAM': [ | ||||
|           type: 'category', | ||||
|           label: 'Learning OAM', | ||||
|           collapsed: false, | ||||
|            items:[ | ||||
|             'platform-engineers/oam/oam-model', | ||||
|             'platform-engineers/oam/x-definition', | ||||
|           ] | ||||
|  | @ -135,8 +138,7 @@ module.exports = { | |||
|           type: 'category', | ||||
|           label: 'Component System', | ||||
|           items: [ | ||||
|             'platform-engineers/components/component-default', | ||||
|             'platform-engineers/components/component-cue', | ||||
|             'platform-engineers/components/custom-component', | ||||
|             'platform-engineers/components/component-terraform', | ||||
|           ] | ||||
|         }, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue