Skip to content

Runbook — Primera instalación real de TLSStress.Art

Lee en tu idioma: English · Português · Español

Estado del alcance (post-congelación de alcance 2026-05-10) — Ver ARCHITECTURE.md para los 37 MÓDULOs canónicos + 7 Test Kinds + arquitectura de safety DOM/CPOS/PIE-PA. ADRs 0014, 0019-0025 cubren adiciones post-Freeze.

Secuencia de onboarding: AccesoCloneInstalarestás aquí · alternativa: Instalación air-gap · setup del mantenedor: Private Repo Setup> Audiencia: Operador que recibió acceso vía Access Broker y está por instalar TLSStress.Art en hardware real por primera vez.

Tiempo estimado: ~2 horas en total. Cada paso tiene tiempo cronometrado.

Por qué existe este runbook

La base de código de TLSStress.Art tiene CI verde, tests unitarios pasando y linting limpio — pero ninguna instalación individual ha sido validada end-to-end contra un Cisco Nexus 9000 + NGFW DUT real antes del operador ejecutarlo. Este runbook es el protocolo que te lleva de "UCS + Nexus en cero" a "primer p99 medido en un panel Grafana", de forma controlada y reproducible.

Si algún paso falla, detente e investiga en vez de saltarte adelante. Las fallas en cada paso tienen procedimientos de recuperación específicos enlazados al final.

Pre-requisitos — antes del paso 1

  • Acceso al repositorio otorgado vía Access Broker (ver ACCESS_REQUEST.es.md)
  • Licencia aceptada a través del License Acceptance Modal del Dashboard (aparece en el primer login)
  • Un host Ubuntu 22.04+ UCS con al menos 32 GB RAM, 16 vCPU, 200 GB disco
  • Un Cisco Nexus 9000 con acceso de gestión vía SSH y puerto trunk disponible
  • Un NGFW DUT (Cisco FTD/ASA/Firepower, Palo Alto, Fortinet o similar) con IP de gestión alcanzable desde el UCS, y trunk-conectado al Nexus
  • IPs de red reservadas:
  • UCS OOBI (eth0): tu red de gestión (ej.: 192.168.90.10/24)
  • IP de gestión del Nexus para scrape SNMP: ej.: 192.168.90.2
  • IP de gestión del NGFW: ej.: 192.168.90.3
  • VLAN 20 (agentes browser engine): 172.16.0.0/16
  • VLAN 30 (agentes synthetic-load engine): 172.17.0.0/16
  • VLANs 101–120 (Synthetic personas): 10.1.{1..20}.0/27, gateway = NGFW
  • VLANs 200–209 (Cloned personas): 10.2.{1..10}.0/27, gateway = NGFW
  • Certificado CA del NGFW en formato PEM, disponible localmente (lo inyectarás como ConfigMap)
  • Archivo .env en la raíz del repo con SNMP_NEXUS_HOST, SNMP_NGFW_HOST, SNMP_COMMUNITY, SNMP_DUT_MODULE (uno de cisco_asa, cisco_firepower, palo_alto, fortinet, generic)

Si algún de estos falta, no procedas. El runbook depende de todos ellos.


Paso 1 — Pre-vuelo de laboratorio (60–90 minutos)

Objetivo: confirmar que el cluster levanta saludable con todas las 30 personas corriendo, antes de cualquier involucramiento del DUT.

1.1 Clona el repositorio en el UCS

Clone autenticado — ver docs/CLONE_FOR_INSTALL.es.md para las cuatro opciones de autenticación. Recomendado para installs permanentes: deploy key SSH (opción B).

ssh ucs-1.example.com
mkdir -p ~/tlsstress && cd ~/tlsstress
# Opción A — gh CLI (recomendado para primera instalación)
sudo apt update && sudo apt install -y gh
gh auth login   # sigue los prompts
gh repo clone nollagluiz/AI_forSE .

Esperado: directorio contiene dashboard/, agent/, personas/, k8s/, platform/, docs/, etc. Tamaño total del clone alrededor de 80 MB.

1.2 Instala K3s + Multus + cert-manager

sudo bash scripts/k8s-install.sh single-node

El script: - Instala K3s - Añade Multus CNI - Añade cert-manager - Aplica labels role=ngfw-dut y dut-data-plane=true al nodo - Configura PV hostpath si es necesario

Esperado (últimas líneas):

✅ K3s up
✅ Multus instalado
✅ cert-manager listo
✅ labels del nodo aplicadas

Verificar:

kubectl get nodes
# esperado: 1 nodo, status Ready, con labels visibles vía:
kubectl get nodes -o wide --show-labels | grep dut-data-plane

1.3 Aplica el stack base

kubectl apply -f k8s/
kubectl apply -k platform/        # Issuers cert-manager + persona-ca-issuer
kubectl apply -k personas/        # 20 Synthetic personas

Espera a que las personas estén Ready (toma 2–5 minutos la primera vez mientras el seeder genera contenido):

watch -n 5 'kubectl get pods -A | grep persona-'
# procede cuando 20 pods estén 1/1 Running con status Ready

Si una persona se queda en Init:0/1 por más de 5 minutos, ver Troubleshooting del Paso 1 abajo.

1.4 Confirma que el Dashboard está alcanzable

kubectl get svc -n web-agents dashboard
# anota el ClusterIP o NodePort

# desde el UCS:
curl -sI http://<dashboard-ip>:3000 | head -5
# esperado: HTTP/1.1 302 Found  (redirect a /login)

# o vía NodePort si expusiste uno:
curl -sI http://<UCS-IP>:<NodePort>/login

Abre el dashboard en un browser. Esperado en la primera carga: - License Acceptance Modal aparece (intercept). Llena role + email Cisco + reconocimientos. Acepta. - Dashboard renderiza con estado vacío — sin agentes aún. - Wordmark TLSStress.Art en la esquina superior izquierda, footer de licencia en la parte inferior de cada página.

1.5 Confirma stack Prometheus + Grafana

kubectl get pods -n observability
# esperado: prometheus-0, grafana-XXX, loki-XXX, alertmanager-XXX todos Running

Abre Grafana (default :3001). Login con admin / admin.

Esperado: - Pantalla de bienvenida dice "TLSStress.Art" (tras PR #190 mergear) - Lista de dashboards muestra todos los 10 dashboards prefijados con "TLSStress.Art —" - "TLSStress.Art — Personas — Overview" muestra hasta 30 personas vivas (20 Synthetic siempre; 10 slots Cloned cuando activos)

1.6 Checklist del Paso 1 antes de proceder

  • Todas las 20 Synthetic personas en 1/1 Running
  • Dashboard alcanzable, License Acceptance aceptado, locale renderizando correctamente
  • Grafana muestra 10 dashboards, ninguno "No data"
  • Prometheus está haciendo scrape de todos los targets (Status → Targets, todos UP)
  • Ningún CrashLoopBackOff en kubectl get pods -A

Si algún ítem falla — no procedas.


Paso 2 — Conexión del DUT (30 minutos)

Objetivo: enrutar tráfico del data-plane a través del NGFW, con TLS decrypt activo.

2.1 Aplica el tuning del Nexus 9000

# Desde una máquina con alcance al IP de gestión del Nexus:
ssh admin@<nexus-mgmt-ip>
# En modo exec del NX-OS:
configure terminal
# Pega el contenido de scripts/nexus/01-apply-tuning.nxos
# Outputs esperados varían; el script deshabilita EEE, define MTU 9216, aplica QoS DSCP AF41,
# y configura ECMP hash con puerto UDP. Confirma con:
show running-config interface Eth1/1
# (Eth1/1 es el puerto trunk al UCS — sustituye por tu interfaz)

Esperado: interfaz trunk muestra mtu 9216, flowcontrol receive off, flowcontrol send off.

Verifica VLANs trunked:

show vlan brief
# esperado VLANs 20, 30, 99, 101–120, 200–209 en estado active

2.2 Inyecta la CA del NGFW en el cluster

# En el UCS (donde clonaste el repo):
kubectl create configmap ngfw-ca \
  --from-file=ca.crt=/path/to/ngfw-ca.pem \
  -n web-agents \
  --dry-run=client -o yaml | kubectl apply -f -

Esperado: configmap/ngfw-ca created (o configured).

2.3 Aplica el overlay DUT

kubectl apply -k k8s/dut/

Esto aplica: - 10-ngfw-ca.yaml — confirma que el ConfigMap está en su lugar - 20-network-attachments.yaml — definiciones NAD Multus (VLANs 20, 30, 99) con rutas apuntando al NGFW - 60-snmp-exporter.yaml — job de scrape SNMP para el NGFW - 70-network-policy-dut.yaml — NetworkPolicy modo DUT - 85-node-tuning.yaml — sysctls del host (buffers UDP/TCP, BBR, FQ) - 15-tls-decrypt-probe.yaml — probe independiente de verificación de TLS decrypt (PR #180) - 95-deployment-mode.yaml — ConfigMap deployment-mode (definido como single-node) - 97-deployment-mode-rules.yaml + 98-topology-correlation.yaml + 99-slo-and-anomaly-rules.yaml — recording rules + alertas

2.4 Aplica los patches de los deployments de agentes

kubectl patch deployment web-agent -n web-agents \
  --type=strategic-merge-patch \
  --patch-file=k8s/dut/40-playwright-patch.yaml

kubectl patch deployment k6-agent -n web-agents \
  --type=strategic-merge-patch \
  --patch-file=k8s/dut/50-k6-patch.yaml

Esos patches añaden interfaz macvlan net1, trust de la CA del NGFW y REJECT_INVALID_CERTS=true. Pods reinician tras el patch.

Espera ambos deployments estén Ready:

kubectl rollout status deployment web-agent -n web-agents
kubectl rollout status deployment k6-agent -n web-agents

2.5 Verifica que el TLS Decrypt Probe coincide

kubectl logs -n web-agents -l app=tls-decrypt-probe --tail=20
# esperado: "decrypt mode: on" o "decrypt mode: off" — nunca "unknown"

Abre Grafana → "TLSStress.Art — TLS Decrypt Mode — NGFW Inspection Verification". La métrica web_agent_tls_decrypt_active debe ser 1 (activo) — significando que el NGFW está descifrando TLS exitosamente.

Si el probe dice 0 o "unknown", no procedas — tu NGFW no está descifrando (o la CA está mal, o la ruta falta). Ver Troubleshooting del Paso 2.

2.6 Checklist del Paso 2

  • Nexus muestra VLANs trunked, MTU 9216, flow-control off
  • ConfigMap CA del NGFW aplicado
  • Overlay DUT aplicado — todos los recursos en k8s/dut/ Created
  • Ambos patches de agente aplicados, deployments con rollout completo
  • TLS Decrypt Probe reporta active (Grafana muestra 1)
  • Ningún CrashLoopBackOff tras el overlay DUT

Paso 3 — Smoke test (15 minutos)

Objetivo: correr el plan más liviano (BASELINE-SMOKE-5M) y confirmar que los datos fluyen por todo el pipeline.

3.1 Identifica planes disponibles

curl -sS http://<dashboard-ip>:3000/api/test-plans/catalog | jq -r '.plans[]|.identifier'

Output esperado: 15 líneas comenzando con BASELINE-SMOKE-5M, BASELINE-SLO-30M, etc.

3.2 Dispara el smoke test

Para Fase 1 (estado actual), el trigger es vía Dashboard UI. Para automatización, ver la API documentada en TEST_PLANS.es.md.

Navega a Dashboard → Test Plans → BASELINE-SMOKE-5M → Run. Confirma que el run inicia.

3.3 Acompaña el run en vivo

En Grafana, abre "TLSStress.Art — Test Plan Execution — Current Run" (tras PR #190 mergear) o "Test Plan Execution — Current Run". Observa:

  • Contador de fase activa avanza por las fases del plan
  • Target de la flota vs real coincide con el plan
  • Latencia p99 comienza a poblar

En el Dashboard, página Runs debe mostrar entradas apareciendo.

3.4 Verifica la tabla runs poblando

kubectl exec -n web-agents <postgres-pod> -- psql -U postgres -d dashboard \
  -c "SELECT COUNT(*) FROM runs WHERE started_at > now() - interval '5 minutes';"
# esperado: > 0 (depende del cycle interval; espera ~50–500 para un smoke de 5min)

3.5 Espera la finalización del plan

BASELINE-SMOKE-5M corre por 5 minutos. Tras finalización, fila test_run_executions recibe endedAt y outcome.

3.6 Checklist del Paso 3

  • Plan inició sin errores
  • Paneles Grafana muestran datos live durante el run
  • Tabla runs populó con > 50 filas
  • Ningún agente en CrashLoopBackOff durante el run
  • Plan completa (status completed en la tabla executions)
  • TLS Decrypt Probe permaneció active durante todo el run

Paso 4 — Primera medida real (35 minutos)

Objetivo: un run de 30 minutos con SLO target que produzca un resultado utilizable.

4.1 Corre BASELINE-SLO-30M

Mismo patrón de trigger que el smoke test. Plan: BASELINE-SLO-30M. Duración: 30 minutos. Target SLO: p99 ≤ 500 ms.

4.2 Durante el run — monitorea

Abre Grafana lado a lado: - "TLSStress.Art — Fleet Status — Deployment Aware" — confirma flota en el target - "TLSStress.Art — SLO + Burn-Rate + Anomaly Detection" — confirma ningún alerta de fast-burn disparando - "TLSStress.Art — Test-Bed Infrastructure Health" — confirma UCS no es el cuello de botella (CPU < 70%, mem estable) - "TLSStress.Art — Topology Correlation — Where Is the Bottleneck" — debe mostrar el NGFW (DUT) como el componente restringido, no tus agentes o personas

Si tus agentes o personas saturan antes que el NGFW, el test bed en sí es el cuello de botella y el resultado no tiene sentido. Detente y revisita el Paso 1 (aumenta el UCS o divide topología a dual/tri/multi-node).

4.3 Tras el run — recolecta

La fila test_run_executions ahora tiene endedAt y outcome. Haz GET /api/test-runs/<exec-id>/report.json y tienes los datos estructurados del reporte (tras PR #185 mergear). Para Fase 1 también puedes navegar /runs/<exec-id>/report para una página HTML print-styled.

4.4 Compara con expectativa del vendor

Toma el p99 observado y compara con: - Specs publicadas de throughput del vendor para el modelo NGFW - Cualesquiera benchmarks anteriores que el cliente tenga en archivo - El slo_target_p99_seconds del plan (el catálogo declara el target)

Un buen primer run cae dentro de ±30% de la spec del vendor para shape de tráfico correspondiente. Drift mayor significa: problema de config del NGFW, cuello de botella de red, o un gap real de performance que vale investigar.

4.5 Checklist del Paso 4

  • Plan completó exitosamente (outcome: completed, no aborted)
  • Resultado p99 disponible y razonable (sin valores absurdos)
  • Ningún alerta disparó indicando self-bottleneck del test bed
  • TLS Decrypt Probe permaneció activo durante todo el run
  • Datos del reporte accesibles vía API + UI
  • Primera medida: documentada — captura run-id, plan-snapshot SHA-256, y p99 observado en tus notas de engagement

Troubleshooting del Paso 1

Síntoma Causa probable Corrección
Personas atascadas en Init:0/1 por > 5 min imagen persona-seeder no descargada o seeder crashea kubectl describe pod <persona-pod> — revisa logs del init-container
Personas Pending para siempre NAD Multus no listo o PV no bound kubectl get networkattachmentdefinitions -A — verifica NADs creadas
Timeouts de cert-manager-webhook webhook lento en la primera instalación Espera 90 s, retry. Si persiste: kubectl rollout restart deployment cert-manager-webhook -n cert-manager
Dashboard 502 desde ingress Postgres no listo kubectl logs -n web-agents postgres-0 — espera "database system is ready to accept connections"

Troubleshooting del Paso 2

Síntoma Causa probable Corrección
TLS Decrypt Probe dice unknown NGFW inalcanzable en data plane, o CA mal Revisa kubectl logs -l app=tls-decrypt-probe, valida rutas vía kubectl exec en una persona y ip route, confirma gestión del NGFW está up
TLS Decrypt Probe dice 0 (off) NGFW presente pero no descifrando Revisa policy de decrypt del NGFW está habilitada, apunta al cert correcto, aplica en las interfaces relevantes
Macvlan no levanta MTU de red del host incompatible o VLAN no trunked nmcli / ip a en host + show interface en Nexus — MTU 9216 ambos lados
connection refused persistente del agente DNS de persona resuelve a IP del NGFW pero ruta no vía macvlan Verifica ruta en agente: kubectl exec <agent> -- ip route get 10.1.5.10 debe mostrar net1

Troubleshooting de los Pasos 3 / 4

Síntoma Causa probable Corrección
Tabla runs vacía durante un run Agentes no están corriendo ciclos kubectl logs -l app=web-agent — busca fallas de register o mismatch de controller-token
Panel Grafana "No data" en medio del run scrape interval > query window O error en query Espera 30 s; si persiste, reimporta JSON del dashboard
Pico p99 a valor absurdo (ej.: 30s) Algún DNS de persona no alcanzable, agente time out Revisa kubectl logs <persona-pod> y el DNS de Service de la persona
Status del plan aborted Operador detuvo el run, o alerta de fleet readiness disparó Lee campo outcome de la fila de ejecución; revisa Alertmanager

Tras tu primer run exitoso

  1. Salva las notas del engagement — run-id, plan-snapshot SHA-256, p99 observado, modelo + versión del NGFW, throughput observado.
  2. Etiqueta el cluster si esto fue un baseline significativo:
    kubectl annotate cluster <cluster> \
      tlsstress.art/baseline-run="<run-id>" \
      tlsstress.art/baseline-plan="BASELINE-SLO-30M" \
      tlsstress.art/baseline-p99-ms="<value>"
    
  3. Elige el siguiente plan basado en objetivos del engagement:
  4. Encontrar capacidad → CAP-FIND-KNEE-30M
  5. Sostenido a 90% → CAP-MAX-1H
  6. Endurance → SOAK-ENDURANCE-24H
  7. Modos de falla → STR-OVERLOAD-15M

Ver TEST_PLANS.es.md para guía de selección de plan.

Relacionados