github.com/oam-dev/kubevela@v1.9.11/design/vela-cli/def_zh.md (about) 1 --- 2 title: 使用CLI编写X-Definitions 3 --- 4 5 ## 简介 6 7 `vela def` 是一组用来帮助用户管理编辑KubeVela中的Definition(包括 ComponentDefinition, TraitDefinition 等)的命令行工具。 8 9 ## 使用背景 10 11 在 KubeVela 中,Definition 的主要能力由 CUE 格式的 Template 来定义,作为一种基于 JSON 格式的语言,CUE 格式的 Template 与原生 Kubernetes 中的 YAML 格式并不相互兼容,在将 CUE 格式的 Template 嵌入 Kubernetes 的 YAML 中时,我们需要将 CUE 转换成为字符串格式,这使得 Definition 在原生 Kubernetes 工具 kubectl 中的使用变得较为复杂。比如一个简单的给已有 Component 打标签的 TraitDefinition 可以通过 `kubectl get trait labels -n vela-system -o yaml` 来获取。 12 13 ```yaml 14 apiVersion: core.oam.dev/v1beta1 15 kind: TraitDefinition 16 metadata: 17 annotations: 18 definition.oam.dev/description: Add labels for your Workload. 19 meta.helm.sh/release-name: kubevela 20 meta.helm.sh/release-namespace: vela-system 21 creationTimestamp: "2021-08-05T07:06:58Z" 22 generation: 1 23 labels: 24 app.kubernetes.io/managed-by: Helm 25 name: labels 26 namespace: vela-system 27 resourceVersion: "8423" 28 uid: 51a7f8b1-f14d-4776-b538-02ac54a55661 29 spec: 30 appliesToWorkloads: 31 - deployments.apps 32 podDisruptive: true 33 schematic: 34 cue: 35 template: "patch: spec: template: metadata: labels: {\n\tfor k, v in parameter 36 {\n\t\t\"\\(k)\": v\n\t}\n}\nparameter: [string]: string\n" 37 status: 38 configMapRef: schema-labels 39 latestRevision: 40 name: labels-v1 41 revision: 1 42 revisionHash: fe7fa9da440dc9d3 43 ``` 44 45 可以看到,作为表达该 Definition 能力核心的 `spec.schematic.cue.template` 是一个经过转化的 CUE 字符串,但很难辨识与编辑。 46 47 另一方面,CUE 语言虽然具有很强的表达能力,但作为一种较新语言的它对于很多 Kubernetes 开发者来说,相对有些陌生,直接编写 CUE 格式可能会花一些时间上手。 48 49 因此,KubeVela 团队在 CLI 工具中加入了一系列相关功能,帮助开发者能够便捷的设计使用各种 Definition 。 50 51 ## 设计 52 53 上文提到的 CUE 与 YAML 混合的 Definition 在 v1.1 版本中,转换为了 CUE 格式的单一描述文件,更加清晰简练的表达了 Definition 的内容与能力。比如上述的 labels 就可以用以下文件来表达 54 55 ```json 56 // labels.cue 57 labels: { 58 annotations: {} 59 attributes: { 60 appliesToWorkloads: ["deployments.apps"] 61 podDisruptive: true 62 } 63 description: "Add labels for your Workload." 64 labels: {} 65 type: "trait" 66 } 67 template: { 68 patch: spec: template: metadata: labels: { 69 for k, v in parameter { 70 "\(k)": v 71 } 72 } 73 parameter: [string]: string 74 } 75 ``` 76 77 其中,第一部分 `labels: {...}` 表达了该 Definition 的基本信息(包括其类型、描述、标签以及基本属性),而第二部分 `template: {...}` 则表达了该 Definition 具体的能力。借用 `vela def` 命令组,KubeVela 用户可以直接直接与 CUE 格式的文件打交道,而不需要直接面对较为复杂的 YAML 文件。 78 79 ## 详细文档 80 81 ### init 82 83 `vela def init` 是一个用来帮助用户初始化新的 Definition 的脚手架命令。用户可以通过 `vela def init my-trait -t trait --desc "My trait description."` 来创建一个新的空白 TraitDefinition ,如下 84 85 ```json 86 "my-trait": { 87 annotations: {} 88 attributes: { 89 appliesToWorkloads: [] 90 conflictsWith: [] 91 definitionRef: "" 92 podDisruptive: false 93 workloadRefPath: "" 94 } 95 description: "My trait description." 96 labels: {} 97 type: "trait" 98 } 99 template: { 100 patch: {} 101 parameter: {} 102 } 103 ``` 104 105 或者是采用 `vela def init my-comp --interactive` 来交互式地创建新的 Definition 。 106 107 ```bash 108 $ vela def init my-comp --interactive 109 Please choose one definition type from the following values: component, trait, policy, workload, scope, workflow-step 110 > Definition type: component 111 > Definition description: My component definition. 112 Please enter the location the template YAML file to build definition. Leave it empty to generate default template. 113 > Definition template filename: 114 Please enter the output location of the generated definition. Leave it empty to print definition to stdout. 115 > Definition output filename: my-component.cue 116 Definition written to my-component.cue 117 ``` 118 119 除此之外,如果用户创建 ComponentDefinition 的目的是一个 Deployment(或者是其他的 Kubernetes Object ),而这个 Deployment 已经有了 YAML 格式的模版,用户还可以通过 `--template-yaml` 参数来完成从 YAML 到 CUE 的自动转换。例如如下的 `my-deployment.yaml` 120 121 ```yaml 122 apiVersion: apps/v1 123 kind: Deployment 124 metadata: 125 name: hello-world 126 spec: 127 replicas: 1 128 selector: 129 matchLabels: 130 app.kubernetes.io/name: hello-world 131 template: 132 metadata: 133 labels: 134 app.kubernetes.io/name: hello-world 135 spec: 136 containers: 137 - name: hello-world 138 image: somefive/hello-world 139 ports: 140 - name: http 141 containerPort: 80 142 protocol: TCP 143 --- 144 apiVersion: v1 145 kind: Service 146 metadata: 147 name: hello-world-service 148 spec: 149 selector: 150 app: hello-world 151 ports: 152 - name: http 153 protocol: TCP 154 port: 80 155 targetPort: 8080 156 type: LoadBalancer 157 ``` 158 159 运行 `vela def init my-comp -t component --desc "My component." --template-yaml ./my-deployment.yaml` 可以得到 CUE 格式的 ComponentDefinition 160 161 ```json 162 "my-comp": { 163 annotations: {} 164 attributes: workload: definition: { 165 apiVersion: "<change me> apps/v1" 166 kind: "<change me> Deployment" 167 } 168 description: "My component." 169 labels: {} 170 type: "component" 171 } 172 template: { 173 output: { 174 metadata: name: "hello-world" 175 spec: { 176 replicas: 1 177 selector: matchLabels: "app.kubernetes.io/name": "hello-world" 178 template: { 179 metadata: labels: "app.kubernetes.io/name": "hello-world" 180 spec: containers: [{ 181 name: "hello-world" 182 image: "somefive/hello-world" 183 ports: [{ 184 name: "http" 185 containerPort: 80 186 protocol: "TCP" 187 }] 188 }] 189 } 190 } 191 apiVersion: "apps/v1" 192 kind: "Deployment" 193 } 194 outputs: "hello-world-service": { 195 metadata: name: "hello-world-service" 196 spec: { 197 ports: [{ 198 name: "http" 199 protocol: "TCP" 200 port: 80 201 targetPort: 8080 202 }] 203 selector: app: "hello-world" 204 type: "LoadBalancer" 205 } 206 apiVersion: "v1" 207 kind: "Service" 208 } 209 parameter: {} 210 211 } 212 ``` 213 214 接下来,用户就可以在该文件的基础上进一步做进一步的修改了。比如将属性中对于 **workload.definition** 中的 *\<change me\>* 去掉。 215 216 ### vet 217 218 在初始化 Definition 文件之后,可以运行 `vela def vet my-comp.cue` 来校验 Definition 是否在语法上有错误。比如如果少写了一个括号,该命令能够帮助用户识别出来。 219 220 ```bash 221 $ vela def vet my-comp.cue 222 Validation succeed. 223 ``` 224 225 ### render / apply 226 227 确认 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 文件进行确认。 228 229 ```yaml 230 apiVersion: core.oam.dev/v1beta1 231 kind: ComponentDefinition 232 metadata: 233 annotations: 234 definition.oam.dev/description: My component. 235 labels: {} 236 name: my-comp 237 namespace: vela-system 238 spec: 239 schematic: 240 cue: 241 template: | 242 output: { 243 metadata: name: "hello-world" 244 spec: { 245 replicas: 1 246 selector: matchLabels: "app.kubernetes.io/name": "hello-world" 247 template: { 248 metadata: labels: "app.kubernetes.io/name": "hello-world" 249 spec: containers: [{ 250 name: "hello-world" 251 image: "somefive/hello-world" 252 ports: [{ 253 name: "http" 254 containerPort: 80 255 protocol: "TCP" 256 }] 257 }] 258 } 259 } 260 apiVersion: "apps/v11" 261 kind: "Deployment" 262 } 263 outputs: "hello-world-service": { 264 metadata: name: "hello-world-service" 265 spec: { 266 ports: [{ 267 name: "http" 268 protocol: "TCP" 269 port: 80 270 targetPort: 8080 271 }] 272 selector: app: "hello-world" 273 type: "LoadBalancer" 274 } 275 apiVersion: "v1" 276 kind: "Service" 277 } 278 parameter: {} 279 workload: 280 definition: 281 apiVersion: apps/v1 282 kind: Deployment 283 ``` 284 285 ```bash 286 $ vela def apply my-comp.cue -n my-namespace 287 ComponentDefinition my-comp created in namespace my-namespace. 288 ``` 289 290 ### get / list / edit / del 291 292 在 apply 命令后,开发者可以采用原生的 kubectl 来对结果进行确认,但是正如我们上文提到的,YAML 格式的结果会相对复杂。使用 `vela def get` 命令可以自动将其转换成 CUE 格式,方便用户查看。 293 294 ```bash 295 $ vela def get my-comp -t component 296 ``` 297 298 或者用户可以通过 `vela def list` 命令来查看当前系统中安装的所有 Definition(可以指定命名空间及类型)。 299 300 ```bash 301 $ vela def list -n my-namespace -t component 302 NAME TYPE NAMESPACE DESCRIPTION 303 my-comp ComponentDefinition my-namespace My component. 304 ``` 305 306 同样的,在使用 `vela def edit` 命令来编辑 Definition 时,用户也只需要对转换过的 CUE 格式 Definition 进行修改,该命令会自动完成格式转换。用户也可以通过设定环境变量 `EDITOR` 来使用自己想要使用的编辑器。 307 308 ```bash 309 $ EDITOR=vim vela def edit my-comp 310 ``` 311 312 类似的,用户可以运行 `vela def del` 来删除相应的 Definition。 313 314 ```bash 315 $ vela def del my-comp -n my-namespace 316 Are you sure to delete the following definition in namespace my-namespace? 317 ComponentDefinition my-comp: My component. 318 [yes|no] > yes 319 ComponentDefinition my-comp in namespace my-namespace deleted. 320 ``` 321