From 901535ca44bef20a47d7125b9b3dc0d4d316e643 Mon Sep 17 00:00:00 2001 From: Bernd Worsch Date: Tue, 10 Mar 2026 09:43:16 +0000 Subject: [PATCH] feat(k3s-baseline): complete WP-0002 T01-T05 - bootstrap.yml: install k3s (server+cluster-init, pinned v1.35.1+k3s1) and Helm (v3.17.3 with checksum verify); fetch kubeconfig to control node - tests/smoke_kube.sh: assert node Ready, helm, CoreDNS, Traefik - docs/kubeconfig.md: usage, merge, context-switch, security note - Makefile: k3s-install and smoke targets with make help Closes T01, T02, T03, T04, T05 of RAIL-BS-WP-0002. Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 20 ++++++++++++++++++++ docs/kubeconfig.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ tests/smoke_kube.sh | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 Makefile create mode 100644 docs/kubeconfig.md diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fb21817 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +.DEFAULT_GOAL := help + +INVENTORY ?= ansible/hosts.ini + +##@ Kubernetes + +k3s-install: ## Install k3s and Helm on all inventory hosts + ansible-playbook -i $(INVENTORY) ansible/bootstrap.yml + +smoke: ## Run Kubernetes smoke tests + bash tests/smoke_kube.sh + +##@ Help + +help: ## Show this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} \ + /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } \ + /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(MAKEFILE_LIST) + +.PHONY: k3s-install smoke help diff --git a/docs/kubeconfig.md b/docs/kubeconfig.md new file mode 100644 index 0000000..d74014f --- /dev/null +++ b/docs/kubeconfig.md @@ -0,0 +1,44 @@ +# Kubeconfig — HostEurope cluster + +## Where it lives + +After running `make k3s-install`, the bootstrap playbook fetches the kubeconfig +from the HostEurope node to: + +``` +~/.kube/config-hosteurope +``` + +This file is gitignored (contains the cluster CA and client certificate) and +must never be committed. + +## Using it directly + +```bash +export KUBECONFIG=~/.kube/config-hosteurope +kubectl get nodes +``` + +## Merging into ~/.kube/config + +```bash +KUBECONFIG=~/.kube/config:~/.kube/config-hosteurope \ + kubectl config view --flatten > /tmp/merged-config +mv /tmp/merged-config ~/.kube/config +chmod 600 ~/.kube/config +``` + +## Switching context + +```bash +kubectl config get-contexts +kubectl config use-context default # or the context name shown above +``` + +## Security note + +The kubeconfig grants full cluster-admin access. Keep it on the control node +only. Do not share or commit it. The server address inside the file is +`127.0.0.1` (k3s default) — if you need to reach the cluster remotely you +will need to either replace the address with the node's actual IP, or use an +SSH tunnel. diff --git a/tests/smoke_kube.sh b/tests/smoke_kube.sh index 8ccd99c..7143946 100644 --- a/tests/smoke_kube.sh +++ b/tests/smoke_kube.sh @@ -1,5 +1,41 @@ #!/usr/bin/env bash set -euo pipefail -kubectl get nodes -kubectl get ns -echo "[OK] basic k8s API reachable" + +PASS=0 +FAIL=0 + +ok() { echo "[OK] $*"; ((PASS++)) || true; } +fail() { echo "[FAIL] $*"; ((FAIL++)) || true; } + +# ── Node Ready ─────────────────────────────────────────────────────────────── +if kubectl get nodes 2>/dev/null | grep -q " Ready"; then + ok "Node(s) in Ready state" +else + fail "No nodes in Ready state" +fi + +# ── Helm ───────────────────────────────────────────────────────────────────── +if helm version --short &>/dev/null; then + ok "helm version: $(helm version --short)" +else + fail "helm not available or erroring" +fi + +# ── CoreDNS ────────────────────────────────────────────────────────────────── +if kubectl get pods -n kube-system -l k8s-app=kube-dns 2>/dev/null | grep -q "Running"; then + ok "CoreDNS pod running in kube-system" +else + fail "CoreDNS pod not running in kube-system" +fi + +# ── Traefik ────────────────────────────────────────────────────────────────── +if kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik 2>/dev/null | grep -q "Running"; then + ok "Traefik ingress controller running in kube-system" +else + fail "Traefik ingress controller not running in kube-system" +fi + +# ── Summary ────────────────────────────────────────────────────────────────── +echo "" +echo "Results: ${PASS} passed, ${FAIL} failed" +[[ "$FAIL" -eq 0 ]]