diff --git a/README.md b/README.md index 694e4f2..336af9f 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,6 @@ Belangrijk: | 01 | ArgoCD bootstrappen | [docs/01-argocd-bootstrap.md](docs/01-argocd-bootstrap.md) | Kern | 30 min | | 02 | podinfo deployen via GitOps | [docs/02-deploy-podinfo.md](docs/02-deploy-podinfo.md) | Kern | 30 min | | 03 | MetalLB + Ingress-Nginx | [docs/03-metallb-ingress.md](docs/03-metallb-ingress.md) | Kern | 45 min | -| 03b | Cloudflare Tunnel (webhooks) | [docs/03b-cloudflare-tunnel.md](docs/03b-cloudflare-tunnel.md) | Bonus | 30–45 min | | 04 | Tekton pipeline | [docs/04-tekton-pipeline.md](docs/04-tekton-pipeline.md) | Kern | 45 min | | 05 | App upgrade + reflectie | [docs/05-app-upgrade.md](docs/05-app-upgrade.md) | Kern | 15 min | | 06 | Prometheus + Grafana | [docs/06-monitoring.md](docs/06-monitoring.md) | Bonus | 60 min | @@ -128,7 +127,6 @@ om precies te zien wat er in die specifieke oefening mist. | `solution/01-argocd-bootstrap` | ArgoCD draait | | `solution/02-deploy-podinfo` | podinfo gesynchroniseerd via ArgoCD | | `solution/03-metallb-ingress` | LAN-toegang via MetalLB + Ingress | -| `solution/03b-cloudflare-tunnel` | Cloudflare tunnel connector (token placeholders) | | `solution/04-tekton-pipeline` | Volledige GitOps CI-loop | | `solution/05-app-upgrade` | podinfo op v6.7.0 | | `solution/06-monitoring` | Prometheus + Grafana actief | diff --git a/docs/03b-cloudflare-tunnel.md b/docs/03b-cloudflare-tunnel.md deleted file mode 100644 index b59eca7..0000000 --- a/docs/03b-cloudflare-tunnel.md +++ /dev/null @@ -1,319 +0,0 @@ -# Oefening 03b (Bonus) — Cloudflare Tunnel voor webhooks - -**Tijd**: ~30–45 minuten -**Doel**: Je lokale workshop-cluster vanaf internet bereikbaar maken voor inkomende webhooks (bijv. GitHub -> Tekton). - ---- - -## Wat je leert - -- Waarom host-only networking (`192.168.56.x`) niet direct bereikbaar is vanaf internet -- Hoe Cloudflare Tunnel verkeer van internet veilig naar een interne Kubernetes-service brengt -- Hoe je dit later gebruikt in Oefening 04 voor echte GitHub webhooks - ---- - -## Leeswijzer - -> **Voor beginners (optioneel):** -> Zie Cloudflare Tunnel als een "uitgaande connector": -> een proces in jouw omgeving belt zelf uit naar Cloudflare. -> Daarna kan Cloudflare inkomend verkeer over die bestaande verbinding terugsturen. -> Je hoeft dus geen poorten op je laptop/router open te zetten. - ---- - -## Vereisten - -- Oefening 03 afgerond (Ingress-Nginx werkt) -- Je repo/fork op `main` - -Optioneel (alleen nodig voor **Route A** hieronder): - -- [cloudflared](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/) op de - host _of_ vm - -Optioneel (alleen nodig voor **Route B** hieronder): - -- Een Cloudflare account -- Eigen domein in Cloudflare - ---- - -## Kies je route - -Je hebt twee manieren: - -- **Route A (geen domein nodig)**: snelle, tijdelijke `*.trycloudflare.com` URL -- **Route B (met eigen domein, aanbevolen)**: stabiele URL zoals `tekton-webhook.` - -Wanneer welke? - -- Gebruik **Route A** als je snel wilt testen zonder domein. -- Gebruik **Route B** als je een blijvende endpoint wilt (handig voor workshop-herhaling en stabiele GitHub webhook). - ---- - -## Route A — Zonder eigen domein (tijdelijke test-URL) - -### A1. Start een quick tunnel vanaf je host - -> **HOST** -> ```bash -> cloudflared tunnel --url http://192.168.56.200 --http-host-header tekton-webhook.192.168.56.200.nip.io -> ``` - -Je krijgt output met een publieke URL, bijvoorbeeld: - -```text -https://random-words.trycloudflare.com -``` - -Laat dit proces open staan. - -> **Voor beginners (optioneel):** -> `--http-host-header` is belangrijk: daarmee blijft Ingress-Nginx de juiste route kiezen voor de Tekton listener. - -### A2. Gebruik deze URL in GitHub webhook - -In GitHub: - -- **Settings -> Webhooks -> Add webhook** -- Payload URL: `https://random-words.trycloudflare.com` -- Content type: `application/json` -- Event: `Just the push event` - -### A3. Beperkingen van Route A - -- URL verandert bij herstart -- Tunnel stopt als je terminal/proces stopt -- Prima voor demo/test, minder geschikt als "vaste" setup - ---- - -## Route B — Met eigen domein (stabiel, aanbevolen) - -## Architectuur (hoog niveau) - -```text -GitHub webhook - | - v -https://tekton-webhook. - | - v -Cloudflare Edge - | - v -Cloudflare Tunnel (cloudflared pod in cluster) - | - v -el-github-push-listener.tekton-pipelines.svc:8080 -``` - -Belangrijk: - -- Dit werkt ook als je cluster alleen op host-only netwerk draait. -- Cloudflare bereikt je cluster via de actieve tunnelverbinding, niet via je LAN-IP. - -### B1. Tunnel in Cloudflare aanmaken - -In Cloudflare dashboard: - -1. Ga naar **Zero Trust** (of **Cloudflare One**) -2. Ga naar **Networks -> Tunnels** -3. Klik **Create a tunnel** -4. Kies **Cloudflared** -5. Geef een naam, bijvoorbeeld `ops-demo-workshop` -6. Cloudflare toont een **Tunnel Token** (lange string) — bewaar deze veilig - -> **Voor beginners (optioneel):** -> Die token is het wachtwoord waarmee jouw `cloudflared` pod zich aanmeldt. -> Iedereen met deze token kan jouw tunnel gebruiken; behandel hem als secret. - -### B2. Public hostname in Cloudflare configureren - -In dezelfde tunnel: - -1. Ga naar **Public Hostnames** -2. Voeg een hostname toe, bijvoorbeeld: - - Subdomain: `tekton-webhook` - - Domain: `` -3. Service type: `HTTP` -4. URL: `http://el-github-push-listener.tekton-pipelines.svc.cluster.local:8080` -5. Sla op - -> **Voor beginners (optioneel):** -> Deze URL is expres een interne Kubernetes-service. -> Alleen de cloudflared pod hoeft die te kunnen bereiken; internet ziet alleen de publieke hostname. - -### B3. Kubernetes manifests toevoegen - -Maak de volgende bestanden. - -**`manifests/networking/cloudflared/namespace.yaml`** - -```yaml -apiVersion: v1 -kind: Namespace -metadata: - name: cloudflare -``` - -**`manifests/networking/cloudflared/token.secret.yaml`** - -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: cloudflared-token - namespace: cloudflare -type: Opaque -stringData: - token: "PLAK_HIER_JE_CLOUDFLARE_TUNNEL_TOKEN" -``` - -**`manifests/networking/cloudflared/deployment.yaml`** - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cloudflared - namespace: cloudflare -spec: - replicas: 1 - selector: - matchLabels: - app: cloudflared - template: - metadata: - labels: - app: cloudflared - spec: - containers: - - name: cloudflared - image: cloudflare/cloudflared:2025.2.1 - args: - - tunnel - - --no-autoupdate - - run - - --token - - $(TUNNEL_TOKEN) - env: - - name: TUNNEL_TOKEN - valueFrom: - secretKeyRef: - name: cloudflared-token - key: token - resources: - requests: - cpu: 20m - memory: 64Mi -``` - -**`apps/networking/cloudflared.yaml`** - -```yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: cloudflared - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "4" -spec: - project: workshop - source: - repoURL: JOUW_FORK_URL - targetRevision: HEAD - path: manifests/networking/cloudflared - destination: - server: https://kubernetes.default.svc - namespace: cloudflare - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true -``` - -Vervang: - -- `PLAK_HIER_JE_CLOUDFLARE_TUNNEL_TOKEN` -- `JOUW_FORK_URL` - -### B4. Committen en pushen - -> **HOST** -> ```bash -> git add apps/networking/cloudflared.yaml manifests/networking/cloudflared/ -> git commit -m "feat: add cloudflared tunnel connector" -> git push -> ``` - -Wacht daarna op `Synced/Healthy`: - -> **VM** -> ```bash -> kubectl get application cloudflared -n argocd -> kubectl get pods -n cloudflare -> ``` - -### B5. Tunnel-status controleren - -> **VM** -> ```bash -> kubectl logs -n cloudflare deploy/cloudflared --tail=100 -> ``` - -Zoek op regels zoals "connected" of "registered tunnel connection". - ---- - -## Voorbereiden op Oefening 04 webhook - -Als je in Oefening 04 Tekton Triggers hebt geïnstalleerd: - -- Bij **Route A**: gebruik je tijdelijke `https://...trycloudflare.com` URL -- Bij **Route B**: gebruik `https://tekton-webhook.` - -Gebruik in beide gevallen **niet** meer de host-only URL met `192.168.56.200.nip.io`. - ---- - -## Probleemoplossing - -| Symptoom | Oplossing | -|--------------------------------------------------------------|------------------------------------------------------------------------------------| -| cloudflared pod blijft CrashLoopBackOff | Controleer of de tunnel token klopt en niet verlopen/ingetrokken is | -| Tunnel lijkt up, maar webhook geeft 502/504 | Controleer of `el-github-push-listener` service bestaat in `tekton-pipelines` | -| Geen verkeer in Tekton na GitHub push | Controleer GitHub webhook deliveries + event type `push` + secret | -| Argo app `cloudflared` blijft `Unknown` | Controleer of `repoURL` in `apps/networking/cloudflared.yaml` naar jouw fork wijst | -| `trycloudflare.com` URL werkt eerst wel maar later niet meer | Quick tunnel is tijdelijk; start opnieuw of gebruik Route B | - ---- - -## Security-opmerking - -Gebruik in een echte omgeving liever: - -- externe secret manager voor tunnel token -- aparte Cloudflare tunnel per omgeving -- least-privilege Cloudflare account/API instellingen - -Voor deze workshop is één token in een Kubernetes Secret voldoende. - ---- - -## Peek-solution - -Wil je een voorbeeld zien zonder alles handmatig te typen? - -- Branch: `solution/03b-cloudflare-tunnel` -- Daarin staan: - - `apps/networking/cloudflared.yaml` - - `manifests/networking/cloudflared/namespace.yaml` - - `manifests/networking/cloudflared/token.secret.yaml` (placeholder token) - - `manifests/networking/cloudflared/deployment.yaml` diff --git a/docs/04-tekton-pipeline.md b/docs/04-tekton-pipeline.md index 9204d30..10ea443 100644 --- a/docs/04-tekton-pipeline.md +++ b/docs/04-tekton-pipeline.md @@ -477,208 +477,6 @@ De naam van een PipelineRun moet uniek zijn: --- -## Bonus: triggeren via Git webhook (optioneel) - -Wil je dat Tekton automatisch runt bij een `git push`? -Dan gebruik je **Tekton Triggers** met een webhook endpoint. - -Als je **GitHub** gebruikt, kun je onderstaande manifests direct volgen. -Gebruik je GitLab/Gitea/Bitbucket, dan blijft het patroon hetzelfde maar de interceptor/payload-mapping kan verschillen. - -> [!IMPORTANT] -> In deze workshop draait de cluster op een VirtualBox host-only netwerk (`192.168.56.x`). -> Dat endpoint is niet publiek bereikbaar vanaf GitHub. -> Dus: GitHub kan `tekton-webhook.192.168.56.200.nip.io` niet direct aanroepen. -> -> Voor echte GitHub webhooks heb je een brug nodig, bijvoorbeeld: -> - een publieke tunnel (`ngrok`, `cloudflared tunnel`) -> - een webhook relay (`smee.io`) -> - of een publiek bereikbare cluster endpoint (geen host-only-only setup) -> -> Als je **Oefening 03b** hebt gedaan, gebruik dan je Cloudflare Tunnel URL -> (bijv. `https://tekton-webhook.`) als webhook endpoint. - -### 1. Triggers resources toevoegen - -**`manifests/ci/triggers/kustomization.yaml`** - -```yaml -resources: - - https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml - - https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml - - triggerbinding.yaml - - triggertemplate.yaml - - eventlistener.yaml - - ingress.yaml -``` - -**`manifests/ci/triggers/triggerbinding.yaml`** - -```yaml -apiVersion: triggers.tekton.dev/v1beta1 -kind: TriggerBinding -metadata: - name: github-push-binding - namespace: tekton-pipelines -spec: - params: - - name: repo-url - value: $(body.repository.clone_url) -``` - -**`manifests/ci/triggers/triggertemplate.yaml`** - -```yaml -apiVersion: triggers.tekton.dev/v1beta1 -kind: TriggerTemplate -metadata: - name: github-push-template - namespace: tekton-pipelines -spec: - params: - - name: repo-url - default: https://github.com/JOUW_USERNAME/JOUW_REPO.git - resourcetemplates: - - apiVersion: tekton.dev/v1 - kind: PipelineRun - metadata: - generateName: webhook-bump- - namespace: tekton-pipelines - spec: - pipelineRef: - name: gitops-image-bump - taskRunTemplate: - serviceAccountName: pipeline-runner - params: - - name: repo-url - value: $(tt.params.repo-url) - - name: new-tag - value: "6.7.0" - - name: git-user-name - value: "Workshop Pipeline" - - name: git-user-email - value: "pipeline@workshop.local" - workspaces: - - name: source - volumeClaimTemplate: - spec: - accessModes: [ ReadWriteOnce ] - resources: - requests: - storage: 1Gi - - name: git-credentials - secret: - secretName: git-credentials -``` - -**`manifests/ci/triggers/eventlistener.yaml`** - -```yaml -apiVersion: triggers.tekton.dev/v1beta1 -kind: EventListener -metadata: - name: github-push-listener - namespace: tekton-pipelines -spec: - serviceAccountName: pipeline-runner - triggers: - - name: on-push - interceptors: - - ref: - name: github - params: - - name: secretRef - value: - secretName: github-webhook-secret - secretKey: secretToken - - name: eventTypes - value: - - push - bindings: - - ref: github-push-binding - template: - ref: github-push-template -``` - -**`manifests/ci/triggers/ingress.yaml`** - -```yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: tekton-triggers - namespace: tekton-pipelines -spec: - ingressClassName: nginx - rules: - - host: tekton-webhook.192.168.56.200.nip.io - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: el-github-push-listener - port: - number: 8080 -``` - -**`apps/ci/tekton-triggers.yaml`** - -```yaml -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: tekton-triggers - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "8" -spec: - project: workshop - source: - repoURL: JOUW_FORK_URL - targetRevision: HEAD - path: manifests/ci/triggers - destination: - server: https://kubernetes.default.svc - namespace: tekton-pipelines - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true -``` - -> **HOST** -> ```bash -> git add apps/ci/tekton-triggers.yaml manifests/ci/triggers/ -> git commit -m "feat: voeg Tekton Triggers webhook flow toe" -> git push -> ``` - -### 2. Webhook secret zetten - -> **VM** -> ```bash -> kubectl -n tekton-pipelines create secret generic github-webhook-secret \ -> --from-literal=secretToken='kies-een-sterke-random-string' \ -> --dry-run=client -o yaml | kubectl apply -f - -> ``` - -### 3. GitHub webhook registreren - -- In GitHub: **Settings → Webhooks → Add webhook** -- Payload URL: `http://tekton-webhook.192.168.56.200.nip.io` -- Content type: `application/json` -- Secret: dezelfde waarde als `secretToken` -- Event: **Just the push event** - -Zonder tunnel/relay of publiek endpoint zal GitHub deze URL niet kunnen bereiken. -Met zo'n brug maakt elke push een nieuwe `PipelineRun` aan. - ---- - ## Probleemoplossing | Symptoom | Oplossing | @@ -690,7 +488,6 @@ Met zo'n brug maakt elke push een nieuwe `PipelineRun` aan. | `root` blijft OutOfSync op app `tekton` | Verwijder de lege `kustomize: {}` uit `apps/ci/tekton.yaml` (Argo normaliseert deze weg in live state) | | PipelineRun faalt met `PodAdmissionFailed` | Controleer dat `tekton-pipelines` label `pod-security.kubernetes.io/enforce=privileged` heeft (via `manifests/ci/tekton/namespace-podsecurity-patch.yaml`) | | Tekton Dashboard toont standaard Nginx/404 | Controleer `apps/ci/tekton-dashboard.yaml` en `manifests/ci/dashboard/ingress.yaml` host/service/poort | -| Webhook maakt geen PipelineRun aan | Check `kubectl get eventlistener -n tekton-pipelines` en controleer GitHub webhook URL/secret/eventtype | --- diff --git a/roadmap.md b/roadmap.md index 665743b..b3c2637 100644 --- a/roadmap.md +++ b/roadmap.md @@ -7,7 +7,6 @@ | 01 | Bootstrap ArgoCD | Core | 30 min | ✅ Implemented | | 02 | Deploy podinfo via GitOps | Core | 30 min | ✅ Implemented | | 03 | MetalLB + Ingress-Nginx (LAN exposure) | Core | 45 min | ✅ Implemented | -| 03b | Cloudflare Tunnel voor webhooks | Bonus | 30–45 min | ✅ Implemented | | 04 | Tekton pipeline (image tag bump → GitOps loop) | Core | 45 min | ✅ Implemented | | 05 | App upgrade via GitOps | Core | 15 min | ✅ Implemented | | 06 | Monitoring: Prometheus + Grafana | Bonus | 60 min | ✅ Implemented | @@ -25,7 +24,6 @@ Model: solution branches are **standalone per exercise** (not cumulative). | `solution/01-argocd-bootstrap` | ArgoCD running, root app applied | | `solution/02-deploy-podinfo` | podinfo synced via ArgoCD | | `solution/03-metallb-ingress` | MetalLB + Ingress-Nginx + podinfo reachable on LAN; CRD `caBundle` drift handling included | -| `solution/03b-cloudflare-tunnel` | Cloudflared tunnel connector manifests met token placeholders | | `solution/04-tekton-pipeline` | Full Tekton GitOps loop working | | `solution/05-app-upgrade` | deployment.yaml bumped to 6.7.0 | | `solution/06-monitoring` | Prometheus + Grafana running |