Nov 1, 2025 · 6285 words · 30 min read

5. Ejecución#

El playbook había funcionado perfectamente durante meses: diez switches de acceso en el laboratorio, dos minutos de principio a fin, resultados limpios cada vez. Cuando el equipo decidió desplegarlo en el inventario completo de 800 switches, nadie esperaba problemas. Los primeros 600 dispositivos se actualizaron sin incidentes. Luego el trabajo se ralentizó. Luego se bloqueó. El servidor RADIUS, que recibía de repente 150 solicitudes de autenticación SSH simultáneas, empezó a rechazar conexiones. Ansible quedó bloqueado en 150 dispositivos a mitad de la ejecución. Un ingeniero mató el trabajo.

Lo que vino después fue el problema más difícil: nadie sabía cuáles de los 600 dispositivos se habían actualizado y cuáles 150 no. No se había registrado ningún estado de ejecución. Volvieron a ejecutar el playbook y confiaron en que la idempotencia los salvaría; lo hizo, esa vez. Pero el incidente reveló algo importante: la capa de ejecución había sido diseñada para el laboratorio, no para la red. Velocidad, paralelismo, límites de error, seguimiento de estado; nada de eso había sido considerado. La automatización funcionaba; la arquitectura de ejecución no.

La mayoría de la gente piensa en la automatización de redes como: “tomar los mismos datos y, sin conectarse como humano en la CLI, hacer algo en la red.” Apostaría a que la mayoría de las personas que empiezan con automatización de redes comienzan ahí. Y sí, eso es lo que hace el bloque de Ejecución. Pero como has visto a lo largo de este libro, la automatización de redes es más grande que este primer paso, y la Ejecución es solo un componente dentro de una arquitectura.

El bloque de Ejecución interactúa directamente con la red para las operaciones más peligrosas (p. ej., cambios de configuración o reinicios). Así que no te saltes este capítulo; es crucial hacerlo bien.

5.1. Fundamentos#

5.1.1. Contexto#

La Ejecución define cómo ejecutar acciones. El qué viene del bloque de Intención, y el cuándo viene de la Orquestación.

En los primeros proyectos de automatización de redes, un script que reinicia una interfaz para un dispositivo e interfaz dados puede ser el primer logro. Ese camino puede crecer hasta convertirse en un sistema mucho más sofisticado.

5.1.2. Objetivos#

¿Qué necesita hacer realmente un sistema de ejecución? Cinco cosas importan:

  1. Obtener los datos correctos en el lugar correcto. Antes de ejecutar cualquier cosa, necesitas saber qué ejecutar (la intención), dónde ejecutarlo (qué dispositivos) y cómo acceder a ellos (credenciales, detalles de conexión). Esto significa obtener el inventario y el estado previsto de la Fuente de Verdad (más al respecto en el Capítulo 4), y a veces consultar datos de observabilidad para entender las condiciones actuales. Sin esta integración, tu motor de ejecución simplemente ejecuta comandos a ciegas.

  2. Arrancar cuando sea necesario, ya sea ahora o más tarde. A veces necesitas ejecución inmediata: un ingeniero hace clic en “desplegar” y espera que ocurra de inmediato. Otras veces, la ejecución debería esperar, desplegarse durante la ventana de mantenimiento, esperar a que un dispositivo se conecte, o reaccionar a un evento de observabilidad. El sistema necesita admitir activadores tanto síncronos como asíncronos.

  3. Rastrear el estado a lo largo del tiempo. Las operaciones de toda la red no son instantáneas. Podrías desplegar en cientos de dispositivos a lo largo de horas. ¿Qué dispositivos tuvieron éxito? ¿Cuáles fallaron? ¿Cuáles siguen pendientes? La gestión de estado también permite la idempotencia (ejecutar la misma tarea dos veces, obtener el mismo resultado), la reversión (deshacer lo que acabas de hacer) y la reanudación (continuar desde donde lo dejaste después de un fallo).

  4. Ejecutar de forma fiable a escala. Un script que funciona para 5 dispositivos a menudo falla (o se degrada) con 500. Necesitas ejecución paralela, manejo de errores, reintentos, limitación de tasa y capacidades de ejecución en seco. El sistema debería gestionar con elegancia los fallos parciales, proporcionar retroalimentación clara sobre lo que salió mal y nunca dejar la red en un estado indefinido.

  5. Funcionar con cualquier dispositivo o plataforma de red. Tu red probablemente tiene Cisco, Arista, Juniper, Application Programming Interface (API)s en la nube, cajas Linux, firewalls y balanceadores de carga. Cada uno habla protocolos diferentes y tiene patrones operacionales diferentes. Tu capa de ejecución necesita adaptadores para todos ellos, con una interfaz común para que el resto de tu automatización no se preocupe por las diferencias.

5.1.3. Pilares#

Cada objetivo se traduce en capacidades específicas:

  1. Capa de integración de datos. Tu motor de ejecución no existe de forma aislada. Necesita acceso programático a tu Fuente de Verdad (inventario, credenciales, intención), tus sistemas de observabilidad (estado actual, métricas de salud) y potencialmente otros sistemas (gestión de tickets, control de cambios, flujos de aprobación).

  2. Mecanismos de activación flexibles. Múltiples formas de iniciar la ejecución importan. Los activadores síncronos incluyen Representational State Transfer (REST) Application Programming Interface (API)s (invocación directa), webhooks (integración con sistemas externos) y llamadas a procedimientos remotos. Los activadores asíncronos incluyen oyentes de eventos (reaccionar a alertas de observabilidad, cambios de estado de dispositivos o eventos externos), programadores (ejecución periódica tipo cron o tareas programadas puntuales) y consumidores de colas de mensajes.

  3. Infraestructura de gestión de estado. Más allá de “¿tiene el dispositivo esta configuración?”. Necesitas estado de ejecución (qué tareas están en ejecución, pendientes, completadas, fallidas), estado deseado (qué debería estar configurado) y estado real (qué está configurado). Esto requiere almacenamiento persistente, soporte de transacciones para operaciones atómicas y mecanismos de bloqueo para prevenir conflictos concurrentes.

  4. Motor de ejecución robusto. Admite tanto flujos de trabajo imperativos (ejecutar comando 1, luego comando 2, luego comando 3) como enfoques declarativos (hacer que el dispositivo se vea así, calcula los pasos tú mismo). El motor gestiona la concurrencia (ejecutar contra múltiples dispositivos en paralelo o en lotes), implementa lógica de reintento con retroceso exponencial, proporciona capacidades de ejecución en seco y gestiona con elegancia los fallos parciales.

  5. Capa de abstracción de protocolos. Los dispositivos de red son un batiburrillo heterogéneo. Algunos hablan Secure Shell (SSH) y esperan comandos Command Line Interface (CLI). Otros usan NETCONF o RESTCONF. Los dispositivos modernos admiten gRPC Network Management Interface (gNMI) para telemetría de streaming y configuración. Las plataformas en la nube exponen Representational State Transfer (REST) APIs. Tu sistema de ejecución necesita adaptadores para todos estos, presentando una interfaz unificada a la lógica de nivel superior.

5.1.4. Alcance#

El bloque de ejecución se sitúa entre la planificación y la acción. Recibe instrucciones de Intención (qué debería estar configurado) y Orquestación (cuándo y cómo hacerlo), luego interactúa directamente con los dispositivos de red para hacer que los cambios ocurran.

En el alcance:

  • Conectarse a dispositivos de red mediante cualquier protocolo admitido
  • Ejecutar cambios de configuración, comandos operacionales, transferencias de archivos, reinicios
  • Gestionar el estado de ejecución y rastrear el progreso
  • Manejar errores, reintentos y reversiones
  • Proporcionar retroalimentación a la Orquestación

Fuera del alcance:

  • Decidir qué configurar (eso es Intención)
  • Orquestar flujos de trabajo complejos de múltiples pasos y decidir cuándo activarlos (eso es Orquestación)
  • Almacenamiento y análisis a largo plazo de los resultados de ejecución (eso es Observabilidad)

Piensa en la ejecución como el motor de un coche: proporciona potencia y movimiento, pero no decide adónde ir ni cuándo girar. Esas decisiones vienen del conductor (Orquestación) siguiendo un mapa (Intención).

5.2. Funcionalidades#

Cinco áreas funcionales clave trabajan juntas para modificar el estado de la red de forma segura y fiable:

  1. Integración de datos: Obtener inventario, credenciales, intención y datos de observabilidad de los sistemas aguas arriba
  2. Activación: Iniciar la ejecución mediante mecanismos síncronos o asíncronos
  3. Gestión de estado: Rastrear el progreso de ejecución, habilitar idempotencia y reversión
  4. Motor: La lógica central que ejecuta tareas con la concurrencia y el manejo de errores apropiados
  5. Adaptador de red: Interfaces específicas de protocolo para comunicarse con dispositivos de red diversos

Estos componentes forman un pipeline: la integración de datos proporciona las entradas, la activación inicia el proceso, el motor ejecuta las tareas usando adaptadores de red, y la gestión de estado rastrea todo a lo largo del proceso.

graph LR
    subgraph Goals["Objetivos"]
        G1[Obtener los datos correctos en el lugar correcto]
        G2[Arrancar cuando sea necesario]
        G3[Rastrear el estado a lo largo del tiempo]
        G4[Ejecutar de forma fiable a escala]
        G5[Funcionar con cualquier dispositivo o plataforma de red]
    end

    subgraph Pillars["Pilares"]
        P1[Capa de integración de datos]
        P2[Mecanismos de activación flexibles]
        P3[Infraestructura de gestión de estado]
        P4[Motor de ejecución robusto]
        P5[Capa de abstracción de protocolos]
    end

    subgraph Functionalities["Funcionalidades"]
        F1[Integración de Datos]
        F2[Activación]
        F3[Gestión de Estado]
        F4[Motor]
        F5[Adaptador de Red]
    end

    G1 --> P1 --> F1
    G2 --> P2 --> F2
    G3 --> P3 --> F3
    G4 --> P4 --> F4
    G5 --> P5 --> F5

La arquitectura interna se ve así:

graph TD
    A[Integración de Datos] --> C[Motor]
    B[Activación] --> C[Motor]
    C --> E[Gestión de Estado]
    E --> C
    C --> D[Adaptador de Red]
    classDef component fill:#e1f5ff,stroke:#4a90e2,stroke-width:2px;
    class A,B,C,D,E component;

5.2.1. Integración de Datos#

Antes de ejecutar cualquier cosa, necesitas datos. El motor de ejecución obtiene información de múltiples fuentes para entender qué hacer y dónde hacerlo.

5.2.1.1. Inventario#

Los datos de inventario definen los dispositivos de destino. Lo cubrimos en el Capítulo 4, pero como mínimo:

  • Destino: Dirección IP o FQDN para llegar al dispositivo
  • Plataforma/SO: Tipo de dispositivo, proveedor, versión del SO (determina qué protocolo y comandos usar)
  • Credenciales: Usuario/contraseña, claves Secure Shell (SSH), tokens de Application Programming Interface (API), rutas de certificados
  • Parámetros de conexión: Puerto SSH, valores de timeout, endpoints de la Application Programming Interface (API)
  • Metadatos: Ubicación del sitio, rol (spine/leaf/edge), entorno (producción/staging)

Los datos de inventario deberían venir de la Fuente de Verdad. Tu motor de ejecución consulta la Application Programming Interface (API) de la Fuente de Verdad en tiempo de ejecución (o recibe los datos a través de la Orquestación cuando se activa).

Nunca almacenes credenciales en archivos de inventario o registros. Usa un sistema de gestión de secretos (HashiCorp Vault, AWS Secrets Manager, CyberArk) e inyecta las credenciales en tiempo de ejecución. La Fuente de Verdad debería proporcionar punteros a esos datos sensibles y recuperarlos en tiempo de ejecución.

5.2.1.2. Datos de Intención#

Los datos de intención son qué quieres configurar o cambiar. Esto viene de tu bloque de Intención/Fuente de Verdad y puede incluir:

  • Artefactos de configuración: Artefactos listos para desplegar que pueden ser datos estructurados usados directamente con APIs, o un conjunto de comandos CLI que construyen la configuración.
  • Comandos: Comandos Command Line Interface (CLI) específicos o llamadas a la Application Programming Interface (API) para ejecutar operaciones de dispositivos.
  • Archivos: Imágenes de software para actualizaciones, archivos de configuración para importar.

Mi recomendación es consumir los artefactos de configuración directamente. El bloque de Intención debería ser responsable de generar el artefacto de configuración con su propia lógica, renderizando plantillas de configuración con datos estructurados que representan el estado (configuraciones de VLAN, políticas de enrutamiento, ACLs).

Los artefactos de configuración pueden volverse obsoletos entre el momento en que se generan y el momento en que los consume el Ejecutor. Donde la frescura de los datos importa, el Orquestador o el activador de Ejecución siempre debería obtener un artefacto actualizado del SoT en lugar de uno en caché.

5.2.1.3. Datos Observados#

La validación de observabilidad generalmente pertenece a la Orquestación, que puede decidir si proceder. En casos simples donde la Orquestación no existe todavía, la Ejecución puede incorporar este rol.

Algunos casos de uso donde los datos de observabilidad se usan cerca del flujo de ejecución:

  • Validación previa a la ejecución: ¿Es el dispositivo accesible? ¿Hay suficiente espacio en disco para una actualización?
  • Degradación elegante: Antes de reiniciar un switch, consultar la observabilidad para ver si hay conectividad redundante.
  • Lógica condicional: Solo aplicar una configuración si se cumplen ciertas condiciones (CPU por debajo del umbral, sin alarmas activas).
  • Drenar capacidad: Antes de ejecutar una operación de drenaje, asegurarse de que la capacidad disponible sea suficiente.

Un patrón común: ejecutar consultas de observabilidad antes y después de la ejecución, comparando resultados para detectar cambios inesperados. El enfoque “snapshot antes/después” captura regresiones que de otro modo pasarían desapercibidas.

5.2.2. Activación#

La ejecución no se inicia sola. Algo tiene que activarla. Los sistemas de ejecución modernos admiten múltiples mecanismos de activación:

Síncrono (inmediato, bloqueante):

Asíncrono (diferido o dirigido por eventos):

  • Oyentes de eventos: Reaccionan a eventos de observabilidad (dispositivo caído, umbral superado), colas de mensajes o sistemas externos. Ansible Event-Driven Automation (EDA) construyó este patrón explícitamente: escuchar eventos, hacer coincidir reglas, activar playbooks automáticamente.
  • Colas de mensajes: Tareas enviadas a una cola (RabbitMQ, Kafka, AWS SQS), los trabajadores las extraen y ejecutan. Permite el almacenamiento en búfer, la cola de prioridad y la limitación de tasa.

La activación generalmente viene de la Orquestación, aunque si esta no existe, otros bloques pueden activar la ejecución directamente.

5.2.3. Gestión de Estado#

La gestión de estado trata de rastrear dónde estás en una ejecución y cómo se ve el mundo para que puedas tomar decisiones inteligentes. Hay dos categorías principales:

  • Estado de ejecución (rastrear la automatización en sí): ¿Qué dispositivos han sido procesados? ¿Qué tareas tuvieron éxito, fallaron o están pendientes? Si una tarea falló con un error transitorio, ¿podemos reintentarla?

  • Estado real de la infraestructura (rastrear el estado de configuración de destino): ¿Qué está configurado actualmente?

Dos enfoques existen:

  • Sin estado/Sin agente (p. ej., Ansible). Cada ejecución se ejecuta de forma independiente. Sin estado persistente entre ejecuciones. Más simple de operar, pero menos eficiente (redescubres todo cada vez) y sin reversión incorporada.

  • Con estado (p. ej., Terraform). El sistema mantiene un archivo de estado persistente que rastrea lo que se desplegó la última vez. Esto permite una planificación precisa de los cambios, ejecución eficiente (solo cambiar lo que es diferente) y reversión (revertir al estado anterior). Pero ahora tienes un archivo de estado que proteger, bloquear y sincronizar entre múltiples operadores.

La ejecución transaccional es el siguiente paso cuando quieres garantías de seguridad más fuertes que “mejor esfuerzo”. Una transacción agrupa múltiples cambios de dispositivos en una sola unidad: o todo se aplica y valida, o el sistema revierte al estado anterior.

En la práctica, la mayoría de la automatización de redes usa un comportamiento “similar a transacciones” en lugar de semántica ACID estricta, porque no todos los dispositivos admiten commit/rollback nativo.

5.2.3.1. Idempotencia#

La idempotencia significa que ejecutar la misma automatización múltiples veces produce el mismo resultado. Aplicar una configuración de VLAN una vez: se crea la VLAN. Aplicarla de nuevo: nada cambia (la VLAN ya existe). Esto es crítico para la fiabilidad: si la ejecución falla a la mitad, puedes volver a ejecutarla de forma segura sin crear duplicados ni romper cosas.

Cómo las herramientas logran la idempotencia:

  • Módulos integrados (p. ej., Ansible): La mayoría de los módulos de Ansible son idempotentes por diseño. El módulo ios_vlan comprueba si la VLAN existe antes de crearla.
  • Comparación de estado (p. ej., Terraform): Terraform compara el estado deseado con el estado actual, calcula una diferencia y solo aplica las diferencias.
  • APIs declarativas (p. ej., NETCONF/YANG): Algunos protocolos manejan la idempotencia de forma nativa. La operación <edit-config> de NETCONF con merge es inherentemente idempotente.
  • Comprobación manual (p. ej., scripts de Python): Si escribes scripts de Python o Go, implementas la idempotencia tú mismo.

La idempotencia es más difícil de lo que parece. La idempotencia perfecta añade overhead. Algunos equipos aceptan “mayormente idempotente” (funciona el 99% del tiempo) en lugar de “perfectamente idempotente” (siempre funciona, pero se ejecuta lentamente).

5.2.4. Motor#

El motor de ejecución es la lógica central que toma una tarea (“configurar esta VLAN en estos 50 switches”) y la ejecuta de forma segura y eficiente. Esto no es Orquestación. El bloque de Orquestación coordina múltiples tareas de ejecución a lo largo del tiempo y las dependencias. El motor simplemente ejecuta bien una tarea (o una cadena simple de tareas).

Lo que hace:

  • Acepta una definición de tarea (qué hacer, qué dispositivos)
  • La descompone en operaciones atómicas (acciones por dispositivo)
  • Ejecuta operaciones con la concurrencia apropiada (serial, paralela, por lotes)
  • Gestiona errores, reintentos y reversiones
  • Informa del progreso y los resultados

Un motor de ejecución puede configurar 100 routers en paralelo, pero no decide cuándo configurarlos, qué configuraciones aplicar según la lógica de negocio, ni qué hacer a continuación según los resultados. Esas son preocupaciones de Orquestación. La Ejecución es el caballo de trabajo; la Orquestación es el capataz.

5.2.4.1. Lenguajes#

EstiloEjemplosFortalezasCompromisos
Lenguajes específicos de dominio (DSL)Ansible (YAML), Terraform (HCL)Menor barrera de entrada, intención autodocumentadaFlexibilidad limitada, depuración más difícil en escenarios complejos
Programación de propósito generalNornir (Python), scripts Python/Go personalizadosMáxima flexibilidad, herramientas de depuración robustasMayor requisito de habilidades, más código que mantener

Muchos equipos usan DSLs (Ansible) para patrones comunes y recurren a código personalizado (módulos Python, plugins) para casos extremos complejos.

5.2.4.2. Imperativo versus Declarativo#

Imperativo: Especificas cómo hacer algo, paso a paso.

Declarativo: Especificas cuál debería ser el estado final, y la herramienta calcula cómo.

En resumen, prefiere el declarativo cuando encaje. Ansible admite ambos:

  • Ansible imperativo:

    - name: Create VLAN 100
      cisco.ios.ios_command:
        commands:
          - vlan 100
          - name Engineering
  • Ansible declarativo:

    - name: Ensure VLAN 100 exists
      cisco.ios.ios_vlans:
        config:
          - vlan_id: 100
            name: Engineering
        state: merged
EnfoqueFortalezasCompromisos
DeclarativoIdempotente por naturaleza; la intención es más fácil de leer; menos errores del operador porque la herramienta gestiona los casos extremosDepende en gran medida de la calidad del módulo/proveedor; menos control sobre la ruta de ejecución
ImperativoControl total sobre cada paso; flujo de ejecución explícito; funciona en casi cualquier entorno con acceso CLIMás código y esfuerzo de pruebas; la idempotencia es tu responsabilidad

La mayoría de los equipos usan declarativo cuando es posible, imperativo cuando es necesario. Recuerda: declarativo significa que alguien más lleva la carga, aunque parezca simple desde fuera.

5.2.4.3. Serial versus Paralelo#

  • Ejecución serial: Procesa los dispositivos uno a uno. Seguro (ves los fallos de inmediato y puedes parar), pero lento.

  • Ejecución paralela: Procesa múltiples dispositivos simultáneamente.

flowchart TD
    subgraph Serial["Serie"]
        S1[Dispositivo 1] --> S2[Dispositivo 2] --> S3[Dispositivo 3]
    end
    subgraph Parallel["Paralelo"]
        P0[Inicio] --> P1[Dispositivo 1]
        P0 --> P2[Dispositivo 2]
        P0 --> P3[Dispositivo 3]
    end

Por qué existe Nornir: Ansible era originalmente serial. Para la automatización de redes a escala, esto era dolorosamente lento. Nornir fue construido desde cero con paralelismo: usa hilos por defecto para ejecutar contra múltiples dispositivos de forma concurrente. Esto lo hace 10-100 veces más rápido para grandes cantidades de dispositivos.

Consideraciones para la ejecución paralela:

  • Impacto en el plano de control: Impactar 1000 dispositivos simultáneamente puede sobrecargar las redes de gestión, las fuentes de datos y los sistemas de autenticación.
  • Gestión de dependencias: Si los dispositivos dependen unos de otros (spine antes que leaf), necesitas ordenación.
  • Radio de explosión de errores: Si tu automatización tiene un bug, la ejecución paralela lo despliega en muchos dispositivos antes de que te des cuenta.

Mi recomendación: usa ejecución paralela con procesamiento por lotes. Procesa dispositivos en grupos de 10-50 (solía llamarlos “oleadas”), verifica el éxito de cada lote antes de continuar. Más sobre estrategias de despliegue en el Capítulo 10.

5.2.4.4. Ejecución en Seco (Modo de Planificación)#

La ejecución en seco es la fase de “planificación” del motor de ejecución: simular cambios sin tocar los dispositivos, luego mostrar una diferencia concreta y los riesgos. Una buena ejecución en seco obtiene el estado actual, calcula las operaciones exactas a nivel de dispositivo que se ejecutarían y valida los prerrequisitos (accesibilidad, esquema, ordenación de dependencias).

Terraform will perform the following actions:

  # aws_vpc.main will be created
  + resource "aws_vpc" "main" {
      + cidr_block = "10.10.0.0/16"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

En la práctica, la ejecución en seco es lo que hace que las aprobaciones sean significativas y las reversiones sean menos probables. Da a los humanos una visión clara de lo que va a suceder.

En mi experiencia, ofrecer capacidades de ejecución en seco es muy conveniente en los primeros días de un proyecto de automatización para obtener la aceptación de los ingenieros de red. Más adelante, la relevancia disminuye.

5.2.4.5. Resiliencia#

La ejecución de red es inherentemente poco fiable: los dispositivos se reinician, la conectividad falla momentáneamente y los planos de control se sobrecargan. La ejecución resiliente gestiona esto con elegancia:

Lógica de reintento:

  • Los fallos transitorios (timeout de conexión, pico temporal de CPU) deberían activar reintentos con retroceso exponencial
  • Distinguir errores reintentables (timeout) de errores permanentes (fallo de autenticación, error de sintaxis)
  • Limitar los intentos de reintento para evitar bucles infinitos

Estrategias de timeout:

  • Timeouts de conexión: cuánto tiempo esperar la respuesta del dispositivo antes de rendirse
  • Timeouts de tarea: cuánto tiempo puede ejecutarse una operación completa (previene bloqueos en dispositivos atascados)

Manejo de errores:

  • Fallar rápido: un dispositivo falla, abortar todo (seguro pero ineficiente)
  • Continuar: registrar el fallo, continuar con otros dispositivos (eficiente pero puede extender el daño)
  • Basado en umbral: si >10% de los dispositivos fallan, parar (equilibrado)

Capacidades de reversión:

  • Tomar snapshots de configuración antes de los cambios
  • Si la ejecución falla, restaurar automáticamente los snapshots

Puntos de control:

  • Guardar el progreso periódicamente
  • Si la ejecución se interrumpe, reanudar desde el último punto de control en lugar de empezar de nuevo

5.2.5. Adaptador de Red#

Los dispositivos de red hablan protocolos diferentes. La capa de adaptador de red abstrae estas diferencias para que las capas superiores no se preocupen de si están hablando con un switch Cisco via Secure Shell (SSH) o un switch Arista via Representational State Transfer (REST) Application Programming Interface (API).

5.2.5.1. Interfaces#

InterfazDescripciónBibliotecas/Herramientas de EjemploUso Típico
Secure Shell (SSH) / Command Line Interface (CLI)Más universal, menos estructurado (texto entrada/salida)Netmiko (Python), scrapli (Python)Plataformas legadas, comandos operacionales específicos del proveedor
NETCONF / RESTCONFGestión estructurada basada en modelos (YANG)ncclient (Python)Configuración declarativa y modelos de datos estandarizados
gRPC Network Management Interface (gNMI) / gNOIInterfaces basadas en gRPC para configuración/estado y RPCs operacionalespygnmi (Python), gnmic (Go CLI)Telemetría de streaming y flujos de trabajo de operaciones modernos
Representational State Transfer (REST) APIsAPIs HTTP/JSON o XML, a menudo específicas de plataformarequests/httpx (Python)APIs de controladores y plataformas de red/nube
JSON-RPC / gRPC de proveedorPatrones RPC estructurados de sistemas operativos de red específicosArista eAPI (JSON-RPC)Ejecución remota de procedimientos rápida con cargas estructuradas

Algunas bibliotecas proporcionan una capa de abstracción con una interfaz común entre plataformas:

  • NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support): Biblioteca Python que proporciona una API unificada entre proveedores. En lugar de escribir código diferente para Cisco vs. Juniper, NAPALM te da una sola API. El compromiso: la abstracción oculta características específicas del proveedor. Para operaciones comunes (obtener configuración, aplicar configuración), es estupendo. Para operaciones más avanzadas, recurres a las interfaces nativas.

5.2.5.2. Operaciones#

La ejecución de red no es solo gestión de configuración:

Tipo de OperaciónQué CubreNotas
Cambios de configuraciónAplicar configuraciones completas/fragmentos/estado declarativoTipo de operación más común
Zero-Touch Provisioning (Zero Touch Provisioning (ZTP))Incorporación automatizada en el primer arranqueRequiere servidores DHCP y bootstrap
Transferencias de archivosSubir imágenes, descargar registros/copias de seguridadProtocolos comunes: SCP, SFTP, TFTP
Operaciones de dispositivosReinicio/recarga, comandos operacionales (ping/traceroute), copias de seguridadComún para operaciones day-2 y remediación
ReversiónRevertir la configuración al estado anterior conocido como buenoReversión nativa en algunas plataformas; restauración de copia de seguridad en otras

Dónde pertenece la validación y el renderizado: La Fuente de Verdad posee la intención. La Ejecución posee las comprobaciones de seguridad a nivel de dispositivo y la validación operacional. La Orquestación decide cuándo validar y qué hacer con los resultados. Una buena regla simple: la validación que cambia el flujo de trabajo pertenece a la Orquestación; la validación que cambia las acciones del dispositivo pertenece a la Ejecución.

5.2.6. Soluciones#

Existen muchas herramientas para la ejecución de red:

HerramientaModelo de ejecución y fortalezasMejor ajustePrincipales limitaciones
AnsibleDSL (YAML), sin agente, gran ecosistema de módulos, fuerte para automatización mixta de servidores/redEquipos que quieren victorias rápidas y amplio soporte de plataformasA gran escala necesita ajuste; la lógica compleja puede volverse difícil de mantener en YAML
TerraformIaC declarativo (HCL), motor de diferencias/planificación robusto, flujos de trabajo con estado, excelente integración en la nubeEquipos que ya estandarizan en Terraform para infraestructuraLa madurez del proveedor de red varía; la gestión de estado añade overhead operacional
SaltBasado en Python con opciones de agente o sin agente, arquitectura dirigida por eventosInstalaciones Salt existentes u operaciones con muchos eventosComunidad de automatización de red más pequeña y incorporación más pronunciada
NornirFramework primero Python, paralelismo con hilos, altamente flexibleEquipos con capacidad Python con necesidades personalizadas o sensibles al rendimientoMenos componentes listos para usar; más propiedad de ingeniería requerida
Python/Go personalizadoMáximo control y libertad de diseño para lógica específica de dominioCasos extremos, plataformas internas y flujos de trabajo altamente especializadosEres responsable de todo: estándares, patrones de fiabilidad, pruebas y soporte del ciclo de vida
Controladores de proveedorControladores de intención y políticas con flujos de trabajo nativos del proveedorEquipos que estandarizan en un ecosistema de un proveedor con APIs de controlador sólidasPatrones menos portables en entornos multi-proveedor

Muchos equipos usan múltiples herramientas según el caso de uso y la infraestructura de red.

5.2.7. Zero Touch Provisioning#

El Zero Touch Provisioning (ZTP) es un patrón de ejecución distinto donde un dispositivo arranca por primera vez y automáticamente obtiene y aplica su configuración completa sin ninguna intervención humana en el dispositivo. El flujo de datos es estructuralmente diferente de las operaciones day-2 y vale la pena tratarlo como un patrón arquitectónico nombrado.

El flujo ZTP

flowchart LR
    A[Dispositivo arranca\nsin configuración] --> B[DHCP asigna\nIP de gestión\ny URL de bootstrap]
    B --> C[Dispositivo obtiene\nconfiguración bootstrap\ndel servidor]
    C --> D[Dispositivo se autentica\nen el SoT y red\nde gestión]
    D --> E[Orquestador detecta\nnuevo dispositivo, activa\ntrabajo de aprovisionamiento]
    E --> F[Ejecutor aplica\nintención completa del SoT]

La clave es que el paso de bootstrap es deliberadamente mínimo: solo la configuración suficiente para poner al dispositivo en la red de gestión y poder autenticarse. El aprovisionamiento completo se ejecuta después como un trabajo estándar del Ejecutor, obteniendo la intención completa de la Fuente de Verdad. Esto significa que ZTP reutiliza el mismo pipeline de ejecución que las operaciones day-2 en lugar de requerir un sistema de aprovisionamiento separado.

Patrones ZTP comunes

PatrónCómo funcionaCompromiso
DHCP + archivo estáticoDHCP apunta a un archivo de configuración estático por dispositivo (emparejado por MAC o número de serie)Simple de implementar; no obtiene del SoT; falla a escala
DHCP + generación dinámicaEl servidor bootstrap consulta el SoT y genera la configuración inicial específica del dispositivo en el momento de la solicitudGuiado por el SoT desde el primer día; requiere que el SoT tenga el dispositivo registrado antes de que arranque
Imagen del SO + configuraciónEl dispositivo descarga tanto la imagen del SO como la configuración durante el arranqueManeja dispositivos sin metal o con reinicio de fábrica; aumenta la complejidad del servidor bootstrap

ZTP introduce una dependencia de secuenciación: el dispositivo debe estar registrado en la Fuente de Verdad antes de que arranque físicamente. En el escenario del campus, esto se maneja mediante la sincronización de ServiceNow a Nautobot: cuando se añade un switch como activo en ServiceNow (antes de que llegue al sitio), Nautobot crea automáticamente el registro del dispositivo con ubicación, rol y proveedor. Cuando el switch arranca, el SoT ya está listo.

5.2.8. Ejecución Híbrida y en la Nube#

El Ejecutor necesita cada vez más operar simultáneamente en dos entornos fundamentalmente diferentes: dispositivos de red tradicionales y plataformas nativas en la nube. Tratarlos de forma idéntica lleva a una automatización frágil; tratarlos como sistemas completamente separados duplica el esfuerzo y crea operaciones inconsistentes.

El problema de la divergencia

DimensiónDispositivos de redPlataformas en la nube
Estilo de APISSH, NETCONF, gNMI (conexiones con estado, de larga duración)REST/HTTP (sin estado, solicitudes de corta duración)
Modelo de autenticaciónCredenciales compartidas (usuario/contraseña, claves SSH)Tokens temporales, cuentas de servicio, roles de instancia
Completación de la operaciónNormalmente síncronaA menudo asíncrona (la API devuelve “aceptado”, requiere sondeo)
Ambigüedad de falloUna sesión NETCONF caída es un fallo claroUn timeout de la API en la nube puede o no haber aplicado el cambio
Enfoque de idempotenciaImperativo por defectoNativo declarativo en la mayoría de las plataformas

La arquitectura recomendada

Mantén Intención (SoT) y Orquestación unificadas. La misma solicitud de negocio que crea una VLAN en los switches del campus puede también necesitar crear un grupo de seguridad en AWS. La Fuente de Verdad contiene ambos. El Orquestador coordina ambos. Solo en la capa de Adaptador de Red diverge la ruta de ejecución: un adaptador maneja NETCONF/Ansible contra los switches del campus; otro maneja Terraform o APIs del proveedor de nube contra el entorno en la nube.

Esto significa que el radio de explosión de un cambio en la API de la nube y un cambio en un dispositivo de red están gobernados por el mismo registro de aprobación y auditoría, que es el resultado arquitectónico correcto aunque los protocolos sean completamente diferentes.

5.2.9. Consideraciones de Seguridad#

El Ejecutor es el componente en tu arquitectura que tiene acceso de escritura a la red. Puede aplicar configuraciones, reiniciar servicios, actualizar firmware y alterar políticas de enrutamiento en cientos de dispositivos simultáneamente. Eso hace que su postura de seguridad sea más consecuente que casi cualquier otro componente, y sin embargo es frecuentemente el más descuidado desde un punto de vista arquitectónico. Un Ejecutor comprometido o mal configurado no es un riesgo de filtración de datos; es un riesgo de interrupción de la red.

Gestión de credenciales

Las credenciales para los dispositivos de red nunca deberían aparecer en playbooks, plantillas, definiciones de trabajos o control de versiones. Almacena los secretos en un gestor de secretos dedicado (HashiCorp Vault, AWS Secrets Manager, CyberArk) e inyéctalos en tiempo de ejecución en el entorno del Ejecutor. Cuando se rotan las contraseñas de los dispositivos, el Ejecutor recoge las nuevas credenciales en su próxima ejecución sin ningún despliegue o reconfiguración.

Mínimo privilegio por operación

No todas las ejecuciones necesitan el mismo nivel de acceso. Las operaciones de lectura deberían usar credenciales de solo lectura. Las operaciones de escritura deberían usar credenciales limitadas al tipo de cambio: un trabajo que despliega cambios de VLAN no debería tener credenciales que permitan cambios de configuración BGP. Donde la plataforma de red admite acceso basado en roles, úsalo para limitar el radio de explosión de cualquier sesión comprometida.

Separación de responsabilidades

Quién puede activar la ejecución y quién puede modificar la lógica de automatización deberían ser roles diferentes con controles de acceso diferentes. Un operador que aprueba e inicia un trabajo de despliegue de VLAN no necesita, y no debería tener, acceso para modificar los roles o plantillas de playbook de Ansible que lo implementan.

Requisitos de registro de auditoría

Cada evento de ejecución debe registrarse con suficiente detalle para reconstruir lo que ocurrió: quién activó el trabajo, qué plantilla de trabajo se usó, qué dispositivos fueron el objetivo, qué parámetros se pasaron, cuál fue el resultado para cada dispositivo y en qué timestamp. Los registros deben conservarse durante el período de cumplimiento aplicable a la organización.

Segmentación de red de la infraestructura de automatización

El Ejecutor y su plano de control (AWX, nodos de control de Ansible) deberían estar en un segmento de red de gestión. El tráfico de ejecución hacia los dispositivos debería fluir a través de la red de gestión fuera de banda donde esté disponible, no a través del mismo plano de datos que el Ejecutor podría estar modificando.

5.3. Ejemplo de Implementación#

5.3.1. Caso de Uso: Despliegue Automatizado de VLAN en un Campus Heterogéneo#

Continuamos con la red del campus del Capítulo 4. La definición del servicio VLAN (su ID, subred, plantillas de configuración por proveedor y grupos de switches de destino) está ahora almacenada en la Fuente de Verdad. Este capítulo se centra en cómo el bloque de Ejecución recoge esa intención y la despliega de forma fiable en los 800 switches.

Escenario: Un equipo de negocio solicita una nueva VLAN para una nueva aplicación. La solicitud llega a través de un sistema de gestión de tickets con detalles: ID de VLAN, nombre, sitios del campus y aprobación. Las operaciones de red despliegan esta VLAN en switches de acceso/distribución de Arista, HPE y Cisco, verifican la conectividad y reportan el éxito.

Requisitos:

  • Desplegar la configuración de VLAN en múltiples switches en paralelo
  • Verificar condiciones previas (la VLAN no existe ya, los switches son accesibles)
  • Realizar ejecución en seco para mostrar qué cambiaría
  • Ejecutar el despliegue real con capacidad de reversión si ocurren fallos
  • Verificar después del despliegue (la VLAN está activa, sin errores)

5.3.2. Arquitectura de la Solución#

  1. Fuente de Verdad: Nautobot (almacena inventario, definiciones de VLAN)
  2. Orquestación/Activación: Coordinación de plantillas de workflow de AWX (lanzamiento por API, webhook, programado)
  3. Observabilidad: Proporciona datos en tiempo real para la toma de decisiones
  4. Ejecución:
    • Motor de Ejecución: Plantillas/tareas de trabajo de Ansible (precomprobación, ejecución en seco, despliegue, verificación, reversión)
    • Integración de Datos: Plugin de inventario de Nautobot en Ansible/AWX
    • Adaptadores de Red: Módulos de Ansible para Cisco IOS XE, Arista EOS y HPE/Aruba
    • Gestión de Estado: Estado de trabajo y workflow de AWX por fase y por resultado de host, con tarea de reversión en las rutas de fallo

Esta solución es para fines ilustrativos; no es una recomendación universal.

5.3.3. Flujo de Implementación#

Este se ejecuta como un workflow de AWX con múltiples nodos de tareas:

  1. Un cambio de intención de VLAN en Nautobot activa AWX mediante webhook
  2. El workflow de AWX comienza y ejecuta la sincronización de inventario (Nautobot)
  3. El trabajo de precomprobación valida la accesibilidad, el estado de VLAN existente y los guardarraíles del sitio
  4. El trabajo de ejecución en seco renderiza las tareas específicas del proveedor sin aplicar cambios
  5. El nodo de aprobación (opcional) controla la ejecución en producción
  6. El trabajo de despliegue aplica la intención de VLAN en lotes paralelos entre proveedores
  7. El trabajo de verificación confirma el estado operacional e intencional
  8. En caso de fallos, el trabajo de reversión se ejecuta solo para el ámbito afectado
  9. La observabilidad recopila datos anteriores y posteriores para apoyar la validación final
  10. La validación final se ejecuta y se publica el resumen de ejecución
flowchart TD
    A[Cambio de Intención VLAN en NetBox] --> B[Webhook a AWX]
    B --> C[Inicio del Flujo de Trabajo AWX]
    C --> E[Sincronización de Inventario desde NetBox]
    E --> F[Tarea de Verificación Previa]
    F --> G[Tarea de Ejecución en Seco]
    G --> H[Nodo de Aprobación]
    H --> I[Tarea de Despliegue]
    I --> J[Tarea de Verificación]
    J --> N[Recopilar Datos de Red]
    N --> L[Validación Final]
    L --> M[Actualizar Ticket e Informe]

    F -->|fallido| X[Detener y devolver errores de validación]
    I -->|hosts con fallos| Y[Tarea de Rollback para dispositivos afectados]
    Y --> J
    F --> N

    classDef sot fill:#cfe8ff,stroke:#0b5fb3,stroke-width:2px;
    classDef orch fill:#ffe0cc,stroke:#c24b00,stroke-width:2px;
    classDef exec fill:#d7f4e1,stroke:#0f7a3b,stroke-width:2px;
    classDef obs fill:#ffd6d6,stroke:#b22222,stroke-width:2px;

    class A sot;
    class B,C,E,H,L,M orch;
    class F,G,I,J,Y,X exec;
    class N obs;

5.3.4. Resumen de la Solución#

Esta implementación demuestra todas las capacidades de ejecución clave:

  • Integración de datos: Obtiene inventario e intención de Nautobot usando inventario dinámico
  • Activación: El workflow de AWX admite API/webhook/programación, más ejecución con control de aprobación
  • Gestión de estado: El estado del workflow/trabajo de AWX rastrea el progreso y los dominios de fallo; la ruta de reversión es explícita
  • Motor: Ansible gestiona la ejecución paralela (configurada mediante forks/procesamiento por lotes), el manejo de errores y la ejecución en seco
  • Adaptador de red: Los módulos de recursos específicos del proveedor mapean una intención a diferentes plataformas (cisco.ios.ios_vlans, arista.eos.eos_vlans)

Características de resiliencia:

  • Las precomprobaciones evitan desplegar en dispositivos no accesibles o crear VLANs duplicadas
  • La ejecución en seco muestra los cambios antes de aplicarlos
  • Los módulos idempotentes hacen segura la re-ejecución
  • La reversión: el nodo de reversión de AWX limita la reversión al ámbito del dispositivo afectado

Consideraciones de escala:

  • La ejecución paralela mediante forks: 50 procesa 50 switches simultáneamente
  • Para despliegues más grandes (500+ switches), dividir en grupos y usar Ansible Tower/AWX para la gestión del workflow

5.4. Resumen#

El bloque de Ejecución es donde la automatización de redes se hace tangible: se aplican configuraciones, se reinician dispositivos, ocurren los cambios. Pero la ejecución fiable es más que enviar comandos por Secure Shell (SSH).

Comienza con la integración de datos y la activación, luego depende de la gestión de estado (idempotencia, reversión y seguridad similar a transacciones), un motor capaz (opciones serial/paralelo, ejecución en seco/planificación, resiliencia) y una capa de adaptador de red que oculta las diferencias de protocolo entre proveedores. La observabilidad alimenta la validación y los guardarraíles, mientras que la orquestación decide cuándo proceder o parar. Las herramientas importan menos que los patrones de ejecución: integra datos, activa intencionalmente, ejecuta de forma determinista, valida resultados y mantén una ruta de reversión limpia.

Empieza pequeño y escala deliberadamente: un flujo de trabajo, una clase de dispositivo y comprobaciones claras antes/después. Añade procesamiento por lotes, límites de tasa y validación más robusta a medida que crece el radio de explosión. La Ejecución es poderosa y arriesgada; prueba exhaustivamente, despliega gradualmente, monitoriza constantemente y siempre planifica la reversión.

El Capítulo 6 introduce la Observabilidad: el bloque que recoge el estado real de la red y lo compara con la intención almacenada en el SoT, cerrando el bucle de retroalimentación que hace posible la validación y la remediación automatizada.

💬 Found something to improve? Send feedback for this chapter