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 ]]