La arquitectura de la mininas, capa a capa
En el post anterior conté la historia de montar la mininas. Aquí desgrano la arquitectura: qué atraviesa exactamente una petición desde tu navegador hasta el fichero en disco, y por qué cada pieza está donde está.
El mapa completo#
[ navegador / app ]
│ HTTPS :443
▼
┌─────────────────────────────┐
│ Cloudflare (proxy + SSL) │ nube naranja, SSL Full (strict)
│ nextcloud/fotos/… (proxied) │
│ └─CNAME→ fl4t ─CNAME→ duckdns (DNS-only)
└─────────────┬───────────────┘
│ origin pull HTTPS :443
▼
[ IP pública dinámica ] 85.85.x.x (duckdns la mantiene al día)
│
▼
┌─────────────────────────────┐
│ Router doméstico — PAT │ 443→30443, 80→30080
└─────────────┬───────────────┘
│ NodePort
▼
┌──────────────────────────── mininas (k3s, 1 nodo) ───────────────────────┐
│ Istio ingress gateway (Envoy) ← NodePort 30080/30443 │
│ │ match por Host (SNI) │
│ ▼ │
│ Gateway + VirtualService (uno por app) │
│ ▼ │
│ Service → Pod de la app ── conecta a ──► su BD (Postgres/MariaDB) │
│ │
│ cert-manager ── emite TLS (Let's Encrypt DNS-01) ──► secret del Gateway │
└──────────────┬─────────────────────────────────┬──────────────────────────┘
│ ficheros pesados │ datos de BD
▼ ▼
[ HDD btrfs /mnt/data ] [ SSD ext4 /mnt/pg_data · /mnt/mysql_data ]
Capa por capa#
1. Cloudflare — el borde#
Los dominios (nextcloud., fotos., receptes., …) son registros proxied
(nube naranja). Cloudflare termina el TLS del cliente, aporta caché/protección y
vuelve a cifrar hacia el origen en modo Full (strict) (funciona porque el
origen presenta un certificado Let’s Encrypt válido).
⚠️ Cloudflare solo proxya HTTP/HTTPS. Para SSH u otros puertos hay que apuntar a un registro DNS-only (gris) o a la IP directa.
2. La cadena DNS#
nextcloud.cortinasval.cat ─CNAME→ fl4t.cortinasval.cat ─CNAME→ c0rt1n4s.duckdns.org
(proxied, naranja) (proxied) (DNS-only, gris → IP real)
fl4t es DNS-only y resuelve a la IP pública real, que un cron de duckdns
mantiene actualizada. Así, si el ISP cambia la IP, el dominio sigue apuntando bien.
3. Router — PAT#
El router traduce los puertos públicos a la mininas:
443 → 192.168.1.201:30443 y 80 → :30080. Esos son los NodePort que expone
Istio. (Detalle vivido: esa .201 debe ser una IP persistente del host, o tras
un reinicio el PAT se queda sin destino.)
4. Istio ingress — un Gateway por host#
Istio (Envoy) recibe en el NodePort y enruta por Host/SNI. El patrón por app es:
| Recurso | Rol |
|---|---|
Gateway | Escucha 80/443 para un host, con el credentialName del cert TLS |
VirtualService | Enruta ese host → el Service de la app |
Service | Balancea al Pod |
🔑 Un solo Gateway por host/puerto. Dos Gateways con el mismo host provocan 404 intermitentes (Istio no sabe con cuál quedarse).
5. cert-manager — TLS automático#
Un ClusterIssuer (Let’s Encrypt) resuelve el reto DNS-01 vía la API de
Cloudflare y genera un Certificate con todos los subdominios como SAN. El secret
resultante lo consume el Gateway. Renovación automática, cero intervención.
6. Almacenamiento — el reparto que importa#
Cada aplicación tiene su propia base de datos en su namespace, y separamos por tipo de dato:
| Dato | Disco | Por qué |
|---|---|---|
| Bases de datos (Postgres/MariaDB) | SSD ext4 (/mnt/pg_data, /mnt/mysql_data) | IOPS: consultas y búsquedas vuelan |
| Ficheros pesados (fotos, adjuntos, media) | HDD btrfs (/mnt/data) | Volumen grande, no necesita IOPS |
Los volúmenes son PersistentVolume de tipo hostPath con política Retain:
los datos viven en rutas concretas del disco y sobreviven a que se borre un pod
o incluso el PVC.
El principio que lo sostiene todo#
Declarativo o no existe. Un reinicio recrea el cluster entero desde el estado
de k3s… pero solo lo que está descrito de forma persistente: manifiestos aplicados,
PVs Retain, discos en fstab, IPs en netplan. Cualquier cosa “añadida a mano”
desaparece. Por eso el siguiente paso natural es GitOps con FluxCD: que todo
esto viva en un repositorio y el cluster se reconcilie solo.
Este blog, por cierto, es un sitio estático servido por un contenedor de ~5 MB detrás de este mismo Istio. La coherencia también es arquitectura.