5.3 KiB
CKA Range Bring-Up — kind + Cilium (matches Mock Exam Pack v1)
Produces cluster
drillson Kubernetes v1.35.0 (= exam version) with nodes named exactly as the drill/mock packs expect:drills-control-plane,drills-worker,drills-worker2. CNI: Cilium 1.19.x — real NetworkPolicy enforcement (kindnet has none; netpol drills would silently pass on it). Versions verified 2026-07-29. Re-check pins if you're reading this much later: kind releases page, cilium.io stable docs.
0. Host prerequisites
- Docker (or compatible), ≥ 8GB RAM free for the 3 nodes
- cgroup v2 on the host — mandatory: k8s 1.35 node images dropped cgroup v1. Check:
stat -fc %T /sys/fs/cgroup→ must printcgroup2fs. Any current distro qualifies. - Tools:
kind≥ v0.31.0 (ships the v1.35.0 default image),kubectl,helmkind version # v0.31.x helm version # v3.x
1. Cluster config — kind-drills.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: drills # ⇒ node names drills-control-plane / drills-worker / drills-worker2
networking:
disableDefaultCNI: true # kindnet out, Cilium in
nodes:
- role: control-plane
image: kindest/node:v1.35.0 # pin explicitly = exam version, survives kind upgrades
- role: worker
image: kindest/node:v1.35.0
- role: worker
image: kindest/node:v1.35.0
Note: kube-proxy stays (default). Do NOT enable Cilium's kube-proxy replacement — the exam cluster runs kube-proxy, and iptables-visible Services are part of the troubleshooting surface you're training.
2. Bring-up — range-up.sh
#!/usr/bin/env bash
set -euo pipefail
CILIUM_VER=1.19.6
kind create cluster --config kind-drills.yaml
# nodes will sit NotReady until CNI lands — expected
# --- Cilium (per cilium.io kind guide) ---
docker pull quay.io/cilium/cilium:v${CILIUM_VER}
kind load docker-image quay.io/cilium/cilium:v${CILIUM_VER} --name drills # skip registry pulls on each node
helm repo add cilium https://helm.cilium.io/ 2>/dev/null; helm repo update
helm install cilium cilium/cilium --version ${CILIUM_VER} \
--namespace kube-system \
--set image.pullPolicy=IfNotPresent \
--set ipam.mode=kubernetes
kubectl -n kube-system rollout status ds/cilium --timeout=180s
kubectl wait --for=condition=Ready node --all --timeout=180s
# --- Gateway API CRDs (standard channel) ---
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
# --- metrics-server (for HPA TARGETS + kubectl top) ---
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl -n kube-system patch deploy metrics-server --type=json \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
# ^ mandatory on kind: kubelet serves self-signed certs; without this metrics-server never goes Ready
# --- helm repo used by drill K4 / mock Q8 ---
helm repo add bitnami https://charts.bitnami.com/bitnami 2>/dev/null; helm repo update
echo "RANGE UP"
3. Smoke test — run before ANY drill session
kubectl get nodes -o wide
# drills-control-plane / drills-worker / drills-worker2 — all Ready, VERSION v1.35.0
kubectl get pods -A | grep -v Running | grep -v Completed # empty
kubectl api-resources | grep -i httproute # gateway.networking.k8s.io present
kubectl top nodes # numbers (may need ~60s after install)
kubectl -n kube-system exec ds/cilium -- cilium status --brief # OK
# NetworkPolicy ENFORCEMENT check — the one that matters (kindnet would pass traffic anyway):
kubectl create ns smoke
kubectl -n smoke run a --image=nginx --labels=app=a --port=80
kubectl -n smoke run b --image=busybox -- sleep 600
kubectl -n smoke wait --for=condition=Ready pod --all --timeout=60s
kubectl -n smoke apply -f - <<'EOF'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: deny-all}
spec:
podSelector: {}
policyTypes: [Ingress]
EOF
AIP=$(kubectl -n smoke get pod a -o jsonpath='{.status.podIP}')
kubectl -n smoke exec b -- wget -qO- -T 2 $AIP && echo "FAIL: netpol NOT enforced" || echo "OK: netpol enforced"
kubectl delete ns smoke --wait=false
If that last line prints FAIL, the CNI install went sideways — do not run K1/Q3 until fixed (kubectl -n kube-system logs ds/cilium | tail).
4. Static pod path sanity (mock Q17 depends on it)
docker exec drills-worker grep staticPodPath /var/lib/kubelet/config.yaml
# expect: staticPodPath: /etc/kubernetes/manifests
5. Teardown / rebuild
kind delete cluster --name drills # full nuke, ~10s
# rebuild = run range-up.sh again, ~3 min total
Rebuild is cheap — prefer a fresh cluster over archaeologically cleaning a broken one between mock attempts. The mock pack's RESET script is for same-day reruns; a new day gets a new cluster.
6. Known deltas vs the real exam (accept, don't fight)
| Real exam | This range |
|---|---|
ssh nodeX |
docker exec -it drills-<node> bash |
| multiple kubectl contexts | one context; discipline = read each task's target ns/node |
| kubeadm package upgrades (apt) | not possible — node image is baked; upgrade tasks stay on KodeKloud/killer |
| several CNIs possible | Cilium everywhere (netpol semantics are standard, so drills transfer) |