Chapter 4 · Part I

Kubernetes Cluster with k3s

k3s is a lightweight, production-grade Kubernetes distribution by Rancher (SUSE). It packages the full Kubernetes control plane into a single binary under 100 MB, stripping components unnecessary for edge and small-cluster deployments. k3s is ideal for DGX Spark Bundle: you get complete Kubernetes API compatibility with minimal system overhead, leaving the bulk of CPU and memory free for GPU workloads.

Install k3s on Spark 1 (Master)

curl -sfL https://get.k3s.io | \
  INSTALL_K3S_EXEC="--write-kubeconfig-mode 644 --disable=traefik" \
  sh -

Configure kubectl

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
echo "export KUBECONFIG=/etc/rancher/k3s/k3s.yaml" >> ~/.bashrc

Get the Join Token

sudo cat /var/lib/rancher/k3s/server/node-token

Join Spark 2 as Worker

curl -sfL https://get.k3s.io | \
  K3S_URL=https://192.168.86.30:6443 \
  K3S_TOKEN=<TOKEN_FROM_SPARK1> \
  sh -

Assign Worker Role Label

kubectl label node spark-7229 node-role.kubernetes.io/worker=worker

Verify Cluster

kubectl get nodes
# Expected:
# NAME         STATUS   ROLES                  VERSION
# spark-720e   Ready    control-plane,master   v1.35.5+k3s1
# spark-7229   Ready    worker                 v1.35.5+k3s1

Install Helm

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version

Shell Completions & kubectl Aliases

Enable tab-completion and a small set of kubectl/helm aliases you will lean on for the rest of the book. Completions are guarded by command -v, so lines for tools you haven't installed yet (gh, uv, poetry) are no-ops until those tools land on PATH.

Option A — One-liner (recommended)

Download and run the idempotent installer script (setup-completions.sh) on both Sparks — it installs both completions and aliases:

curl -fsSL https://mohnishbasha.github.io/dgx-spark-bundle/books/from-box-to-cluster/scripts/setup-completions.sh | bash

Safe to re-run — the script uses two marker blocks (completions, aliases) and skips whichever is already installed.

Option B — Manual: completions

{
  echo 'command -v kubectl >/dev/null && source <(kubectl completion bash)'
  echo 'command -v helm    >/dev/null && source <(helm completion bash)'
  echo 'command -v gh      >/dev/null && source <(gh completion -s bash)'
  echo 'command -v uv      >/dev/null && eval "$(uv generate-shell-completion bash)"'
  echo 'command -v poetry  >/dev/null && source <(poetry completions bash)'
} >> ~/.bashrc

source ~/.bashrc

Option C — Manual: kubectl / helm aliases

The k alias is worth its weight in gold — you will type it thousands of times. The complete -F __start_kubectl k line rewires kubectl's completion so k Tab works exactly like kubectl Tab.

{
  echo "alias k='kubectl'"
  echo "alias kgp='kubectl get pods'"
  echo "alias kgs='kubectl get svc'"
  echo "alias kgn='kubectl get nodes'"
  echo "alias kga='kubectl get all'"
  echo "alias kd='kubectl describe'"
  echo "alias kl='kubectl logs'"
  echo "alias kx='kubectl exec -it'"
  echo "alias kaf='kubectl apply -f'"
  echo "alias kdel='kubectl delete'"
  echo "alias kns='kubectl config set-context --current --namespace'"
  echo "alias h='helm'"
  echo 'command -v kubectl >/dev/null && complete -o default -F __start_kubectl k'
  echo 'command -v helm    >/dev/null && complete -o default -F __start_helm    h'
} >> ~/.bashrc

source ~/.bashrc

Cheat sheet:

AliasExpands toUse
kkubectlEverything.
kgpkubectl get podskgp -A for all namespaces.
kgnkubectl get nodesCheck spark-720e / spark-7229 readiness.
kgakubectl get allEverything in the current namespace.
kdkubectl describekd pod <name>.
klkubectl logskl -f <pod> to tail.
kxkubectl exec -itkx <pod> -- bash.
kafkubectl apply -fApply a manifest.
kdelkubectl deleteDelete a resource.
knskubectl config set-context --current --namespacekns core-services — persists across sessions.
hhelmSame pattern as k.

Verify with k TabTab, kgp, and kns kube-system. Repeat on Spark 2 if you plan to run kubectl from there as well.

NVIDIA GPU Operator

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update

helm install gpu-operator nvidia/gpu-operator \
  --namespace gpu-operator \
  --create-namespace
# Verify both GPUs visible
kubectl get nodes -o json | grep '"nvidia.com/gpu":'
# Expected: "nvidia.com/gpu": "1"  (one per node)

kubectl get nodes -o json | grep "nvidia.com/gpu.family"
# Expected: "nvidia.com/gpu.family": "blackwell"

Create Namespaces

kubectl create namespace core-services
kubectl create namespace monitoring