Blueprint for a Local GitLab + Kubernetes CI/CD Stack¶
A reproducible, fully local GitLab + Kubernetes CI/CD stack — one repo, one machine, agent-driven. A 5-node kind cluster hosts a self-managed GitLab (chart-bundled Envoy Gateway terminates *.local.example.net), a registered Runner, and OpenBao for secret injection. Push a commit, get a running workload on https://<app>.apps.local.example.net.
What you'll build, and how long it takes¶
The blueprint delivers three layers, each with its own runbook and idempotent re-run contract:
| Phase | What lands on your machine | Wall-clock |
|---|---|---|
| Phase 1 — Cluster | 5-node kind cluster (1 control-plane + 4 workers), local-path StorageClass, host-side port mappings 127.0.0.1:{80,443,22} → {30080,30443,30022} |
~2 minutes |
| Phase 2 — Stack | Gateway API CRDs, self-signed wildcard CA + certs (*.local.example.net infra tier + *.apps.local.example.net apps tier), bootstrap-OpenBao, GitLab CE 19.x with bundled OpenBao subchart, in-cluster registry, GitLab Runner (k8s executor), chart-bundled Postgres/Redis/MinIO |
~10–15 minutes (mostly GitLab's first boot) |
| Phase 3 — App | blueprint-apps GitLab group + 4 projects (shared-code, guestbook, redis, redis-slave), per-project .gitlab-ci.yml rendered from apps/shared-code/templates/, smoke pipelines green |
~3 minutes |
End state: https://gitlab.local.example.net for the GitLab UI, https://guestbook.apps.local.example.net for the demo workload — both behind the same Envoy Gateway data plane, both served from one NodePort Service (30443) on the kind control-plane.
Designed to be run by an AI coding agent¶
The repo ships four Agent Skills that walk an agent (GitHub Copilot, Cursor, Claude Code, Codex — anything that follows the agentskills.io standard) through each phase end-to-end, plus the per-app publishing flow:
.agents/skills/provision-phase-1/SKILL.md— cluster bring-up + Headlamp.agents/skills/provision-phase-2/SKILL.md— Gateway API + OpenBao + GitLab + Runner + wildcard certs.agents/skills/provision-phase-3/SKILL.md—blueprint-appsgroup + 4 projects + per-project CI.agents/skills/provision-new-3p-app/SKILL.md— add a 3rd-party / in-tree-chart app (headlamp, kyverno, anything vendored from an upstream helm chart). Sibling ofprovision-phase-3; reuses its helpers via the newblueprint-publish-appCLI so each app can be (re)published on demand without booting the full 6-step Phase 3 pipeline.
Each skill has the same shape: Pre-flight → Install → Smoke tests → Iteration loop. The smoke tests are the contract — the skill doesn't declare a phase "done" until they pass.
A typical agent session looks like:
Open
k8s-cicd-gitlab/in your agent. The skills auto-load as background context. Then prompt:Run
provision-phase-1end-to-end and report when the 5 nodes are Ready. Then runprovision-phase-2and report when GitLab is reachable athttps://gitlab.local.example.net. Then runprovision-phase-3and report when the four GitLab projects exist and the smoke pipelines are green. Then runprovision-new-3p-appfor headlamp. Don't run anything that needssudo— print the command and ask me to run it. Follow each skill's Smoke tests section before declaring green.
If your agent doesn't auto-discover skills, paste the four SKILL.md files into the first message — they're self-contained.
How to use this site¶
The site mirrors docs/ in the repo and is the rendered MkDocs Material view. The recommended reading order is:
- Prerequisites — what's installed on the host (kind, kubectl, helm, tofu, uv, docker/podman, ~10 GB RAM).
- Phase 1 — cluster bring-up via OpenTofu, with the node-shapes + port-mappings + storage contract.
- Phase 2 — bootstrap package architecture, the install pipeline (12+ steps, all idempotent), secrets inventory.
- Phase 3 — GitLab-side provisioning, the per-project CI template, the apps-tier routing architecture (
*.apps.<domain>). - Accessing apps — the
*.apps.<domain>listener on the chart-managedgitlab-gwGateway; how the apps-wildcard cert + cross-namespace redis wiring work. - Provisioning 3rd-party apps — how to add an upstream-helm-chart app (headlamp, kyverno, anything vendored) as a GitOps-managed GitLab project. Covers
blueprint-new-app(scaffold the source-of-truth files) +blueprint-publish-app(sync to GitLab, render CI, set variables, commit + push, trigger pipeline). - Secrets — where each secret comes from, who owns it, how it survives a
tofu destroy. - Smart docs / C4 architecture — system context, container, component, and 5 deep dives on the bootstrap package, the Phase-2 pipeline, the Phase-3 pipeline, the OpenTofu IaC layer, and the sample apps.
If anything in this site disagrees with ../README.md or ../AGENTS.md, the source wins — the site is generated, the source is canonical.
What you get at the end¶
Cluster infrastructure — 5-node kind cluster + local-path StorageClass¶
flowchart LR
CP[Control-plane] --> N1[Worker 1]
CP --> N2[Worker 2]
CP --> N3[Worker 3]
CP --> N4[Runner worker]
SC[local-path SC]
Application pods (Phase 2) — CloudNativePG, Redis, MinIO, bootstrap-OpenBao¶
flowchart LR
PG[CloudNativePG] --> R[Redis]
R --> M[MinIO]
M --> OB[OpenBao]
GitLab stack — Envoy Gateway + GitLab CE 19.x + chart-bundled OpenBao + Runner + 4 projects + registry¶
flowchart LR
EG[Envoy Gateway] --> GL[GitLab CE]
GL --> CBO[Chart-bundled OpenBao]
GL --> R[Runner]
GL --> P[4 projects<br/>blueprint-apps/*]
GL --> Reg[In-cluster registry]
Sample workload — guestbook Pod reachable as https://guestbook.apps.local.example.net¶
Apps don't share a listener with the GitLab-infra FQDNs — they ride a separate chart-managed apps-https listener on the same Gateway (gitlab-gw), backed by its own wildcard cert (*.apps.<domain>). The Redis Services live in different namespaces (redis-demo, redis-slave-demo); the chart's env-var-driven REDIS_MASTER_HOST / REDIS_REPLICA_HOST config wires the cross-namespace connection declaratively. See Accessing apps for the full two-listener / two-cert / cross-ns design.
flowchart LR
Reg[Registry<br/>guestbook image] --> Pod[guestbook Pod]
Pod -->|apps-https listener<br/>+ HTTPRoute| URL[https://guestbook.apps.local.example.net]
Pod -->|REDIS_MASTER_HOST env| RM[redis-master.redis-demo]
Pod -->|REDIS_REPLICA_HOST env| RR[redis-replica.redis-slave-demo]
Out-of-cluster — browser hits two wildcard tiers; git push triggers Runner pipelines¶
flowchart LR
B[Browser] -->|HTTPS infra| Infra[*.<br/>local.example.net]
B -->|HTTPS apps| Apps[*.<br/>apps.local.example.net]
Push[git push] -->|webhook| R[Runner]
R -->|helm lint → kaniko → helm upgrade| Deploy[Deploy]
What this site contains¶
This site is the rendered MkDocs view of the docs/ directory in this repo. It contains:
- Runbooks —
Prerequisites,Phase 1,Phase 2,Phase 3,Accessing apps,Secrets. These are the per-phase how-tos for both humans and AI agents. - Smart docs (C4 architecture) —
Project Overview,Architecture Overview,Workflow Overview, plus fiveDeep divescovering the bootstrap package, the Phase-2 pipeline, the Phase-3 pipeline, the OpenTofu IaC layer, and the sample apps.
The canonical sources live in this repo:
README.md— top-level quick start, post-install cheat-sheet, iteration loop.AGENTS.md— hard rules + layout map for AI agents and humans..agents/skills/provision-phase-{1,2,3}/SKILL.md— the per-phase iteration loop runbooks.
If anything in this site disagrees with ../README.md or ../AGENTS.md, the source wins — the site is generated, the source is canonical.