Saltar a contenido

aws-wl-htg-nonpro

aws-wl-htg-nonpro es la cuenta AWS que aloja todos los entornos de no producción del proyecto IRIS: desarrollo (dev), entornos efímeros por feature branch (dev-features) y pruebas (test). También aloja servicios auxiliares que solo existen fuera de producción (la instancia SugarCRM de desarrollo).

La estructura es la misma que en producción para que ambas cuentas sean operacionalmente intercambiables: red, EKS, ArgoCD, ECR cross-account, IRSA y External Secrets se comportan igual. La diferencia está en lo que se quita o se relaja: no hay Aurora, las réplicas Redis y MySQL son únicas, no se exige TLS donde no aporta valor y la observabilidad es más ligera.

La infraestructura vive en dos repositorios complementarios:

  • aws-infrastructure/aws-wl-htg-nonpro/ — Terraform: VPC, EKS, RDS, ElastiCache, S3, IAM, EC2.
  • kubernetes-clusters/kubernetes-htg-nonpro/ — manifiestos GitOps de la plataforma del cluster.

Datos clave

Concepto Valor
Cuenta AWS 913305982008
Alias aws-wl-htg-nonpro
Región eu-south-2 (Spain)
Región ECR (compartida) eu-west-1
Acceso administrativo AWS IAM Identity Center → AWSAdministratorAccess
Entornos alojados dev, dev-features, test
Repositorio Terraform aws-infrastructure/aws-wl-htg-nonpro
Repositorio GitOps kubernetes-clusters/kubernetes-htg-nonpro

Acceso

Igual que en producción, todo el acceso humano va por AWS IAM Identity Center. No existen usuarios IAM con credenciales estáticas.

aws sso login --profile htg-nonpro
aws sts get-caller-identity --profile htg-nonpro
aws eks --region eu-south-2 update-kubeconfig --name htg-nonpro --profile htg-nonpro
kubectl get nodes

El rol SSO AWSAdministratorAccess se mapea al cluster mediante una EKS Access Entry con AmazonEKSClusterAdminPolicy.

Red

La VPC htg-nonpro ocupa 10.10.128.0/18 (no se solapa con htg-pro, que está en 10.10.192.0/18, lo que permitirá VPC peering futuro sin renumerar). Se divide en los mismos tres tipos de subredes replicadas en las tres AZ de eu-south-2:

Tipo Función Tamaño
Públicas ALBs, NAT Gateway, bastion /24
Privadas Nodos EKS, pods, instancia SugarCRM dev (al estar en pública con EIP, los demás workloads van privados) /20
Database Subnet group dedicado a RDS y ElastiCache /24

NAT único (single_nat_gateway = true). Mismo etiquetado que la cuenta productiva: kubernetes.io/role/{elb,internal-elb} para el ALB Controller y karpenter.sh/discovery = htg-nonpro para que Karpenter aprovisione nodos en las subredes correctas.

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

Arquitectura de cómputo

La estrategia es idéntica a producción — Karpenter sobre Fargate, sin Node Groups gestionados— pero más austera: un único NodePool, sin 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

La diferencia operativa frente a htg-pro es que el EC2NodeClass del nonpro fija explícitamente los metadataOptions:

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

Con httpPutResponseHopLimit: 1 se impide que un proceso dentro de un contenedor llegue al endpoint IMDS de la instancia, evitando que pueda obtener credenciales del IAM role del nodo. httpTokens: required fuerza IMDSv2.

Add-ons gestionados

Mismo conjunto que en htg-pro, con dos pequeñas diferencias:

Add-on Diferencias con htg-pro
aws-efs-csi-driver Versión por defecto (en htg-pro está fijada a v2.3.1-eksbuild.1)
aws_cloudwatch_metrics Sin tolerations adicionales para karpenter.sh/nodepool (no hay pool con taint)

EBS y EFS CSI se asocian por Pod Identity a los roles EBS_CSI_DriverRole y EFS_CSI_DriverRole.

Add-ons de plataforma (EKS Blueprints)

Mismo aws-ia/eks-blueprints-addons que en producción: ALB Controller, AWS for Fluent Bit (0.1.35) y CloudWatch Agent.

Fluent Bit está configurado con la misma lógica de pipelines paralelos que htg-pro (parser JSON dedicado para infra-iris-api-*), apuntando a sus propios log groups:

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

Retención fijada a 14 días.

Plataforma GitOps (kubernetes-htg-nonpro)

La capa de plataforma sigue la misma organización que en producción pero con menos piezas: lo justo para que las aplicaciones se desplieguen y se puedan depurar, sin componentes de cost-optimization ni de monitorización avanzada.

platform/         # ArgoCD, External Secrets, Karpenter, KEDA, Reloader
observability/    # PMM

Faltan respecto a htg-pro: Prometheus Operator, Prometheus, Prometheus Adapter y PerfectScale.

ArgoCD

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
Service gRPC NodePort argocd-grpc con backend-protocol-version: HTTP2

Bootstrap. Igual que en producción:

kubectl apply -k platform/argocd/overlays

Autenticación. Admin local deshabilitado, SAML contra el SSO de IAM Identity Center (entidad y callback contra argocd-nonpro.htg-express.com). Los mismos cuatro grupos están mapeados a los mismos roles que en htg-pro:

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

Acceso a ECR. El mecanismo es idéntico al de htg-pro pero apunta al rol cross-account ecr-access-shared-htg-nonpro:

  1. ServiceAccount aws-ac-htg-cicd-ecr con anotación eks.amazonaws.com/role-arn: arn:aws:iam::203965864736:role/ecr-access-shared-htg-nonpro.
  2. ECRAuthorizationToken (External Secrets) genera un token cada hora sobre ese SA.
  3. ExternalSecret aws-ac-htg-cicd-ecr lo materializa con la etiqueta argocd.argoproj.io/secret-type: repository.

El rol cross-account vive en la cuenta CI/CD (913305982008) bajo el módulo ecr_access_htg_nonpro y acepta a los ServiceAccount argocd/aws-ac-htg-cicd-ecr, infra-iris-api-{dev,dev-features,test}-ecr, infra-iris-chat-{dev,test}-ecr, infra-iris-frontend-{dev,dev-features,test}-ecr e infra-iris-myhtg-{dev,test}-ecr.

External Secrets Operator

Mismas características que en htg-pro: valores por defecto, se conecta a AWS Secrets Manager con IRSA y los SecretStore se definen por aplicación.

Karpenter (resources)

Controlador desplegado por Terraform (helm_release.karpenter versión 1.6.0).

EC2NodeClass default con la AMI bottlerocket@latest, IAM role htg-nonpro y autodescubrimiento por karpenter.sh/discovery: htg-nonpro. Como se ha mencionado, fija explícitamente metadataOptions (IMDSv2 con hop limit 1).

NodePool default — único pool de la cuenta:

  • amd64 sobre hypervisor Nitro
  • Familia t3 en spot y on-demand
  • Límite global de 64 vCPU
  • expireAfter: 720h, consolidación tras 1 min, disruption budget 10 %

A diferencia de htg-pro, no hay NodePool de cómputo: las cargas pesadas (procesadores PHP, builders) no existen aquí.

KEDA

A diferencia de producción, htg-nonpro instala KEDA para experimentar con autoescalado basado en eventos (colas, métricas externas). KEDA convive con el HPA estándar y aporta ScaledObjects que pueden disparar el escalado a partir de Redis, SQS, Prometheus remoto, etc.

Configuración relevante de los valores Helm:

  • Operator: 2 réplicas en HA, con PodDisruptionBudget (minAvailable: 1)
  • Metrics Server: 2 réplicas en HA con PDB
  • Webhooks: 2 réplicas con PDB
  • Logging en formato JSON para que Fluent Bit lo envíe estructurado

Reloader

Despliegue con valores Helm por defecto, igual que en producción.

Observabilidad

PMM (Percona Monitoring and Management)

Aquí PMM monitoriza las instancias RDS de la cuenta nonpro y se usa también como herramienta de pruebas antes de promover cambios a la PMM de producción. Por eso la versión está fijada explícitamente (en htg-pro se usa el latest gestionado por el operator).

Parámetro Valor
URL https://pmm.htg-express.com (mismo host que producción, distinto ALB y certificado)
Imagen percona/pmm-server:3.4.1
Almacenamiento 25 GiB sobre gp2
ServiceAccount pmm-service-accountarn:aws:iam::913305982008:role/InfraPmm
Certificado arn:aws:acm:eu-south-2:913305982008:certificate/f23c4db5-ca20-4368-80b3-a2372fb7b319

La contraseña del admin se materializa con un ExternalSecret en pmm/pmm-secret desde el secreto infra/pmm (pmmAdminPassword) mediante el rol InfraPmm.

Bases de datos

RDS MySQL — 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)
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.

RDS MySQL — 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

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.

No hay Aurora

A diferencia de htg-pro, no se aprovisiona Aurora Serverless en esta cuenta. Para iris-api-test se utiliza la propia instancia iris-api-dev o una base efímera materializada por la aplicación; los entornos efímeros (dev-features) comparten DB con dev.

Cache (ElastiCache Redis)

Una única instancia Redis simple, sin réplicas ni TLS, suficiente para los entornos de desarrollo y pruebas:

Parámetro Valor
Replication group iris-api-dev
Engine Redis 7.1
Tipo de nodo cache.t3.micro
Nodos 1
Encriptación en reposo Sí (por defecto del módulo)
Encriptación en tránsito No
Parameter group redis7 por defecto
Acceso Solo desde el SG del cluster EKS

No hay un cluster separado para queues — al no haber carga real, se comparte.

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. El acceso se concede vía IRSA a la aplicación que corresponda; iris-chat-dev aparece referenciado en los roles de dev y dev-features porque ambos entornos lo comparten.

Identidades IAM

Un rol IRSA por entorno y aplicación. El trust policy de cada uno está restringido al sub exacto del ServiceAccount.

Rol IAM ServiceAccount Recursos
EcrReadOnlyRole external-secrets/external-secrets AmazonEC2ContainerRegistryReadOnly (legacy, mantenido para compatibilidad)
InfraIrisApiDev infra-iris-api-dev/infra-iris-api-dev Secrets infraIrisApi/dev/*, S3 (iris-api-files-dev, iris-chat-dev)
InfraIrisApiDevFeatures infra-iris-api-dev-features/infra-iris-api-dev-features Secrets infraIrisApi/devFeatures-*, S3 (iris-api-files-dev-features, iris-chat-dev)
InfraIrisApiTest infra-iris-api-test/infra-iris-api-test Secrets infraIrisApi/test-*, S3 (iris-api-files-test, iris-chat-test)
InfraIrisChatDev infra-iris-chat-dev/infra-iris-chat-dev Secrets infraIrisChat/dev-*, S3 (iris-chat-dev)
InfraIrisChatTest infra-iris-chat-test/infra-iris-chat-test Secrets infraIrisChat/test-*, S3 (iris-chat-test)
InfraPmm pmm/pmm-service-account Secrets infra/pmm-*
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

Para los ServiceAccount infra-iris-*-ecr el rol cross-account es arn:aws:iam::203965864736:role/ecr-access-shared-htg-nonpro (sección Integración con la cuenta CI/CD).

Instancias EC2 auxiliares

bs1245 — Bastion

Parámetro Valor
AMI AlmaLinux 9.5 (ami-0fcdf92274127bd3e)
Tipo t3.medium
Disco 50 GiB gp3
EIP Sí (sin prevent_destroy)
Puerto SSH 27
Acceso Cuentas nominales + clave personal
IMDS v2 obligatorio

Está en dos SGs:

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

Sirve además como salto para tunelizar a las RDS y al Redis privado (las RDS de no producción están en subred database aunque marcadas como publicly_accessible = true; en la práctica el SG bloquea internet).

bs1252 — SugarCRM dev

Parámetro Valor
AMI AlmaLinux 9.5
Tipo t3.2xlarge
Disco 50 GiB gp3
EIP
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.

Integración con la cuenta CI/CD

Los workloads del cluster htg-nonpro consumen las mismas imágenes y Helm charts que htg-pro desde el ECR compartido 203965864736.dkr.ecr.eu-west-1.amazonaws.com, pero con un rol cross-account dedicado:

  • En la cuenta CI/CD (913305982008aws-ac-htg-cicd) se define ecr-access-shared-htg-nonpro (módulo ecr_access_htg_nonpro), cuya trust policy admite a los ServiceAccount argocd/aws-ac-htg-cicd-ecr y infra-iris-*-{dev,dev-features,test}-ecr.
  • Cada ServiceAccount lleva la anotación eks.amazonaws.com/role-arn apuntando al rol cross-account.
  • ArgoCD lo combina con el ECRAuthorizationToken de External Secrets para conseguir un token corto-lived sin almacenar credenciales en el cluster.

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