Skip to content

RoFz/gitops-kind-argocd

Repository files navigation

gitops-kind-argocd

Reference implementation for running a local Kubernetes cluster with kind, managed via ArgoCD using the App of Apps pattern with sync waves, cert-manager TLS, and Traefik ingress.

Overview

This repository demonstrates how to manage a local kind cluster entirely through GitOps using ArgoCD. The structure follows the App of Apps pattern where a single root Application manages all child applications, each of which may manage its own set of child applications and Kubernetes resources.

Application hierarchy

cluster-my-cluster          (root App of Apps, apply this once manually)
├── infra-cert-manager       (group parent)
│   ├── infra-cert-manager-helm       (Helm chart, wave 1)
│   └── infra-cert-manager-resources  (ClusterIssuer, wave 2)
├── infra-traefik            (group parent)
│   ├── infra-traefik-helm            (Helm chart, wave 1)
│   └── infra-traefik-resources       (Middleware, Certificates, IngressRoutes, wave 2)
├── infra-argocd             (group parent)
│   └── infra-argocd-resources        (ConfigMap, Certificate, IngressRoutes)
├── infra-kubernetes-dashboard (group parent)
│   ├── infra-kubernetes-dashboard-helm
│   └── infra-kubernetes-dashboard-resources
├── app-podinfo              (group parent)
│   ├── app-podinfo-helm
│   └── app-podinfo-resources
└── app-whoami               (group parent)
    └── app-whoami-resources

Key patterns

  • App of Apps: each application group has its own app.yaml (parent) that discovers helm.yaml and resources.yaml within its folder
  • Sync waves: Helm charts deploy at wave 1; dependent resources (ClusterIssuers, IngressRoutes, Certificates) deploy at wave 2
  • Retry policy: wave 2 apps retry automatically until dependencies are ready (e.g., cert-manager CRDs exist before ClusterIssuer is applied)
  • Cascade finalizer: deleting a parent app cascades to all child apps automatically
  • IngressRoute CRDs: Traefik's native CRDs are used for routing instead of standard Ingress resources, with cross-namespace Middleware references
  • TLS everywhere: all services use cert-manager-issued TLS certificates from an internal CA

Prerequisites

  • Docker
  • kind
  • kubectl
  • ArgoCD CLI (optional)
  • An internal CA (root or intermediate) with the certificate and private key available locally

Getting started

1. Create the kind cluster

kind create cluster --name my-cluster --config configs/kind-config-my-cluster.yaml

2. Install ArgoCD

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

3. Create the internal CA secret

Before ArgoCD syncs cert-manager resources, create the CA secret manually:

kubectl create secret tls internal-ca \
  --cert=path/to/ca.crt \
  --key=path/to/ca.key \
  --namespace cert-manager

The cert-manager namespace will be created by ArgoCD in a later step, so you may need to create it first: kubectl create namespace cert-manager

4. Update repo URLs

Replace all occurrences of <your-github-username> in the YAML files with your actual GitHub username:

find argocd/ -name "*.yaml" -exec sed -i '' 's/<your-github-username>/yourusername/g' {} +

5. Bootstrap ArgoCD

Apply the root Application once. ArgoCD manages everything else from this point forward:

kubectl apply -f argocd/kind/my-cluster/app.yaml

6. Access ArgoCD UI

# Get the initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

# Port-forward until the IngressRoute is active
kubectl port-forward svc/argocd-server -n argocd 8080:443

Once infra-argocd-resources syncs, ArgoCD will be available at https://argocd.k8s.example.internal (after adding the entry to /etc/hosts).

7. Add /etc/hosts entries

127.0.0.1   argocd.k8s.example.internal
127.0.0.1   traefik.k8s.example.internal
127.0.0.1   dashboard.k8s.example.internal
127.0.0.1   podinfo.k8s.example.internal
127.0.0.1   whoami.k8s.example.internal

Repository structure

gitops-kind-argocd/
├── argocd/
│   └── kind/
│       └── my-cluster/
│           ├── argocd/
│           │   ├── resources/
│           │   │   ├── argocd-params.yaml
│           │   │   ├── certificate.yaml
│           │   │   └── ingressroute.yaml
│           │   ├── app.yaml
│           │   └── resources.yaml
│           ├── cert-manager/
│           │   ├── resources/
│           │   │   └── clusterissuer.yaml
│           │   ├── app.yaml
│           │   ├── helm.yaml
│           │   └── resources.yaml
│           ├── kubernetes-dashboard/
│           │   ├── resources/
│           │   │   ├── certificate.yaml
│           │   │   ├── ingressroute.yaml
│           │   │   └── serversTransport.yaml
│           │   ├── app.yaml
│           │   ├── helm.yaml
│           │   └── resources.yaml
│           ├── podinfo/
│           │   ├── resources/
│           │   │   ├── certificate.yaml
│           │   │   └── ingressroute.yaml
│           │   ├── app.yaml
│           │   ├── helm.yaml
│           │   └── resources.yaml
│           ├── traefik/
│           │   ├── resources/
│           │   │   ├── certificate-dashboard.yaml
│           │   │   ├── ingressroute-dashboard.yaml
│           │   │   └── middleware-https-redirect.yaml
│           │   ├── app.yaml
│           │   ├── helm.yaml
│           │   └── resources.yaml
│           ├── whoami/
│           │   ├── resources/
│           │   │   ├── certificate.yaml
│           │   │   ├── deployment.yaml
│           │   │   ├── ingressroute.yaml
│           │   │   └── service.yaml
│           │   ├── app.yaml
│           │   └── resources.yaml
│           └── app.yaml
└── configs/
    └── kind-config-my-cluster.yaml

Adding a new application

  1. Create a folder under argocd/kind/my-cluster/<app-name>/
  2. Add app.yaml (group parent), helm.yaml (if Helm-based), resources.yaml, and a resources/ folder with manifests
  3. The root cluster-my-cluster app auto-discovers the new app.yaml on next sync
  4. Add the hostname to /etc/hosts

Adapting for your environment

Placeholder Replace with
<your-github-username> Your GitHub username
k8s.example.internal Your internal domain
my-cluster Your cluster name
internal-ca Your ClusterIssuer name (if different)

Security notes

  • The internal-ca secret is created manually and never committed to this repository
  • No secrets, private keys, or tokens are stored in this repository
  • The resources-finalizer.argocd.argoproj.io finalizer ensures cascading deletion of child apps
  • server.insecure: "true" in argocd-params.yaml disables ArgoCD's own TLS (Traefik handles it); do not use this in production without a proper ingress setup

About

Reference implementation for running a local Kubernetes cluster with kind, managed via ArgoCD using the App of Apps pattern with sync waves, cert-manager TLS, and Traefik ingress.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors