Skip to content

// installation

Kubernetes

Applies to

Product: Server · Audience: Platform Operator

Cluster requirements for basebox, ingress controller, CloudNativePG and the differences between single-node and CPU/GPU-node layouts. At the end of this step your cluster offers everything the basebox umbrella chart requires.

Official documentation: Kubernetes with kubeadm · Calico · CloudNativePG · ingress-nginx

What the chart requires

Requirement Value
Kubernetes 1.23+ (verified: 1.33.7; 1.33+ recommended)
Helm 3.x (verified: 3.20.0)
Ingress controller Any; the chart ships nginx annotations
Storage Dynamic volume provisioning with a default storage class
Databases CloudNativePG operator in the cluster
GPU NVIDIA GPU Operator (or equivalent) on GPU nodes – see NVIDIA / GPU
Registry Pull access to gitea.basebox.health from the nodes' runtime

1. Install Kubernetes (kubeadm)

The verified path with kubeadm, containerd and Calico is under Server Preparation Guide → Step 7 with all commands. The order:

  1. Add the Kubernetes repository (1.33), install kubelet kubeadm kubectl and pin them with apt-mark hold.
  2. Disable swap; set kernel modules overlay, br_netfilter and the sysctl parameters for bridge netfilter and IP forwarding.
  3. Configure containerd before running kubeadm init – the default configuration has the CRI plugin disabled:
    sudo mkdir -p /etc/containerd
    containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
    sudo systemctl restart containerd && sudo systemctl enable containerd
    
  4. sudo kubeadm init --pod-network-cidr=10.244.0.0/16, then set up kubeconfig for your user.
  5. Network plugin: kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.3/manifests/calico.yaml
  6. Check: kubectl get nodes shows the node Ready.

Alternative distributions such as k3s work; note the DNS problem with systemd-resolved there – solution in the FAQ.

2. Single node or several nodes

Single node (the reference configurations): control plane and workloads on the same machine. The control-plane taint prevents pods from being scheduled by default. Two paths:

  • Tolerations in the values of the components that need them (GPU Operator; see its values file in the Server Preparation Guide) – the clean path for production.
  • Remove the taint – for development/test only:
    kubectl taint nodes --all node-role.kubernetes.io/control-plane-
    

CPU and GPU nodes: the basebox platform runs on CPU nodes, service models and inference on GPU nodes. Label nodes (nvidia.com/gpu: "true", possibly gpu-type) and use nodeSelector/tolerations in the values of the GPU services – examples on the Inference Server and Ragsrv pages. The GPU Operator only needs to work on the GPU nodes.

Separate clusters for platform and inference: Deployment topologies.

3. Ingress controller

The chart configures ingress resources with nginx annotations: 20 MB body for uploads, large buffers for JWT headers, 24-hour timeouts for WebSocket and streaming, buffering off, CORS, cache control. Install ingress-nginx (or a controller that understands these annotations) and note the ingress class (nginx) and the external IP:

kubectl get svc -A | grep -i ingress

The annotations in detail: Helm chart overview → Ingress configuration.

4. Storage class

basebox needs dynamic volume provisioning for the PostgreSQL clusters, media and model caches. For evaluation a local storage class suffices (local-path, default in the quick start); for production a storage class on SSD/NVMe with snapshots or replication. Set it as default or name it in the values (storageClass). Capacity planning: Storage.

kubectl get storageclass

5. CloudNativePG operator

Every basebox service with a database (AISRV, storesrv, ragsrv, Keycloak) gets its own PostgreSQL cluster, managed by CloudNativePG:

helm repo add cnpg https://cloudnative-pg.github.io/charts
helm upgrade --install cnpg \
  --namespace cnpg-system \
  --create-namespace \
  cnpg/cloudnative-pg
kubectl get pods -n cnpg-system

The umbrella chart also contains the operator as a dependency (cnpg-operator.fullnameOverride: cnpg); install it only once – either beforehand as here or via the chart.

6. cert-manager (optional)

For public domains with automatic certificates: install cert-manager and create a ClusterIssuer (e.g. letsencrypt-prod). Not needed with an internal CA or for evaluation – see Networking.

7. Verify

kubectl get nodes -o wide
kubectl get pods -A
kubectl get storageclass
kubectl get svc -A | grep -i ingress
kubectl get pods -n cnpg-system
kubectl get pods -n gpu-operator            # on GPU nodes
kubectl describe nodes | grep -A5 "Allocated resources"

Everything Ready/Running, a default storage class, an ingress IP, GPU resources on the GPU nodes – then the cluster is ready.

Common failure patterns

Symptom Cause Solution
kubeadm init: "unknown service runtime.v1.RuntimeService" containerd CRI disabled Step 1.3, then kubeadm reset and init again
Pods Pending Control-plane taint, no storage class, no GPU Tolerations; kubectl get pvc; check GPU Operator
inference/ragsrv-support: "Temporary error in name resolution" k3s with systemd-resolved Point coredns at an external DNS (FAQ)
Image pull fails on nodes Registry access of the runtime Test the pull from the runtime, not just from the workstation

Next step: Storage