🛠️ Automatizando pruebas de rendimiento con n8n + K6.io + IA (POC)

11 September, 2025 | IA

En los equipos de QA y DevOps uno de los retos más frecuentes es entender cuanto soporta una aplicación bajo carga antes de empezar a fallar. Las herramientas tradicionales permiten hacer pruebas de rendimiento, pero muchas veces requieren configuraciones estáticas.

¿Qué pasaría si pudiéramos automatizar este ajuste y dejar que un flujo inteligente vaya calibrando la prueba hasta encontrar el punto de quiebre?

En este artículo te comparto un Proof of Concept (POC) donde combino n8n, K6.io y un motor de IA (Gemini) para orquestar pruebas de rendimiento con auto-tuning. El objetivo no es reemplazar pipelines de CI/CD como GitHub Actions o Azure DevOps, sino explorar cómo la automatización puede ayudarnos a iterar más rápido, registrar métricas clave y detectar patrones de fallo de manera temprana.

Objetivo del POC

  • Ejecutar pruebas de carga con K6 en un contenedor aislado.
  • Recoger métricas clave (p95, throughput, errorRate).
  • Usar IA para decidir ajustes de parámetros en cada iteración.
  • Persistir resultados en PostgreSQL.
  • Consolidar la información en un reporte final.

Arquitectura del flujo

  1. Inicialización de parámetros:
    • vus = 30
    • duration = 30s
    • target = URL objetivo
    • maxIter = 5
  2. Persistencia:
    • Guardar configuración en PostgreSQL con un ID único de ejecución.
  3. Loop de ejecución:
    • Ejecutar script de K6 en un contenedor externo.
    • Generar archivo output.json con métricas.
    • Extraer resultados relevantes.
    • Pasar métricas a un nodo IA para evaluar y decidir nuevos parámetros.
    • Guardar resultados y volver al loop.
  4. Finalización:
    • Recuperar todas las iteraciones desde PostgreSQL.
    • Armar tabla con métricas por iteración.
    • Enviar reporte vía correo o cualquier conector de n8n.

Contenedor de ejecución

Para no sobrecargar el worker de n8n, el script de K6 corre en un contenedor externo.

Ejemplo de comando usado dentro del nodo de SSH:

sh -lc "mkdir -p /workspace/output && \
VUS='{{ $json.vus }}' \
DURATION='{{ $json.duration }}' \
TARGET='{{ $('Init Params').item.json.target }}' \
k6 run --summary-export /workspace/output/out.json /workspace/k6/script.js"

#.dockerfile

FROM grafana/k6:0.51.0 AS k6base

FROM alpine:3.20

# Herramientas mínimas
RUN apk add --no-cache \
      openssh \
      bash \
      git \
      zip \
      docker-cli \
      shadow \
      curl

# Copiar binario de k6 desde la imagen oficial
COPY --from=k6base /usr/bin/k6 /usr/bin/k6

# Usuario 'runner' (solo dev; en prod usa llaves)
RUN adduser -D -s /bin/bash runner && echo "runner:runner" | chpasswd

# Config SSH: permitir password para 'runner' (dev)
# (en producción usa llaves y desactiva PasswordAuthentication)
RUN sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g' /etc/ssh/sshd_config && \
    sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/g' /etc/ssh/sshd_config && \
    sed -i 's/^#\?UsePAM.*/UsePAM no/g' /etc/ssh/sshd_config

# Script de arranque: genera host keys y arranca sshd
RUN printf '%s\n' \
  '#!/bin/sh' \
  'set -e' \
  'ssh-keygen -A' \
  'mkdir -p /var/run/sshd' \
  '# (solo dev) dar permisos al socket docker si existe:' \
  '[ -S /var/run/docker.sock ] && chmod 666 /var/run/docker.sock || true' \
  'exec /usr/sbin/sshd -D -e -p 2222' \
  > /usr/local/bin/start-sshd.sh && chmod +x /usr/local/bin/start-sshd.sh

EXPOSE 2222
CMD ["/usr/local/bin/start-sshd.sh"]

# docker-compose.yml

services:
  nodo-ssh:
    build:
      context: .
    container_name: n8n-runner
    environment:
      - TZ=America/Lima
    volumes:
      - ./workspace:/workspace
    ports:
      - "2222:2222"    # SSH
    restart: unless-stopped

Script de K6

El script de K6 es básico para esta POC.
Su objetivo es generar carga contra el TARGET definido en cada iteración.

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: __ENV.VUS ? parseInt(__ENV.VUS) : 10,
  duration: __ENV.DURATION || '60s',
};

export default function () {
  const url = __ENV.TARGET || 'https://test.k6.io';
  const res = http.get(url);
  check(res, { 'status is 200': (r) => r.status === 200 });
  sleep(1);
}

Extracción de métricas

Del archivo output.json se seleccionan valores clave:

  • status → estado general de la ejecución.
  • p95 → percentil 95 de latencia.
  • throughput → número total de requests completados.
  • errorRate → porcentaje de errores.

Algoritmo de auto-tuning con IA

El corazón de este POC no está solo en correr pruebas con K6, sino en cómo la IA interpreta las métricas y ajusta dinámicamente los parámetros de la siguiente ejecución.

Para guiar al modelo, definimos un prompt estructurado que actúa como política de auto-tuning. El flujo recibe las métricas de la última corrida (p95, errorRate, throughput) junto con los parámetros utilizados (vus, duration, target, iter) y, en base a ellos, decide si aumentar, reducir o detener la prueba.

SLOs definidos

  • Latencia p95 ≤ 500 ms.
  • ErrorRate ≤ 1% (0.01).

Estrategia de ajuste

  1. Si errorRate > 0.01 → reducir VUs en 30%, mantener duración en 90s.
  2. Si p95 > 500 ms → reducir VUs en 20%.
    • Si la iteración anterior también superó los 500 ms, la reducción será del 30%.
  3. Si p95 ≤ 300 ms y errorRate ≤ 0.005 → aumentar VUs 25% y fijar duration=90s.
  4. Si 300 < p95 ≤ 400 ms → aumentar VUs 15%.
  5. Si 400 < p95 ≤ 500 ms → aumentar VUs 5%, manteniendo duration.
  6. Detener (stop=true) cuando:
    • 450 ≤ p95 ≤ 500 ms con errorRate ≤ 0.01, o
    • Un aumento de VUs provoca p95 > 500 ms en 2 iteraciones consecutivas.
  7. Nunca reducir VUs salvo que se violen los SLOs anteriores.

Salida esperada

La IA debe devolver siempre un JSON estricto con la siguiente forma:

{
  "next": { "vus": <entero>, "duration": "<segundos>s" },
  "stop": <true|false>,
  "reason": "<explicación breve>"
}

Persistencia y análisis final

  • Todos los resultados se guardan en PostgreSQL asociados al run_id.
  • Al completar el loop, se consultan todas las iteraciones.
  • Se arma una tabla en HTML

Conclusiones

Este POC demostró que n8n puede ser más que un orquestador de integraciones: también puede convertirse en una herramienta útil para automatizar pruebas técnicas en QA. Al integrar K6.io con un motor de IA logramos:

  • Iterar dinámicamente sobre configuraciones de VUs y duraciones.
  • Analizar métricas clave como p95, errorRate y throughput sin intervención manual.
  • Detectar patrones de degradación más rápido.

Aunque este flujo es experimental y tiene limitaciones, abre la puerta a nuevas formas de aplicar IA en escenarios de testing.

Automatizar pruebas de rendimiento con n8n + K6.io + IA es posible, escalable y promete ahorrar tiempo valioso en QA.

Próximos pasos:

  • Probar con escenarios de mayor carga.
  • Integrar notificaciones en Slack/Teams.
  • Extender criterios de ajuste (CPU, memoria, logs de error).
  • Explorar prompts más optimizados.
  • Conectar resultados a dashboards.
  • Usar datos históricos para predecir puntos de quiebre antes de ejecutar nuevas cargas.