IRIS API
Descripción
IRIS API es el backend central de la plataforma IRIS de HTG Express. Es una API REST construida con Laravel (PHP) que gestiona la lógica de negocio: transportes, facturación, cotizaciones, gestión de vehículos, comunicaciones con proveedores y clientes, integración con servicios externos (Expeditors, Project44, Altia, TicketBAI) y notificaciones push.
La aplicación está desplegada en Kubernetes (EKS) en AWS, región eu-south-2. La infraestructura sigue un modelo GitOps: los recursos de Kubernetes se definen mediante un chart de Helm, los valores de configuración por entorno viven en un repositorio Git, y ArgoCD se encarga de sincronizar el estado del cluster con lo declarado en Git.
Arquitectura
graph TB
User([Usuario / Frontend]) -->|HTTPS| ALB[Application Load Balancer]
ALB --> Nginx[Nginx]
subgraph Pod["Pod API (EKS)"]
Nginx -->|FastCGI :9000| PHP[PHP-FPM 8.3]
Exporter[PHP-FPM Exporter]
Cleanup[Temp Cleanup]
end
PHP --> Aurora[(Aurora MySQL)]
PHP --> Redis[(ElastiCache Redis)]
PHP --> S3[(S3 Bucket)]
PHP --> ExtServices[Servicios externos]
Redis -->|Encolado| Workers[Workers KEDA]
Workers --> Aurora
Workers --> S3
Workers --> ExtServices
Scheduler[CronJob Laravel Scheduler] --> Aurora
style Pod fill:#f5f5f5,stroke:#333
Componentes
La solución combina servicios gestionados de AWS con recursos desplegados dentro de EKS. El ALB expone la aplicación hacia internet, Kubernetes ejecuta los pods de la API y los workers, y los servicios gestionados externos aportan persistencia, colas, almacenamiento, secretos y observabilidad.
| Componente | Servicio AWS | Función |
|---|---|---|
| Load Balancer | ALB (Application Load Balancer) | Punto de entrada HTTPS, terminación TLS |
| Aplicación | EKS (pods Nginx + PHP-FPM) | Procesamiento de peticiones HTTP |
| Workers | EKS (pods PHP) con KEDA | Procesamiento asíncrono de colas Redis |
| Base de datos | Aurora MySQL / RDS MySQL | Persistencia de datos |
| Caché y colas | ElastiCache Redis | Caché de aplicación y broker de colas |
| Almacenamiento | S3 | Archivos (CMRs, documentos, imágenes) |
| Secretos | Secrets Manager + ESO | Gestión segura de credenciales |
| Logs | CloudWatch Logs | Centralización de logs |
| Métricas | CloudWatch + Prometheus | Métricas de infraestructura y PHP-FPM |
Entornos
IRIS API se despliega en cuatro entornos diferenciados. Los entornos de no-producción (dev, dev-features y test) comparten la cuenta AWS 913305982008, lo que permite centralizar los recursos de validación y desarrollo. Producción se ejecuta en una cuenta AWS independiente (200702211100) para aislar cargas críticas, permisos, certificados, secretos y recursos operativos.
| Entorno | URL | Namespace | Cuenta AWS | GitOps |
|---|---|---|---|---|
| Producción | iris-api.htg-express.com |
infra-iris-api-pro |
200702211100 | pro/values.yaml |
| Test | api-test.htg-express.com |
infra-iris-api-test |
913305982008 | test/values.yaml |
| Dev | api-dev-li.htg-express.com |
infra-iris-api-dev |
913305982008 | dev/values.yaml |
| Dev Features | api-dev-features.htg-express.com |
infra-iris-api-dev-features |
913305982008 | dev-features/values.yaml |
Repositorios
El despliegue de IRIS API se apoya en tres repositorios con responsabilidades claramente separadas:
| Tipo | Proyecto Bitbucket | Repositorio | Responsabilidad |
|---|---|---|---|
| Código | IRIS | htgexpress/api | Código fuente Laravel y Dockerfile |
| Helm chart | IRIS | Helm charts | htgexpress/helm-iris-php | Plantillas Kubernetes parametrizadas |
| GitOps | IRIS | GitOps | htgexpress/infra-iris-api | Valores Helm por entorno |
Esta separación permite que el equipo de desarrollo evolucione la aplicación sin tocar infraestructura, que el chart pueda reutilizarse con distintos parámetros y que los cambios de configuración por entorno queden auditados en un repo independiente. ArgoCD combina el chart con el values.yaml correspondiente para generar y aplicar los manifiestos Kubernetes.
Estructura del repositorio GitOps
El repositorio GitOps contiene exclusivamente los valores Helm (values.yaml) para cada entorno. No contiene definiciones de Application de ArgoCD ni manifiestos Kubernetes directos; estas viven en un repositorio de configuración de ArgoCD aparte.
infra-iris-api/
├── dev/
│ └── values.yaml
├── dev-features/
│ └── values.yaml
├── test/
│ └── values.yaml
└── pro/
└── values.yaml
Helm chart
Todos los recursos Kubernetes que componen el despliegue se generan a partir de un único chart de Helm: infra-iris-api, alojado en el repositorio htgexpress/helm-iris-php. El chart es propio (no reutiliza charts comunitarios) y está versionado de forma independiente al código de la aplicación.
CI/CD
El recorrido completo desde un commit hasta producción tiene tres pasos: Bitbucket Pipelines construye la imagen Docker y la sube a ECR, actualiza el image.tag en el repositorio GitOps y, a partir de ahí, ArgoCD se encarga de sincronizar el cluster.
Pipeline (Bitbucket Pipelines)
Existen dos flujos en el pipeline de la aplicación:
Automático (rama develop)
Se ejecuta en cada push a develop y despliega siempre a dev:
- Build: construye la imagen Docker usando
docker/php/php.api.dockerfile. - Tag: el tag de la imagen es el SHA corto del commit (7 caracteres, ej.:
dc6a4cc). - Push: sube la imagen a ECR.
- Deploy: actualiza el
image.tagendev/values.yamldel repo GitOps mediante el pipedeploy-helm-values.
graph LR
Push[Push a develop] --> Build[Build imagen]
Build --> ECR[Push a ECR]
ECR --> GitOps[Actualizar dev/values.yaml]
GitOps --> ArgoCD[ArgoCD sincroniza]
Manual (cualquier entorno)
La promoción a test, dev-features o pro se hace mediante el pipeline manual-deploy, que permite desplegar cualquier referencia Git a cualquier entorno:
| Variable | Descripción | Valores |
|---|---|---|
GIT_REF |
Commit SHA, tag o rama | current (por defecto), SHA, tag, rama |
ENVIRONMENT |
Entorno destino | dev, dev-features, test, pro |
Pasos:
- Resuelve la referencia Git y determina el tag de imagen (tag Git si existe, si no SHA corto).
- Verifica si la imagen ya existe en ECR para evitar builds innecesarios.
- Si no existe, construye y sube la imagen.
- Actualiza el
image.tagen{ENVIRONMENT}/values.yamldel repo GitOps.
En la práctica, esto significa que dev recibe un SHA en cada push a develop, mientras que test y pro reciben tags semánticos (1.1.165, 1.1.164...) lanzados manualmente cuando una versión está validada.
Variables de pipeline requeridas
| Variable | Descripción |
|---|---|
AWS_ACCESS_KEY_ID |
Credenciales IAM para ECR |
AWS_SECRET_ACCESS_KEY |
Credenciales IAM para ECR |
AWS_REGION |
Región del registry ECR |
AWS_ACCOUNT_ID |
ID de cuenta AWS |
ECR_REPOSITORY |
Nombre del repositorio ECR (ej.: iris/api) |
BITBUCKET_USERNAME |
Usuario para clonar el repo GitOps |
BITBUCKET_APP_PASSWORD |
App password para clonar el repo GitOps |
Imágenes Docker
El pod de la aplicación se construye a partir de dos imágenes propias publicadas en ECR: una imagen base común (sistema operativo + PHP + extensiones) y una imagen de aplicación que añade el código de IRIS API sobre la base. Esta separación reduce el tiempo de build (la base no cambia con cada commit), garantiza un entorno PHP idéntico entre servicios y simplifica las actualizaciones del runtime.
graph LR
Debian[php:8.3.30-fpm-bookworm<br/>imagen oficial PHP] --> Base[iris/base/php:8.3.30-fpm<br/>imagen base HTG]
Base --> App[iris/api:<tag><br/>imagen de aplicación]
App --> Pod[Pod en EKS]
Ambas imágenes se almacenan en el mismo registry ECR:
203965864736.dkr.ecr.eu-west-1.amazonaws.com
Imagen base: iris/base/php
Imagen compartida entre IRIS API e IRIS Chat. Parte de la imagen oficial php:8.3.30-fpm-bookworm y añade todo lo necesario para ejecutar las aplicaciones Laravel del proyecto.
| Campo | Valor |
|---|---|
| Repositorio ECR | iris/base/php |
| Tag actual | 8.3.30-fpm |
| Imagen origen | php:8.3.30-fpm-bookworm (Debian Bookworm) |
| Dockerfile | docker/php/php.base.dockerfile (en el repo de IRIS API) |
| Usuario por defecto | laravel (no-root) |
| Puerto expuesto | 9000 (PHP-FPM) |
| Timezone | Europe/Madrid |
Extensiones PHP instaladas:
| Tipo | Extensiones |
|---|---|
Core / docker-php-ext-install |
bcmath, exif, gd (con freetype/jpeg), gmp, intl, pcntl, pdo_mysql, soap, zip |
| PECL | apcu, imagick, mailparse, redis |
Paquetes de sistema relevantes:
git,curl,zip,unzip: utilidades básicas para Composer y operaciones de build.libfreetype6-dev,libjpeg-dev,libwebp-dev,libpng-dev,libmagickwand-dev: librerías para procesado de imágenes (GD, Imagick).libgmp-dev,libonig-dev,libpq-dev,libssl-dev,libxml2-dev,libzip-dev,libmcrypt-dev,libmemcached-dev: dependencias de las extensiones PHP.tesseract-ocrcon paquetes de idioma (deu,eng,fra,spa): OCR para procesado de documentos (CMRs).
La imagen se reconstruye únicamente cuando es necesario actualizar la versión de PHP, alguna extensión o un paquete de sistema. No forma parte del pipeline automático de la aplicación.
Imagen de aplicación: iris/api
Es la imagen que efectivamente se despliega en cada release. Se construye mediante un Dockerfile multi-etapa que parte de la imagen base:
| Campo | Valor |
|---|---|
| Repositorio ECR | iris/api |
| Dockerfile | docker/php/php.api.dockerfile |
| Imagen base | iris/base/php:8.3.30-fpm |
| Convención de tag | SHA corto (dev), tag semántico X.Y.Z (test y pro) |
Etapas del build:
- Etapa Composer: a partir de la imagen
composer:2.9.5, copia el código fuente y ejecutacomposer installcon flags optimizados para producción:--no-dev: omite dependencias de desarrollo.--optimize-autoloadery--apcu-autoloader: genera un autoload optimizado y cacheable en APCu.--ignore-platform-reqs: ignora los requisitos de plataforma del runtime de Composer (el destino real es la imagen base).
- Etapa final: a partir de la imagen base
iris/base/php, copia el código de la aplicación y los directoriosvendor/ypublic/generados en la etapa anterior. El usuario final del contenedor eslaravel.
El tag de la imagen se inyecta dinámicamente desde el pipeline de Bitbucket y queda reflejado en el campo image.tag del values.yaml del entorno correspondiente.
Despliegue (GitOps)
ArgoCD
Una vez la imagen está publicada y el values.yaml del entorno actualizado, ArgoCD entra en juego. Cada entorno tiene una Application de ArgoCD que apunta al chart Helm infra-iris-api y al values.yaml correspondiente del repo GitOps.
El flujo completo de un despliegue es:
- El pipeline de Bitbucket (o un cambio manual) actualiza el
image.tagen elvalues.yamldel entorno. - ArgoCD detecta el cambio en el repositorio.
- ArgoCD renderiza el chart Helm con los nuevos valores.
- ArgoCD aplica los cambios al cluster (rolling update).
- Tras la sincronización, el Job de migraciones se ejecuta como hook
PostSync.
Migraciones
Las migraciones de base de datos se ejecutan automáticamente como un Job de ArgoCD con hook PostSync:
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
Esto garantiza que las migraciones se ejecuten después de que los pods se hayan actualizado a la nueva versión. El Job tiene un timeout de 300 segundos y 3 reintentos.
Configuración
Esta sección describe cómo se inyecta la configuración a los pods. Hay tres mecanismos diferenciados por su naturaleza: ConfigMaps (no sensible), External Secrets (sensible) y los valores del Helm chart que controlan el dimensionado y comportamiento de cada entorno.
Variables de entorno (ConfigMaps)
Las variables no sensibles se inyectan mediante ConfigMaps. El ConfigMap common contiene la configuración de la aplicación Laravel y se genera a partir del bloque configuration.additionalConfigMaps.common del values.yaml.
Secretos
Los secretos se gestionan mediante External Secrets Operator (ESO), que sincroniza valores desde AWS Secrets Manager hacia Secrets nativos de Kubernetes. La autenticación entre ESO y Secrets Manager utiliza IRSA (IAM Role for Service Accounts), eliminando la necesidad de access keys estáticas dentro del cluster.
| Entorno | Clave en Secrets Manager | IAM Role |
|---|---|---|
| Dev | infraIrisApi/dev/common |
InfraIrisApiDev |
| Dev Features | infraIrisApi/devFeatures |
InfraIrisApiDevFeatures |
| Test | infraIrisApi/test |
InfraIrisApiTest |
| Pro | infraIrisApi/pro |
InfraIrisApiPro |
Los secretos almacenados se agrupan en las siguientes categorías:
| Categoría | Variables | Descripción |
|---|---|---|
| Aplicación | APP_KEY, SECRET_*_ENCRYPT |
Clave de cifrado Laravel |
| Base de datos | DB_*, DB_*_GALOPIN, PRICING_DB_* |
Conexiones MySQL (principal, Galopin, Pricing) |
| Redis | REDIS_*, REDIS_QUEUE_* |
Caché y colas |
| S3 | AWS_BUCKET, AWS_URL, AWS_DEFAULT_REGION |
Almacenamiento de archivos |
| OAuth | PASSPORT_PRIVATE_KEY, PASSPORT_PUBLIC_KEY |
Claves Laravel Passport (Base64) |
MAIL_* |
Configuración SMTP | |
| IMAP | IMAP_* |
Lectura de buzones (operaciones, tracking, Magreb) |
GOOGLE_* |
FCM (push notifications), Maps | |
| Pusher | PUSHER_* |
WebSockets |
| NAS/FTP | NAS_FTP_* |
Acceso a NAS para documentos SUN |
| TicketBAI | CERT_TBAI_*, HTG_*, LICENCIA_TBAI, etc. |
Facturación electrónica TicketBAI |
| Telegram | TELEGRAM_BOT_TOKEN |
Notificaciones Telegram |
Configuración por entorno
Aunque todos los entornos usan el mismo chart, los values.yaml se diferencian para ajustar el dimensionado y el comportamiento al uso esperado:
| Parámetro | Dev | Dev Features | Test | Pro |
|---|---|---|---|---|
image.tag |
SHA commit | SHA commit | Semántico | Semántico |
resources.requests.cpu |
2 | 1 | 1 | 2 |
resources.requests.memory |
2048Mi | 512Mi | 512Mi | 2048Mi |
configuration.phpFpm.maxChildren |
4 | 4 | 4 | 16 |
opcache.memory_consumption |
128 | 128 | 128 | 256 |
autoscaling.enabled |
false | false | false | true |
podDisruptionBudget.enabled |
- | - | - | true |
phpFpmExporter.enabled |
false | false | false | true (sidecar) |
| Workers | 1 (default) |
1 (default) |
1 (default) |
4 tipos con KEDA |
MAIL |
Mailpit (interno) | Mailpit (interno) | Mailpit (interno) | SMTP real |
TICKETBAI_ACTIVE |
false | false | false | true |
Recursos altos en dev
El entorno dev está dimensionado al mismo nivel que producción (2 CPU / 2 GiB) porque se utiliza para reproducir condiciones reales de carga durante el desarrollo. dev-features y test mantienen recursos mínimos al usarse para validación funcional.
Recursos Kubernetes
A partir del chart infra-iris-api y del values.yaml de cada entorno, ArgoCD materializa en el cluster un conjunto de recursos organizados en cinco bloques funcionales: el deployment principal de la API, los workers asíncronos, las tareas programadas, la integración con servicios de plataforma (ALB, ESO, ECR) y las políticas de scheduling.
Esta sección describe qué recursos crea el chart y bajo qué condiciones. Los nombres concretos siguen el patrón infra-iris-api-<entorno> y los valores específicos (réplicas, ARNs, endpoints, IAM roles, certificados ACM) viven en el values.yaml del entorno correspondiente en el repositorio GitOps.
Aplicación
El deployment principal agrupa todos los contenedores del pod web. Algunos son siempre activos y otros se incorporan como sidecars en función de los valores del chart:
| Contenedor | Imagen | Activación | Función |
|---|---|---|---|
nginx |
nginx (versión por entorno) |
Siempre | Servidor HTTP, proxy FastCGI hacia PHP-FPM |
app |
iris/api:<tag> |
Siempre | Aplicación Laravel sobre PHP-FPM 8.3 |
php-fpm-exporter |
hipages/php-fpm_exporter |
phpFpmExporter.enabled |
Métricas Prometheus de PHP-FPM |
temp-cleanup |
busybox |
tempCleanup.enabled |
Sidecar que limpia ficheros temporales antiguos |
Recursos asociados:
| Recurso | Activación | Detalle |
|---|---|---|
| Service | Siempre | ClusterIP, puerto 80 (apunta a nginx) |
| HPA | autoscaling.enabled |
Autoescalado por CPU y métrica PHP-FPM (ver Autoescalado) |
| PodDisruptionBudget | podDisruptionBudget.enabled |
Evita interrupciones simultáneas durante drenajes o consolidación de nodos |
Exposición externa
El acceso desde internet se canaliza a través de un Ingress que el AWS Load Balancer Controller materializa como un Application Load Balancer. La estructura del Ingress es común a todos los entornos; los datos específicos (host público, ARN del certificado, nombre del ALB) se inyectan desde las anotaciones del values.yaml.
| Parámetro estructural | Valor |
|---|---|
IngressClass |
alb |
| Esquema | internet-facing |
| Tipo target | IP (directo a pods, sin pasar por NodePort) |
| Política TLS | ELBSecurityPolicy-TLS13-1-2-2021-06 (TLS 1.3 / 1.2) |
| Redirección HTTP→HTTPS | Habilitada |
| Health check path | /api/v1/test (/ en no-producción) |
| Parámetro por entorno | Origen |
|---|---|
| Host público | ingress.hosts[].host |
| Certificado TLS (ACM) | Anotación alb.ingress.kubernetes.io/certificate-arn |
| Nombre del ALB | Anotación alb.ingress.kubernetes.io/load-balancer-name |
Workers asíncronos
Los workers se despliegan como Deployments independientes (uno por tipo de cola Redis). Cada entrada de workers[] en el values.yaml se traduce en:
- Un
Deploymentque ejecutaphp artisan queue:work --queue=<cola> .... - Opcionalmente un
ScaledObjectde KEDA que escala el deployment según la longitud de la lista Redis correspondiente (worker.autoscaling.enabled). KEDA crea internamente el HPA asociado.
El número y tipo de workers varía por entorno:
- No-producción (
dev,dev-features,test): un único workerdefaultcon réplica fija. - Producción: cuatro workers diferenciados por cola (
default,priority,multimail,vehicle-position-autovalidation), todos con autoescalado KEDA.
Los rangos de réplicas y umbrales de cada worker se definen en pro/values.yaml.
Tareas programadas y puntuales
| Recurso | Nombre lógico | Descripción |
|---|---|---|
| CronJob | laravel-scheduler |
Ejecuta php artisan schedule:run cada minuto (timezone Europe/Madrid) |
| CronJob | run-commands |
Comandos ad-hoc; suspendido por defecto, se activa manualmente cuando se necesita |
| Job | migrations |
php artisan migrate --force; se lanza como hook PostSync de ArgoCD en cada despliegue |
Estos recursos se definen en los bloques cronjobs[] y jobs[] del values.yaml. Cada entrada con enabled: true se materializa como un manifiesto independiente.
Configuración e identidad
Estos recursos no se ejecutan como pods, pero son necesarios para que el deployment funcione correctamente:
| Recurso | Nombre lógico | Función |
|---|---|---|
| ConfigMap | common |
Variables de entorno de la aplicación Laravel |
| ConfigMap | nginx |
Configuración del servidor nginx |
| ConfigMap | php |
Directivas de php.ini (timezone, opcache, memory_limit, etc.) |
| ConfigMap | php-fpm |
Configuración del pool FPM (www.conf, overrides) |
| SecretStore | aws-secretsmanager |
Conexión de ESO con AWS Secrets Manager (autenticación IRSA) |
| ExternalSecret | common |
Sincroniza los secretos de la aplicación a un Secret de K8s |
| ExternalSecret | ecr-image-pull-secret |
Genera el dockerconfigjson necesario para pull de imágenes desde ECR |
| ServiceAccount | infra-iris-api-<env> |
IRSA para Secrets Manager (rol InfraIrisApi<Env>) |
| ServiceAccount | infra-iris-api-<env>-ecr |
IRSA para ECR (rol ecr-access-shared-htg-{pro|nonpro}) |
| PodMonitor | infra-iris-api-<env> |
Configura Prometheus para recolectar métricas del php-fpm-exporter (solo si está activo) |
Autoescalado
El chart soporta dos mecanismos de autoescalado independientes:
HPA del deployment principal (activado por autoscaling.enabled). Se basa en dos métricas combinadas:
| Métrica | Origen | Configurable en |
|---|---|---|
| CPU | Uso medio de CPU de los pods | autoscaling.targets.cpu |
phpFpmProcessUtilization |
Porcentaje de procesos PHP-FPM activos (php-fpm-exporter + PodMonitor) | autoscaling.targets.phpFpmProcessUtilization |
Los rangos minReplicas / maxReplicas y los targets concretos se definen en el values.yaml del entorno. En los entornos de no-producción el HPA está deshabilitado y se usa una réplica fija.
KEDA para workers (activado por workers[].autoscaling.enabled). Cada worker tiene su propia configuración de escalado dirigida por eventos de cola Redis, lo que permite que workers de baja prioridad lleguen a una réplica residual mientras que workers críticos arranquen con un mínimo alto para absorber picos. Los parámetros (minReplicaCount, maxReplicaCount, listLength, pollingInterval, cooldownPeriod) se definen por entrada en el values.yaml.
Scheduling
Los pods están configurados para ejecutarse en el NodePool compute de Karpenter, separado del NodePool por defecto del cluster. Esto se logra combinando nodeSelector y tolerations:
nodeSelector:
node-pool: compute
tolerations:
- key: karpenter.sh/nodepool
value: compute
effect: NoSchedule
El deployment principal aplica además una regla de anti-afinidad preferente para distribuir las réplicas en nodos distintos y mejorar la tolerancia a fallos de nodo:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: infra-iris-api
topologyKey: kubernetes.io/hostname
Operaciones
Health checks
La aplicación expone health checks en dos niveles, configurados como probes del pod principal:
| Probe | Puerto | Path | Descripción |
|---|---|---|---|
| Startup | 80 (Nginx) | /api/v1/test |
Espera hasta 60s (30 intentos × 2s) a que la app arranque |
| Readiness | 9000 (PHP-FPM) | TCP | Verifica que PHP-FPM acepta conexiones |
| Liveness | 9000 (PHP-FPM) | TCP | Reinicia el pod si PHP-FPM deja de responder |
Verificar manualmente desde fuera del cluster:
curl -s https://iris-api.htg-express.com/api/v1/test
Logs
Los logs se centralizan en CloudWatch Logs mediante Fluent Bit (aws-for-fluent-bit, desplegado como DaemonSet en kube-system).
Flujo de logs
Fluent Bit recoge los logs de stdout/stderr de cada contenedor (/var/log/containers/*.log) y aplica un pipeline con dos ramas: una específica para IRIS API y un OUTPUT catch-all para el resto del cluster.
graph LR
Containers["/var/log/containers/*.log"] --> Tail[Input: tail]
Tail --> K8sFilter[Filter: kubernetes]
K8sFilter -->|Pod infra-iris-api*| IrisRewrite[Rewrite tag + JSON parser]
K8sFilter -->|Resto| CatchAll[(Log group catch-all)]
IrisRewrite --> IrisOutput[(Log group infra-iris-api)]
- Pods de la API y el scheduler (
infra-iris-api-*, contenedoresappynginx): los logs vienen en formato JSON estructurado desde Laravel. Fluent Bit aplica un parser JSON, eleva el bloquecontextal nivel raíz y los envía al log group de la aplicación, usando el campostreamdel log como nombre del stream CloudWatch. - Workers de cola, cronjob
run-commands, sidecars (temp-cleanup,php-fpm-exporter) y resto del cluster: caen en el OUTPUT catch-all, sin parser JSON, en un único log group por cluster.
Log groups
Los nombres siguen el patrón /aws/eks/<cluster>/.... En el cluster de producción:
| Log group | Contenido | Streams | Retención |
|---|---|---|---|
/aws/eks/htg-pro/infra-iris-api/infra-iris-api-pro |
Logs estructurados de la API y el scheduler | Uno por área de la aplicación (bill, client, transport, app_login, alarms, auto_bill...) |
14 días |
/aws/eks/htg-pro/infra-iris-api/default |
Fallback cuando un pod infra-iris-api* emite logs sin el campo stream |
default |
14 días |
/aws/eks/htg-pro/aws-fluentbit-logs |
Catch-all del cluster: workers, sidecars, demás namespaces | Prefijo fluentbit-kube.var.log.containers.* |
14 días |
Los entornos de no-producción siguen el mismo patrón en su cluster correspondiente.
Variable AWS_CLOUDWATCH_GROUP
El ConfigMap common incluye una variable AWS_CLOUDWATCH_GROUP (/pro/service/iris, /dev/service/iris...). Es herencia de la configuración anterior y no se usa en el flujo actual vía Fluent Bit; queda disponible por si alguna integración necesita escribir directamente con el SDK de AWS.
Queries guardadas en CloudWatch Logs Insights
Existe un conjunto de queries preconfiguradas para acelerar el troubleshooting habitual. Se acceden desde CloudWatch → Logs Insights → Queries → Saved queries. Todas atacan el log group catch-all /aws/eks/htg-pro/aws-fluentbit-logs, ya que los workers son la principal fuente de actividad asíncrona a inspeccionar.
| Query | Propósito |
|---|---|
API pro/default-worker - Actividad |
Últimos 200 mensajes del worker default |
API pro/priority-worker - Actividad |
Últimos 200 mensajes del worker priority |
API pro/multimail-worker - Actividad |
Últimos 200 mensajes del worker multimail |
API pro/vehicle-position-autovalidation-worker - Actividad |
Últimos 200 mensajes del worker correspondiente |
API pro/Errores Workers |
Logs de default-worker con data.level_name = ERROR |
API pro/Errores (FAIL) por worker |
Mensajes con FAIL en cualquier worker (últimas 100 entradas) |
API pro/Errores TLS-SMTP |
Fallos relacionados con TLS o STARTTLS en envíos SMTP |
API pro/Resumen jobs por worker y hora |
Conteo agregado de jobs DONE/FAIL por worker y franja horaria |
Consultas ad-hoc
Para investigaciones puntuales:
# Logs estructurados de la API (con context Laravel)
aws logs tail /aws/eks/htg-pro/infra-iris-api/infra-iris-api-pro \
--profile htg-pro --region eu-south-2 --follow
# Logs del catch-all filtrando por worker
aws logs tail /aws/eks/htg-pro/aws-fluentbit-logs \
--profile htg-pro --region eu-south-2 --follow \
--filter-pattern 'default-worker'
# Logs directos desde kubectl (sin pasar por CloudWatch)
kubectl logs -n infra-iris-api-pro deployment/infra-iris-api-pro -c app --tail=100 -f
kubectl logs -n infra-iris-api-pro deployment/default-worker -c app --tail=100 -f
Referencia técnica
Stack
| Capa | Tecnología | Versión |
|---|---|---|
| Runtime | PHP-FPM | 8.3 |
| Framework | Laravel | 10 |
| Web server | Nginx | 1.28 |
| Base de datos | Aurora MySQL / RDS MySQL | 8.0 |
| Caché y colas | ElastiCache Redis | - |
| Almacenamiento | Amazon S3 | - |
| Contenedor | Docker | Multi-stage |
| Orquestación | Kubernetes (EKS) | 1.32 |
| CI/CD | Bitbucket Pipelines | - |
| GitOps | ArgoCD | - |
| Helm chart | infra-iris-api |
0.4.6 |
| Autoescalado workers | KEDA | - |
| Secretos | AWS Secrets Manager + ESO | - |
| Métricas PHP-FPM | php-fpm_exporter + PodMonitor | 2.2 |
| Reloader | Stakater Reloader | - |
| Autenticación API | Laravel Passport (OAuth 2.0) | - |