eu-staging Environment: k3d with its own ArgoCD#
What We Built#
A staging environment on a k3d cluster, following the same isolated-ArgoCD pattern
established in eu-prod-minikube. This completes the three-tier pipeline:
| |
All environments run the same image versions: svc1:nginx:1.27, svc2:nginx:1.26.
Promotion means bumping these tags in Git - ArgoCD on each cluster picks up the change.
k3d vs Minikube#
| Minikube | k3d | |
|---|---|---|
| Runs on | VM (Docker Machine or HyperKit) | Docker containers |
| Startup time | ~60s | ~10s |
| LoadBalancer access | minikube tunnel assigns real IP | Host port mapping to 127.0.0.1 |
| Built-in Traefik | No | Yes (k3s default - we disable it) |
| Multi-node clusters | Limited | Easy (--agents N) |
| Resource overhead | Higher | Lower |
Key insight: k3d wraps k3s inside Docker containers. k3s includes Traefik by default, but since we manage Traefik via ArgoCD, we disable the built-in one at cluster creation.
Port Mapping in k3d#
Minikube uses minikube tunnel to expose LoadBalancer services on real IPs (e.g. 192.168.x.x).
k3d uses a different model: at cluster creation you bind host ports to the cluster’s internal load balancer.
| |
All staging hostnames resolve to 127.0.0.1 in /etc/hosts. The non-standard ports
(8880/8443 instead of 80/443) avoid requiring root privileges and don’t conflict with
other services on the host.
Cluster Setup#
1. Install k3d#
| |
2. Create the cluster#
| |
Flags explained:
--port "8880:80@loadbalancer"- map host port 8880 to the k3d load balancer’s port 80--port "8443:443@loadbalancer"- map host port 8443 to the k3d load balancer’s port 443--k3s-arg "--disable=traefik@server:0"- disable k3s’s built-in Traefik on the server node; ArgoCD will manage it
The kubectl context is automatically set to k3d-eu-staging.
| |
3. Install ArgoCD#
| |
4. Bootstrap#
| |
This applies the root Application, which points ArgoCD at environments/eu-staging-k3d/platform/.
ArgoCD then deploys everything in sync-wave order:
| Wave | What deploys |
|---|---|
| 0 | cert-manager |
| 1 | cert-manager-config (ClusterIssuer), reloader |
| 2 | Traefik |
| 3 | argocd-config (ingress + password + insecure mode) |
| 4 | ApplicationSet → svc1, svc2 |
5. Add hostnames to /etc/hosts#
| |
6. Access#
| Service | URL |
|---|---|
| ArgoCD UI | https://argocd.eu-staging-k3d.ravikrs.local:8443 |
| svc1 | https://svc1.eu-staging-k3d.ravikrs.local:8443 |
| svc2 | https://svc2.eu-staging-k3d.ravikrs.local:8443 |
Login: admin / admin (same bcrypt hash as eu-prod-minikube).
Environment Configuration#
| eu-dev-rancher | eu-staging-k3d | eu-prod-minikube | |
|---|---|---|---|
| Cluster | Rancher Desktop | k3d | Minikube |
| svc1 image | nginx:1.27 | nginx:1.27 | nginx:1.27 |
| svc2 image | nginx:1.26 | nginx:1.26 | nginx:1.26 |
| Replicas | 1 | 1 | 2 |
| Namespace | alpha-dev | alpha-staging | alpha-prod |
| Hostnames | *.eu-dev-rancher.ravikrs.local | *.eu-staging-k3d.ravikrs.local | *.eu-prod-minikube.ravikrs.local |
| Host ports | 80 / 443 (Rancher default) | 8880 / 8443 | minikube tunnel |
Cluster Lifecycle#
| |
Gotchas#
k3s built-in Traefik must be disabled#
If you forget --disable=traefik@server:0, k3s installs its own Traefik on port 80/443
inside the cluster. When ArgoCD then tries to install Traefik via Helm, the two instances
conflict. Always disable it at cluster creation - it cannot be cleanly disabled after the fact.
Port mapping is set at creation time#
Unlike Minikube where you run minikube tunnel on demand, k3d port mappings are baked in at
k3d cluster create. To change them you must delete and recreate the cluster.
Browser will show certificate warning#
The TLS certificate is issued by the local local-ca-issuer (self-signed). The browser
will warn on first visit. Trust the cert in Keychain (macOS) or use --insecure with curl.
/etc/hosts uses 127.0.0.1, not a cluster IP#
k3d’s load balancer listens on localhost. Unlike Minikube’s tunnel which gives you a routable
cluster IP, all k3d traffic goes through 127.0.0.1:<host-port>. This means you cannot
access staging from another machine on the same network (Minikube tunnel can allow this).