Bootstrap a regular (non-ITAR) k3s cluster on cnode1/2/3 with embedded
etcd. All cluster communication — node registration, API server, etcd
peering, flannel VXLAN — runs exclusively over Tailscale IPs. Zero LAN
addresses appear in node status or TLS certificates.
Scripts (k8s/):
- env.sh: shared config (Tailscale IPs, SSH opts, k3s version)
- wipe.sh: remove existing k3s from all cnodes
- install-cp.sh: full bootstrap (cnode1 --cluster-init, then cnode2/3 join)
- join-servers.sh: re-join cnode2/3 only (fixes broken join state)
- post-setup.sh: apply NoSchedule taints, fetch kubeconfig, verify
- verify.sh: 13-point health check (nodes, Tailscale IPs, taints, etcd,
CoreDNS, API server, workload isolation)
- probe-nodes.sh: SSH + Tailscale reachability check
All 3 cnodes are tainted control-plane:NoSchedule so no user workloads
can schedule on the control plane. 13/13 health checks pass.
Docs updated: k8s README TL;DR reflects k3s (not Talos) as the deployed
choice, with Talos preserved for the future ITAR cluster.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
48 lines
1.2 KiB
Bash
48 lines
1.2 KiB
Bash
#!/usr/bin/bash
|
|
# k8s/env.sh — shared config for all k8s scripts. Source this.
|
|
#
|
|
# All cluster communication goes over Tailscale IPs. No LAN IPs, ever.
|
|
|
|
# --- Nodes (Tailscale 100.x addresses) ---
|
|
CNODE1_NAME="pfv-k8s-cnode1"
|
|
CNODE1_IP="100.97.178.106"
|
|
|
|
CNODE2_NAME="pfv-k8s-cnode2"
|
|
CNODE2_IP="100.109.34.72"
|
|
|
|
CNODE3_NAME="pfv-k8s-cnode3"
|
|
CNODE3_IP="100.106.222.18"
|
|
|
|
ALL_CNODES=("$CNODE1_IP" "$CNODE2_IP" "$CNODE3_IP")
|
|
ALL_CNODE_NAMES=("$CNODE1_NAME" "$CNODE2_NAME" "$CNODE3_NAME")
|
|
|
|
# Bootstrap node (first etcd member)
|
|
BOOTSTRAP_IP="$CNODE1_IP"
|
|
BOOTSTRAP_NAME="$CNODE1_NAME"
|
|
|
|
# --- SSH ---
|
|
SSH_USER="localuser"
|
|
SSH_OPTS=(-o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=15)
|
|
|
|
# --- k3s ---
|
|
K3S_VERSION="v1.36.2+k3s1"
|
|
K3S_API_PORT="6443"
|
|
|
|
# Shared TLS SANs (all cnodes + hostnames so certs are valid cluster-wide)
|
|
TLS_SANS=(
|
|
"$CNODE1_IP" "$CNODE2_IP" "$CNODE3_IP"
|
|
"$CNODE1_NAME" "$CNODE2_NAME" "$CNODE3_NAME"
|
|
)
|
|
|
|
# Helper: run a command on a node as root (via passwordless sudo)
|
|
cn() {
|
|
local ip="$1"; shift
|
|
ssh "${SSH_OPTS[@]}" "${SSH_USER}@${ip}" "sudo -n bash -c '$*'" 2>&1
|
|
}
|
|
|
|
# Helper: run a heredoc script on a node
|
|
cn_file() {
|
|
local ip="$1"
|
|
ssh "${SSH_OPTS[@]}" "${SSH_USER}@${ip}" "sudo -n bash -s"
|
|
}
|