diff --git a/README.md b/README.md index 2e90402..5fa4fc0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Kubernetes GitOps Workshop -Twee en een half tot vier uur hands-on cluster operations met ArgoCD, MetalLB, Ingress-Nginx en Tekton. Alles draait lokaal op een single-node k3s cluster in een VM. +Twee en een half tot vier uur hands-on cluster operations met ArgoCD, MetalLB, Ingress-Nginx en Tekton. Alles draait +lokaal op een single-node k3s cluster in een VM. --- @@ -8,11 +9,11 @@ Twee en een half tot vier uur hands-on cluster operations met ArgoCD, MetalLB, I Je hebt drie dingen nodig op je laptop. Installeer ze de dag van tevoren — niet op de dag zelf. -| Tool | Download | -|----------------|-------------------------------------------------------| -| VirtualBox 7.x | https://www.virtualbox.org/wiki/Downloads — herstart je laptop erna | -| Vagrant 2.4.x | https://developer.hashicorp.com/vagrant/downloads | -| Git | https://git-scm.com/downloads | +| Tool | Download | +|----------------|---------------------------------------------------------------------| +| VirtualBox 7.x | https://www.virtualbox.org/wiki/Downloads — op Windows: reboot alleen als installer/Windows daarom vraagt | +| Vagrant 2.4.x | https://developer.hashicorp.com/vagrant/downloads | +| Git | https://git-scm.com/downloads | Minimaal 12 GB vrij RAM en ~15 GB schijfruimte. Snelle check: @@ -26,20 +27,41 @@ Als één van de drie niets teruggeeft: installeren en opnieuw proberen. ## Aan de slag -**Fork eerst de repo** naar je eigen GitHub-account — ga naar https://github.com/paulharkink/ops-demo en klik Fork. Zo kun je zelf pushen zonder dat je toegang nodig hebt tot de originele repo. +**Fork eerst de repo** naar je eigen GitHub-account — ga naar https://github.com/paulharkink/ops-demo en klik Fork. Zo +kun je zelf pushen zonder dat je toegang nodig hebt tot de originele repo. +1. Clone je fork op je host-machine. ```bash -git clone https://github.com/JOUW_USERNAME/ops-demo.git -cd ops-demo -vagrant up # eerste keer ~10–15 min -vagrant ssh # gebruik dit voor VM-toegang (geen handmatige ssh nodig) -cd /vagrant -./scripts/bootstrap.sh +git clone https://github.com/JOUW_USERNAME/ops-demo.git && cd ops-demo +``` +2. Start de VM. +```bash +vagrant up +``` +3. Run bootstrap vanaf je host (script voert bootstrap in de VM uit). +```bash +./scripts/bootstrap-from-host.sh +``` +```powershell +./scripts/bootstrap-from-host.ps1 +``` +4. Open ArgoCD UI via tunnel. +```bash +./scripts/argocd-ui-tunnel.sh +``` +```powershell +./scripts/argocd-ui-tunnel.ps1 +``` +5. Open in je browser: +```text +https://localhost:8080 ``` -Volg dan de oefeningen in volgorde. Zie [docs/vm-setup.md](docs/vm-setup.md) als er iets misgaat bij de VM. +Volg daarna de oefeningen in volgorde. Zie [docs/vm-setup.md](docs/vm-setup.md) als er iets misgaat bij de VM. -Voor alle workshopstappen geldt: log in op de VM met `vagrant ssh`. Je hoeft het VM-IP niet te weten om in te loggen. +Belangrijk: +- Je hoeft het VM-IP niet te weten om in te loggen of te tunnelen; gebruik `vagrant ssh`. +- Je hoeft de repo niet opnieuw in de VM te clonen: Vagrant mount je host-repo automatisch als `/vagrant`. --- @@ -74,12 +96,8 @@ Beginners: focus op 01–03 (~1u45m). De rest: probeer 01–05 te halen. ## Vastgelopen? -Elke solution branch is cumulatief — hij bevat alles t/m die oefening. Je kunt een PR openen van een solution branch naar jouw eigen branch om precies te zien wat er mist. - -```bash -git fetch origin -git show origin/solution/03-metallb-ingress:manifests/networking/metallb/metallb-config.yaml -``` +Elke solution branch is cumulatief — hij bevat alles t/m die oefening. Je kunt een PR openen van een solution branch +naar jouw eigen branch om precies te zien wat er mist. | Branch | Bevat | |--------------------------------|-------------------------------------| diff --git a/Vagrantfile b/Vagrantfile index c22f39d..2ebc466 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -51,6 +51,14 @@ $provision = <<-SHELL cp /etc/rancher/k3s/k3s.yaml /home/vagrant/.kube/config # Point server to host-only IP so it works outside the VM too sed -i "s|127.0.0.1|#{HOST_ONLY_IP}|g" /home/vagrant/.kube/config + # Name the kube context explicitly so workshop scripts can verify target cluster + if kubectl --kubeconfig /home/vagrant/.kube/config config get-contexts ops-demo >/dev/null 2>&1; then + kubectl --kubeconfig /home/vagrant/.kube/config config use-context ops-demo + else + CURRENT_CONTEXT=$(kubectl --kubeconfig /home/vagrant/.kube/config config current-context) + kubectl --kubeconfig /home/vagrant/.kube/config config rename-context "${CURRENT_CONTEXT}" ops-demo + kubectl --kubeconfig /home/vagrant/.kube/config config use-context ops-demo + fi chown -R vagrant:vagrant /home/vagrant/.kube chmod 600 /home/vagrant/.kube/config diff --git a/scripts/argocd-ui-tunnel.ps1 b/scripts/argocd-ui-tunnel.ps1 new file mode 100644 index 0000000..8e7bc7b --- /dev/null +++ b/scripts/argocd-ui-tunnel.ps1 @@ -0,0 +1,18 @@ +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$RepoRoot = Split-Path -Parent $PSScriptRoot +Set-Location $RepoRoot + +$status = vagrant status --machine-readable | Out-String +if ($status -notmatch ',state,running') { + Write-Host '[ops-demo] VM is not running; starting with vagrant up...' + vagrant up +} + +Write-Host '[ops-demo] Ensuring VM-side port-forward is running...' +vagrant ssh -c "pgrep -f 'kubectl -n argocd port-forward svc/argocd-server 8080:443' >/dev/null || nohup kubectl -n argocd port-forward svc/argocd-server 8080:443 >/tmp/argocd-port-forward.log 2>&1 &" | Out-Null + +Write-Host '[ops-demo] Opening SSH tunnel localhost:8080 -> VM:8080' +Write-Host '[ops-demo] Keep this terminal open while using https://localhost:8080' +vagrant ssh -- -L 8080:127.0.0.1:8080 diff --git a/scripts/argocd-ui-tunnel.sh b/scripts/argocd-ui-tunnel.sh new file mode 100755 index 0000000..37ffd48 --- /dev/null +++ b/scripts/argocd-ui-tunnel.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +cd "${REPO_ROOT}" + +command -v vagrant >/dev/null 2>&1 || { + echo "ERROR: required command not found: vagrant" >&2 + exit 1 +} + +echo "[ops-demo] Checking VM status..." +if ! vagrant status --machine-readable | rg -q ',state,running'; then + echo "[ops-demo] VM is not running; starting with vagrant up..." + vagrant up +fi + +echo "[ops-demo] Ensuring VM-side port-forward is running..." +vagrant ssh -c "pgrep -f 'kubectl -n argocd port-forward svc/argocd-server 8080:443' >/dev/null || nohup kubectl -n argocd port-forward svc/argocd-server 8080:443 >/tmp/argocd-port-forward.log 2>&1 &" >/dev/null + +echo "[ops-demo] Opening SSH tunnel localhost:8080 -> VM:8080" +echo "[ops-demo] Keep this terminal open while using https://localhost:8080" +vagrant ssh -- -L 8080:127.0.0.1:8080 diff --git a/scripts/bootstrap-from-host.ps1 b/scripts/bootstrap-from-host.ps1 new file mode 100644 index 0000000..0cd4341 --- /dev/null +++ b/scripts/bootstrap-from-host.ps1 @@ -0,0 +1,43 @@ +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$RepoRoot = Split-Path -Parent $PSScriptRoot +Set-Location $RepoRoot + +function Ensure-VagrantRunning { + $status = vagrant status --machine-readable | Out-String + if ($status -notmatch ',state,running') { + Write-Host '[ops-demo] VM is not running; starting with vagrant up...' + vagrant up + } +} + +Write-Host '[ops-demo] Checking VM status...' +Ensure-VagrantRunning + +Write-Host '[ops-demo] Running bootstrap in VM...' +$output = vagrant ssh -c "cd /vagrant && ./scripts/bootstrap.sh" | Out-String +Write-Host $output + +$password = $null +if ($output -match 'ArgoCD admin-wachtwoord:\s*(\S+)') { + $password = $Matches[1] +} + +if (-not $password) { + $fallback = vagrant ssh -c "kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d" | Out-String + $password = $fallback.Trim() +} + +Write-Host '' +Write-Host '[ops-demo] Bootstrap complete.' +if ($password) { + Write-Host "[ops-demo] ArgoCD admin password: $password" +} else { + Write-Host '[ops-demo] Could not extract ArgoCD admin password automatically.' +} + +Write-Host '' +Write-Host 'Next step to open ArgoCD UI from host:' +Write-Host ' ./scripts/argocd-ui-tunnel.ps1' +Write-Host 'Then browse: https://localhost:8080' diff --git a/scripts/bootstrap-from-host.sh b/scripts/bootstrap-from-host.sh new file mode 100755 index 0000000..afbb69b --- /dev/null +++ b/scripts/bootstrap-from-host.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +cd "${REPO_ROOT}" + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "ERROR: required command not found: $1" >&2 + exit 1 + } +} + +require_cmd vagrant + +echo "[ops-demo] Checking VM status..." +if ! vagrant status --machine-readable | rg -q ',state,running'; then + echo "[ops-demo] VM is not running; starting with vagrant up..." + vagrant up +fi + +log_file="$(mktemp)" +trap 'rm -f "${log_file}"' EXIT + +echo "[ops-demo] Running bootstrap in VM..." +vagrant ssh -c "cd /vagrant && ./scripts/bootstrap.sh" | tee "${log_file}" + +password="$(sed -n 's/.*ArgoCD admin-wachtwoord: //p' "${log_file}" | tail -n 1 | tr -d '\r')" +if [[ -z "${password}" ]]; then + password="$(vagrant ssh -c "kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d" 2>/dev/null | tr -d '\r')" +fi + +echo "" +echo "[ops-demo] Bootstrap complete." +if [[ -n "${password}" ]]; then + echo "[ops-demo] ArgoCD admin password: ${password}" +else + echo "[ops-demo] Could not extract ArgoCD admin password automatically." +fi + +echo "" +echo "Next step to open ArgoCD UI from host:" +echo " ./scripts/argocd-ui-tunnel.sh" +echo "Then browse: https://localhost:8080" diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 4de5dcb..fee2156 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -20,11 +20,52 @@ set -euo pipefail ARGOCD_NAMESPACE="argocd" ARGOCD_CHART_VERSION="7.7.11" REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +EXPECTED_NODE_NAME="ops-demo" +EXPECTED_HOST_ONLY_IP="$(awk -F'"' '/^HOST_ONLY_IP = "/ {print $2; exit}' "${REPO_ROOT}/Vagrantfile" 2>/dev/null || true)" +EXPECTED_HOST_ONLY_IP="${EXPECTED_HOST_ONLY_IP:-192.168.56.10}" +EXPECTED_API_SERVER="https://${EXPECTED_HOST_ONLY_IP}:6443" + +die() { + echo "FOUT: $*" >&2 + exit 1 +} + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || die "verplichte tool ontbreekt: $1" +} echo "══════════════════════════════════════════════" echo " ops-demo Bootstrap" echo "══════════════════════════════════════════════" +# ── Preflight checks ────────────────────────────────────────────────────────── +require_cmd git +require_cmd kubectl +require_cmd helm + +if ! kubectl get nodes >/dev/null 2>&1; then + die "kubectl kan het cluster niet bereiken. Log in op de VM met 'vagrant ssh' en run het script vanaf /vagrant." +fi + +CURRENT_CONTEXT="$(kubectl config current-context 2>/dev/null || true)" +CURRENT_SERVER="$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null || true)" +if [[ "${CURRENT_SERVER}" != "${EXPECTED_API_SERVER}" ]]; then + die "kubectl wijst naar '${CURRENT_SERVER:-onbekend}', verwacht '${EXPECTED_API_SERVER}'. Controleer je context eerst (huidige context: ${CURRENT_CONTEXT:-onbekend})." +fi + +if ! kubectl get node "${EXPECTED_NODE_NAME}" -o name >/dev/null 2>&1; then + die "verwachte node '${EXPECTED_NODE_NAME}' niet gevonden in huidige cluster. Stop om deploy naar de verkeerde cluster te voorkomen." +fi + +if [[ "${CURRENT_CONTEXT}" != "ops-demo" ]]; then + echo "WAARSCHUWING: huidige context is '${CURRENT_CONTEXT:-onbekend}', verwacht 'ops-demo'." + echo " Cluster-checks zijn wel geslaagd; je kunt doorgaan." +fi + +if [[ "${PWD}" != /vagrant* ]]; then + echo "WAARSCHUWING: je staat niet in /vagrant. Aanbevolen: 'cd /vagrant' voor je dit script draait." +fi + # ── 1. Detecteer fork URL ───────────────────────────────────────────────────── REMOTE_URL=$(git -C "${REPO_ROOT}" remote get-url origin 2>/dev/null || echo "") if [[ -z "${REMOTE_URL}" ]]; then @@ -103,9 +144,16 @@ echo " Bootstrap geslaagd!" echo "" echo " ArgoCD admin-wachtwoord: ${ARGOCD_PASSWORD}" echo "" -echo " Open de ArgoCD UI — voer dit uit in een nieuw terminal:" -echo " kubectl port-forward svc/argocd-server -n argocd 8080:443" -echo " Dan: https://localhost:8080 (login: admin / ${ARGOCD_PASSWORD})" +if [[ -n "${SSH_CONNECTION:-}" ]]; then + echo " Je draait via SSH (headless VM). Gebruik deze flow:" + echo " 1) Op je laptop: vagrant ssh -- -L 8080:127.0.0.1:8080" + echo " 2) In die VM-shell: kubectl port-forward svc/argocd-server -n argocd 8080:443" + echo " 3) Open op je laptop: https://localhost:8080 (login: admin / ${ARGOCD_PASSWORD})" +else + echo " Open de ArgoCD UI — voer dit uit in een nieuw terminal:" + echo " kubectl port-forward svc/argocd-server -n argocd 8080:443" + echo " Dan: https://localhost:8080 (login: admin / ${ARGOCD_PASSWORD})" +fi echo "" echo " apps/root.yaml is aangemaakt met jouw fork-URL." echo " Volgende stap (Oefening 01):"