Skip to main content
Version: Next

Organisation Trait

Say that in our organisation, we want to sets up os and arch node affinity on the main component

This can be achieved with a "myorgsetup" trait which is added to an application as follows:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: arch.test
spec:
components:
- name: arch.test
type: webservice
properties:
image: myimage:1.0.0
traits:
- type: myorgsetup

Trait definition

We can add a trait definition myorgsetup.cue as follows:

myorgsetup: {
alias: ""
annotations: {}
attributes: {
appliesToWorkloads: ["*"]
podDisruptive: true
}
description: "Add myorg default affinity"
labels: {}
type: "trait"
}

template: {
// +patchStrategy=jsonMergePatch
patch: {
spec: template: spec: {
affinity: {
nodeAffinity: {
requiredDuringSchedulingIgnoredDuringExecution: {
nodeSelectorTerms: [{
matchExpressions: [{
key: "kubernetes.io/os"
operator: "In"
values: [ parameter.os ]
},
{
key: "kubernetes.io/arch"
operator: "In"
values: [ parameter.arch ]
}
]
}]
}
}
}
}
}

parameter: {
// +usage=The os for the node affinity
os: *"linux" | string

// +usage=The arch for the node affinity
arch: *"arm64" | string
}
}

We can apply this to the cluster with vela def apply -f myorgsetup.cue then apply the application on the cluster.

Or to try it out locally first if we have the application as app.yml in a new dir and myorgsetup.cue in a subdir called kubevela:

  • add the webservice definition from the cluster with vela def get webservice > kubevela/webservice.cue
  • run the following command to see the rendered deployment : vela dry-run -d kubevela -f app.yml --offline

(although "--offline" you will need to have a valid KUBECONFIG to a running cluster)

This should produce:

---
# Application(arch.test) -- Component(arch.test)
---

apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {}
labels:
app.oam.dev/appRevision: ""
app.oam.dev/component: arch.test
app.oam.dev/name: arch.test
app.oam.dev/namespace: default
app.oam.dev/resourceType: WORKLOAD
workload.oam.dev/type: webservice
name: arch.test
namespace: default
spec:
selector:
matchLabels:
app.oam.dev/component: arch.test
template:
metadata:
labels:
app.oam.dev/component: arch.test
app.oam.dev/name: arch.test
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
- key: kubernetes.io/arch
operator: In
values:
- arm64
containers:
- image: myimage:1.0.0
name: arch.test

Note : you can change the os and/or arch with trait properties, e.g.:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: arch.test
spec:
components:
- name: arch.test
type: webservice
properties:
image: myimage:1.0.0
traits:
- type: myorgsetup
properties:
os: windows
arch: amd64

But in our trait definition we've defaulted them to linux and arm64, so they do not have to be specified if this meets the requirements for the org.

Each app.yml does need to have the

      traits:
- type: myorgsetup

added, but then you've then got a touchpoint to add anything else your org needs with minimal noise in the application definition.

The trait would need a bit of refinement to correctly deal with e.g. cronjobs as they have a slightly different yaml format, but hopefully this demonstrates that it's pretty simple to get started with custom traits to simply add standard behaviours for your org.

Refs

This example was first posted in a thread on the Kubevela slack channel