Después de años recomendando arquitecturas cloud a clientes, llegué a una conclusión simple: no se puede opinar con autoridad sobre Kubernetes, redes o resiliencia si nunca se ha operado nada fuera de una consola administrada. Mi homelab nació de esa necesidad — un lugar para romper cosas sin que le cueste dinero a nadie más que a mí.

El hardware

Nada exótico. El setup actual corre sobre:

  • Un mini-PC con 32 GB de RAM y un procesador de 8 núcleos como nodo principal.
  • Dos Raspberry Pi 4 como nodos worker adicionales, útiles para probar arquitecturas ARM.
  • Un NAS con RAID 1 para almacenamiento persistente y backups.
  • Un switch gestionado con VLANs para separar tráfico de gestión del tráfico de las cargas.

La decisión deliberada fue no sobre-invertir en hardware. El objetivo no es tener un datacenter personal, es tener un entorno realista donde los problemas de red, almacenamiento y orquestación se comporten como en producción, aunque a escala mínima.

Base: Linux, sin abstracciones intermedias

El nodo principal corre Debian 12 sin ninguna capa de virtualización de escritorio. Todo se administra por SSH y systemd. Esta decisión es intencional: quiero enfrentar los mismos problemas que enfrentaría administrando un servidor en AWS o en un datacenter propio — gestión de usuarios, permisos, actualizaciones, firewalls con nftables, y observabilidad con herramientas estándar como journalctl y node_exporter.

# Ejemplo real de mi configuración de nftables para el nodo principal
table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;
    ct state established,related accept
    iif lo accept
    tcp dport 22 ip saddr 192.168.10.0/24 accept
    tcp dport { 80, 443 } accept
    ip protocol icmp accept
  }
}

Docker primero, Kubernetes cuando el problema lo justifica

Un error común al armar un homelab es saltar directo a Kubernetes porque "es lo que se usa en la industria". Yo empiezo casi todo en Docker Compose. Si el servicio no necesita escalado horizontal, failover automático o gestión declarativa de múltiples réplicas, Compose es más simple de operar y depurar:

# docker-compose.yml — stack de observabilidad local
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - '9090:9090'

  grafana:
    image: grafana/grafana:latest
    depends_on:
      - prometheus
    ports:
      - '3000:3000'
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  grafana-data:

Cuando un caso de uso sí justifica orquestación real —por ejemplo, simular el failover de un servicio ante la caída de un nodo— migro esa carga específica a un clúster k3s, la distribución liviana de Kubernetes que corre cómodamente en los Raspberry Pi:

curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
kubectl get nodes -o wide

Qué he aprendido operando esto

Lo más valioso no ha sido ninguna tecnología puntual, sino la fricción operativa que solo aparece cuando uno es responsable del ciclo completo: actualizar un kernel y tener que resolver un driver de red roto, perder un disco del NAS y ejecutar un restore real desde backup, o depurar por qué un pod queda en CrashLoopBackOff sin ningún dashboard administrado que lo explique por ti.

Ese tipo de experiencia directa es la que después se traduce en decisiones arquitectónicas más honestas en el trabajo: cuándo vale la pena la complejidad de Kubernetes, cuándo un simple servicio en ECS es suficiente, y por qué la observabilidad no es un extra, es lo primero que hay que instalar.