Diseño E Implementación De Una Arquitectura Cloud-Native Basada en Microservicios Desplegados en Kubernetes

1 Introducción
Este artículo aborda la implementación de una infraestructura cloud-native desplegada en Amazon Web Services (AWS), basada en una arquitectura de microservicios desarrollados en Go. Asimismo, se incorpora un pipeline de integración y despliegue continuo (CI/CD) que permite automatizar el proceso de despliegue, así como garantizar la alta disponibilidad, la tolerancia a fallos y el escalado de los servicios mediante el uso de workflows en GitHub y herramientas como FluxCD.
La infraestructura propuesta representa un escenario habitual en entornos de producción actuales, donde las arquitecturas basadas en microservicios han sustituido en gran medida a los sistemas monolíticos tradicionales. En estos últimos, la aplicación se construye como una única unidad, lo que puede simplificar el desarrollo inicial, pero introduce limitaciones a medida que el sistema crece en complejidad. En particular, la acumulación de responsabilidades en un único componente dificulta su mantenimiento y provoca que un fallo pueda afectar al sistema completo.
Por el contrario, en una arquitectura de microservicios, cada componente se encarga de una funcionalidad específica y opera de forma independiente. Esto permite mejorar la disponibilidad del sistema, ya que el fallo de un servicio no implica la caída total de la aplicación. Además, el desacoplamiento entre servicios facilita la evolución del sistema y la incorporación de nuevas funcionalidades, así como su escalabilidad y mantenibilidad a largo plazo.
En cuanto al uso de plataformas cloud, estas, en comparación con infraestructuras tradicionales basadas en servidores locales, permiten disponer de recursos bajo demanda, facilitando la escalabilidad, la alta disponibilidad y la gestión de la infraestructura. En este contexto, proveedores como AWS, Microsoft Azure o Google Cloud ofrecen servicios gestionados que simplifican el despliegue y la operación de aplicaciones distribuidas.
La adopción de una arquitectura cloud-native supone un reto, especialmente en lo relativo al despliegue, la gestión de la infraestructura y la comunicación entre servicios. Herramientas como Kubernetes o los sistemas de CI/CD permiten abordar estos desafíos.
Para poder llevar esto a cabo, se emplea Terraform para el aprovisionamiento de la infraestructura en la nube. Sobre esta infraestructura, se despliega un clúster Kubernetes en el que se utiliza FluxCD como herramienta de entrega continua, conectada a un repositorio de GitHub que contiene los manifiestos necesarios para el despliegue y gestión de la aplicación.
En cuanto a la aplicación desarrollada, esta tiene como finalidad el seguimiento del precio de productos en una determinada web. Para ello, se implementa una arquitectura basada en microservicios compuesta por una API (Application Programming Interface) y un servicio de scraping, complementados con un componente de reprogramación de tareas basado en tecnología serverless mediante AWS Lambda.
Nota: Se presupone que el lector de este artículo cuenta con conocimientos en las tecnologías utilizadas en la realización del trabajo.
Nota 2: La memoria del trabajo aparecerá publicada en la web de la politécnica a finales de mes cuando realice la defensa de la misma. En ella se muestra una explicación más detallada del trabajo, para poder entender el funcionamiento con pocos conocimientos del tema del mismo.
2 Desarrollo
Antes de entrar en materia, conviene hacer una vista de alto nivel al diseño del sistema y la elección del stack tecnológico.
Los microservicios han sido desarrollados en Go (o Golang), un lenguaje diseñado por Google específicamente para abordar problemas de escalabilidad y sistemas distribuidos. La elección de este lenguaje se justifica por su rendimiento cercano a lenguajes de bajo nivel pero con una gestión de memoria simplificada. Además, su adopción es un estándar de facto en el ecosistema cloud-native, siendo el lenguaje en el que se basan infraestructuras críticas como Kubernetes, lo que garantiza una integración óptima y un despliegue eficiente en contenedores.
Para soportar el funcionamiento de estos servicios, se han desplegado los siguientes recursos en AWS:
- Se emplea Amazon DynamoDB para el almacenamiento de los trabajos, así como una instancia de Amazon Relational Database Service (RDS) con PostgreSQL para la gestión de usuarios. Asimismo, se utiliza una función AWS Lambda para la implementación del re-scheduler.
- A nivel de red, se define una Virtual Private Cloud (VPC) que engloba toda la infraestructura, compuesta por dos subredes públicas y dos privadas. En estas últimas se alojan los recursos principales, como el clúster de EKS y la base de datos RDS. La configuración se completa con las correspondientes tablas de enrutamiento, un Internet Gateway y un NAT Gateway para habilitar la conectividad externa.
- Se utiliza Amazon Simple Notification Service (SNS) para la notificación de cambios de precio a los usuarios.
- Para la gestión de colas de mensajes se emplea Amazon Simple Queue Service (SQS).
- Amazon CloudWatch se utiliza para la recopilación y monitorización de métricas del sistema.
- Amazon Route 53 se emplea para la gestión de nombres de dominio, proporcionando un punto de acceso estable a determinados recursos de la infraestructura.
- Finalmente, se despliega un clúster de Amazon Elastic Kubernetes Service (EKS) en el que se instala FluxCD. Mediante un enfoque GitOps, este se encarga de aplicar los manifiestos definidos en un repositorio de GitHub y garantizar la consistencia entre el estado deseado y el estado real del sistema. Adicionalmente, se despliega el Ingress Controller de NGINX, que expone la aplicación mediante un Elastic Load Balancer (ELB), actuando como punto de entrada externo.
El controlador de Ingress NGINX está deprecado, sin actualizaciones desde marzo de 2026. La alternatiba natural sería utilizar el Gateway API de Kubernetes.
En la siguiente figura se muestra el diagrama de la arquitectura de la infraestructura desplegada, proporcionando una visión global de los componentes descritos.

¿Por qué este stack y no otro?
Para las bases de datos, se optó por dos soluciones según el caso de uso: DynamoDB para los jobs (acceso simple por clave, sin joins) y RDS PostgreSQL para usuarios (datos relacionales con garantías ACID). Cada una donde tiene sentido.
En mensajería, se descartó Kafka por ser excesivo para este volumen — requiere mantener un clúster propio y está pensado para millones de eventos. Con SQS/SNS es suficiente y sin overhead operativo. Se eligió SNS sobre SES para las notificaciones por su flexibilidad para añadir canales adicionales como SMS sin modificar la arquitectura.
El re-scheduler se implementó como Lambda en vez de un pod de Kubernetes. Su lógica es reducida y se ejecuta puntualmente, por lo que no tiene sentido mantener un proceso corriendo 24/7 sin carga.
Para la orquestación, la decisión estuvo entre EKS, ECS y EC2. ECS es más sencillo pero ata al ecosistema AWS. EC2 implicaría gestionar la orquestación manualmente, inviable para este proyecto. Se eligió EKS por su portabilidad, su ecosistema consolidado (FluxCD, NGINX Ingress…) y por ser el estándar en entornos profesionales.
Finalmente, se escogió Terraform sobre CloudFormation por ser agnóstico al proveedor, tener un ecosistema de módulos más amplio y un lenguaje (HCL) más legible y mantenible.
2.1 Microservicios
Los microservicios de la arquitectura, desarrollados en Go, desplegados en los worker nodes del clúster de EKS mediante FluxCD, tal y como se describe en la sección de Automatización y Pipeline CI/CD. El funcionamiento de estos microservicios queda ilustrado en la siguiente figura:

El usuario se registra e inicia sesión en la aplicación a través del API Gateway. Una vez autenticado, recibe en una cookie el token JWT con el que puede acceder a los endpoints /validate, /jobs (GET, POST, DELETE) y /jobs/:id.
Al registrarse, el usuario recibe un correo de Amazon SNS solicitando su suscripción para poder ser notificado. Cuando se crea un job (compuesto de la URL del producto y el precio objetivo), este se encola en SQS. El scraper consume la cola mediante 5 hilos en paralelo: extrae la URL y el precio, hace scraping de la web y compara con el precio objetivo. Si el precio es igual o inferior, se notifica al usuario vía email.
El re-scheduler se encarga de reencolar los trabajos que, tras ser procesados por el scraper, no han alcanzado la condición deseada. Una vez que el scraper elimina el mensaje de la cola, el re-scheduler evalúa el último precio registrado y, si no se cumple la condición, genera un nuevo mensaje en SQS para su próximo ciclo.
El código fuente del API Gateway y del Scraper está disponible en los repositorios públicos de GitHub, mientras que el código del re-scheduler, al tratarse de una función Lambda de menor extensión, se incluye en el Anexo.
2.1.1 API Gateway
Para el desarrollo de este microservicio se ha optado por la librería Gin, un framework de Go ligero orientado a la construcción de APIs REST, así como por el SDK de AWS para Go.
El punto de entrada de la aplicación se encuentra en main.go. Antes de inicializar el router, se ejecuta una función init en la que se establecen las conexiones con los servicios externos:
| |
A continuación, en la función principal, se configura el router y se definen los endpoints:
| |
La API queda expuesta en el puerto 9090, accesible desde el exterior a través del ELB bajo el prefijo /api/v1. El middleware de autenticación se sitúa deliberadamente después de los endpoints públicos de autenticación.
Durante el registro (/signup), el usuario envía sus credenciales, se genera un hash de la contraseña y se almacena en PostgreSQL. Adicionalmente, el usuario es suscrito a un topic de SNS. Para el inicio de sesión (/signin), se valida la contraseña y se genera un JWT firmado:
| |
El middleware de autenticación obtiene el token desde la cookie y procede a su validación:
| |
En cuanto a la estructura de datos persistida en DynamoDB para los jobs:
| |
Las pruebas de los handlers se realizan de forma aislada mediante mocks de las dependencias externas, definiendo una interfaz que abstrae la operación PutItem:
| |
Esto permite inyectar una implementación simulada durante los tests sin necesidad de conexiones reales con AWS.
Además de la implementación funcional, el repositorio incorpora un flujo de integración continua definido mediante GitHub Actions. Dicho flujo automatiza la ejecución de pruebas, la construcción de la imagen de contenedor a partir del Dockerfile ubicado en la raíz del proyecto, y el almacenamiento de dicha imagen en el GHCR (ilustrado en el diagrama de los micros), garantizando que cada cambio validado pueda integrarse en condiciones reproducibles
2.1.2 Scraper
Para el desarrollo de este microservicio se ha optado por Playwright, una biblioteca de automatización de navegadores, junto con el SDK de AWS para Go.
Al igual que en el API Gateway, antes de la ejecución de la función principal se inicializan las conexiones con DynamoDB, SQS y SNS mediante una función init.
La función main define una estrategia de procesamiento concurrente basada en cinco workers:
| |
Cada worker actualiza el estado del job a processing antes de procesarlo, evitando que el re-scheduler lo reencole de forma prematura. La extracción se realiza lanzando un navegador Firefox en modo headless:
| |
Una vez creada la página, el servicio navega hasta la URL del job y localiza los selectores del título y precio según el dominio (Amazon, PCComponentes). Si el precio actual es inferior o igual al objetivo, el job pasa a estado notified y se envía una notificación via SNS. En caso contrario, el estado se actualiza a active y se almacena el último precio para el siguiente ciclo.
Finalmente, al igual que en el API Gateway, el repositorio incorpora un flujo de integración continua definido mediante GitHub Actions. Dicho flujo automatiza la ejecución de pruebas, la construcción de la imagen del servicio a partir del Dockerfile definido en la raíz del repositorio y su publicación en el GHCR.
2.1.3 Lambda Re-Scheduler
El re-scheduler se ha implementado como una función AWS Lambda cuya responsabilidad consiste en reencolar los trabajos que continúan en estado active tras haber sido procesados por el scraper. Consulta DynamoDB, identifica los jobs que no han alcanzado el precio objetivo y genera un nuevo mensaje en SQS.
Su interés no reside en la complejidad algorítmica sino en la decisión arquitectónica de desacoplar la lógica de replanificación del proceso principal de scraping, aprovechando el modelo serverless de AWS Lambda.
2.2 Infraestructura como Código (IaC)
El aprovisionamiento de la infraestructura se ha automatizado mediante Terraform. Una de las motivaciones principales es ajustarse al presupuesto del entorno AWS Academy Learner Lab (límite de 50$): gracias a IaC, se puede levantar y eliminar toda la infraestructura en minutos.
El código fuente descrito en esta sección puede encontrarse en el repositorio de GitHub.
Los recursos están estructurados en módulos:
| |
Estos módulos nos sirven para levantar los recursos mostrados en la siguiente imagen:

Nota: por cuestiones de alcance, el topic de SNS, la cola SQS y la función Lambda del re-scheduler se desplegaron manualmente. El entorno Learner Lab regenera ARNs en cada sesión, lo que hacía inviable gestionarlos desde Terraform sin complejidad añadida.
Para la configuración de la función Lambda, se crea una nueva instancia indicando un nombre y seleccionando Amazon Linux 2023 como runtime. Posteriormente, en la opción Configure custom execution role, se selecciona el rol existente LabRole. En caso de no especificar un rol manualmente, AWS intentaría generar uno automáticamente; sin embargo, esta funcionalidad se encuentra restringida en el entorno utilizado.
Finalmente, se añade el código fuente de la función. Para ello, es necesario compilarlo previamente:
| |
El trigger se configura mediante Amazon EventBridge con una regla que se ejecuta cada minuto, y por último añadimos las variables de entorno utilizadas por la Lambda.
Para la configuración de SQS, se modifican dos parámetros relevantes: el tamaño máximo de mensaje (256 KB) y el Receive message wait time (20 segundos), para reducir el número de respuestas vacías del polling continuo del scraper.

En cuanto a la creación del topic, se le asigna un nombre (PricesNotification) y se habilita el cifrado, manteniéndose el resto de parámetros con su configuración por defecto.
Respecto al tfstate, en un entorno real se almacenaría en un bucket de S3 (Simple Storage Service) con state locking mediante DynamoDB, para ello hacemos uso del módulo público tfstate-backend de Cloud Posse:
| |
En la configuración de la VPC se definen dos subredes públicas y dos privadas en distintas zonas de disponibilidad:
| |
En EKS se habilita el cifrado de secretos mediante AWS KMS:
| |
RDS se configura como no accesible públicamente, con un Security Group que restringe el acceso solo al clúster EKS:
| |
Se configuran alarmas en CloudWatch para errores de Lambda, CPU de RDS/EKS y longitud de la cola SQS, notificando a un topic de SNS cifrado con KMS:
| |
Por último, Route53 expone un alias estable para RDS (db.dev.internal), evitando modificar la configuración de los microservicios cuando se recrea la instancia:
| |
La estimación de costes de la infraestructura, calculada con Infracost, asciende a 187$/mes con todos los recursos activos 24/7. En la práctica, solo se consumieron 19$ durante el desarrollo del TFG gracias a levantar y destruir la infra según la necesidad.
| Módulo | Recurso | Coste mensual (USD) |
|---|---|---|
| eks | Cluster EKS | $73.00 |
| eks | Node Group (2x t3.medium + 40GB gp2) | $64.74 |
| networks | NAT Gateway | $32.85 |
| rds | RDS PostgreSQL db.t3.micro + 20GB gp2 | $15.44 |
| cloudwatch | Alarmas CloudWatch (4x standard) | $0.40 |
| route53 | Hosted Zone | $0.50 |
| terraform_state_backend | S3 + DynamoDB (estado Terraform) | variable |
| dynamo | DynamoDB tabla jobs | variable |
| cloudwatch | SNS Topic Alarms | variable |
| Total base mensual | $186.93 |
Los recursos marcados como variable dependen del uso (peticiones, almacenamiento, notificaciones) y tienen coste cero o mínimo en el entorno de desarrollo. El coste total base corresponde a recursos con precio fijo independiente del tráfico.
2.3 Orquestación con Kubernetes
La orquestación en Kubernetes se apoya en Ingress, Services, Deployments, ConfigMaps, Secrets, metrics-server y HPA, desplegados mediante FluxCD (explicación en la sección Automatización y Pipeline CI/CD).
La API escucha en el puerto 9090, expuesta mediante un Service de tipo ClusterIP:
| |
Para gestionar la entrada de tráfico se utiliza el Ingress Controller de NGINX, instalado mediante HelmRelease y HelmRepository. En la definición del Ingress se especifican las reglas de enrutamiento HTTP hacia el servicio correspondiente. En particular, se define la ruta raíz (/) para redirigir todas las peticiones entrantes hacia el Service de la API:
| |
En el values.yaml se define un Service de tipo LoadBalancer para el Ingress Controller, lo que provoca la creación automática de un ELB en AWS:
| |
Por otro lado, se hace uso de los recursos ConfigMap para la inyección de variables deconfiguración no sensibles en los microservicios, así como Secret para el almacenamientode información sensible, como credenciales de AWS o webhooks externos.
Los secretos (credenciales AWS, webhook Discord, conexión a RDS) se crean manualmente en el clúster y no se incluyen en el repositorio por motivos de seguridad:
| |
En este caso se definen tres secretos: uno para el webhook de Discord, otro con las credenciales de AWS necesarias para que los microservicios interactúen con los servicios del proveedor, y un tercero con la configuración de acceso a la base de datos Postgres desplegada en RDS.
Por último, se configura un metric server, encargado de exponer las métricas de CPU y memoria de los pods a la API de Kubernetes, requisito indispensable para el funcionamiento del HPA.
2.4 Automatización y Pipeline CI/CD
El ciclo de vida del software se apoya en dos mecanismos complementarios: GitHub Actions para la integración continua y FluxCD para la entrega continua. GitHub Actions valida el código, ejecuta pruebas y construye imágenes de contenedor; FluxCD implementa el enfoque GitOps sobre EKS tomando un repositorio Git como única fuente de verdad.
El código completo de FluxCD se encuentra en el repositorio público flux-repo-tfg.
FluxCD se inicializa con:
| |
Una vez completado el proceso de bootstrap, FluxCD despliega y mantiene sincronizados los recursos definidos en el repositorio, entre los que se incluyen los manifiestos de los microservicios, los servicios internos, las reglas de ingress, el servidor de métricas, las configuraciones asociadas al registro de imágenes y los objetos necesarios para automatizar la actualización de versiones desplegadas en el clúster. En la imagen de la sección de microservicios se ilustran algunos de los componentes desplegados por Flux.
Como caso de uso representativo, puede considerarse la monitorización de nuevas versiones de imágenes en GHCR y la actualización automática de los manifiestos. La política de actualización automática de imágenes:
| |
| |
Por último, para materializar estos cambios en el repositorio GitOps se utiliza un recurso de tipo ImageUpdateAutomation, encargado de actualizar automáticamente los manifiestos cuando se detecta una nueva versión válida de la imagen.
Con este enfoque, al hacer push al repositorio del microservicio, GitHub Actions construye y publica la nueva imagen en GHCR; FluxCD detecta la nueva versión, actualiza el manifiesto automáticamente (commit del bot de Flux) y reconcilia el clúster, enviando una notificación a Discord.
2.5 Comunicación entre servicios
La comunicación entre componentes sigue un modelo asíncrono y desacoplado. En lugar de llamadas directas entre microservicios, el intercambio se realiza mediante SQS como intermediario, y SNS como canal de salida para notificaciones.
El flujo completo:
- El usuario llama al API Gateway, que encola el mensaje en SQS.
- El scraper lee de esa cola y procesa el mensaje.
- Si el precio alcanzó el objetivo se notifica via SNS al usuario.
- Si no, la Lambda consulta DynamoDB buscando jobs en estado
activey los reinserta en SQS para el siguiente ciclo.
Este flujo queda ilustrado en la siguiente imagen:

Se configura un visibility timeout de 30 segundos en SQS para garantizar que un mensaje no sea consumido por múltiples workers simultáneamente. Además, el scraper actualiza el estado del job a processing en DynamoDB antes de procesarlo, evitando que el re-scheduler lo reencole de forma prematura.
2.6 Seguridad
En términos de seguridad se distingue entre security-of-the-cloud (responsabilidad de AWS: hardware, red física, hipervisores…) y security-in-the-cloud (responsabilidad del desarrollador):
- At-rest: cifrado habilitado en RDS PostgreSQL y en la tabla DynamoDB.
- In-transit: como limitación, no se ha configurado TLS, por lo que las comunicaciones externas se realizan mediante HTTP. La comunicación interna entre pods tampoco cuenta con TLS al no haberse implementado un service mesh.
Por otra parte, a nivel de filtrado de red, para el control del tráfico a la RDS se hace uso de los Security Groups, aceptando solo el procedente del Security Group del clúster de EKS, como se muestra a continuación:
| |
El acceso a la aplicación se controla a través del API Gateway con autenticación JWT. A nivel de infraestructura, la separación entre subredes públicas y privadas garantiza que solo los componentes que requieren exposición exterior sean accesibles desde Internet. La entrada al sistema se centraliza a través del Ingress Controller y del ELB, reduciendo así la superficie de exposición de la arquitectura.
Por último, la configuración de los servicios desplegados en Kubernetes se gestiona mediante ConfigMaps y recursos de tipo Secret. Esta separación permite distinguir entre parámetros de configuración no sensibles y credenciales o valores confidenciales, manteniendo una separación entre configuración general y credenciales sensibles dentro de los manifiestos del clúster.

2.7 Escalabilidad y Recursos
El sistema se diseñó teniendo en cuenta la escalabilidad y el uso eficiente de recursos. Se aplicaron dos mecanismos principales:
- Resource requests y limits en los Deployments para evitar que un pod consuma todos los recursos del nodo.
- HPA para el scraper y la API, ajustando dinámicamente el número de réplicas según la carga.
Límites definidos para la API:
| |
Y para el scraper (ajustados tras un OOMKilled durante las pruebas):
| |
El HPA se configuró con un umbral del 50% de CPU y un rango de 1 a 10 réplicas para la API, y de 1 a 4 para el scraper. El grupo de nodos EKS se diseñó con un mínimo de 1 nodo, un deseado de 2 y un máximo de 3 instancias t3.medium (2 vCPUs, 4 GB RAM), con capacidad para escalar hasta 6 cores y 12 GB mediante el Cluster Autoscaler.
Escalar el scraper por CPU no es lo ideal, ya que es un servicio asíncrono cuya carga depende del número de mensajes en la cola SQS, no del tráfico HTTP. Se usa la CPU como métrica proxy dada la ausencia de un HPA basado en métricas personalizadas. Una mejora futura sería adoptar KEDA para escalar en base al número de mensajes en SQS.

3 Validación y Pruebas
En este capítulo se valida el correcto funcionamiento del sistema, tanto a nivel funcional como de infraestructura y automatización del despliegue.
3.1 Validación funcional de la API
3.1.1 Endpoint /signup
La API permite registrar correctamente un nuevo usuario.

Tras el registro, la API suscribe automáticamente al usuario a un topic de SNS, enviando un correo de confirmación.

Como podemos observar, el usuario queda registrado como suscriptor una vez aceptada la invitación.

También se ha validado el comportamiento ante errores, como la ausencia del campo contraseña.

3.1.2 Endpoint /signin
La API autentica al usuario correctamente con credenciales válidas, generando una cookie con el token JWT.
Con credenciales incorrectas devuelve error de autenticación, y sin sesión activa devuelve 401 Unauthorized.
3.1.3 Endpoint /validate
Permite comprobar si el usuario se encuentra autenticado mediante la cookie de sesión.

3.1.4 Endpoint /jobs
Permite crear, listar y eliminar trabajos del usuario autenticado.
Al crear un job con un precio objetivo superior al precio actual, el sistema envía un email con el asunto Price Alert, confirmando el correcto funcionamiento del flujo de notificaciones.
Si falta algún parámetro se devuelve un 400 Bad Request:

Listar los trabajos:

Borrar los trabajos:

3.1.5 Endpoint /jobs/:id
Permite consultar o eliminar un trabajo concreto por su identificador. Si no existe, devuelve 404 Not Found.
3.2 Procesamiento asíncrono de trabajos
Al crear un trabajo, este se almacena con estado pending. Una vez procesado por el scraper, el estado pasa a active y se actualiza el último precio. En algún momento intermedio puede observarse el estado processing, indicando que el scraper ha leído el trabajo de la cola SQS.

3.3 Monitorización del sistema
Para validar el comportamiento de los componentes asíncronos se utilizaron las herramientas de monitorización de AWS.
3.4 Validación de la infraestructura
Se configuraron alarmas en CloudWatch para monitorizar el estado de los recursos desplegados.

3.5 Automatización del despliegue
Al realizar un commit en el repositorio, GitHub Actions construye y publica automáticamente la nueva imagen. FluxCD detecta la nueva versión, actualiza el manifiesto (commit automático del bot de Flux) y genera una notificación en Discord confirmando la reconciliación del clúster.
3.6 Pruebas de carga y rendimiento
Una vez validado el funcionamiento del sistema, se realizaron pruebas de carga con k6 para analizar su comportamiento bajo diferentes niveles de demanda.
Como se ha mencionado en la sección de Escalabilidad y Recursos, el scraper debería escalarse en función de parámetros como el número de mensajes en la cola y no el uso de CPU. Por ello, estas pruebas evalúan principalmente la capacidad de respuesta de la API.
3.6.1 Test de Carga
El objetivo de esta prueba es determinar cómo responderá el sistema ante una carga constante. En este ejemplo utilizamos 50 usuarios virtuales concurrentes durante 4 minutos ejecutando llamadas HTTP GET al endpoint /jobs.
| |
Resultado: 100% de checks exitosos sobre 6.837 peticiones, latencia media de 541ms, mediana de 114ms y p(95) de 2.26s.

3.6.2 Test de Estrés
En una prueba de estrés, lo que queremos ver es como la aplicación manejará una carga mayor. En este caso, empezamos con una carga de 100 usuarios virtuales y vamos escalándolo progresivamente:
| |
Resultado: 80.145 peticiones a 333 req/s, latencia media de 147ms, mediana de 110ms. Solo un 0.61% de fallos (491 peticiones) en los momentos de mayor carga con 1000 VUs simultáneos.

3.6.3 Test de Pico
Pueden darse escenarios en los que el sistema reciba un pico repentino de tráfico y no sea capaz de responder adecuadamente. En el fragmento que se muestra a continuación se simula una transición brusca desde una carga moderada de 50 usuarios virtuales hasta 2000 usuarios virtuales en tan solo 10 segundos:
| |
Resultado: 71.54% de fallos, todos por timeout, con latencia media de 18.5s. El HPA no dispone de tiempo suficiente para reaccionar ante un incremento tan abrupto: el comportamiento esperado en un spike test.

3.6.4 Resumen
En la tabla se muestra un resumen con los resultados de las pruebas.
| Escenario | VUs | Peticiones | Tasa de error | Latencia media | P95 |
|---|---|---|---|---|---|
| Carga (sostenida) | 50 | 6.837 | 0,00% | 541ms | 2.260ms |
| Estrés (progresiva) | 1.000 | 80.145 | 0,61% | 147ms | 151ms |
| Pico (avalancha) | 2.000 | 8.518 | 71,54% | 18.510ms | >60.000ms |
4 Vídeo DEMO
5 Conclusiones
Este trabajo sirve para entender la importancia que tienen actualmente los diseños de arquitecturas basadas en microservicios, así como el enfoque cloud-native.
Hemos profundizado en todas las etapas del ciclo de vida de una aplicación hasta llegar a producción, desde el desarrollo, empezando por la elección del stack tecnológico, pasando por la contenerización y validación de los servicios, automatizados mediante GitHub Actions, acabando con el despliegue en un clúster de EKS utilizando una herramienta basada en GitOps, como es FluxCD, en la que mediante un repositorio como única fuente de verdad, definimos el estado deseado del clúster.
También hemos indagado en el despliegue de una infraestructura automatizada mediante Infraestructura como Código, pudiendo levantarla de forma declarativa y persistente, y almacenando el estado de la misma en un backend de S3.
Nuevamente, todo el código está disponible en los repositorios de GitHub de mi cuenta.
👉 https://github.com/azuar4e/api-gateway-tfg
👉 https://github.com/azuar4e/scraper-tfg
Gracias por leer, nos vemos en la próxima, ¡Cuidaos! 👋
6 Anexo
| |













