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: Acceso → Clone → Instalar ← está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
.enven la raíz del repo conSNMP_NEXUS_HOST,SNMP_NGFW_HOST,SNMP_COMMUNITY,SNMP_DUT_MODULE(uno decisco_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 muestra1) - 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
runspopuló con > 50 filas - Ningún agente en CrashLoopBackOff durante el run
- Plan completa (status
completeden la tabla executions) - TLS Decrypt Probe permaneció
activedurante 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, noaborted) - 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¶
- Salva las notas del engagement — run-id, plan-snapshot SHA-256, p99 observado, modelo + versión del NGFW, throughput observado.
- 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>" - Elige el siguiente plan basado en objetivos del engagement:
- Encontrar capacidad →
CAP-FIND-KNEE-30M - Sostenido a 90% →
CAP-MAX-1H - Endurance →
SOAK-ENDURANCE-24H - Modos de falla →
STR-OVERLOAD-15M
Ver TEST_PLANS.es.md para guía de selección de plan.
Relacionados¶
PRIVATE_REPO_SETUP.es.md— visibilidad del repo + branch protectionACCESS_REQUEST.es.md— cómo operadores ganan acceso para clonarCLONE_FOR_INSTALL.es.md— cuatro opciones de autenticación paragit cloneTEST_PLANS.es.md— los 15 planes del catálogoMONITORING_TEST_VALIDITY.es.md— alertas que señalan cuándo el test bed en sí es el cuello de botellaTLS_DECRYPT_MODE_VERIFICATION.es.md— probe de issuer usado en el paso 2.5USAGE_POLICY.es.md— qué cuenta como uso autorizado durante este run