Version: v1.3

How-to

In this section we will introduce how to define a trait.

A trait in KubeVela can be defined by simply reference a existing Kubernetes API resource.

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: TraitDefinition
  3. metadata:
  4. name: ingress
  5. spec:
  6. definitionRef:
  7. name: ingresses.networking.k8s.io

Let’s attach this trait to a component instance in Application:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: Application
  3. metadata:
  4. name: testapp
  5. spec:
  6. components:
  7. - name: express-server
  8. type: webservice
  9. properties:
  10. cmd:
  11. - node
  12. - server.js
  13. image: oamdev/testapp:v1
  14. port: 8080
  15. traits:
  16. - type: ingress
  17. properties:
  18. rules:
  19. - http:
  20. paths:
  21. - path: /testpath
  22. pathType: Prefix
  23. backend:
  24. service:
  25. name: test
  26. port:
  27. number: 80

Note that in this case, all fields in the referenced resource’s spec will be exposed to end user and no metadata (e.g. annotations etc) are allowed to be set trait properties. Hence this approach is normally used when you want to bring your own CRD and controller as a trait, and it dose not rely on annotations etc as tuning knobs.

The recommended approach is defining a CUE based schematic for trait as well. In this case, it comes with abstraction and you have full flexibility to templating any resources and fields as you want. Note that KubeVela requires all traits MUST be defined in outputs section (not output) in CUE template with format as below:

  1. outputs: <unique-name>:
  2. <full template data>

Below is an example for ingress trait.

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: TraitDefinition
  3. metadata:
  4. name: ingress
  5. spec:
  6. podDisruptive: false
  7. schematic:
  8. cue:
  9. template: |
  10. parameter: {
  11. domain: string
  12. http: [string]: int
  13. }
  14. // trait template can have multiple outputs in one trait
  15. outputs: service: {
  16. apiVersion: "v1"
  17. kind: "Service"
  18. spec: {
  19. selector:
  20. app: context.name
  21. ports: [
  22. for k, v in parameter.http {
  23. port: v
  24. targetPort: v
  25. },
  26. ]
  27. }
  28. }
  29. outputs: ingress: {
  30. apiVersion: "networking.k8s.io/v1beta1"
  31. kind: "Ingress"
  32. metadata:
  33. name: context.name
  34. spec: {
  35. rules: [{
  36. host: parameter.domain
  37. http: {
  38. paths: [
  39. for k, v in parameter.http {
  40. path: k
  41. backend: {
  42. serviceName: context.name
  43. servicePort: v
  44. }
  45. },
  46. ]
  47. }
  48. }]
  49. }
  50. }

Let’s attach this trait to a component instance in Application:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: Application
  3. metadata:
  4. name: testapp
  5. spec:
  6. components:
  7. - name: express-server
  8. type: webservice
  9. properties:
  10. cmd:
  11. - node
  12. - server.js
  13. image: oamdev/testapp:v1
  14. port: 8080
  15. traits:
  16. - type: ingress
  17. properties:
  18. domain: test.my.domain
  19. http:
  20. "/api": 8080

CUE based trait definitions can also enable many other advanced scenarios such as patching and data passing. They will be explained in detail in the following documentations.

Last updated on Nov 1, 2022 by Tianxin Dong