Version: v1.0

Resource Model

This documentation will explain the core resource model of KubeVela which is fully powered by Open Application Model (OAM).

Application

The Application is the core API of KubeVela. It allows End User to work with a single artifact to capture the complete application deployment with simplified primitives.

This provides a simpler path for on-boarding End User to the platform without leaking low level details in runtime infrastructure. For example, they will be able to declare a “web service” without defining a detailed Kubernetes Deployment + Service combo each time, or claim the auto-scaling requirements without referring to the underlying KEDA ScaleObject. They can also declare a cloud database with same API if they want.

Every application is composed by multiple components with attachable operational behaviors (traits). For example:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: Application
  3. metadata:
  4. name: application-sample
  5. spec:
  6. components:
  7. - name: foo
  8. type: webservice
  9. properties:
  10. image: crccheck/hello-world
  11. port: 8000
  12. traits:
  13. - type: ingress
  14. properties:
  15. domain: testsvc.example.com
  16. http:
  17. "/": 8000
  18. - type: sidecar
  19. properties:
  20. name: "logging"
  21. image: "fluentd"
  22. - name: bar
  23. type: aliyun-oss # cloud service
  24. bucket: "my-bucket"

The Application resource in KubeVela is a LEGO-style entity and does not even have fixed schema. Instead, it is assembled by below building block entities that are maintained by the platform-engineers. Though the application object doesn’t have fixed schema, it is a composition object assembled by several programmable building blocks as shown below.

Component

The component model (ComponentDefinition API) is designed to allow component providers to encapsulate deployable/provisionable entities with a wide range of tools, and hence give a easier path to End User to deploy complicated microservices across hybrid environments at ease. A component normally carries its workload type description (i.e. WorkloadDefinition), a encapsulation module with a parameter list.

Hence, a components provider could be anyone who packages software components in form of Helm chart of CUE modules. Think about 3rd-party software distributor, DevOps team, or even your CI pipeline.

Components are shareable and reusable. For example, by referencing the same Alibaba Cloud RDS component and setting different parameter values, End User could easily provision Alibaba Cloud RDS instances of different sizes in different availability zones.

End User will use the Application entity to declare how they want to instantiate and deploy a group of certain components. In above example, it describes an application composed with Kubernetes stateless workload (component foo) and a Alibaba Cloud OSS bucket (component bar) alongside.

How it Works?

In above example, type: worker means the specification of this component (claimed in following properties section) will be enforced by a ComponentDefinition object named worker as below:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: ComponentDefinition
  3. metadata:
  4. name: worker
  5. annotations:
  6. 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."
  7. spec:
  8. workload:
  9. definition:
  10. apiVersion: apps/v1
  11. kind: Deployment
  12. schematic:
  13. cue:
  14. template: |
  15. output: {
  16. apiVersion: "apps/v1"
  17. kind: "Deployment"
  18. spec: {
  19. selector: matchLabels: {
  20. "app.oam.dev/component": context.name
  21. }
  22. template: {
  23. metadata: labels: {
  24. "app.oam.dev/component": context.name
  25. }
  26. spec: {
  27. containers: [{
  28. name: context.name
  29. image: parameter.image
  30. if parameter["cmd"] != _|_ {
  31. command: parameter.cmd
  32. }
  33. }]
  34. }
  35. }
  36. }
  37. }
  38. parameter: {
  39. image: string
  40. cmd?: [...string]
  41. }

Hence, the properties section of backend only exposes two parameters to fill: image and cmd, this is enforced by the parameter list of the .spec.template field of the definition.

Traits

Traits (TraitDefinition API) are operational features provided by the platform. A trait augments the component instance with operational behaviors such as load balancing policy, network ingress routing, auto-scaling policies, or upgrade strategies, etc.

To attach a trait to component instance, the user will declare .type field to reference the specific TraitDefinition, and .properties field to set property values of the given trait. Similarly, TraitDefinition also allows you to define template for operational features.

In the above example, type: autoscaler in frontend means the specification (i.e. properties section) of this trait will be enforced by a TraitDefinition object named autoscaler as below:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: TraitDefinition
  3. metadata:
  4. annotations:
  5. definition.oam.dev/description: "configure k8s HPA for Deployment"
  6. name: hpa
  7. spec:
  8. appliesToWorkloads:
  9. - webservice
  10. - worker
  11. schematic:
  12. cue:
  13. template: |
  14. outputs: hpa: {
  15. apiVersion: "autoscaling/v2beta2"
  16. kind: "HorizontalPodAutoscaler"
  17. metadata: name: context.name
  18. spec: {
  19. scaleTargetRef: {
  20. apiVersion: "apps/v1"
  21. kind: "Deployment"
  22. name: context.name
  23. }
  24. minReplicas: parameter.min
  25. maxReplicas: parameter.max
  26. metrics: [{
  27. type: "Resource"
  28. resource: {
  29. name: "cpu"
  30. target: {
  31. type: "Utilization"
  32. averageUtilization: parameter.cpuUtil
  33. }
  34. }
  35. }]
  36. }
  37. }
  38. parameter: {
  39. min: *1 | int
  40. max: *10 | int
  41. cpuUtil: *50 | int
  42. }

The application also have a sidecar trait.

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: TraitDefinition
  3. metadata:
  4. annotations:
  5. definition.oam.dev/description: "add sidecar to the app"
  6. name: sidecar
  7. spec:
  8. appliesToWorkloads:
  9. - webservice
  10. - worker
  11. schematic:
  12. cue:
  13. template: |-
  14. patch: {
  15. // +patchKey=name
  16. spec: template: spec: containers: [parameter]
  17. }
  18. parameter: {
  19. name: string
  20. image: string
  21. command?: [...string]
  22. }

Please note that the End User do NOT need to know about definition objects, they learn how to use a given capability with visualized forms (or the JSON schema of parameters if they prefer). Please check the Generate Forms from Definitions section about how this is achieved.

Standard Contract Behind The Abstractions

Once the application is deployed, KubeVela will index and manage the underlying instances with name, revisions, labels and selector etc in automatic approach. These metadata are shown as below.

LabelDescription
workload.oam.dev/type=<component definition name>The name of its corresponding ComponentDefinition
trait.oam.dev/type=<trait definition name>The name of its corresponding TraitDefinition
app.oam.dev/name=<app name>The name of the application it belongs to
app.oam.dev/component=<component name>The name of the component it belongs to
trait.oam.dev/resource=<name of trait resource instance>The name of trait resource instance
app.oam.dev/appRevision=<name of app revision>The name of the application revision it belongs to

Consider these metadata as a standard contract for any “day 2” operation controller such as rollout controller to work on KubeVela deployed applications. This is the key to ensure the interoperability for KubeVela based platform as well.

No Configuration Drift

Despite the efficiency and extensibility in abstracting application deployment, IaC (Infrastructure-as-Code) tools may lead to an issue called Infrastructure/Configuration Drift, i.e. the generated component instances are not in line with the expected configuration. This could be caused by incomplete coverage, less-than-perfect processes or emergency changes. This makes them can be barely used as a platform level building block.

Hence, KubeVela is designed to maintain all these programmable capabilities with Kubernetes Control Loop and leverage Kubernetes control plane to eliminate the issue of configuration drifting, while still keeps the flexibly and velocity enabled by IaC.