Reference Cluster module
cluster.roles
How the environment claims each infrastructure role, and which packages and flavours provide it.
cluster.roles.<role> records whether the environment already provides an
infrastructure role, such as the CNI or the cluster’s default StorageClass.
Flavours set these bindings; a cluster file overrides them when its
environment differs. Packages never set a binding: a package claims a role
through meta.roles.
| Field | Type | Default | Meaning |
|---|---|---|---|
binding | null | absent | shadowable | exclusive | null | How the environment claims the role. |
provider | string or null | null | Display name of the environment’s implementation. Informational only. |
binding | Meaning |
|---|---|
null | Unknown. Consumers that rely on the role warn. |
absent | The environment does not provide the role. A managed instance fills it. Without one, a consumer that requires the role fails to build, and an optional dependency on it is null. |
shadowable | The environment provides a default, usually through a platform import. A managed instance that claims the role replaces it. |
exclusive | The environment owns the role. A managed instance that claims it is an evaluation error. |
Keys must be roles from the registry in kix/lib/eval/roles.nix.
The role name is also a dependency alias: a package that declares a dependency with the role’s name gets the instance that provides it, managed or imported.
| Role | Provider’s out | Packages that claim it |
|---|---|---|
cni | none | cilium |
network-policy-enforcer | netpol | cilium |
dns | fqdn | coredns |
storageClasses | storageClassName, the class a claim gets when it names none | storage-classes |
loadBalancer | none; a provider’s presence allows type: LoadBalancer Services | none |
metricsApi | none; a provider’s presence allows HorizontalPodAutoscalers on resource metrics and the descheduler’s KubernetesMetrics source | metrics-server |
registryMirror | none; the role exists so that an environment that runs its own mirror (k3s or RKE2 with embedded-registry: true, bound exclusive) refuses a second one | spegel |
snapshotController | crds, the VolumeSnapshotClass, VolumeSnapshotContent, and VolumeSnapshot handles for scope.mkCR | snapshot-controller |
A CSI driver package such as zfs-localpv does not claim storageClasses.
A consumer names the driver instance with
deps.storageClasses = ref.<namespace>.<instance>, or the instance sets
aliases = [ "storageClasses" "zfsLocalPv" ] to serve every consumer. Keep
zfsLocalPv in that list: the package’s one-instance-per-cluster check
matches on it.
No package takes loadBalancer or metricsApi as a dependency; evaluation
checks the resources that need them. With the binding absent and no provider
instance, a type: LoadBalancer Service fails evaluation, and so do a
HorizontalPodAutoscaler that reads metrics.k8s.io (autoscaling/v1, an
autoscaling/v2 HPA with no metrics, or a Resource or ContainerResource
metric) and a descheduler whose policy.metricsProviders lists
KubernetesMetrics. With the binding null, they evaluate with a warning.
Flavour bindings
Section titled “Flavour bindings”Each cell is the flavour’s default binding. “import” means the flavour also
declares a platform import in kube-system that provides the role.
| Flavour | cni | dns | storageClasses | loadBalancer | snapshotController | metricsApi | registryMirror |
|---|---|---|---|---|---|---|---|
aks | exclusive | shadowable, import | shadowable, import | shadowable | null | exclusive | null |
eks | exclusive | shadowable, import | absent | shadowable | null | absent | null |
gke | exclusive | shadowable, import | shadowable, import | shadowable | null | exclusive | null |
gke-autopilot | exclusive | shadowable, import | shadowable, import | exclusive | null | exclusive | null |
k3s | exclusive | shadowable, import | shadowable, import | exclusive | null | exclusive | null |
kind | exclusive | shadowable, import | shadowable, import | absent | absent | absent | absent |
kubeadm | absent | shadowable, import | absent | absent | null | absent | null |
openshift | exclusive | shadowable, import | absent | absent | null | null | null |
ovh | exclusive | shadowable, import | shadowable, import | shadowable | null | null | null |
rke2 | follows cluster.flavor.rke2.cni (cilium: shadowable, import) | shadowable, import | absent | absent | exclusive, import | exclusive | null |
scaleway | exclusive | shadowable, import | shadowable, import | shadowable | null | null | null |
talos | exclusive | shadowable, import | absent | absent | null | absent | null |
No flavour binds network-policy-enforcer.
Overriding a binding
Section titled “Overriding a binding”A cluster whose environment differs from its flavour’s assumption sets the binding in its own module. An RKE2 cluster that disables RKE2’s snapshot charts runs its own controller:
cluster.roles.snapshotController.binding = "absent";instances.storage.snapshot-controller.package = packages.snapshot-controller;A k3s server started with --disable=metrics-server runs its own:
cluster.roles.metricsApi.binding = "absent";instances.metrics-server.metrics-server.package = packages.metrics-server;