Licensed to be used in conjunction with basebox, only.
// installation
Kubernetes
Step 4 of 10 · Path A (bare metal)
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 (Kubernetes 1.33):
1. Add the Kubernetes repository, install and pin the components:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
2. Disable swap, set kernel modules and sysctl parameters:
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
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. Initialise the cluster and set up kubeconfig for your user:
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
5. Install the 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. Then install the GPU Operator – see NVIDIA / GPU → GPU Operator.
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; values file under NVIDIA / GPU → GPU Operator) – the clean path for production.
- Remove the taint – for development/test only:
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:
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.
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 |
Back: NVIDIA / GPU · Next: Storage