Getting started
Host onboarding
Humans run four commands. The installer owns the release bundle, the pinned versions, and the baseline. This page is the operational companion to the repository guide.
Conventions
KUBECONFIG_HUB points at the management cluster and KUBECONFIG_HOST at the host cluster. Always pass an explicit KUBECONFIG= so a command cannot target the wrong cluster.0. Prerequisites (platform team, one time)
- Pinned versions from the release: host K3s
v1.36.3+k3s1, K3kv1.2.0, child K3sv1.34.2+k3s1, OCM Hubv1.3.1. - Registry mirrors configured and verified with a small image pull.
- Profile and topology labels on every host node:
hardware.kubecell.io/profile,topology.topolvm.io/node,topology.kubernetes.io/zone. - Controller image available to both clusters, matching architecture.
1. doctor — read-only preflight
go run ./cmd/kubecell-installer doctor management --bundle <release-dir>go run ./cmd/kubecell-installer doctor host --bundle <release-dir> \ --device huawei.com/Ascend910Stop at the first failure. On the host side, confirm: nodes Ready, profile labels present, TopoLVM capacity available, and accelerator resources reported by the Device Plugin.
2. The four commands
# 1. join — host contextKUBECONFIG=<host-kubeconfig> clusteradm join \ --hub-token "$(clusteradm get token)" \ --hub-apiserver https://hub.example.com:6443 \ --cluster-name <cell-name> --wait# 2. accept — management context (mandatory manual gate)KUBECONFIG=<hub-kubeconfig> clusteradm accept --clusters <cell-name> --wait# 3. chart — install the host chartkubectl create ns kubecell-systemhelm install kubecell-host ./charts/kubecell-host \ --namespace kubecell-system \ --set image.repository=<controller-repo> \ --set image.tag=<tag> --set image.pullPolicy=IfNotPresent# 4. cell — generate from live discovery, then applygo run ./cmd/kubecell-installer host --step=cell --cell <cell-name> \ --kubeconfig <host-kubeconfig> | grep -v '^#' > cell.yamlkubectl apply-n kubecell-system -f cell.yamlDo not reuse a stale token
Between fetching the hub token and runningclusteradm join, do not call get token twice — the older token may expire. The ManagedCluster name must equal the future Cell name; the generator enforces this.3. Cell and class
The Cell comes from live discovery, so you only apply it. The class is drafted from observed allocatable capacity and then tuned down to the tenant envelope.
go run ./cmd/kubecell-installer suggest-class \ --cell-file cell.yaml --name <class-name># The draft reflects observed allocatable capacity.# Adjust the numbers down to the tenant envelope you are comfortable with,# then apply the VirtualNodeClass.4. Appending same-profile workers (Case B)
Growing an existing Cell does not create a new Cell and does not run OCM onboarding. Join the new machine as a K3s agent of the same host cluster, label it, and confirm it shows up in inventory. Existing workloads are neither migrated nor interrupted.
# Case B: append same-profile workers to an existing Cell# 1. Join the existing host cluster as a K3s agent with an independent data directory.# This deletes no data on that machine and runs no OCM onboarding.# 2. Re-apply profile and topology labels, wait for node Ready and platform DaemonSets.# 3. Confirm the new node appears in inventory:kubectl-n kubecell-system get cell <cell-name> \ -o jsonpath='{range .status.nodes[*]}{.name}{"\t"}{.ready}{"\n"}{end}'5. Troubleshooting quick reference
| Symptom | Likely cause | Action |
|---|---|---|
| clusteradm init reports success but installs nothing | Wrong kubeconfig context | Re-run with an explicit KUBECONFIG= prefix |
| OCM components stuck in ImagePullBackOff | Image not available from the configured mirror | Fix the component PullSpec to a reachable registry |
| Preloaded image not recognized by kubelet | Short tag or incomplete layers | Re-tag with the fully qualified name and verify with crictl inspecti |
| Child CoreDNS Pending | Third-party Pod without resources blocked by LimitRange | Covered by the kubecell-defaults baseline in the Foundation Work |
| Child PVC reports no free storage | Missing TopoLVM topology labels | Re-apply topology.topolvm.io/node and topology.kubernetes.io/zone labels |
| TopoLVM CSINode has no driver | Custom kubelet root directory not passed to the chart | Pass it with --set on the host chart |
| Traefik :80 unreachable | Conflicting Service or stale host-port binding | Use hostNetwork via values, remove stale load-balancer helpers, clear stale NAT chains |
| Child Ingress returns 503 | Mirrored Endpoints carry a mismatched port name | The controller strips port names; for older clusters clear the port name to "" |
| Volumes remain after VirtualCluster deletion | Orphaned logical volumes after the child API is gone | Remove only cluster-created volumes with lvremove; leave the volume group intact |
| Zero accelerators reported | Device Plugin registration mismatch | Check plugin Pod logs for registration failures before changing anything |