Aplicaciones
Las aplicaciones se despliegan después de todos los niveles de infraestructura, cada una desde su propio Helm chart y publicada en la clase extranet.
| Charts | oci://registry-1.docker.io/reiizumi/<chart>; testing usa la variante -develop si existe |
| Versión | testing sigue cada nueva versión del chart (*); producción sigue la versión mayor actual |
| Namespace | Uno por aplicación, con su nombre |
| Manifiestos | apps/base/<aplicación>/, con nombres y variante del chart en apps/<entorno>/<aplicación>/ |
| Aplicación | Qué es | testing |
|---|---|---|
| documoon | Esta web | www.test.lb.moon.cat |
| shizen | Generador de escenarios para wargames | shizen.test.lb.moon.cat |
| fumi | Gestor de colecciones de manga, con base de datos y login | fumi.test.lb.moon.cat, fumi-api.test.lb.moon.cat |
| kirin | Gestor de economía personal, con base de datos y login | kirin.test.lb.moon.cat, kirin-api.test.lb.moon.cat |
Los nombres de testing son CNAMEs de extranet.test.lb.moon.cat en el DNS local.
Qué recibe cada aplicación
Cada carpeta de aplicación contiene un Namespace, un OCIRepository para su chart, un HelmRelease y una NetworkPolicy, y sigue las reglas del clúster:
| Regla | Cómo |
|---|---|
Ingress en extranet con certificado de cert-manager | Valores ingress del chart |
| Una réplica, sin autoescalado | replicaCount: 1 |
| Recursos | Requests según el uso medido, límite de memoria, sin límite de CPU |
| Rollback automático | remediation.retries: 3 en instalación y actualización |
| Corrección de cambios manuales | driftDetection.mode: enabled |
| Red | Entrada solo desde Traefik; salida solo hacia donde la aplicación lo necesita |
| Sin token de Kubernetes | serviceAccount.automount: false |
| Logs | Por OpenTelemetry si la aplicación lo soporta; si no, la etiqueta monitoring/logs |
La ficha de despliegue
El clúster bloquea todo por defecto: sin tráfico de salida, sin privilegios, sin disco, sin API de Kubernetes y con un límite de memoria. Por eso cada aplicación debe declarar lo que necesita antes de desplegarse. Lo que no se declara simplemente no funciona, normalmente en silencio, como un timeout.
Cada aplicación lo aporta en su ficha de despliegue, una plantilla que se guarda en su propio repositorio (por ejemplo como DEPLOYMENT.md) y que no depende del entorno:
| Necesidad | Por qué importa | Ejemplo (fumi) |
|---|---|---|
| Nombres | Ingress, certificado y registro DNS | fumi, fumi-api |
| Puertos en los que escucha | La NetworkPolicy solo deja entrar a Traefik por ellos | frontend 8080, API 3000 |
| Todo lo que llama, por componente | La salida está denegada salvo que se permita | PgBouncer 6432, Keycloak, MangaDex 443 |
| Base de datos y migraciones | Solo PostgreSQL externo, a través de PgBouncer | fumi, job pre-install |
| Secrets | Se guardan cifrados | DATABASE_URL, MANGADEX_* |
| Login | El cliente lo crea quien gestiona Keycloak | Cliente público fumi |
| Telemetría | Decide la etiqueta de logs y la anotación de métricas | Las tres señales por OTLP |
| Health | Sondas de liveness y readiness | /liveness, /readiness |
| Usuario y sistema de ficheros | restricted exige no-root; solo hay emptyDir | No-root, raíz de solo lectura en la API |
| Memoria y CPU | Requests y límite de memoria | - |
| Estado | Sin volúmenes, todo estado va en la base de datos o el cliente | Ninguno |
El ejemplo completo es la ficha de fumi.
Añadir una aplicación
Con fumi como referencia, en testing:
- Base de datos: ejecutar Create User en el stack de PostgreSQL con el nombre de la aplicación.
- Login: crear su cliente, roles y scopes en el realm
moon, normalmente importando su manifiestoKeycloakApplicationen Horizon. - DNS: añadir sus nombres como alias de
extranet.test.lb.moon.caten la red de Horizon. - Manifiestos: crear
apps/base/fumi/(namespace, repositorio, release y network policy) y el overlayapps/testing/fumi/con sus nombres, su configuración y el secret cifrado:
sops apps/testing/fumi/secret.yaml
- Subir y aplicar:
git add . && git commit && git push
flux reconcile kustomization flux-system --with-source
Validar:
flux get helmreleases -n fumi # fumi True
kubectl -n fumi get pods,ingress,certificate
curl -sI https://fumi.test.lb.moon.cat/ | head -1 # HTTP/2 200
Después, iniciar sesión con un usuario del realm moon que tenga el rol fumi:user. En Grafana, Tempo muestra el servicio fumi-api y Loki {cluster="tanya", service_name="fumi-api"}.
Particularidades
- documoon: web estática servida por nginx, sin base de datos, login ni secrets. Usa
baselineporque su imagen ejecuta nginx como root en el puerto 80. Su log de acceso se recoge por etiqueta. - shizen: web estática con nginx no-root en el
8080y raíz de solo lectura. Cambia muy poco, así que está fijada a una versión del chart y Flux solo la revisa una vez al año; una versión nueva es un commit cambiando el tag. - fumi: frontend, API sobre PostgreSQL y un job de migración que actualiza el esquema antes de cada release (si falla, se mantiene la versión anterior). Envía trazas, métricas y logs por OpenTelemetry.
- kirin: interfaz en React y API en Quarkus sobre PostgreSQL. Sus categorías y métodos de pago son recursos de Kubernetes (CRDs del chart), aplicados después por la
Kustomizationapps-configs, así que su API sí lee la API de Kubernetes. Conecta por PgBouncer conprepareThreshold=0y envía trazas por OpenTelemetry.
Las CRDs de kirin son plantillas normales del chart: desinstalar el release borra todas las categorías y métodos de pago. Flux los vuelve a aplicar desde Git, pero no se conserva nada más.
Actualizaciones
FluxCD despliega cada nueva versión del chart y lo notifica en Slack: cualquier versión en testing, la misma versión mayor en producción. Una actualización fallida vuelve atrás sola.