Arquitectura
Homelab de seis equipos heterogéneos en casa: x86 reciclados, mini-PCs y una Raspberry Pi. Juntos forman un clúster k3s con el control-plane en alta disponibilidad. Sirve de laboratorio de DevOps, observabilidad y seguridad, y aloja algunos servicios de uso diario (DNS con Pi-hole, n8n, Jira y Confluence).
Vista general
flowchart TB
internet((Internet)) --> cf[Cloudflare<br/>*.example.com]
cf -- túnel --> cfd[cloudflared<br/>master-3]
lan((LAN 192.0.2.0/24)) --> vip
lan --> lb
subgraph cp[Control-plane HA · etcd 3 miembros]
direction LR
master-1[master-1<br/>.112 · MASTER VIP]
master-2[master-2<br/>.139]
g2[master-3<br/>.129]
end
vip[VIP 192.0.2.250:6443<br/>keepalived + haproxy] --> cp
subgraph wk[Workers]
direction LR
sz[worker-2 .164]
nuc[worker-1 .128]
worker-3[worker-3 .197]
end
cp --- wk
cfd --> traefik
lb[MetalLB L2<br/>192.0.2.240-245] --> traefik[Traefik .240<br/>Ingress]
lb --> pihole[Pi-hole DNS .241]
traefik --> apps[Jira · Confluence · n8n ⏸]
Capas
| Capa | Tecnología | Detalle |
|---|---|---|
| Sistema | Ubuntu 26.04 (Debian 13 en worker-3) | nodes/README.md |
| Distribución Kubernetes | k3s v1.34.6 | Embebe containerd, flannel, CoreDNS, Traefik, metrics-server y local-path |
| Control-plane | 3 masters con etcd embebido | Tolera la caída de un master |
| Endpoint de la API | VIP 192.0.2.250 con keepalived (VRRP) y haproxy (TCP) |
red.md |
| Red de pods | flannel VXLAN (por defecto en k3s) | --flannel-iface fijado por nodo |
LoadBalancer |
MetalLB en modo L2, pool 192.0.2.240-245 |
ServiceLB/Klipper desactivado |
| Ingress | Traefik (el de k3s) en 192.0.2.240 |
|
| Publicación a Internet | Cloudflare Tunnel (cloudflared en master-3) |
Sin puertos abiertos en el router. Desde el 2026-11-01 sin rutas: no hay nada publicado (se vuelve a publicar con Cloudflare Access delante) |
| Almacenamiento | Longhorn (replicado) y local-path (disco del nodo) | almacenamiento.md |
| GitOps | Argo CD contra el repo example-org/GitOps |
4 aplicaciones (filebeat-routing-job, jenkins-lab, vector-kafka-elastic y homepage); el resto se instala con Helm a mano (R3) |
| Observabilidad | kube-prometheus-stack, ECK (Elasticsearch y Kibana), Kafka, Flink y Vector | aplicaciones.md |
| Seguridad | Kyverno, Falco, Trivy Operator, Policy Reporter | seguridad.md |
| Copias | Velero (solo objetos) hacia MinIO dentro del clúster | backups.md ⚠️ |
Decisiones de diseño
- k3s en lugar de kubeadm: un solo binario, consume poco y encaja con hardware modesto y mezcla de arquitecturas (amd64 y arm64).
- etcd embebido con 3 masters: permite hacer drain y reiniciar un master sin perder la API. Se migró desde SQLite el 2026-07-03.
- La VIP en una interfaz
dummy0con/32: si la VIP va como IP secundaria de la interfaz real, flannel la elige como IP pública del nodo y rompe la red overlay. Con/24en lugar de/32se secuestra la ruta de toda la subred. Las dos cosas pasaron; ver incidentes.md. - MetalLB en lugar de ServiceLB: IPs estables y dedicadas por servicio (Pi-hole necesita una IP fija para DNS).
- Cloudflare Tunnel: publica servicios sin abrir puertos ni exponer la IP de casa.
- Masters que también ejecutan cargas: master-2 y master-3 no tienen taint de control-plane, para aprovechar el hardware. A cambio, una carga con mucho I/O en un master afecta a etcd. Ya ha pasado con filebeat y trivy (ver incidentes.md).
Limitaciones conocidas
- Todos los nodos van por cable desde el 2026-10-27 (master-1, el master dueño de la VIP, iba por WiFi). Si cae master-1, la VIP pasa a master-2 o master-3 (nodes/README.md).
- Los cortes periódicos entre el router y los equipos cableados (~11 s cada ~33 s) se resolvieron el 2026-10-27 cambiando el cable entre el router y el switch (incidentes).
- Varias aplicaciones con estado siguen en
local-path, atadas a un nodo concreto (almacenamiento.md). - Velero solo guarda manifiestos y los guarda dentro del propio clúster, en MinIO (backups.md).
La lista completa con prioridades está en pendientes.md.