Infraestructura GitOps para Homelab
“Dos Nodos, Un Repo, Cero kubectl Manual”
Los entornos de pruebas en la nube son demasiado abstractos. Haces clic en un boton y aparece un cluster Kubernetes. Nunca sientes lo que pasa cuando el CNI bloquea silenciosamente la red y tienes que depurarlo desde una sesion SSH muerta. Monte este homelab para sentirlo.
El hardware
Dos nodos en una LAN domestica:
- Raspberry Pi 4B con 8GB RAM: ejecuta el plano de control de K3s. ARM64. Bajo consumo, completamente silencioso, en una estanteria.
- Caja AMD64 antigua con 4GB RAM: ejecuta todas las cargas de trabajo reales. Prometheus, Grafana, Loki, ArgoCD, Home Assistant, todo.
Todo esta definido en este repositorio. Si el cluster se quema, puedo reconstruirlo desde git clone y make.
El stack
K3s en lugar de Kubernetes vanilla. Realmente funciona en una Pi sin consumir toda la RAM. Binario unico, etcd embebido, incluye todo lo necesario.
Cilium 1.18.9 como CNI. Redes basadas en eBPF sin kube-proxy. Hubble proporciona observabilidad a nivel de red. Fijado a la version 1.18 porque la 1.19.x bloquea silenciosamente la red en ARM64. Esa fue una semana divertida de depuracion.
ArgoCD para GitOps. El patron app-of-apps despliega todo: una aplicacion raiz despliega el cluster entero. Nunca ejecuto kubectl apply manualmente.
MetalLB asigna IPs reales a los servicios en la LAN. Sin NodePorts, sin reenvio de puertos. Los servicios son accesibles en sus direcciones reales.
Traefik gestiona el trafico de entrada. Sirve Grafana, la interfaz de ArgoCD y Home Assistant en HTTPS con certificados de cert-manager.
Prometheus, Grafana, Loki, OpenTelemetry para el stack de observabilidad. Metricas, logs y trazas alimentando dashboards. Loki conserva 28 dias de todo.
Home Assistant ejecutandose como StatefulSet con un PVC de 10Gi para domotica.
Cosas que aprendi por las malas
Cilium 1.19.x esta roto en ARM64. Muerte silenciosa de la red del host. El demonio SSH sigue funcionando, asi que la maquina parece viva, pero todas las conexiones TCP expiran. Sin errores en ningun log. Tuve que conectar fisicamente un teclado y monitor para averiguar que estaba pasando. Fijado a 1.18.9 hasta que upstream lo solucione.
No ejecutes pods de aplicacion en el plano de control con Cilium. La ClusterIP del servidor API se vuelve inaccesible desde los pods en el mismo nodo. Simplemente mantén el plano de control con taint y deja que sea solo plano de control.
4GB de RAM es justo. Con Prometheus, Loki, Grafana, ArgoCD y Home Assistant compitiendo por memoria en el nodo worker, tuve que ajustar agresivamente. Las caches de memcached de Loki pasaron de 10GB a 128MB. Traefik paso de 256MB a 384MB. Funciona, pero apenas. La proxima mejora es mas RAM.
Los diffs de Helm en ArgoCD no manejan datos ConfigMap multilinea. Helm los renderiza como cadenas entrecomilladas. Kubernetes los almacena como escalares de bloque. ArgoCD los ve como recursos completamente diferentes y marca la aplicacion como desincronizada para siempre. Solucionado con ignoreDifferences en el manifiesto de la aplicacion.
kube-bench en K3s muestra falsos positivos. La herramienta fue escrita para rutas de kubeadm. K3s pone todo bajo /var/lib/rancher/k3s/. Escribi un script de filtrado para suprimir los hallazgos irrelevantes.