Improve bootstrap safety and add host-side ArgoCD access scripts

This commit is contained in:
Paul Harkink 2026-02-28 18:34:56 +01:00
parent c68292e599
commit 71c1f79f6f
7 changed files with 228 additions and 24 deletions

View file

@ -1,6 +1,7 @@
# Kubernetes GitOps Workshop # 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.
--- ---
@ -9,8 +10,8 @@ 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. Je hebt drie dingen nodig op je laptop. Installeer ze de dag van tevoren — niet op de dag zelf.
| Tool | Download | | Tool | Download |
|----------------|-------------------------------------------------------| |----------------|---------------------------------------------------------------------|
| VirtualBox 7.x | https://www.virtualbox.org/wiki/Downloads — herstart je laptop erna | | 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 | | Vagrant 2.4.x | https://developer.hashicorp.com/vagrant/downloads |
| Git | https://git-scm.com/downloads | | Git | https://git-scm.com/downloads |
@ -26,20 +27,41 @@ Als één van de drie niets teruggeeft: installeren en opnieuw proberen.
## Aan de slag ## 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 ```bash
git clone https://github.com/JOUW_USERNAME/ops-demo.git git clone https://github.com/JOUW_USERNAME/ops-demo.git && cd ops-demo
cd ops-demo ```
vagrant up # eerste keer ~1015 min 2. Start de VM.
vagrant ssh # gebruik dit voor VM-toegang (geen handmatige ssh nodig) ```bash
cd /vagrant vagrant up
./scripts/bootstrap.sh ```
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 0103 (~1u45m). De rest: probeer 0105 te halen.
## Vastgelopen? ## 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. 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
```
| Branch | Bevat | | Branch | Bevat |
|--------------------------------|-------------------------------------| |--------------------------------|-------------------------------------|

8
Vagrantfile vendored
View file

@ -51,6 +51,14 @@ $provision = <<-SHELL
cp /etc/rancher/k3s/k3s.yaml /home/vagrant/.kube/config cp /etc/rancher/k3s/k3s.yaml /home/vagrant/.kube/config
# Point server to host-only IP so it works outside the VM too # 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 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 chown -R vagrant:vagrant /home/vagrant/.kube
chmod 600 /home/vagrant/.kube/config chmod 600 /home/vagrant/.kube/config

View file

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

24
scripts/argocd-ui-tunnel.sh Executable file
View file

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

View file

@ -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'

45
scripts/bootstrap-from-host.sh Executable file
View file

@ -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"

View file

@ -20,11 +20,52 @@ set -euo pipefail
ARGOCD_NAMESPACE="argocd" ARGOCD_NAMESPACE="argocd"
ARGOCD_CHART_VERSION="7.7.11" ARGOCD_CHART_VERSION="7.7.11"
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" 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 "══════════════════════════════════════════════"
echo " ops-demo Bootstrap" echo " ops-demo Bootstrap"
echo "══════════════════════════════════════════════" 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 ───────────────────────────────────────────────────── # ── 1. Detecteer fork URL ─────────────────────────────────────────────────────
REMOTE_URL=$(git -C "${REPO_ROOT}" remote get-url origin 2>/dev/null || echo "") REMOTE_URL=$(git -C "${REPO_ROOT}" remote get-url origin 2>/dev/null || echo "")
if [[ -z "${REMOTE_URL}" ]]; then if [[ -z "${REMOTE_URL}" ]]; then
@ -103,9 +144,16 @@ echo " Bootstrap geslaagd!"
echo "" echo ""
echo " ArgoCD admin-wachtwoord: ${ARGOCD_PASSWORD}" echo " ArgoCD admin-wachtwoord: ${ARGOCD_PASSWORD}"
echo "" echo ""
echo " Open de ArgoCD UI — voer dit uit in een nieuw terminal:" if [[ -n "${SSH_CONNECTION:-}" ]]; then
echo " kubectl port-forward svc/argocd-server -n argocd 8080:443" echo " Je draait via SSH (headless VM). Gebruik deze flow:"
echo " Dan: https://localhost:8080 (login: admin / ${ARGOCD_PASSWORD})" 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 ""
echo " apps/root.yaml is aangemaakt met jouw fork-URL." echo " apps/root.yaml is aangemaakt met jouw fork-URL."
echo " Volgende stap (Oefening 01):" echo " Volgende stap (Oefening 01):"