Saltar a contenido

aws-wl-htg-pro

aws-wl-htg-pro es la cuenta de AWS del entorno productivo de IRIS. Aloja las aplicaciones, bases de datos, servicios auxiliares y componentes de infraestructura necesarios para operar la plataforma en producción.

Datos clave

Concepto Valor
Cuenta AWS 200702211100
Alias aws-wl-htg-pro
Región eu-south-2 (Spain)

Acceso

aws-wl-htg-pro es una cuenta miembro de la AWS Organization de HTG. La autenticación no se configura en la propia cuenta: vive centralizada en AWS IAM Identity Center, habilitado en la cuenta de gestión de la organización en eu-west-1. Los operadores se logean una sola vez contra el portal SSO corporativo y, desde ahí, asumen permission sets sobre esta cuenta mediante credenciales temporales. No hay usuarios IAM ni claves de acceso estáticas.

Red

La cuenta opera sobre una única VPC, htg-pro, desplegada en las tres zonas de disponibilidad de eu-south-2. La VPC default (172.31.0.0/16) que AWS provisiona automáticamente no se usa.

VPC

Parámetro Valor
Nombre htg-pro
ID vpc-04eae10f64aaf3438
CIDR primario 10.10.192.0/18
CIDRs secundarios (ninguno)
DNS hostnames Habilitado
DNS resolution Habilitado
Tenancy default

Subredes

Tres tipos de subred (pública, privada y database) replicados en las tres AZ de eu-south-2.

Tipo Nombre AZ CIDR Subnet ID
Pública htg-pro-public-eu-south-2a eu-south-2a 10.10.204.0/26 subnet-0684ee297f0d5ffbf
Pública htg-pro-public-eu-south-2b eu-south-2b 10.10.204.64/26 subnet-03afb76d61336c5f0
Pública htg-pro-public-eu-south-2c eu-south-2c 10.10.204.128/26 subnet-06e3e438c3ed4faf2
Privada htg-pro-private-eu-south-2a eu-south-2a 10.10.192.0/22 subnet-0d59b1e19017e81bf
Privada htg-pro-private-eu-south-2b eu-south-2b 10.10.196.0/22 subnet-0aceda1f30491b9ae
Privada htg-pro-private-eu-south-2c eu-south-2c 10.10.200.0/22 subnet-071596a65bb5421fd
Database htg-pro-db-eu-south-2a eu-south-2a 10.10.208.0/26 subnet-08567c9dfc7bbfd76
Database htg-pro-db-eu-south-2b eu-south-2b 10.10.208.64/26 subnet-054688274dd354496
Database htg-pro-db-eu-south-2c eu-south-2c 10.10.208.128/26 subnet-00ee8936d7bc6f6c3

Resumen por bloque:

  • Públicas: 10.10.204.0/24 (3 × /26 en uso, /26 libre). Albergan los ALBs internet-facing, el NAT Gateway y el bastion.
  • Privadas: 10.10.192.0/20 (3 × /22 en uso). Albergan los nodos EKS, los pods y el resto de cargas internas.
  • Database: 10.10.208.0/24 (3 × /26 en uso, /26 libre). Subnet group dedicado a RDS/Aurora y ElastiCache.

El espacio 10.10.209.0/24 – 10.10.255.255 queda reservado para futuro crecimiento.

Routing

Route table Asociaciones Ruta default
htg-pro-public 3 subredes públicas 0.0.0.0/0 → IGW igw-05bc629703598c3b4
htg-pro-private 3 subredes privadas 0.0.0.0/0 → NAT nat-0e14707e2ea4483c8
htg-pro-db 3 subredes database 0.0.0.0/0 → IGW igw-05bc629703598c3b4
htg-pro-default (sin asociaciones) sólo ruta local

Todas las tablas incluyen además la ruta local 10.10.192.0/18 para tráfico intra-VPC.

Salida a internet

Recurso ID Ubicación
Internet Gateway igw-05bc629703598c3b4 VPC htg-pro
NAT Gateway nat-0e14707e2ea4483c8 htg-pro-public-eu-south-2a
EIP de salida 51.49.182.136 Asociada al NAT Gateway

51.49.182.136 es la IP pública que ven los servicios externos cuando una carga de subred privada inicia una conexión saliente; es la dirección a comunicar para listas blancas (proveedores SMTP, APIs de partners, etc.).

Cluster EKS

Control plane

Parámetro Valor
Nombre htg-pro
Versión Kubernetes 1.33
Endpoint público Habilitado
Modo de autenticación API_AND_CONFIG_MAP
OIDC provider oidc.eks.eu-south-2.amazonaws.com/id/796CA0EFA9D1593A9366F128AB595613

El control plane lo gestiona AWS. El cluster utiliza EKS Access Entries (modo API) para la autorización, lo que evita gestionar manualmente el ConfigMap aws-auth.

Arquitectura de cómputo

El cluster no tiene Node Groups gestionados ni Auto Scaling Groups: toda la capacidad de cómputo la aprovisiona Karpenter, el autoscaler de nodos de Kubernetes mantenido por AWS.

Karpenter sustituye al binomio clásico Cluster Autoscaler + Managed Node Group. En lugar de mantener pools predefinidos de instancias y escalarlos en bloque, observa los pods que están pendientes de programación, infiere los requirements exactos (CPU, memoria, arquitectura, zona, taints/tolerations) y lanza directamente la instancia EC2 que mejor encaja. Cuando esos pods desaparecen o caben en menos nodos, los consolida apagando los que sobran.

Las ventajas frente a la alternativa tradicional son las que justifican su adopción aquí:

  • Right-sizing automático: cada nodo tiene el tipo de instancia que la carga necesita; no se paga capacidad sobredimensionada de un pool genérico.
  • Aprovisionamiento rápido: Karpenter habla directamente con la API de EC2, sin pasar por ASGs, lo que reduce el ciclo "pod pending → nodo Ready" a unos pocos segundos.
  • Diversidad de tipos sin esfuerzo: una sola política puede declarar varias familias y generaciones (c5/c7/m5/m7/...) y Karpenter elige según disponibilidad y precio (incluido Spot) en cada AZ.
  • Consolidación continua: empaqueta cargas dispersas y termina nodos infrautilizados, traduciéndose directamente en ahorro de coste.
graph LR
    subgraph Fargate
        Karpenter[Karpenter controller]
    end
    subgraph EC2["Nodos EC2 (Bottlerocket)"]
        Default["NodePool default<br/>(t3, workloads generales)"]
        Compute["NodePool compute<br/>(c5/m5/c7/m7/c8/m8, CPU intensivo)"]
    end
    Karpenter -->|aprovisiona| Default
    Karpenter -->|aprovisiona| Compute

El propio controlador de Karpenter no puede correr sobre los nodos que él mismo aprovisiona (problema del huevo y la gallina). Por eso vive en un Fargate Profile asociado al namespace karpenter, lo que garantiza que esté disponible aunque el cluster se quede momentáneamente sin nodos EC2.

Sobre EC2, el cluster define dos NodePools especializados:

  • default: workloads generales sobre familia t3 (burstable), apto para servicios web ligeros, controladores y demás piezas de plataforma.
  • compute: workloads intensivos en CPU sobre familias c5/c7/m5/m7/c8/m8. Lleva un taint que obliga a los pods a tolerarlo explícitamente para programarse aquí.

Las AMI de los nodos son Bottlerocket, la distribución mínima orientada a contenedores de AWS. La configuración detallada de NodePools y EC2NodeClass se documenta en Karpenter (resources).

Add-ons del cluster

Un add-on es una pieza de software que extiende el cluster con responsabilidades transversales —red, almacenamiento, autenticación, observabilidad, balanceo, etc.— que no forman parte del control plane de Kubernetes pero que la mayoría de cargas dan por hecho. En htg-pro los add-ons se agrupan en dos capas según cómo se gestiona su ciclo de vida:

  • Gestionados por EKS: AWS publica versiones oficiales de cierto conjunto de componentes y se encarga de instalarlos y actualizarlos a través de la propia API de EKS. Solo se declara qué add-on y qué versión.
  • De plataforma: el resto se despliegan como cargas normales del cluster (Deployments, DaemonSets, controladores) y se mantienen con las mismas herramientas que las aplicaciones de negocio.

Gestionados por EKS

Add-on Propósito
vpc-cni Asigna IPs de la VPC a los pods
kube-proxy Reglas iptables para Services
coredns DNS interno
eks-pod-identity-agent Habilita Pod Identity (alternativa a IRSA)
aws-ebs-csi-driver Volúmenes EBS para PVCs
aws-efs-csi-driver Volúmenes EFS (v2.3.1)

EBS y EFS CSI usan Pod Identity Association (no IRSA) con los roles EBS_CSI_DriverRole y EFS_CSI_DriverRole respectivamente.

De plataforma

Capa de componentes comunes desplegados sobre el cluster que dan soporte transversal a las aplicaciones:

Componente Propósito
AWS Load Balancer Controller Crea ALBs/NLBs a partir de Ingress y Service type=LoadBalancer
Metrics Server Métricas de CPU/memoria para HPA y kubectl top
CloudWatch Agent Envía métricas del cluster a CloudWatch
AWS for Fluent Bit (0.1.35) Envía logs de los pods a CloudWatch Logs

Plataforma GitOps

Sobre el cluster se monta una capa de plataforma: un conjunto de componentes que no hacen negocio, pero de los que las aplicaciones dependen para funcionar (despliegue, secretos, autoescalado, métricas). Toda esta capa se gestiona en GitOps: su estado deseado vive en el repositorio kubernetes-htg-pro y ArgoCD lo reconcilia continuamente contra el cluster. Cualquier cambio se hace en el repositorio, no aplicando manifiestos a mano.

Componente Función Documentación
ArgoCD Motor GitOps; reconcilia plataforma y aplicaciones ArgoCD
External Secrets Operator Sincroniza secretos desde AWS Secrets Manager External Secrets Operator
Karpenter Aprovisiona nodos EC2 a demanda Arquitectura de cómputo
KEDA Autoescalado por eventos (colas, métricas externas) KEDA
Reloader Reinicia Deployments cuando cambia un ConfigMap o Secret asociado Reloader

ArgoCD

ArgoCD es el motor GitOps del cluster. Reconcilia tanto el resto de componentes de plataforma como las aplicaciones de negocio.

Parámetro Valor
URL https://argocd.htg-express.com
Manifiesto base argoproj/argo-cd stable/manifests/ha/install.yaml (HA)
Ingress ALB internet-facing, TLS 1.3 (ELBSecurityPolicy-TLS13-1-2-2021-06)
Certificado arn:aws:acm:eu-south-2:200702211100:certificate/b8332795-02f0-468b-beed-f429be577751
Backend HTTPS con condición Content-Type: application/grpc para argocd-grpc

Autenticación. El acceso local de admin está deshabilitado (admin.enabled: "false"). Todos los usuarios autentican vía AWS IAM Identity Center mediante un conector SAML configurado en Dex contra https://portal.sso.eu-west-1.amazonaws.com/.... Los grupos sincronizados desde el SAML assertion se mapean a roles RBAC de ArgoCD:

Grupo SSO Rol ArgoCD
AWSAdministrators role:applications
ExternalDevTeam role:applications
HTGDevTeam role:applications
Linube role:admin

El rol role:applications da acceso completo a aplicaciones, applicationsets, logs y exec scoped al proyecto applications.*, y read-only sobre proyectos, repos y clusters.

Acceso a Secrets Manager. ArgoCD lee algunas configuraciones (por ejemplo el repo de Helm charts) desde AWS Secrets Manager. Para ello se ha aprovisionado el rol IAM ArgoCD con permisos secretsmanager:GetSecretValue sobre argoCD/* y se asocia al ServiceAccount argocd-secret-manager vía IRSA. El SecretStore aws-secrets-manager-store enlaza External Secrets con ese rol.

Acceso a ECR. Los Helm charts viven en el ECR compartido 203965864736.dkr.ecr.eu-west-1.amazonaws.com (cuenta CI/CD). El acceso es cross-account sin credenciales estáticas:

  1. Un ECRAuthorizationToken de External Secrets corre sobre el ServiceAccount argocd-aws-ac-htg-cicd-ecr, que tiene anotado el rol arn:aws:iam::203965864736:role/ecr-access-shared-htg-pro.
  2. Cada hora el generator emite un token y External Secrets lo materializa como un Secret aws-ac-htg-cicd-ecr con la etiqueta argocd.argoproj.io/secret-type: repository.
  3. ArgoCD lo detecta automáticamente y lo usa como credencial para pull de los charts OCI.

El rol cross-account está definido en la cuenta CI/CD aws-ac-htg-cicd (913305982008) bajo aws-infrastructure/aws-ac-htg-cicd/, en el módulo ecr_access_htg_pro.

External Secrets Operator

Materializa secretos desde AWS Secrets Manager en Secret nativos de Kubernetes para que las aplicaciones no se acoplen a AWS. Los SecretStore se definen por aplicación y autentican con IRSA, sin credenciales estáticas en el cluster.

KEDA

KEDA aporta autoescalado basado en eventos (colas, métricas externas, etc.) y convive con el HPA estándar mediante ScaledObjects que pueden disparar el escalado desde Redis, SQS, Prometheus remoto y demás fuentes. Se mantiene en aws-wl-htg-nonpro como banco de pruebas antes de plantear su llegada a producción.

La configuración del despliegue prioriza alta disponibilidad: 2 réplicas con PodDisruptionBudget (minAvailable: 1) tanto en el operator como en el metrics server y los webhooks. Los logs se emiten en formato JSON para que Fluent Bit los envíe estructurados a CloudWatch.

Reloader

Despliegue con valores Helm por defecto. Observa los namespaces y reinicia automáticamente cualquier Deployment, StatefulSet o DaemonSet cuyo ConfigMap o Secret asociado cambie. Esto elimina la necesidad de un kubectl rollout restart cuando External Secrets sincroniza nuevas credenciales.

Bases de datos

Toda la persistencia transaccional vive en el subnet group de base de datos de la VPC. Ninguna instancia es accesible directamente desde internet; se accede por la VPC (cluster EKS) o por túnel SSH a través del bastion.

iris-api-pro

Cluster Aurora Serverless v2 que respalda al backend principal iris-api. Es el dato más crítico de la cuenta.

Parámetro Valor
Engine Aurora MySQL 8.0.mysql_aurora.3.11.1
Topología 2 instancias db.serverless (writer + reader)
Escalado 2 – 32 ACUs
Cifrado en reposo Sí (KMS)
Backup 14 días, ventana 02:00-03:00
Deletion protection Habilitado
Parameter group app-cmsws-opta-pro-params (performance_schema=1, TZ Europe/Paris)
Master password Gestionado por AWS (manage_master_user_password) en Secrets Manager

Los ingresos están restringidos al CIDR privado de la VPC (cluster EKS) y al SG del bastion. La password rota automáticamente y la consumen las aplicaciones vía External Secrets sobre el secreto infraIrisApi/pro-*.

galopin-pro

Base de datos del servicio Galopin (consultada por iris-api).

Parámetro Valor
Engine MySQL 8.0.45
Tipo db.t4g.xlarge
Storage 20 – 50 GiB gp3
Backups Sí (retención por defecto)
Deletion protection Habilitado
Publicly accessible Sí (sigue restringido por SG)
Owner tag linube

Los ingresos al SG galopin-pro-db están restringidos al SG principal del cluster EKS y al SG del bastion.

suite-crm-pro

Base de datos de la instancia productiva de SuiteCRM, que corre sobre la EC2 bs1264.

Parámetro Valor
Engine MySQL 8.4.7
Tipo db.t4g.small
Storage 20 – 30 GiB gp3
Deletion protection Habilitado

Solo se permite acceso desde el SG del bastion y desde el SG de bs1264.

Acceso local

Las bases de datos viven en las subredes database de la VPC, sin ruta de entrada desde Internet, así que no se puede conectar a ellas directamente desde fuera de AWS. La forma habitual de acceder desde un equipo local (cliente CLI, GUI tipo MySQL Workbench, scripts de soporte, etc.) es a través del bastion, abriendo un túnel SSH.

El bastion como punto único de entrada

bs1256 es una pequeña instancia EC2 en una subred pública con EIP fija (15.216.0.166), cuyo único papel es aceptar conexiones SSH autenticadas y, una vez dentro de la VPC, abrir conexiones TCP hacia los recursos privados (RDS, ElastiCache, pods…). No corre aplicaciones de negocio. Su especificación completa y los Security Groups asociados se documentan en bs1256 — Bastion.

Cada operador necesita:

  • Una cuenta nominal propia en el bastion (no hay usuario compartido).
  • Su clave pública SSH añadida en ~/.ssh/authorized_keys de esa cuenta.
  • Conexión saliente al puerto 27 del bastion (no usa el 22 estándar).

Qué es un túnel SSH

Un túnel SSH —o local port forwarding— es una funcionalidad de OpenSSH que abre un puerto en el equipo local y reenvía todo el tráfico que reciba, cifrado dentro de la sesión SSH, hasta el otro extremo, donde se completa la conexión final. Mientras el túnel está activo, hablar con 127.0.0.1:<puerto-local> desde el portátil es equivalente a hablar con el destino real estando dentro de la VPC.

[ Cliente local ]  --SSH cifrado-->  [ Bastion bs1256 ]  --VPC privada-->  [ Aurora / RDS ]
   127.0.0.1:3306                       :27                                  endpoint:3306

La opción de ssh que abre el túnel es -L <puerto-local>:<endpoint-destino>:<puerto-destino>. La opción -N le dice que no abra shell, sólo mantenga la sesión viva para el reenvío de puerto.

Procedimiento

  1. Abrir el túnel contra el endpoint deseado (writer o reader, según convenga):

    ssh -p 27 -N \
        -L 3306:iris-api-pro.cluster-c10egmuiu8xw.eu-south-2.rds.amazonaws.com:3306 \
        <usuario>@15.216.0.166
    

    Cierra el túnel con Ctrl-C cuando hayas terminado.

  2. Conectar el cliente a 127.0.0.1:3306 con las credenciales del paso 1:

    mysql -h 127.0.0.1 -P 3306 -u <usuario> -p
    

Endpoints disponibles

Base de datos Endpoint Secreto
Aurora writer iris-api-pro.cluster-c10egmuiu8xw.eu-south-2.rds.amazonaws.com rds!cluster-a0eff523-242c-4f71-9b52-f0d804756ab6
Aurora reader iris-api-pro.cluster-ro-c10egmuiu8xw.eu-south-2.rds.amazonaws.com rds!cluster-a0eff523-242c-4f71-9b52-f0d804756ab6
RDS galopin-pro galopin-pro.c10egmuiu8xw.eu-south-2.rds.amazonaws.com rds!db-d96d9423-1db9-4b1f-87ed-d2351e0a8e14
RDS suite-crm-pro suite-crm-pro.c10egmuiu8xw.eu-south-2.rds.amazonaws.com rds!db-8c9f4e43-772d-4543-af86-43660bf234a2

Todas escuchan en el puerto 3306. Si necesitas mantener varios túneles abiertos simultáneamente, asigna puertos locales distintos (-L 3307:…, -L 3308:…, etc.) para evitar choques.

Los clusters Redis se acceden con la misma técnica, sustituyendo el endpoint por el de ElastiCache y el puerto por 6379. Ver Cache y colas.

Configuración persistente

Para no repetir el puerto y la EIP en cada comando, conviene declarar el bastion en ~/.ssh/config:

Host htg-pro-bastion
    HostName 15.216.0.166
    Port 27
    User <usuario>
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60

A partir de ese alias, abrir el túnel se reduce a:

ssh -N -L 3306:iris-api-pro.cluster-c10egmuiu8xw.eu-south-2.rds.amazonaws.com:3306 htg-pro-bastion

Redis

iris-api consume dos clusters ElastiCache Redis distintos por motivos operativos: uno para caché efímera y otro para colas de trabajo persistentes. Las políticas de eviction están afinadas a cada uso.

iris-api-pro-cache

Caché de respuestas HTTP, datos calculados y similares.

Parámetro Valor
Engine Redis 7.1
Tipo de nodo cache.t3.small
Réplicas 2 (multi-AZ, failover automático)
Encriptación en reposo
Encriptación en tránsito No (favorece latencia; el dato no es sensible)
Política de eviction allkeys-lru
Ventana de mantenimiento sun:05:00-sun:06:00

iris-api-pro-queues

Colas de trabajos (worker) y sesiones; aquí sí importa la durabilidad.

Parámetro Valor
Engine Redis 7.1
Tipo de nodo cache.m7g.large
Réplicas 2 (multi-AZ, failover automático)
Encriptación en reposo
Encriptación en tránsito
Política de eviction volatile-lru
Snapshots Retención 7 días, ventana 04:00-05:00
Ventana de mantenimiento sun:06:00-sun:07:00

Los SGs iris-api-pro-redis-cache e iris-api-pro-redis-queues solo aceptan conexiones desde el SG del cluster EKS y desde el SG del bastion.

Almacenamiento (S3)

Bucket Propósito
iris-api-files-pro Adjuntos y ficheros gestionados por iris-api (Laravel)
iris-chat-pro Adjuntos del módulo iris-chat

Ambos buckets son privados. Las aplicaciones acceden a ellos vía IRSA con los roles InfraIrisApiPro e InfraIrisChatPro (ver sección siguiente).

Identidades IAM

Todas las cargas que necesitan permisos en AWS los obtienen vía IRSA (IAM Roles for Service Accounts), nunca con credenciales estáticas. El trust policy de cada rol está limitado al sub exacto del ServiceAccount.

Rol IAM ServiceAccount Recursos a los que accede
ArgoCD argocd/argocd-secret-manager Secrets Manager (argoCD/*)
InfraIrisApiPro infra-iris-api-pro/infra-iris-api-pro Secrets Manager (infraIrisApi/pro-*), S3 (iris-api-files-pro, iris-chat-pro)
InfraIrisChatPro infra-iris-chat-pro/infra-iris-chat-pro Secrets Manager (infraIrisChat/pro-*), S3 (iris-chat-pro)
Perfectscale perfectscale/perfectscale Secrets Manager (perfectscale-*)
EBS_CSI_DriverRole kube-system/ebs-csi-controller-sa (Pod Identity) EBS CSI
EFS_CSI_DriverRole kube-system/efs-csi-controller-sa (Pod Identity) EFS CSI

Además, los ServiceAccount infra-iris-*-pro-ecr (uno por aplicación) tienen anotado el rol cross-account arn:aws:iam::203965864736:role/ecr-access-shared-htg-pro para hacer pull de las imágenes desde el ECR de la cuenta CI/CD.

Instancias EC2 auxiliares

Dos instancias EC2 viven fuera del cluster, en subredes públicas con EIP:

bs1256 — Bastion

Parámetro Valor
AMI AlmaLinux 9.7
Tipo t3.small
Disco 50 GiB gp3
EIP prevent_destroy = true
Puerto SSH 27 (no estándar)
Acceso Cuentas nominales + clave personal
IMDS v2 obligatorio

El bastion es el único punto de entrada SSH a la red. Está en tres SGs:

  • bastion: egress total (4/6, TCP/UDP).
  • linube_access: ingress SSH/monitorización desde la operación de Linube.
  • staff_access: SSH al puerto 27 desde cualquier origen (controlado por usuario + clave).

bs1264 — SuiteCRM producción

Parámetro Valor
AMI AlmaLinux 9.7
Tipo t3.xlarge
Disco 50 GiB gp3
EIP prevent_destroy = true
Puertos abiertos 80 y 443 desde internet
Base de datos RDS suite-crm-pro

SuiteCRM no encajaba en el modelo Kubernetes/Helm del resto del stack, así que se mantiene como una EC2 tradicional con su propio SG y EIP.

Integración con la cuenta CI/CD

La cuenta aws-ac-htg-cicd (913305982008) aloja el ECR compartido 203965864736.dkr.ecr.eu-west-1.amazonaws.com donde se publican todas las imágenes y los Helm charts del proyecto IRIS. Los workloads de esta cuenta los consumen sin credenciales estáticas mediante un rol cross-account:

  • En la cuenta CI/CD se define ecr-access-shared-htg-pro (módulo ecr_access_htg_pro en aws-infrastructure/aws-ac-htg-cicd/), con una trust policy que admite a los ServiceAccount argocd-aws-ac-htg-cicd-ecr, infra-iris-api-pro-ecr, infra-iris-chat-pro-ecr, infra-iris-frontend-pro-ecr e infra-iris-myhtg-pro-ecr.
  • Cada uno de esos ServiceAccount en htg-pro está anotado con eks.amazonaws.com/role-arn apuntando al rol cross-account.
  • ArgoCD se autentica además vía un ECRAuthorizationToken que renueva la credencial cada hora (ver sección ArgoCD).