This commit is contained in:
yangsoon
2021-05-12 13:43:15 +08:00
committed by GitHub
parent ba8c6c020a
commit c4cb69120e
6 changed files with 220 additions and 209 deletions

View File

@@ -1,110 +0,0 @@
---
title: Specify Definition Revision in Application
---
Each time the platform provider update ComponentDefinition/TraitDefinition, a corresponding DefinitionRevision will be generated.
And the DefinitionRevision can be regarded as a snapshot of ComponentDefinition/TraitDefinition.
In this section, we will introduce how to specify a revision in Application.
## Usage of Definition
Suppose we need a `worker` to run a background service. And the platform provider has already provided a `worker`
ComponentDefinition for us(The ComponentDefinition `worker` may have been updated multiple times).
Assume the platform provider registered the `v1` version of the `worker` like below:
**Click to see how to register the v1 version of the worker**
<details>
```shell
kubectl apply -f https://raw.githubusercontent.com/oam-dev/kubevela/master/docs/examples/definition-revision/worker-v1.yaml
```
</details>
We can use `kubectl vela show` to see the specification doc of the `worker`.
```shell
$ kubectl vela show worker
# Properties
+-------+----------------------------------------------------+----------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+-------+----------------------------------------------------+----------+----------+---------+
| cmd | Commands to run in the container | []string | false | |
| image | Which image would you like to use for your service | string | true | |
+-------+----------------------------------------------------+----------+----------+---------+
```
Assume the platform provider has updated the version of the `worker` to `v2` like below.
**Click to see how to update**
<details>
```shell
kubectl apply -f https://raw.githubusercontent.com/oam-dev/kubevela/master/docs/examples/definition-revision/worker-v2.yaml
```
</details>
The latest worker ComponentDefinition adds the `port` parameter, allowing users to specify the port exposed by the container.
```shell
$ kubectl vela show worker
# Properties
+-------+----------------------------------------------------+----------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+-------+----------------------------------------------------+----------+----------+---------+
| cmd | Commands to run in the container | []string | false | |
| image | Which image would you like to use for your service | string | true | |
| port | Which port do you want customer traffic sent to | int | true | |
+-------+----------------------------------------------------+----------+----------+---------+
```
When the platform provider updated the two versions of the worker, the corresponding DefinitionRevision will
be generated to store the snapshot information.
```shell
$ kubectl get definitionrevision -l="componentdefinition.oam.dev/name=worker"
NAME REVISION HASH TYPE
worker-v1 1 76486234845427dc Component
worker-v2 2 cb22fdc3b037702e Component
```
## Specify Definition Version in Application
We can specify the Component to use a specific version of the Definition in Application,
By default, the application will always use the latest Definition to render the Component.
But the latest Definition may not be compatible with user's application, so we can specify the old version like `v1` of the worker to render the Component.
we can specify the version of Definition in format `definitionName@version`.
```yaml
# testapp.yaml
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: testapp
spec:
components:
- name: backend
type: worker@v1
properties:
image: crccheck/hello-world
```
```shell
kubectl apply -f testapp.yaml
```
The `v1` version of the `worker` only allows the container to expose port `8000`.
```shell
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
backend 1/1 1 1 3m7s
$ kubectl get deployment backend -o jsonpath="{.spec.template.spec.containers[0].ports[0].containerPort}"
8000
```

View File

@@ -234,3 +234,42 @@ spec:
The specification of `schematic` is explained in following CUE and Helm specific documentations.
Also, the `schematic` filed enables you to render UI forms directly based on them, please check the [Generate Forms from Definitions](openapi-v3-json-schema) section about how to.
## Definition Revisions
In KubeVela, definition entities are mutable. Each time a `ComponentDefinition` or `TraitDefinition` is updated, a corresponding `DefinitionRevision` will be generated to snapshot this change. Hence, KubeVela allows user to reference a specific revision of definition to declare an application.
### Specify Definition Revision in Application
For example, we can update the `webservice` component definition by applying a new definition with same name as below.
```shell
kubectl apply -f https://raw.githubusercontent.com/oam-dev/kubevela/master/docs/examples/definition-revision/webservice-v2.yaml
```
A new definition revision will be automatically generated, `v2` is the latest version, `v1` is the previous one.
```shell
$ kubectl get definitionrevision -l="componentdefinition.oam.dev/name=webservice" -n vela-system
NAME REVISION HASH TYPE
webservice-v1 1 3f6886d9832021ba Component
webservice-v2 2 b3b9978e7164d973 Component
```
Users can specify the revision with `@version` approach, for example, if a user want to stick to using the `v1` revision of `webservice` component:
```yaml
# testapp.yaml
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: testapp
spec:
components:
- name: server
type: webservice@v1
properties:
image: crccheck/hello-world
port: 8000
```
If no revision is specified, KubeVela will always use the latest revision for a given component definition.

View File

@@ -0,0 +1,181 @@
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: webservice
namespace: vela-system
annotations:
definition.oam.dev/description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers."
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
if parameter.addRevisionLabel {
"app.oam.dev/appRevision": context.appRevision
}
}
template: {
metadata: labels: {
"app.oam.dev/component": context.name
if parameter.addRevisionLabel {
"app.oam.dev/appRevision": context.appRevision
}
}
spec: {
containers: [{
name: context.name
image: parameter.image
if parameter["cmd"] != _|_ {
command: parameter.cmd
}
if parameter["args"] != _|_ {
command: parameter.args
}
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
}
}
if parameter["volumes"] != _|_ {
volumeMounts: [ for v in parameter.volumes {
{
mountPath: v.mountPath
name: v.name
}}]
}
}]
if parameter["volumes"] != _|_ {
volumes: [ for v in parameter.volumes {
{
name: v.name
if v.type == "pvc" {
persistentVolumeClaim: {
claimName: v.claimName
}
}
if v.type == "configMap" {
configMap: {
defaultMode: v.defaultMode
name: v.cmName
if v.items != _|_ {
items: v.items
}
}
}
if v.type == "secret" {
secret: {
defaultMode: v.defaultMode
secretName: v.secretName
if v.items != _|_ {
items: v.items
}
}
}
if v.type == "emptyDir" {
emptyDir: {
medium: v.medium
}
}
}}]
}
}
}
}
}
parameter: {
// +usage=Which image would you like to use for your service
// +short=i
image: string
// +usage=Commands to run in the container
cmd?: [...string]
// +usage=Arguments to the cmd
args?: [...string]
// +usage=Which port do you want customer traffic sent to
// +short=p
port: *80 | int
// +usage=Define arguments by using environment variables
env?: [...{
// +usage=Environment variable name
name: string
// +usage=The value of the environment variable
value?: string
// +usage=Specifies a source the value of this var should come from
valueFrom?: {
// +usage=Selects a key of a secret in the pod's namespace
secretKeyRef: {
// +usage=The name of the secret in the pod's namespace to select from
name: string
// +usage=The key of the secret to select from. Must be a valid secret key
key: string
}
}
}]
// +usage=Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core)
cpu?: string
// If addRevisionLabel is true, the appRevision label will be added to the underlying pods
addRevisionLabel: *false | bool
// +usage=Declare volumes and volumeMounts
volumes?: [...{
name: string
mountPath: string
// +usage=Specify volume type, options: "pvc","configMap","secret","emptyDir"
type: "pvc" | "configMap" | "secret" | "emptyDir"
if type == "pvc" {
claimName: string
}
if type == "configMap" {
defaultMode: *420 | int
cmName: string
items?: [...{
key: string
path: string
mode: *511 | int
}]
}
if type == "secret" {
defaultMode: *420 | int
secretName: string
items?: [...{
key: string
path: string
mode: *511 | int
}]
}
if type == "emptyDir" {
medium: *"" | "Memory"
}
}]
}

View File

@@ -1,48 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: worker
namespace: default
annotations:
definition.oam.dev/description: "Describes long-running, scalable, containerized services that running at backend. They do NOT have network endpoint to receive external network traffic."
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
}
ports: [{
containerPort: 8000
}]
}]
}
}
}
}
parameter: {
// +usage=Which image would you like to use for your service
image: string
// +usage=Commands to run in the container
cmd?: [...string]
}

View File

@@ -1,50 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: worker
namespace: default
annotations:
definition.oam.dev/description: "Describes long-running, scalable, containerized services that running at backend. They do NOT have network endpoint to receive external network traffic."
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
}
ports: [{
containerPort: parameter.port
}]
}]
}
}
}
}
parameter: {
// +usage=Which image would you like to use for your service
image: string
// +usage=Commands to run in the container
cmd?: [...string]
// +usage=Which port do you want customer traffic sent to
port: int
}

View File

@@ -43,7 +43,6 @@ module.exports = {
'end-user/traits/more',
]
},
'end-user/definition-revision',
'end-user/scopes/appdeploy',
'end-user/scopes/rollout-plan',
{