The fluxcd addon pin was a holdover from the #3150-era model where app charts rendered nested HelmReleases into the target cluster and needed an in-cluster helm-controller. Consumers now keep their releases on the management cluster and remote-apply via spec.kubeConfig, so the management Flux resolves charts and applies manifests — nothing inside the ComputePlane reconciles HelmReleases. This also decouples the module from the FluxCD addon removal (#3379). certManager and ingressNginx stay pinned: Certificate and Ingress objects land inside the cluster and need their controllers there. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io>
ComputePlane
A managed, isolated environment for running code-executing (untrusted-code) catalog applications — notebooks, workflow "code" nodes, plugin systems.
This tenant module provisions a single-tenant, Cozystack-managed cluster by
deploying the ordinary apps/kubernetes chart (Kamaji control plane +
KubeVirt-VM worker nodes) with operator-fixed values, sourced from this
package's own source-only ExternalArtifact
(cozystack-computeplane-application-kubevirt-kubernetes). The tenant gets the
same substrate as any managed kind: Kubernetes cluster, but holds no admin
kubeconfig for it. The security posture (Cozystack-enablement addons, withheld
credentials) is baked into the chart and cannot be overridden; the one
tenant-facing knob is nodeGroups — its listed fields are schema-validated,
unlisted NodeGroup fields pass through to the wrapped chart unvalidated.
The cluster HelmRelease is named computeplane-cluster and its release name
is derived from it, so Kamaji writes the admin kubeconfig to the Secret
computeplane-cluster-admin-kubeconfig (key super-admin.svc) — the derived
contract consumed by the HelmReleases of placement: ComputePlane
applications. The tenant never sees that Secret: tenant-visible secrets are an
allowlist, and this module's ApplicationDefinition includes nothing, which
withholds every Secret in the module's lineage by construction.
Prerequisite: an etcd module must be available to the tenant — its own,
or one inherited from an ancestor tenant (the _namespace.etcd context
propagates down the tenant tree, so enabling a redundant local etcd is not
required). The tenant Kubernetes machinery — including the cluster-autoscaler
that brings up the default scale-from-zero md0 node group — is backed by
that etcd; without it the wrapped chart collapses to its awaiting-etcd
status beacon and the ComputePlane provisions no control plane or workers
(the HelmReleases still report Ready over the empty shell, so check for the
beacon ConfigMap when nothing comes up).
See the full design in cozystack/community design-proposals/compute-plane.
Parameters
Cluster shape
| Name | Description | Type | Value |
|---|---|---|---|
nodeGroups |
Worker node groups of the ComputePlane cluster (cluster shape only — the security posture is fixed by the module and cannot be overridden through this knob; note that unlisted NodeGroup fields pass through to the wrapped chart unvalidated). Same structure as the kubernetes application's nodeGroups. When left empty, the wrapped kubernetes chart emits its default scale-from-zero md0 group with roles: [ingress-nginx], so the cluster sits idle until a pending Pod (e.g. the ingress-nginx controller) triggers the cluster-autoscaler. Supplied groups are authoritative (not merged with the default), so at least one of them must carry roles: [ingress-nginx] — enforced at render time. |
map[string]object |
{} |
nodeGroups[name].minReplicas |
Minimum number of replicas. | int |
0 |
nodeGroups[name].maxReplicas |
Maximum number of replicas. | int |
10 |
nodeGroups[name].instanceType |
Virtual machine instance type. | string |
u1.medium |
nodeGroups[name].diskSize |
System disk size for the worker VM. Carries the Talos OS image, kubelet state, containerd image cache, and any local-path PVCs. | quantity |
20Gi |
nodeGroups[name].storageClass |
StorageClass for worker node persistent disks. When empty, falls back to the application-level storageClass of the wrapped kubernetes app. | string |
"" |
nodeGroups[name].roles |
List of node roles. At least one group must carry ingress-nginx — the module pins the ingress-nginx addon on, and its controller only schedules onto nodes with that role (enforced at render time). |
[]string |
[] |
nodeGroups[name].resources |
Explicit CPU and memory for each worker node, as an alternative to instanceType sizing. Set both cpu and memory together or neither. |
object |
{} |
nodeGroups[name].resources.cpu |
CPU available. | quantity |
"" |
nodeGroups[name].resources.memory |
Memory (RAM) available. | quantity |
"" |
nodeGroups[name].gpus |
List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | []object |
[] |
nodeGroups[name].gpus[i].name |
Name of GPU, such as "nvidia.com/AD102GL_L40S". | string |
"" |
nodeGroups[name].kubelet |
Kubelet resource reservations for this node group. | object |
{} |
nodeGroups[name].kubelet.systemReservedMemory |
Memory reserved for host OS. Auto-computed from instanceType if empty. | string |
"" |
nodeGroups[name].kubelet.kubeReservedMemory |
Memory reserved for kubelet and container runtime. Auto-computed from instanceType if empty. | string |
"" |
nodeGroups[name].kubelet.systemReservedCpu |
CPU reserved for host OS. Auto-computed from instanceType if empty. | string |
"" |
nodeGroups[name].kubelet.kubeReservedCpu |
CPU reserved for kubelet and container runtime. Auto-computed from instanceType if empty. | string |
"" |
nodeGroups[name].kubelet.evictionHardMemory |
Hard eviction threshold for memory (absolute like 200Mi or percentage like 7%). | string |
7% |
nodeGroups[name].kubelet.evictionSoftMemory |
Soft eviction threshold for memory (absolute like 1Gi or percentage like 10%). | string |
10% |