Saltar a contenido

aws-wl-htg-nonpro

aws-wl-htg-nonpro es la cuenta de AWS de los entornos no productivos de IRIS. Aloja dev, dev-features y test: aplicaciones, bases de datos, servicios auxiliares e infraestructura. Su arquitectura es deliberadamente equivalente a la de aws-wl-htg-pro para que ambos entornos sean operativamente intercambiables; las diferencias se concentran en lo que se relaja o se omite (sin Aurora, sin réplicas en bases de datos y caché, sin TLS donde no aporta valor, observabilidad más ligera).

Datos clave

Concepto Valor
Cuenta AWS 913305982008
Alias aws-wl-htg-nonpro
Región eu-south-2 (Spain)
Entornos alojados dev, dev-features, test

Acceso

aws-wl-htg-nonpro 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-nonpro, desplegada en las tres zonas de disponibilidad de eu-south-2. Su CIDR (10.10.128.0/18) no se solapa con el de aws-wl-htg-pro (10.10.192.0/18), lo que permite plantear un VPC peering futuro sin renumerar. La VPC default (172.31.0.0/16) que AWS provisiona automáticamente no se usa.

VPC

Parámetro Valor
Nombre htg-nonpro
ID vpc-021a4126b9ae07693
CIDR primario 10.10.128.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-nonpro-public-eu-south-2a eu-south-2a 10.10.140.0/26 subnet-05e5eea5dbaa57098
Pública htg-nonpro-public-eu-south-2b eu-south-2b 10.10.140.64/26 subnet-0c27ec0d40b74a276
Pública htg-nonpro-public-eu-south-2c eu-south-2c 10.10.140.128/26 subnet-0132923b55b96c166
Privada htg-nonpro-private-eu-south-2a eu-south-2a 10.10.128.0/22 subnet-05bfb55e5554280f8
Privada htg-nonpro-private-eu-south-2b eu-south-2b 10.10.132.0/22 subnet-09933c0a6b0cdb460
Privada htg-nonpro-private-eu-south-2c eu-south-2c 10.10.136.0/22 subnet-0ed32b346f1e1bcde
Database htg-nonpro-db-eu-south-2a eu-south-2a 10.10.144.0/26 subnet-0af225c466dd0b52d
Database htg-nonpro-db-eu-south-2b eu-south-2b 10.10.144.64/26 subnet-0c1bb114cd5fc0da7
Database htg-nonpro-db-eu-south-2c eu-south-2c 10.10.144.128/26 subnet-0079e66c7c4e9b90e

Resumen por bloque:

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

El espacio 10.10.145.0/24 – 10.10.191.255 queda reservado para futuro crecimiento.

Routing

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

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

Salida a internet

Recurso ID Ubicación
Internet Gateway igw-0ca40b967891c0107 VPC htg-nonpro
NAT Gateway nat-08d0cd86c5acfc854 htg-nonpro-public-eu-south-2a
EIP de salida 18.100.22.119 Asociada al NAT Gateway

18.100.22.119 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-nonpro
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/FE5540FF48F49F2BF9DA4A6FDBCEE1C1

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

Igual que en producción, el cluster no tiene Node Groups gestionados ni Auto Scaling Groups: toda la capacidad de cómputo la aprovisiona Karpenter, observando los pods pendientes y lanzando la instancia EC2 que mejor encaja en cada caso. La motivación y el funcionamiento general se documentan en Arquitectura de cómputo de aws-wl-htg-pro.

La diferencia operativa con producción es que aquí basta con un único NodePool: las cargas de no producción no requieren un pool de cómputo dedicado.

graph LR
    subgraph Fargate
        Karpenter[Karpenter controller]
    end
    subgraph EC2["Nodos EC2 (Bottlerocket)"]
        Default["NodePool default<br/>(t3, spot+on-demand)"]
    end
    Karpenter -->|aprovisiona| Default

El EC2NodeClass de no producción endurece IMDS de los nodos:

metadataOptions:
  httpEndpoint: enabled
  httpProtocolIPv6: disabled
  httpPutResponseHopLimit: 1
  httpTokens: required

httpTokens: required fuerza IMDSv2. httpPutResponseHopLimit: 1 impide que un proceso dentro de un contenedor alcance el endpoint IMDS de la instancia, evitando que pueda obtener credenciales del IAM role del nodo desde un pod.

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-nonpro 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.
  • 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 (versión por defecto del add-on)

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
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

Fluent Bit y CloudWatch Logs. Fluent Bit recoge la salida estándar de todos los pods y la entrega a CloudWatch Logs siguiendo dos pipelines en paralelo:

  • Los logs etiquetados como infra-iris-api-* se parsean como JSON (Reserve_Data + lift sobre el campo context) y se enrutan a un log group dedicado por namespace.
  • El resto del tráfico va a un log group común sin transformaciones.
Log group Contenido
/aws/eks/htg-nonpro/infra-iris-api/<namespace> Logs estructurados de los entornos iris-api
/aws/eks/htg-nonpro/aws-fluentbit-logs Resto de logs de pods

La retención está fijada en 14 días.

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-nonpro 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-nonpro.htg-express.com
Manifiesto base argoproj/argo-cd stable/manifests/ha/install.yaml (HA)
Ingress ALB internet-facing, TLS 1.3
Certificado arn:aws:acm:eu-south-2:913305982008:certificate/f23c4db5-ca20-4368-80b3-a2372fb7b319
Backend HTTPS con condición Content-Type: application/grpc para argocd-grpc

Autenticación. El acceso local de admin está deshabilitado. Todos los usuarios autentican vía AWS IAM Identity Center mediante un conector SAML configurado en Dex (entidad y callback contra argocd-nonpro.htg-express.com). Los mismos cuatro grupos están mapeados a los mismos roles que en aws-wl-htg-pro:

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

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-nonpro.
  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 (203965864736) bajo aws-infrastructure/aws-ac-htg-cicd/, en el módulo ecr_access_htg_nonpro.

External Secrets Operator

Materializa secretos definidos en AWS Secrets Manager como Secret nativos de Kubernetes, evitando que las aplicaciones tengan que hablar directamente con la API de AWS para leer credenciales. Cada aplicación declara sus propios SecretStore/ExternalSecret y se autentica 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

Observa los Deployments, StatefulSets y DaemonSets del cluster y los reinicia automáticamente cuando cambia un ConfigMap o Secret asociado. Cierra el bucle con External Secrets: al rotar una credencial en Secrets Manager, los pods se reciclan solos sin intervención manual.

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-dev

Base de datos transaccional compartida por los entornos dev y dev-features del backend.

Parámetro Valor
Engine MySQL 8.0.43
Tipo db.t4g.small
Storage 20 – 30 GiB gp3
Multi-AZ No
Publicly accessible Sí (controlado por SG)
Deletion protection Habilitado
Parameter group iris-api-dev-params (performance_schema=1, TZ Europe/Paris)
Backups Sí (retención por defecto)
Enhanced monitoring 60s (rol IAM compartido con sugar-crm-dev)
Master password Gestionado por AWS (manage_master_user_password) en Secrets Manager
Owner tag linube

El SG iris-api-dev-db admite ingress desde el cluster EKS, desde el bastion, desde la subred del operador SaaS Qlik (seis rangos IPv4 documentados en el código) y desde el salto operativo de Linube.

sugar-crm-dev

Base de datos de la instancia de SugarCRM de desarrollo, que corre sobre la EC2 bs1252.

Parámetro Valor
Engine MySQL 8.4.7
Tipo db.t4g.small
Storage 20 – 30 GiB gp3
Multi-AZ No
Deletion protection Habilitado
Publicly accessible Sí (controlado por SG)
Master password Gestionado por AWS (manage_master_user_password) en Secrets Manager

Solo acepta conexiones desde el SG del bastion y desde el SG de bs1252. Reutiliza el rol de Enhanced Monitoring creado por iris-api-dev.

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

bs1245 es una pequeña instancia EC2 en una subred pública con EIP fija (51.95.47.78), 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 bs1245 — 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 bs1245 ]  --VPC privada-->  [ RDS / Redis ]
   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:

    ssh -p 27 -N \
        -L 3306:iris-api-dev.clw60my4me1d.eu-south-2.rds.amazonaws.com:3306 \
        <usuario>@51.95.47.78
    

    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
RDS iris-api-dev iris-api-dev.clw60my4me1d.eu-south-2.rds.amazonaws.com rds!db-1eea6b69-468a-43ca-a524-162963fe3308
RDS sugar-crm-dev sugar-crm-dev.clw60my4me1d.eu-south-2.rds.amazonaws.com rds!db-32ef53b8-b355-4427-9724-050a63c8f535

Ambas 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.

El cluster Redis se accede con la misma técnica, sustituyendo el endpoint por el de ElastiCache y el puerto por 6379. Ver Cache (ElastiCache Redis).

Configuración persistente

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

Host htg-nonpro-bastion
    HostName 51.95.47.78
    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-dev.clw60my4me1d.eu-south-2.rds.amazonaws.com:3306 htg-nonpro-bastion

Redis

Un único cluster ElastiCache Redis simple, sin réplicas ni TLS, suficiente para los entornos de desarrollo y pruebas. No hay un cluster separado para queues: al no haber carga real, se comparte el mismo nodo.

Parámetro Valor
Replication group iris-api-dev
Engine Redis 7.1
Tipo de nodo cache.t3.micro
Nodos 1
Endpoint master.iris-api-dev.fwjspa.eus2.cache.amazonaws.com:6379
Encriptación en reposo
Encriptación en tránsito No
Parameter group redis7 por defecto

El SG asociado solo acepta conexiones desde el SG del cluster EKS y desde el SG del bastion.

Almacenamiento S3

Bucket Entorno Aplicación
iris-api-files-dev dev Adjuntos iris-api (Laravel)
iris-api-files-dev-features dev-features Adjuntos iris-api para feature branches
iris-api-files-test test Adjuntos iris-api
iris-chat-dev dev / dev-features Adjuntos iris-chat (compartido)
iris-chat-test test Adjuntos iris-chat

Todos los buckets son privados. Las aplicaciones acceden a ellos vía IRSA con los roles que se documentan en la sección siguiente; iris-chat-dev aparece referenciado en los roles de dev y dev-features porque ambos entornos lo comparten.

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
InfraIrisApiDev infra-iris-api-dev/infra-iris-api-dev Secrets Manager (infraIrisApi/dev/*), S3 (iris-api-files-dev, iris-chat-dev)
InfraIrisApiDevFeatures infra-iris-api-dev-features/infra-iris-api-dev-features Secrets Manager (infraIrisApi/devFeatures-*), S3 (iris-api-files-dev-features, iris-chat-dev)
InfraIrisApiTest infra-iris-api-test/infra-iris-api-test Secrets Manager (infraIrisApi/test-*), S3 (iris-api-files-test, iris-chat-test)
InfraIrisChatDev infra-iris-chat-dev/infra-iris-chat-dev Secrets Manager (infraIrisChat/dev-*), S3 (iris-chat-dev)
InfraIrisChatTest infra-iris-chat-test/infra-iris-chat-test Secrets Manager (infraIrisChat/test-*), S3 (iris-chat-test)
InfraPmm pmm/pmm-service-account Secrets Manager (infra/pmm-*)
EcrReadOnlyRole external-secrets/external-secrets AmazonEC2ContainerRegistryReadOnly (legacy, mantenido para compatibilidad)
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-*-{dev,dev-features,test}-ecr (uno por aplicación y entorno) tienen anotado el rol cross-account arn:aws:iam::203965864736:role/ecr-access-shared-htg-nonpro 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:

bs1245 — Bastion

Parámetro Valor
AMI AlmaLinux 9.5 (ami-0fcdf92274127bd3e)
Tipo t3.medium
Disco 50 GiB gp3
EIP 51.95.47.78
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 dos SGs:

  • bastion: ingress SSH al puerto 27 desde 0.0.0.0/0 y egress total.
  • linube_access: ingress de monitorización y SSH desde la operación de Linube.

bs1252 — SugarCRM dev

Parámetro Valor
AMI AlmaLinux 9.5
Tipo t3.2xlarge
Disco 50 GiB gp3
EIP 15.216.55.96
Puertos abiertos 80 y 443 desde internet
Base de datos RDS sugar-crm-dev

SugarCRM funciona como su análogo en producción (SuiteCRM): una pila tradicional fuera del cluster con LAMP y MySQL gestionado, con su propio SG y EIP.

Integración con la cuenta CI/CD

La cuenta aws-ac-htg-cicd (203965864736) 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-nonpro (módulo ecr_access_htg_nonpro en aws-infrastructure/aws-ac-htg-cicd/), con una trust policy que admite a los ServiceAccount argocd-aws-ac-htg-cicd-ecr y infra-iris-*-{dev,dev-features,test}-ecr.
  • Cada uno de esos ServiceAccount en htg-nonpro 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).

El esquema es deliberadamente idéntico al de aws-wl-htg-pro: aislamos por cuenta (un rol cross-account distinto por cluster) pero compartimos el mismo patrón.