# HomeK8s step checks: the complete list of checks the portal can ask this Pi # to run. Each prints a short result and exits 0 when it passes. They run as # root, only read state, and are embedded in the agent binary (checks.go). # The portal names a check and its arguments; it never sends code. # # Set by the agent: KUBECONFIG=/etc/kubernetes/admin.conf, RUN_AS=. have() { command -v "$1" >/dev/null 2>&1; } check_agent_online() { echo "✓ $(hostname) is talking to the portal"; } check_swap_off() { if [ -z "$(/sbin/swapon --noheadings 2>/dev/null)" ]; then echo "✓ swap is off" else echo "✗ swap is still on:"; /sbin/swapon --show; return 1; fi } check_modules() { local ok=0 m for m in overlay br_netfilter; do if grep -qw "^$m" /proc/modules; then echo "✓ $m loaded"; else echo "✗ $m not loaded"; ok=1; fi grep -qsw "$m" /etc/modules-load.d/*.conf || { echo "✗ $m not in /etc/modules-load.d/ (won't survive a reboot)"; ok=1; } done return $ok } check_sysctl() { local ok=0 k v for k in net.ipv4.ip_forward net.bridge.bridge-nf-call-iptables; do v=$(cat "/proc/sys/${k//.//}" 2>/dev/null) if [ "$v" = 1 ]; then echo "✓ $k = 1"; else echo "✗ $k = ${v:-missing}"; ok=1; fi done return $ok } check_cgroup_memory() { if grep -qw memory /sys/fs/cgroup/cgroup.controllers; then echo "✓ memory cgroup enabled" else echo "✗ memory cgroup disabled: add cgroup_enable=memory to cmdline.txt and reboot"; return 1; fi } check_containerd() { systemctl is-active -q containerd || { echo "✗ containerd is not running"; return 1; } echo "✓ containerd is running" if grep -q 'SystemdCgroup = true' /etc/containerd/config.toml; then echo "✓ SystemdCgroup = true" else echo "✗ SystemdCgroup is not true in /etc/containerd/config.toml"; return 1; fi } check_apiserver() { [ -f /etc/kubernetes/admin.conf ] || { echo "✗ no cluster yet (/etc/kubernetes/admin.conf missing)"; return 1; } if kubectl get --raw=/readyz >/dev/null 2>&1; then echo "✓ API server is ready" else echo "✗ API server is not answering"; return 1; fi } check_kubeconfig() { if setpriv --reuid="$RUN_AS" --regid="$(id -g "$RUN_AS")" --init-groups env -i HOME="$(getent passwd "$RUN_AS" | cut -d: -f6)" PATH=/usr/bin:/bin kubectl version >/dev/null 2>&1; then echo "✓ kubectl works for $RUN_AS" else echo "✗ kubectl doesn't work for $RUN_AS yet (copy admin.conf to ~/.kube/config)"; return 1; fi } check_nodes_ready() { # [minimum count] local want=${1:-1} ready total total=$(kubectl get nodes --no-headers 2>/dev/null | wc -l) ready=$(kubectl get nodes --no-headers 2>/dev/null | awk '$2=="Ready"' | wc -l) kubectl get nodes 2>&1 [ "$ready" -ge "$want" ] && [ "$ready" = "$total" ] && { echo "✓ $ready/$total nodes Ready"; return 0; } echo "✗ $ready/$total nodes Ready (want $want)"; return 1 } check_dns_ready() { local n n=$(kubectl -n kube-system get pods -l k8s-app=kube-dns --no-headers 2>/dev/null | awk '$3=="Running"' | wc -l) [ "$n" -ge 1 ] && { echo "✓ CoreDNS running ($n pods)"; return 0; } echo "✗ CoreDNS isn't running yet"; kubectl -n kube-system get pods -l k8s-app=kube-dns 2>&1; return 1 } check_deployment() { # NAME [replicas] [namespace] local name=$1 want=${2:-1} ns=${3:-default} avail avail=$(kubectl -n "$ns" get deploy "$name" -o jsonpath='{.status.availableReplicas}' 2>/dev/null) [ "${avail:-0}" -ge "$want" ] && { echo "✓ deployment $name has ${avail} available replicas"; return 0; } echo "✗ deployment $name has ${avail:-0} available replicas (want $want)"; return 1 } check_service() { # NAME [namespace] kubectl -n "${2:-default}" get svc "$1" >/dev/null 2>&1 && { echo "✓ service $1 exists"; kubectl -n "${2:-default}" get svc "$1"; return 0; } echo "✗ service $1 not found"; return 1 }