Trait
A Trait is a composable capability you attach to a Component without changing its ComponentType — persistent storage, autoscaling, a monitoring sidecar, a network policy. Where a ComponentType defines the base shape of a workload, a Trait is an overlay any compatible component can opt into. A component can attach the same Trait multiple times using distinct instance names.
A ClusterTrait is the cluster-scoped variant; the platform's shared cross-cutting capabilities ship as ClusterTraits.
| Kind | Trait / ClusterTrait |
| API group | openchoreo.dev/v1alpha1 |
| Scope | Namespaced / Cluster |
| Audience | Platform engineer |
| Attached by | Component (spec.traits[]) |
| Gated by | ComponentType allowedTraits |
Key spec fields
| Field | What it does |
|---|---|
spec.parameters.openAPIV3Schema | What a developer sets per trait instance (mount path, volume name) |
spec.environmentConfigs.openAPIV3Schema | What's overridable per environment via the binding (size, storage class) |
spec.creates[] | New Kubernetes resources the Trait adds (PVC, ConfigMap, ServiceMonitor) |
spec.patches[] | JSON-Patch modifications to resources the ComponentType already produced (add a volume, inject env, attach a sidecar) |
Creates vs patches is the conceptual core: creates generate new resources; patches reach
into the resources the ComponentType made (with array-filtered paths like
containers[?(@.name=='main')]) without the ComponentType knowing the Trait exists.
Create in the portal
- Open Create… → Platform Resources → ClusterTrait (or Trait for namespace scope).
- In the in-portal YAML editor, define the parameter / environment schemas, the
creates, and thepatches. - Click Create. Allow it on a ComponentType via
allowedTraitsso developers can attach it.
Full guide: Traits.
Example
A persistent-volume ClusterTrait — creates a PVC and patches the Deployment to mount it:
apiVersion: openchoreo.dev/v1alpha1
kind: ClusterTrait
metadata:
name: persistent-volume
spec:
parameters:
openAPIV3Schema:
type: object
properties:
volumeName: { type: string }
mountPath: { type: string }
environmentConfigs:
openAPIV3Schema:
type: object
properties:
size: { type: string, default: "10Gi" }
creates:
- template:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ${metadata.name}-${trait.instanceName} # unique per attachment
namespace: ${metadata.namespace}
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: ${environmentConfigs.size}
patches:
- target: { kind: Deployment, group: apps, version: v1 }
operations:
- op: add
path: /spec/template/spec/volumes/-
value:
name: ${parameters.volumeName}
persistentVolumeClaim:
claimName: ${metadata.name}-${trait.instanceName}
trait.instanceName is what makes the same Trait attachable multiple times.
See also
- Traits (authoring guide) — the patching grammar and schema model.
- Component type — the base templates Traits overlay and the
allowedTraitsgate. - Resource type — for managed infrastructure, a separate abstraction from a Trait.
- Upstream: patching syntax.