Saltar al contenido principal

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.

Chartsoci://registry-1.docker.io/reiizumi/<chart>; testing usa la variante -develop si existe
Versióntesting sigue cada nueva versión del chart (*); producción sigue la versión mayor actual
NamespaceUno por aplicación, con su nombre
Manifiestosapps/base/<aplicación>/, con nombres y variante del chart en apps/<entorno>/<aplicación>/
AplicaciónQué estesting
documoonEsta webwww.test.lb.moon.cat
shizenGenerador de escenarios para wargamesshizen.test.lb.moon.cat
fumiGestor de colecciones de manga, con base de datos y loginfumi.test.lb.moon.cat, fumi-api.test.lb.moon.cat
kirinGestor de economía personal, con base de datos y loginkirin.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:

ReglaCómo
Ingress en extranet con certificado de cert-managerValores ingress del chart
Una réplica, sin autoescaladoreplicaCount: 1
RecursosRequests según el uso medido, límite de memoria, sin límite de CPU
Rollback automáticoremediation.retries: 3 en instalación y actualización
Corrección de cambios manualesdriftDetection.mode: enabled
RedEntrada solo desde Traefik; salida solo hacia donde la aplicación lo necesita
Sin token de KubernetesserviceAccount.automount: false
LogsPor 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:

NecesidadPor qué importaEjemplo (fumi)
NombresIngress, certificado y registro DNSfumi, fumi-api
Puertos en los que escuchaLa NetworkPolicy solo deja entrar a Traefik por ellosfrontend 8080, API 3000
Todo lo que llama, por componenteLa salida está denegada salvo que se permitaPgBouncer 6432, Keycloak, MangaDex 443
Base de datos y migracionesSolo PostgreSQL externo, a través de PgBouncerfumi, job pre-install
SecretsSe guardan cifradosDATABASE_URL, MANGADEX_*
LoginEl cliente lo crea quien gestiona KeycloakCliente público fumi
TelemetríaDecide la etiqueta de logs y la anotación de métricasLas tres señales por OTLP
HealthSondas de liveness y readiness/liveness, /readiness
Usuario y sistema de ficherosrestricted exige no-root; solo hay emptyDirNo-root, raíz de solo lectura en la API
Memoria y CPURequests y límite de memoria-
EstadoSin volúmenes, todo estado va en la base de datos o el clienteNinguno

El ejemplo completo es la ficha de fumi.

Añadir una aplicación​

Con fumi como referencia, en testing:

  1. Base de datos: ejecutar Create User en el stack de PostgreSQL con el nombre de la aplicación.
  2. Login: crear su cliente, roles y scopes en el realm moon, normalmente importando su manifiesto KeycloakApplication en Horizon.
  3. DNS: añadir sus nombres como alias de extranet.test.lb.moon.cat en la red de Horizon.
  4. Manifiestos: crear apps/base/fumi/ (namespace, repositorio, release y network policy) y el overlay apps/testing/fumi/ con sus nombres, su configuración y el secret cifrado:
sops apps/testing/fumi/secret.yaml
  1. 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 baseline porque 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 8080 y 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 Kustomization apps-configs, así que su API sí lee la API de Kubernetes. Conecta por PgBouncer con prepareThreshold=0 y envía trazas por OpenTelemetry.
precaución

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.