From ac3a4639f6e952032021f9a0fd7fd1cec59019a8 Mon Sep 17 00:00:00 2001 From: Richard Stephens Date: Sun, 22 Feb 2026 15:55:11 +0000 Subject: [PATCH] Add Flux GitOps bootstrap for minikube Set up a complete GitOps pipeline using Flux CD to manage a minikube cluster. Includes bootstrap script, Traefik ingress controller via HelmRelease, and a hello-world nginx deployment. Co-Authored-By: Claude Opus 4.6 --- apps/kustomization.yaml | 4 ++ apps/nginx-hello/deployment.yaml | 30 ++++++++++ apps/nginx-hello/kustomization.yaml | 6 ++ apps/nginx-hello/namespace.yaml | 4 ++ apps/nginx-hello/service.yaml | 16 ++++++ bootstrap.sh | 57 +++++++++++++++++++ clusters/minikube/apps.yaml | 17 ++++++ clusters/minikube/flux-system/gotk-sync.yaml | 24 ++++++++ .../minikube/flux-system/kustomization.yaml | 4 ++ clusters/minikube/infrastructure.yaml | 15 +++++ infrastructure/kustomization.yaml | 4 ++ infrastructure/traefik/helmrelease.yaml | 33 +++++++++++ infrastructure/traefik/helmrepository.yaml | 9 +++ infrastructure/traefik/kustomization.yaml | 6 ++ infrastructure/traefik/namespace.yaml | 4 ++ 15 files changed, 233 insertions(+) create mode 100644 apps/kustomization.yaml create mode 100644 apps/nginx-hello/deployment.yaml create mode 100644 apps/nginx-hello/kustomization.yaml create mode 100644 apps/nginx-hello/namespace.yaml create mode 100644 apps/nginx-hello/service.yaml create mode 100755 bootstrap.sh create mode 100644 clusters/minikube/apps.yaml create mode 100644 clusters/minikube/flux-system/gotk-sync.yaml create mode 100644 clusters/minikube/flux-system/kustomization.yaml create mode 100644 clusters/minikube/infrastructure.yaml create mode 100644 infrastructure/kustomization.yaml create mode 100644 infrastructure/traefik/helmrelease.yaml create mode 100644 infrastructure/traefik/helmrepository.yaml create mode 100644 infrastructure/traefik/kustomization.yaml create mode 100644 infrastructure/traefik/namespace.yaml diff --git a/apps/kustomization.yaml b/apps/kustomization.yaml new file mode 100644 index 0000000..291857e --- /dev/null +++ b/apps/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - nginx-hello diff --git a/apps/nginx-hello/deployment.yaml b/apps/nginx-hello/deployment.yaml new file mode 100644 index 0000000..cc8b881 --- /dev/null +++ b/apps/nginx-hello/deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-hello + namespace: nginx-hello + labels: + app: nginx-hello +spec: + replicas: 2 + selector: + matchLabels: + app: nginx-hello + template: + metadata: + labels: + app: nginx-hello + spec: + containers: + - name: nginx + image: nginx:1.27-alpine + ports: + - containerPort: 80 + name: http + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi diff --git a/apps/nginx-hello/kustomization.yaml b/apps/nginx-hello/kustomization.yaml new file mode 100644 index 0000000..4e78622 --- /dev/null +++ b/apps/nginx-hello/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - deployment.yaml + - service.yaml diff --git a/apps/nginx-hello/namespace.yaml b/apps/nginx-hello/namespace.yaml new file mode 100644 index 0000000..d07271c --- /dev/null +++ b/apps/nginx-hello/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nginx-hello diff --git a/apps/nginx-hello/service.yaml b/apps/nginx-hello/service.yaml new file mode 100644 index 0000000..3a45dbf --- /dev/null +++ b/apps/nginx-hello/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: nginx-hello + namespace: nginx-hello + labels: + app: nginx-hello +spec: + type: ClusterIP + selector: + app: nginx-hello + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..f1292b7 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +echo "=== Step 1: Ensuring minikube is running ===" +if minikube status --format='{{.Host}}' 2>/dev/null | grep -q "Running"; then + echo "minikube is already running." +else + echo "Starting minikube..." + minikube start --driver=docker +fi + +echo "" +echo "=== Step 2: Checking Flux prerequisites ===" +flux check --pre + +echo "" +echo "=== Step 3: Installing Flux controllers ===" +flux install + +echo "" +echo "=== Step 4: Applying GitRepository and root Kustomization ===" +kubectl apply -f "${SCRIPT_DIR}/clusters/minikube/flux-system/gotk-sync.yaml" + +echo "" +echo "=== Step 5: Triggering reconciliation and waiting ===" +sleep 5 +flux reconcile source git flux-system +sleep 5 +flux reconcile kustomization flux-system + +echo "Waiting for infrastructure kustomization to become ready..." +kubectl wait --for=condition=Ready kustomization/infrastructure \ + -n flux-system --timeout=300s || true + +echo "Waiting for apps kustomization to become ready..." +kubectl wait --for=condition=Ready kustomization/apps \ + -n flux-system --timeout=300s || true + +echo "" +echo "=== Step 6: Final status ===" +echo "--- Flux resources ---" +flux get all + +echo "" +echo "--- All pods ---" +kubectl get pods -A + +echo "" +echo "--- Services ---" +kubectl get svc -A + +echo "" +echo "Bootstrap complete." +echo "To access nginx-hello: kubectl port-forward -n nginx-hello svc/nginx-hello 8080:80" +echo "To access Traefik dashboard: minikube service traefik-dashboard -n traefik --url (if enabled)" diff --git a/clusters/minikube/apps.yaml b/clusters/minikube/apps.yaml new file mode 100644 index 0000000..2514fdd --- /dev/null +++ b/clusters/minikube/apps.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: apps + namespace: flux-system +spec: + interval: 10m0s + path: ./apps + prune: true + sourceRef: + kind: GitRepository + name: flux-system + dependsOn: + - name: infrastructure + wait: true + timeout: 5m0s diff --git a/clusters/minikube/flux-system/gotk-sync.yaml b/clusters/minikube/flux-system/gotk-sync.yaml new file mode 100644 index 0000000..9c4793f --- /dev/null +++ b/clusters/minikube/flux-system/gotk-sync.yaml @@ -0,0 +1,24 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: flux-system + namespace: flux-system +spec: + interval: 1m0s + ref: + branch: main + url: https://gitea-1.rustation.com/richards/iaac-new-dev.git +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: flux-system + namespace: flux-system +spec: + interval: 10m0s + path: ./clusters/minikube + prune: true + sourceRef: + kind: GitRepository + name: flux-system diff --git a/clusters/minikube/flux-system/kustomization.yaml b/clusters/minikube/flux-system/kustomization.yaml new file mode 100644 index 0000000..a0e1816 --- /dev/null +++ b/clusters/minikube/flux-system/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - gotk-sync.yaml diff --git a/clusters/minikube/infrastructure.yaml b/clusters/minikube/infrastructure.yaml new file mode 100644 index 0000000..cd09c0f --- /dev/null +++ b/clusters/minikube/infrastructure.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: infrastructure + namespace: flux-system +spec: + interval: 10m0s + path: ./infrastructure + prune: true + sourceRef: + kind: GitRepository + name: flux-system + wait: true + timeout: 5m0s diff --git a/infrastructure/kustomization.yaml b/infrastructure/kustomization.yaml new file mode 100644 index 0000000..8f492af --- /dev/null +++ b/infrastructure/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - traefik diff --git a/infrastructure/traefik/helmrelease.yaml b/infrastructure/traefik/helmrelease.yaml new file mode 100644 index 0000000..607f27b --- /dev/null +++ b/infrastructure/traefik/helmrelease.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: traefik + namespace: flux-system +spec: + interval: 10m0s + targetNamespace: traefik + storageNamespace: traefik + chart: + spec: + chart: traefik + version: ">=34.0.0 <35.0.0" + sourceRef: + kind: HelmRepository + name: traefik + reconcileStrategy: ChartVersion + install: + createNamespace: true + remediation: + retries: 3 + upgrade: + remediation: + retries: 3 + values: + service: + type: NodePort + ports: + web: + nodePort: 30080 + websecure: + nodePort: 30443 diff --git a/infrastructure/traefik/helmrepository.yaml b/infrastructure/traefik/helmrepository.yaml new file mode 100644 index 0000000..6deae5b --- /dev/null +++ b/infrastructure/traefik/helmrepository.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + name: traefik + namespace: flux-system +spec: + interval: 1h0m0s + url: https://traefik.github.io/charts diff --git a/infrastructure/traefik/kustomization.yaml b/infrastructure/traefik/kustomization.yaml new file mode 100644 index 0000000..b4a3d7c --- /dev/null +++ b/infrastructure/traefik/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - helmrepository.yaml + - helmrelease.yaml diff --git a/infrastructure/traefik/namespace.yaml b/infrastructure/traefik/namespace.yaml new file mode 100644 index 0000000..c088a91 --- /dev/null +++ b/infrastructure/traefik/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: traefik