Arquitectura¶
El sistema tiene dos flujos coordinados desde GitLab: uno crea y configura infraestructura; el otro entrega una versión de la aplicación sobre esa infraestructura. Los repositorios de despliegue conservan las referencias de imagen, mientras que los estados de OpenTofu conservan la relación entre configuración y recursos cloud.
Responsabilidades y control¶
flowchart TB
source["Repositorios de aplicación"] --> ci["Pipeline de aplicación"]
templates["Plantillas compartidas"] --> ci
ci --> registry["Container Registry"]
ci --> manifests["Manifiestos versionados"]
manifests --> apply["Job deploy"]
apply --> agent["GitLab Agent y clúster elegido"]
infra["Pipeline OpenTofu"] --> cloud["Infraestructura y plataforma"]
infra <--> state["Estados HTTP en GitLab"]
cloud --> agent
El pipeline de aplicación produce la imagen y actualiza un repositorio de manifiestos. Después aplica su contenido mediante un contexto proporcionado por GitLab Agent. La decisión DEPLOY_TARGET=eks|gke determina el contexto. El flujo es una entrega iniciada por CI; no hay un reconciliador continuo versionado que vuelva a aplicar Git periódicamente o corrija por sí solo cambios manuales en el clúster.
El pipeline de infraestructura se divide en network, kubernetes, database y platform. Cada raíz usa su propio estado remoto y consume outputs de otras raíces cuando los necesita. platform crea el namespace de aplicación, el secreto de base de datos y el agente; en AWS también instala el controlador de balanceo.
Plano de ejecución en AWS¶
flowchart TB
client["Cliente HTTPS"] --> alb["ALB público"]
alb --> web["Service web y frontend"]
alb --> rest["Service rest y API"]
rest --> db["RDS MySQL privado"]
web -. "API del mismo origen" .-> rest
nodes["Nodos EKS privados"] --> nat["NAT Gateway"]
nat --> external["Registry y servicios externos"]
El Ingress del frontend enruta /api/v1 al Service rest:8080 y / a web:8080, con ingressClassName: alb. El cliente JavaScript llama a la API bajo el mismo origen; la relación funcional del diagrama no implica que el servidor frontend actúe como proxy. Declara listeners HTTP/HTTPS, redirección a HTTPS y un certificado ACM existente. El nombre DNS histórico y la referencia de certificado deben adaptarse al entorno destino; el manifiesto no demuestra que se creen el registro DNS o el certificado.
EKS y RDS utilizan subredes privadas. La VPC contiene tres subredes privadas y tres públicas; un NAT Gateway proporciona salida. La regla de entrada de RDS permite MySQL desde el security group de los nodos EKS. RDS no tiene IP pública y su configuración fija multi_az = false.
El grupo de nodos tiene tamaños mínimo, máximo y deseado. Esto no equivale a demostrar que se haya instalado un controlador de escalado de nodos por carga: no aparece Cluster Autoscaler ni Karpenter en los recursos revisados. El detalle y sus implicaciones están en AWS.
Plano de ejecución en GCP¶
flowchart TB
web["Service web y frontend"] --> api["Service rest y API"]
api --> private["Private Service Access"]
private --> sql["Cloud SQL MySQL privado"]
nodes["Nodos GKE privados"] --> nat["Cloud NAT y Cloud Router"]
nat --> external["Registry y servicios externos"]
network["VPC y rangos secundarios"] --> nodes
La VPC es global y contiene subredes regionales. GKE usa modo VPC nativo y rangos secundarios de pods y Services. Sus nodos son privados; el endpoint de administración se configura separadamente y es público por defecto. Cloud NAT ofrece salida a los nodos y Cloud SQL usa una conexión privada con ipv4_enabled = false.
El diagrama muestra relaciones de dependencia y conectividad interna. La publicación HTTP de GKE no queda resuelta por el Ingress versionado, que selecciona el controlador ALB de AWS y referencia ACM. El código de plataforma GCP no instala un controlador compatible con ese manifiesto. Para reproducir el acceso externo de GKE hace falta una configuración específica del destino o recuperar la configuración externa usada por el autor. Véase GCP.
Contratos entre componentes¶
| Contrato | Productor | Consumidor | Condición de funcionamiento |
|---|---|---|---|
Imagen Registry/rama:SHA |
Build de cada app | Deployment web o rest |
La imagen debe existir y poder descargarse |
Secreto rest |
Raíz platform |
Backend mediante envFrom |
Credenciales y endpoint coherentes con la base creada |
Secreto registry |
Configuración adicional del entorno | Ambos Deployments | Está referenciado, pero no se crea en los recursos revisados |
Contexto …:eks-agent o …:gke-agent |
GitLab Agent y permisos CI | Job deploy |
Agente conectado y acceso autorizado |
| Outputs de estados | Raíces anteriores de IaC | terraform_remote_state |
Mismo proveedor/entorno y permisos de lectura |
Manifiestos en main |
update-k8s-manifests |
Job deploy |
Token con capacidad real de escritura y lectura |
Los namespaces y nombres de Services coinciden entre nubes, pero las cuentas, redes y bases son independientes. La compatibilidad funcional de Kubernetes no elimina las particularidades de ingress, IAM, almacenamiento o red de cada proveedor.
Límites arquitectónicos¶
No hay configuración de replicación MySQL entre nubes, balanceo global, recuperación automática de una región ni despliegue simultáneo de ambos servicios como transacción. Los proyectos frontend y backend tienen pipelines independientes y sus imágenes se promueven por separado.
ENVIRONMENT distingue nombres de estados y grupos de exclusión mutua del pipeline; no se propaga automáticamente a todos los nombres cloud ni a los tags, varios de los cuales conservan valores fijos de desarrollo. Crear estados con prefijos distintos no garantiza infraestructura aislada. La guía de estado detalla esta frontera.
Fuentes¶
- Dependencias entre raíces y nombres de estado
- Ingress y rutas HTTP
- Red privada y acceso a RDS
- Configuración GKE
- Cloud SQL y Private Service Access
- Memoria: PDF 29–30 y 49–55; impresas 23–24 y 43–49. Mapa de la memoria.