This setup creates a minimal local Kubernetes cluster optimized for CI/CD workflows with ArgoCD and GitHub Actions runners.
- Docker installed and running
- At least 4GB RAM available
- Linux or macOS (Windows WSL2 also works)
chmod +x setup-cluster.sh
./setup-cluster.sh --allThis single command sets up the Cluster, Istio, Monitoring, ArgoCD, Rollouts, and a Demo App.
./setup-cluster.shchmod +x setup-monitoring.sh
./setup-monitoring.shchmod +x setup-argocd.sh
./setup-argocd.shchmod +x setup-argo-rollouts.sh
./setup-argo-rollouts.shchmod +x setup-loki.sh
./setup-loki.sh./setup-custom-metrics.shchmod +x setup-github-runners.sh
./setup-github-runners.sh- URL: http://localhost/monitoring
- Username: admin
- Password: (shown after setup-monitoring.sh completes)
- URL: http://localhost/rollouts
- Note: No authentication (read-only view by default)
- URL: https://localhost:30080
- Username: admin
- Password: (shown after setup-argocd.sh completes)
Install the CLI:
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x argocd
sudo mv argocd /usr/local/bin/argocdLogin:
argocd login localhost:30080 --username admin --password <your-password> --insecureIn your GitHub workflow, use the labels you configured:
name: CI Pipeline
on: [push]
jobs:
build:
runs-on: [self-hosted, kind, local-cicd]
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
echo "Running on local Kind cluster!"
kubectl version- Navigate to http://localhost:30080
- Click "New App"
- Fill in your repository details
- Click "Create"
Edit sample-argocd-app.yaml with your repository details:
kubectl apply -f sample-argocd-app.yamlargocd app create my-app \
--repo https://github.com/your-org/your-repo.git \
--path k8s/manifests \
--dest-server https://kubernetes.default.svc \
--dest-namespace default \
--sync-policy automated# View all pods across namespaces
kubectl get pods -A
# Check cluster info
kubectl cluster-info --context kind-cicd-cluster
# Stop the cluster (pause - quick restart)
./shutdown-cluster.sh
# Then select option 1
# Restart a stopped cluster
./restart-cluster.sh
# Delete the cluster completely
./shutdown-cluster.sh
# Then select option 2
# Or directly: kind delete cluster --name cicd-cluster
# Recreate the cluster from scratch
./setup-cluster.sh# List applications
argocd app list
# Sync an application
argocd app sync my-app
# Get application details
argocd app get my-app
# View application logs
kubectl logs -n argocd deployment/argocd-server -f# List runners
kubectl get runners -n github-runners
# View runner logs
kubectl logs -n github-runners -l app.kubernetes.io/name=actions-runner
# Scale runners
kubectl scale runnerdeployment github-runner -n github-runners --replicas=3
# Delete runners
kubectl delete runnerdeployment github-runner -n github-runnersThis minimal setup uses approximately:
- CPU: 2 cores
- Memory: 4GB RAM
- Disk: 10GB
You can adjust resources by modifying the Kind configuration or runner deployment specs.
# Check ArgoCD pods
kubectl get pods -n argocd
# Check service
kubectl get svc -n argocd
# Restart ArgoCD server
kubectl rollout restart deployment argocd-server -n argocd# Check runner controller logs
kubectl logs -n actions-runner-system deployment/arc-actions-runner-controller
# Check runner pods
kubectl get pods -n github-runners
# Verify PAT is valid
kubectl get secret -n actions-runner-system# Check Docker is running
docker ps
# Delete and recreate
kind delete cluster --name cicd-cluster
./setup-cluster.shgraph TB
subgraph "Local Machine (Host)"
Browser([Access via Browser])
subgraph "Kind Cluster (cicd-cluster)"
Gateway[Istio Ingress Gateway]
subgraph "Monitoring Namespace"
Grafana[Grafana]
Prometheus[Prometheus]
Loki[Loki]
Promtail[Promtail]
end
subgraph "Argo Namespace"
ArgoCD[ArgoCD]
end
subgraph "Rollouts Namespace"
Rollouts[Argo Rollouts]
RolloutDash[Rollouts Dashboard]
end
subgraph "GitHub Runners"
ARC[GitHub Actions Runners]
end
subgraph "Apps"
App[Sample App]
end
end
end
%% Routing
Browser -->|80 /monitoring| Gateway
Browser -->|80 /rollouts| Gateway
Browser -->|30080| ArgoCD
Gateway --> Grafana
Gateway --> RolloutDash
Gateway --> App
%% Monitoring Flow
Prometheus -.->|Scrapes| App
Promtail -.->|Collects Logs| App
Promtail -.-> Loki
Grafana -->|Queries| Prometheus
Grafana -->|Queries| Loki
%% GitOps Flow
ArgoCD -->|Deploys| App
ArgoCD -->|Manages| Rollouts
%% External Connections
ARC <--> GitHub[(GitHub Actions)]
ArgoCD <--> GitHub
- Developer pushes code to GitHub
- GitHub Actions runner (in cluster) picks up the job
- Runner builds/tests the application
- Runner updates Kubernetes manifests in Git
- ArgoCD detects changes and syncs to cluster
- Application is deployed automatically
- Use Git for everything: Store all manifests in Git repositories
- Separate environments: Use different namespaces or clusters for dev/staging/prod
- Resource limits: Always set resource requests and limits
- Monitor runners: Keep an eye on runner pod status and logs
- Backup: Export ArgoCD configurations regularly
- Security: Use RBAC and limit runner permissions
If you want to stop the cluster but keep it for later:
./shutdown-cluster.sh
# Select option 1 (Stop cluster)This pauses the Docker containers without deleting data. To restart:
./restart-cluster.shTo completely remove everything:
# Delete the cluster
./shutdown-cluster.sh
# Select option 2 (Delete cluster)
# Or use kind directly
kind delete cluster --name cicd-cluster
# Remove downloaded binaries (optional)
sudo rm /usr/local/bin/kind
sudo rm /usr/local/bin/kubectl
sudo rm /usr/local/bin/helm
sudo rm /usr/local/bin/argocd- Set up a GitHub repository with Kubernetes manifests
- Create a GitHub Actions workflow
- Deploy your first application via ArgoCD
- Configure webhooks for automatic syncing
- Set up monitoring (Prometheus/Grafana)