Nov 30, 2025 · 7758 words · 37 min read

2. Principi di Design#

Un team di network automation ha trascorso sei mesi a costruire un sistema di cui andava genuinamente fiero. Estraeva l’intent da un modello di dati strutturato, generava le configurazioni dei dispositivi tramite un motore di templating, validava le modifiche rispetto a una libreria di policy e le applicava via NETCONF con supporto completo al rollback. Architetturalmente, era solido. La demo al management andò bene. Poi lo consegnarono al team di network operations.

L’adozione non arrivò mai. Gli operatori continuavano a usare la CLI. Alla domanda del perché, le risposte erano sempre le stesse: “Non so cosa farà prima che lo faccia.” “Se qualcosa va storto, non riesco a capire cosa è successo.” “Non capisco come leggere l’output.” Il team di automazione aveva costruito qualcosa di tecnicamente impressionante ma operativamente opaco. Non c’era una modalità dry-run, nessuna anteprima delle modifiche in formato leggibile, nessun audit trail scritto in termini che gli operatori riconoscessero. Il sistema era una black box che chiedeva fiducia senza averla guadagnata. Sei mesi di lavoro ingegneristico rimasti inutilizzati.

Questo risultato è più comune di quanto la maggior parte dei team ammetta. L’automazione non fallisce solo per bug o architetture scadenti. Fallisce perché le persone che dovrebbero affidarsi ad essa non si fidano. Esploreremo i principi di design fondamentali che rendono l’automazione di rete affidabile, scalabile e sicura. Non sono teorie astratte: sono la differenza tra un’automazione che viene adottata e genera valore reale, e un’automazione che viene ignorata e alla fine abbandonata.

Molti di questi principi si applicano anche ad altri progetti software. Ma l’automazione di rete ha caratteristiche uniche in quanto supporta infrastrutture critiche. I network engineer hanno costruito e mantenuto questi sistemi per decenni seguendo un modello basato su cautela, precisione e verifica manuale. Ora stiamo chiedendo loro di adottare un modello fondamentalmente diverso. E questo richiede fiducia.

2.1 Costruire la Fiducia#

Prima di entrare nei principi specifici, parliamo di fiducia. È la pietra angolare di un’automazione di rete vincente. Senza di essa, l’adozione diventa quasi impossibile.

Perché la fiducia è così importante? Perché senza di essa, i network engineer non adotteranno la tua automazione. Devono credere che fornisca almeno lo stesso livello di confidenza dei processi manuali che sostituisce (più altri vantaggi).

Ancora più complicato: i sistemi di automazione sono spesso costruiti da ingegneri che potrebbero non avere una profonda esperienza di networking. Quindi l’automazione deve compensare incorporando caratteristiche forti ed esplicite che la rendano sicura, affidabile e facile da personalizzare e gestire per i team di network engineering.

La rilevanza dell’automazione affidabile è ispirata alla presentazione di Damien Garros Building Trustworthy Network Automation ad Autocon3.

Per semplificare, ecco le quattro caratteristiche fondamentali di cui abbiamo bisogno:

  • Predictable: Risultati consistenti e deterministici. Gli ingegneri devono sapere cosa accadrà prima di premere “go”, e ottenere lo stesso comportamento ogni volta.
  • Reliable: Gestisca gli errori in modo controllato. Si riprenda dai guasti. Garantisca che le operazioni si completino in modo sicuro (o vengano annullate tramite rollback) anche in condizioni impreviste e su larga scala.
  • Usable: Interfacce che consentano agli ingegneri di validare, interpretare e controllare il comportamento senza eccessiva complessità. Con guardrail.
  • Understandable: Non può essere una black box. Deve esporre intent, passi, risultati e decisioni in un modo che costruisca la fiducia nelle persone.
graph BT
  %% ===== Middle Layer =====
  subgraph L2[**Qualità**]
    direction LR
    B1[Predictable]:::layer2
    B2[Reliable]:::layer2
    B3[Usable]:::layer2
    B4[Understandable]:::layer2
  end

  %% ===== Top Layer =====
  subgraph L1[" "]
    direction TB
    A[Fiducia]:::layer1
  end

  %% ===== Connections: Behavior → Outcome =====
  B1 --> A
  B2 --> A
  B3 --> A
  B4 --> A

  %% ===== Styling =====
  classDef layer1 fill:#ffcccc,stroke:#b8860b,stroke-width:2px,color:#000;
  classDef layer2 fill:#ffe6cc,stroke:#4682b4,stroke-width:1.5px,color:#000;

La prevedibilità o il comportamento deterministico stanno diventando sempre più rilevanti con l’ingresso delle tecnologie AI/ML nel dominio della network automation, in quanto introducono una determinata componente di casualità.

Queste caratteristiche non sono negoziabili, non sono un afterthought. Ed i network engineer che utilizzeranno e dipenderanno dall’automazione devono riconoscerle.

Ho costruito molte soluzioni di network automation. Niente è più frustrante che vedere una soluzione ben progettata essere ignorata o abbandonata perché gli operatori di rete non si fidavano di essa. Questi principi ti aiutano ad evitare che accada.

Dunque, date queste caratteristiche, esploriamo i principi che le supportano.

2.2 Principi di Design#

Con la fiducia come fondamenta, andiamo ad esplorare i principi di design che supportano le qualità necessarie per un’automazione affidabile, prevedibile e scalabile

L’elenco completo potrebbe essere molto più lungo (lo amplieremo in seguito quando introdurremo altri principi dall’ingegneria del software). Ma ci sono sei principi fondamentali che ogni soluzione di network automation dovrebbe incorporare:

  • Idempotency: La stessa operazione eseguita più volte = stesso stato finale. Riduce gli effetti collaterali, elimina l’ambiguità, rende l’automazione più comprensibile e sicura da ripetere.
  • Transactional: Le modifiche si completano interamente o falliscono in modo sicuro. Nessuno stato parziale, inconsistente o applicato a metà. Essenziale per la prevedibilità e abilita i rollback a livello di rete.
  • Intent-Driven: Definisci lo stato desiderato del sistema in diverse condizioni. Migliora la prevedibilità, riduce il carico cognitivo, rende il sistema più usabile.
  • Dry Run Friendly: Mostra cosa farebbe prima di farlo. Rende l’automazione più usabile e affidabile permettendo alle persone di validare le azioni, visualizzare i risultati e rilevare i problemi prima che raggiungano la rete.
  • Versioning: Supporta il versioning sia dei dati che della logica. Torna indietro o avanti nel tempo, recupera stati precedenti, mantieni più stati in parallelo. Rafforza la prevedibilità e l’affidabilità'.
  • Testabile: Un ambiente di test adeguato è essenziale prima di eseguire modifiche in produzione. Migliora l’affidabilità e aiuta gli ingegneri a comprendere il comportamento del sistema.

Questi principi non sono esclusivi del networking, si applicano all’automazione in qualsiasi dominio IT. Ma diventano particolarmente critici nel networking, dove le modifiche comportano un rischio operativo significativo.

Questi sei principi costituiscono le fondamenta di una network automation sicura, prevedibile e affidabile. Gettano le basi per concetti più avanzati introdotti in seguito. Diventano ancora più importanti quando si scala l’automazione su infrastrutture grandi e complesse.

graph BT
  %% ===== Bottom Layer =====
  subgraph L3[**Principi**]
    direction LR
    C1[Idempotency]:::layer3
    C2[Versioned]:::layer3
    C3[Transactional]:::layer3
    C4[Testabile]:::layer3
    C5[Dry Run]:::layer3
    C6[Intent-Driven]:::layer3
  end

  %% ===== Middle Layer =====
  subgraph L2[**Qualità**]
    direction LR
    B1[Predictable]:::layer2
    B2[Reliable]:::layer2
    B3[Usable]:::layer2
    B4[Understandable]:::layer2
  end

  %% ===== Top Layer =====
  subgraph L1[" "]
    direction TB
    A[Trust]:::layer1
  end

  %% ===== Connections: Foundation → Behavior =====
  C1 --> B1
  C1 --> B4

  C2 --> B3
  C2 --> B2

  C3 --> B1
  C3 --> B2

  C4 --> B2
  C4 --> B4

  C5 --> B3
  C5 --> B4

  C6 --> B1
  C6 --> B3

  %% ===== Connections: Behavior → Outcome =====
  B1 --> A
  B2 --> A
  B3 --> A
  B4 --> A

  %% ===== Styling =====
  classDef layer1 fill:#ffcccc,stroke:#b8860b,stroke-width:2px,color:#000;
  classDef layer2 fill:#ffe6cc,stroke:#4682b4,stroke-width:1.5px,color:#000;
  classDef layer3 fill:#ccffcc,stroke:#228b22,stroke-width:1.5px,color:#000;

Ognuno di questi principi di design merita un approfondimento a sè. Li esploreremo in un ordine che riflette le loro dipendenze logiche: partiamo con la definizione di cosa vogliamo ottenere, poi ci assicuriamo che avvenga in modo sicuro e corretto, e infine validiamo che funzioni.

2.2.1. Intent-Driven#

Perché iniziare dall’intent? Prima di discutere come eseguire l’automazione, dobbiamo capire cosa stiamo cercando di ottenere. L’intent-driven design è la base su cui si costruisce tutto il resto.

Un caso d’uso comune per iniziare con l’automazione: script o playbook che eseguono azioni semplici. Configurare un’interfaccia up o down fornendo l’FQDN ed il nome dell’interfaccia. Ciò però crea un problema. La prossima persona che lavorerà su quell’interfaccia non saprà qual è il suo Desired State. Dovrebbe essere up o down?

Questo problema riguarda sia le operazioni manuali che quelle automatizzate. Ma con l’automazione, il problema peggiora. Non puoi dedurre con certezza l’intent di rete dal suo stato attuale, specialmente quando sono state applicate molte modifiche ad hoc. La configurazione effettiva della rete è il risultato della tua logica Intent-Driven, non un record affidabile della stessa.

L’intent si manifesta a diversi livelli a seconda delle esigenze di variabilità e personalizzazione. Gli ambienti semplici potrebbero richiedere meno dati variabili e possono fare affidamento sui template. Altri dati potrebbero richiedere una revisione cross-team, mentre alcuni possono essere aggiornati seguendo convenzioni e guardrail.

Qualcuno potrebbe sostenere che il proprio intent è semplicemente l’ Actual State della rete: “controlla la configurazione, quello è il mio intent.” Sebbene questo sia tecnicamente un intent, non puoi dimostrare che corrisponda al tuo intent originale o reale e che non sia stato alterato dalle circostanze, a meno che tu non abbia una fonte separata con cui confrontarlo. La configurazione di rete è l’output del tuo intent, non l’intent stesso.

Quindi la qualità dei tuoi dati Intent-Driven determina direttamente la qualità della tua automazione. Questo concetto è strettamente correlato alla Source of Truth (SoT) (SoT), che tratteremo in dettaglio nel Capitolo 4.

Infrastructure as Code (IaC): L’automazione intent-driven è il fondamento dell’Infrastructure as Code (IaC): trattare le definizioni dell’infrastruttura di rete come codice software. Con IaC, ottieni version control, processi di code review, testing e la capacità di trattare le modifiche all’infrastruttura allo stesso modo delle modifiche software. Questo collega l’automazione di rete con le best practice dell’ingegneria del software. IaC mantiene template, inventory e intent come file sotto version control. Le modifiche vengono revisionate, testate e tracciate, non applicate come edit CLI una tantum.

Partendo dall’intent, il principio successivo garantisce che, una volta definito ciò che vogliamo, possiamo eseguirlo in modo sicuro e coerente.

2.2.2. Idempotency#

Perché l’idempotency è importante: L’idempotency garantisce che esecuzioni ripetute producano lo stesso risultato. È essenziale perché l’automazione viene spesso eseguita più volte per errore, da meccanismi di retry, o per design. Senza idempotency, ogni esecuzione potrebbe apportare modifiche imprevedibili.

Idempotency significa che eseguire la stessa operazione più volte produce lo stesso stato finale, senza effetti collaterali indesiderati.

Ad esempio, nel provisioning automatizzato delle ACL, se definiamo una regola, ci aspettiamo:

  • Se la regola non esiste, viene aggiunta in una posizione specifica.
  • Se la regola esiste già, non vengono aggiunti duplicati.
  • Se in seguito viene aggiunta un’altra regola, quella precedente rimane intatta e non viene riordinata.

Sembra ovvio, ma la realtà è più complessa. Il sistema deve implementare una logica per garantire l’idempotency. Ad esempio, deve verificare:

  • Qual è lo stato attuale dell’ACL?
  • La regola ne fa già parte?
  • In caso contrario, quale differenza deve essere applicata?

Senza idempotency, la configurazione potrebbe essere applicata in ordine imprevedibile, compromettendo la riproducibilità.

L’idempotency si applica alle diverse dimensioni dell’automazione di rete. Ad esempio, quando si richiede un indirizzo IP via DHCP o da un sistema IPAM che comprende la mappatura tra la richiesta dell’identificatore e il risultato:

Figura 1: Esempio di Idempotency (da Damien Garros’ Autocon3 talk)

Come leggerai in seguito, per ottenere l’idempotency, è preferibile usare modelli Declarative invece di quelli Imperative. Definisci lo stato finale piuttosto che i passi. Questo non significa che usare la modalità imperativa sia impossibile, ma è più complicato.

L’idempotency si concentra sulla coerenza all’interno di una singola esecuzione. Il principio transazionale garantisce che le modifiche vengano applicate atomicamente su più sistemi, prevenendo stati parziali o inconsistenti.

2.2.3. Transazionale#

Perché la transazionalità è importante: Le modifiche di rete spesso interessano più dispositivi simultaneamente. Senza transazionalità, un guasto a metà percorso lascia la rete in uno stato inconsistente: alcuni dispositivi aggiornati, altri no. Particolarmente problematico nei sistemi distribuiti, dove coordinare più attori è intrinsecamente complesso.

Transactional è un concetto comune nei database, dove più modifiche vengono applicate atomicamente per mantenere la coerenza. Nel networking (un sistema distribuito), la transazionalità è ancora più complicata, ma non è un problema nuovo. Nel 2006, NETCONF (RFC 6241) ha introdotto il network-wide commit che applica le modifiche globalmente su più dispositivi o esegue il rollback completo se la validazione fallisce. Questa Atomic Operation previene stati parziali in cui alcuni dispositivi hanno applicato la modifica ma altri no: uno scenario da incubo per il troubleshooting. Tuttavia, non tutte le piattaforme supportano NETCONF e la complessità di integrazione varia significativamente. Quindi, sebbene il problema sia risolto in teoria, l’implementazione pratica dipende dalla tua infrastruttura.

Fornire un comportamento transazionale previene operazioni parziali o incomplete (difficili da diagnosticare e che lasciano i sistemi in stati imprevedibili) ed è essenziale per evitare di erodere la fiducia nella tua automazione. Una rete in cui alcuni dispositivi hanno applicato una modifica ed altri no è decisamente peggiore di una rete che ha eseguito un rollback completo.

Quindi, in generale, come potremmo applicare la transazionalità al networking? Si tratta di una combinazione di tecniche:

  • NETCONF: Funzionalità di network management che supportano il coordinamento distribuito. Ma il supporto è molto limitato.
  • Transazioni database-backed: Archivia le modifiche di configurazione in un database con proprietà ACID, poi applicale in batch coordinati con capacità di Rollback
  • Change notification queue: Cattura tutte le modifiche previste, validale come gruppo, poi eseguile con un meccanismo di Rollback coordinato se un dispositivo fallisce
  • Pattern two-phase commit: Prima prepara le modifiche su tutti i dispositivi (fase 1), poi esegui il commit simultaneamente (fase 2), con Rollback se la fase 2 fallisce su qualsiasi dispositivo
  • Log transazionali: Registra ogni tentativo di modifica con dettagli sufficienti per annullare operazioni parziali manualmente o automaticamente

Si noti che tutti i meccanismi in un ambiente distribuito richiedono capacità di rollback per garantire un rollback senza interruzioni. Hai bisogno di un commit o snapshot che possa essere attivato (internamente o esternamente alla piattaforma) per tornare a uno stato precedente. Ciò non è sempre disponibile. Dove non sono disponibili commit atomici nativi, implementa una fase di “prepare” validata e usa un commit coordinato orchestrato o un rollout graduale per ridurre il rischio (da usare solo quando non è disponibile l’atomicità nativa).

Questo principio si collega naturalmente al Versioning: quando qualcosa va storto, devi sapere esattamente in quale stato ti trovi così puoi tornare a una versione nota come funzionante.

2.2.4. Versioned#

Perché il versioning è importante: Ogni modifica comporta un rischio. Il versioning ti permette di sapere esattamente cosa è cambiato, quando è cambiato, chi l’ha cambiato, e fornisce la capacità di ripristinare se necessario. Rappresenta le fondamenta di operazioni sicure su larga scala.

Storicamente, il network engineering gestiva il cambiamento attraverso backup delle configurazioni: snapshot utilizzati per scopi di rollback. Tuttavia, riconciliare lo stato post-modifica dopo un rollback è estremamente complesso perché i backup mancano di contesto.

Nell’ingegneria del software, i Version Control System (VCS) come Git sono una pratica standard (non ho mai lavorato in nessun ambiente senza qualche forma di VCS). Questi sistemi consentono:

  • Collaborazione semplificata: Più sviluppatori contribuiscono al codice e possono andare avanti su branch diversi
  • Viaggio nel tempo: Tornare a punti precedenti nella storia per capire cosa è cambiato e quando
  • Raggruppamento atomico: Più modifiche ai file possono essere raggruppate insieme come una singola unità

Applicare il Versioning all’automazione di rete offre vantaggi significativi:

  • Verificabilità e Tracciabilità: Traccia facilmente chi ha cambiato cosa e quando, rendendo il sistema trasparente
  • Collaborazione Cross-team: Facilita la revisione delle modifiche e abilita lo sviluppo collaborativo dell’automazione
  • Atomic Operationi: Le modifiche correlate su più file possono essere applicate insieme, prevenendo stati parziali o incompleti
  • Integrazione CI/CD: Pipeline automatizzate possono attivare test e validazione ogni volta che vengono rilevate modifiche al codice

I template di configurazione sono un esempio lampante di dati che beneficiano del versioning. Una singola modifica al template impatta tutte le configurazioni derivate in tutta la rete, rendendo il version control essenziale. In generale, tutti i dati dovrebbero essere archiviati in modo versionato. È comune avere file YAML o JavaScript Object Notation (JSON) versionati che modellano dati di qualsiasi tipo, o dati con relazioni più complesse.

GitOps: Un pattern emergente che porta il versioning ad un livello superiore: il repository Git diventa la singola source of truth, ed un controller confronta continuamente il Desired State in Git con l’Actual State nella rete, correggendo automaticamente il drift. Sta guadagnando adozione nella network automation, specialmente in ambienti cloud-native e integrati con Kubernetes.

Il versioning fornisce la storia e l’audit trail. Il principio successivo garantisce la validazione del corretto funzionamento delle modifiche prima del deployment.

2.2.5. Testabile#

Perché la testabilità è importante: L’automazione su larga scala amplifica gli errori. Un bug in un playbook che interessa un dispositivo è gestibile. Lo stesso bug applicato a 10.000 dispositivi è un disastro. Il testing è la tua rete di sicurezza prima del deployment in produzione.

Il testing è particolarmente impegnativo nel networking. Spesso non possiedi l’intera rete (pensa ai peering BGP su Internet, dove non possiedi l’altro lato), oppure la scala è proibitiva (immagina di testare un data center fabric con migliaia di switch). Riprodurre scenari di test reali può essere quasi impossibile o proibitivamente costoso.

Ciò non significa che tu sia senza opzioni. Puoi implementare il testing a più livelli che validano il comportamento dell’automazione e lo stato della rete in varie circostanze.

La testing pyramid fornisce un framework utile:

graph BT
  %% Unit tests (base)
  U1["Unit Test<br/>(Qualità dei Dati, Logica)"]:::unit

  %% Integration tests
  I1["Integration Test<br/>(Ambiente Simulato)"]:::integration

  %% End-to-end tests (top)
  E1["End-to-End Test<br/>(Lab, Validazione)"]:::enduser

  %% Links
  U1 --> I1
  I1 --> E1

  %% Styling
  classDef unit fill:#a6e3a1,stroke:#3b7a57,stroke-width:2px,color:#000;
  classDef integration fill:#89b4fa,stroke:#1e3a8a,stroke-width:2px,color:#000;
  classDef enduser fill:#f9e2af,stroke:#b8860b,stroke-width:2px,color:#000;
  • Gli Unit Test validano la qualità dei dati, la logica di base e comportamenti specifici in isolamento usando mock o sistemi fake. Vengono eseguiti rapidamente e intercettano gli errori fondamentali in anticipo.
  • Gli Integration Test introducono sistemi di terze parti in un ambiente simulato (e semplificato). I diversi componenti di automazione interagiscono tra loro e con varianti di rete simulate, consentendo di validare i punti di integrazione (ad esempio, simulando l’Application Programming Interface (API) o l’interfaccia Secure Shell (SSH) Command Line Interface (CLI) di un dispositivo di rete).
  • Gli End-to-End Test validano il comportamento in scenari quasi reali utilizzando ambienti di rete virtualizzati o lab che simulano parte della rete di produzione (approfondiremo questo argomento nel Capitolo 9).

Gli assistenti AI per la scrittura di codice sono sempre più utili per la generazione di test. Se riesci ad articolare cosa testare, questi strumenti possono aiutare a creare suite di test complete rapidamente (e individuare difetti logici che potresti non notare a prima vista).

Il punto cruciale: l’automazione richiede testing continuo per garantire che nulla si rompa man mano che i sistemi crescono. Una regressione introdotta tardi nello sviluppo è molto più costosa di una intercettata durante gli unit test. Man mano che la tua automazione scala, tutto ciò diventa non negoziabile.

Strategie di Testing Avanzate:

  • Chaos Engineering: Inietta intenzionalmente guasti (interruzioni dei dispositivi, latenza di rete) per validare che la tua automazione e il monitoring li gestiscano in modo controllato (Netflix ha reso popolare questo approccio con il loro Chaos Monkey).
  • Property-Based Testing: Definisci proprietà che devono essere sempre vere (es. “BGP dovrebbe sempre convergere entro 30 secondi”) e lascia che i framework di test generino scenari per verificarle.

Infine, prima di deployare qualsiasi modifica, gli operatori hanno bisogno di visibilità su cosa accadrà.

2.2.6. Dry-Run Friendly#

Perché la capacità dry-run è importante: Anche con tutte le salvaguardie precedenti, le persone hanno bisogno di capire cosa farà l’automazione prima che venga eseguita. La capacità dry-run fa da ponte tra fiducia e azione: mostra agli operatori esattamente cosa cambierà prima che venga apportata qualsiasi modifica.

In qualsiasi decisione importante, è fondamentale capire il piano d’azione prima dell’esecuzione. Quando si costruisce una casa, si vuole vedere come apparirà prima di approvare la costruzione. Allo stesso modo, nel network engineering, siamo abituati a processi di change management che revisionano i piani di esecuzione prima del deployment.

Con l’automazione di rete, la frequenza e la portata delle modifiche possono aumentare drammaticamente. Fornire agli operatori una chiara visibilità su ciò che verrà eseguito prima che accada è essenziale per costruire fiducia e abilitare una revisione adeguata.

Esistono strumenti che forniscono questa capacità Dry Run, ma puoi sempre crearne uno tuo se necessario:

  • Ansible: I flag --check e --diff mostrano cosa verrebbe modificato
  • Terraform: Il comando terraform plan mostra la differenza tra lo stato attuale e il Desired State
  • API di rete custom: Alcune potrebbero esporre una modalità “dry-run” o di anteprima

Ecco un esempio di come appare questa visibilità:

Ansible Diff Output

- description: Uplink to CoreSwitch1
+ description: Uplink to CoreSwitch2
  mtu: 9216

Terraform Plan Output

~ description = "Uplink to CoreSwitch1" -> "Uplink to CoreSwitch2"
  mtu          = 9216

Custom Network API Preview Response

{
  "operation": "PATCH",
  "path": "/interfaces/Gi0-1",
  "changes": [
    {
      "field": "description",
      "current_value": "Uplink to CoreSwitch1",
      "proposed_value": "Uplink to CoreSwitch2",
    }
  ],
  "mtu": 9216
}

I dry run trasformano l’automazione da un approccio “speriamo per il meglio” in un processo deliberato e revisionabile.

Concetti Avanzati di Dry-Run:

  • Impact Analysis: Oltre a mostrare cosa cambia, analizza e comunica l’impatto sul business (es. “Questo interesserà temporaneamente il 10% del traffico”)
  • Staged Rollout: Implementa il dry-run su larga scala rilasciando gradualmente le modifiche a un sottoinsieme di dispositivi prima, validando l’impatto prima del deployment completo
  • Network Simulation: Combina con strumenti di testing di rete per eseguire dry-run su una replica della rete di produzione

2.3. Pattern di Decisione Architetturale#

Oltre ai principi fondamentali, ci sono concetti e considerazioni chiave che fanno da ponte tra la teoria e l’implementazione pratica. Questi pattern ti aiutano a prendere decisioni strategiche sulla tua architettura di network automation.

2.3.1. Dichiarativo vs. Imperativo#

La scelta tra approcci dichiarativi e imperativi è fondamentale. Ognuno ha punti di forza e trade-off, a seconda del caso d’uso. La gestione della configurazione dell’infrastruttura può seguire due approcci:

  • La network automation Declarative definisce lo stato finale desiderato; il sistema capisce come ottenerlo. Esempio: “Voglio che l’interfaccia Gi0/1 abbia un MTU di 9000.” Il motore di network automation determina lo stato attuale e applica solo le modifiche necessarie. Si concentra sul COSA, i risultati desiderati.
  • La network automation Imperative specifica i passi esatti da eseguire. Esempio: “Mostra la configurazione dell’interfaccia, analizzala, calcola la differenza, invia questi esatti comandi CLI in quest’ordine.” Si concentra sul COME, le azioni specifiche.

Gli approcci dichiarativi supportano naturalmente l’Idempotency, le capacità Dry Run e il comportamento Transactional, ma richiedono infrastrutture e sistemi che li supportino.

Gli approcci imperativi offrono un controllo preciso ma sono più difficili da rendere idempotenti e più soggetti a effetti collaterali indesiderati. Tuttavia, potrebbero essere l’unica opzione quando il sistema target non dispone di capacità dichiarative.

Il trade-off principale: gli approcci dichiarativi scalano meglio. Quando disponibili, la complessità dell’implementazione di workflow complessi rimane costante, mentre gli approcci imperativi vedono la complessità crescere esponenzialmente man mano che i workflow diventano più intricati.

La maggior parte dei moderni framework di network automation (Terraform, Ansible, Kubernetes, o strumenti basati su Yet Another Next Generation (YANG)) tendono verso modelli Declarative pur consentendo fallback Imperative quando necessario (es. moduli raw di Ansible, Command Line Interface (CLI) diretto, Netmiko).

Alcuni strumenti come Ansible possono funzionare in entrambi i modi a seconda del tipo di modulo. I moduli network-specific (come cisco.ios.ios_interfaces) sono dichiarativi, mentre ansible.netcommon.cli_command esegue comandi imperativi. Nell’esempio seguente, vedrai entrambi gli approcci:

- name: Approcci Imperativo vs. Dichiarativo in Ansible
  hosts: switches
  gather_facts: no
  vars:
    interface_name: GigabitEthernet0/1
    new_description: Uplink to CoreSwitch2
  tasks:
    - name: Imperativo - Esegui comandi esatti
      ansible.netcommon.cli_command:
        command: |
          configure terminal
          interface {{ interface_name }}
          description {{ new_description }}
          no shutdown
          end
      # Ripetere questo task potrebbe aggiungere duplicati e viola l'idempotency

    - name: Dichiarativo - Definisci lo stato desiderato
      cisco.ios.ios_interfaces:
        config:
          - name: "{{ interface_name }}"
            description: "{{ new_description }}"
            enabled: true
        state: merged
      # Ripetere questo task è sicuro, converge allo stato desiderato

Tieni presente che con un approccio dichiarativo, stai delegando la logica a un sistema esterno, e in alcuni scenari questo potrebbe non essere un’opzione disponibile. Nota nell’esempio precedente come si utilizza il modulo Ansible cisco.ios.ios_interfaces che implementa la logica necessaria per fornire il comportamento dichiarativo.

L’approccio dichiarativo è più sicuro e prevedibile, ma richiede il supporto del modulo per il tuo dispositivo specifico.

2.3.2. Infrastruttura Mutabile vs. Immutabile#

Il concetto: Permetti modifiche in-place all’infrastruttura (la rete), o sostituisci l’infrastruttura interamente quando sono necessarie modifiche?

  • Infrastruttura Mutabile: Approccio tradizionale in cui si accede ai dispositivi via Secure Shell (SSH) e si modificano le configurazioni direttamente (o le si modifica tramite NETCONF, gNMI, o qualsiasi Application Programming Interface (API)). Modifiche applicate in-place.
    • Pro: Meno dirompente, overhead minore.
    • Contro: Più difficile tracciare lo stato, aumenta il rischio di Configuration Drift.
  • Infrastruttura Immutabile: Non si modifica mai l’infrastruttura in esecuzione. Invece, si crea una nuova infrastruttura con le modifiche desiderate e si sposta il traffico/le connessioni. Utilizzata ampiamente nel cloud (container, VM) ma meno comune nel networking.
    • Pro: Stato prevedibile, più facile da verificare, elimina il drift.
    • Contro: Richiede orchestrazione, recovery più complessa, maggiore overhead di risorse.

Nella network automation, siamo tipicamente in uno stato ibrido: le configurazioni sono mutabili (le modifichiamo in-place), ma il principio di immutabilità dovrebbe guidare il design: versiona tutto, traccia le modifiche e sii in grado di ricostruire da zero se necessario.

2.3.3. Greenfield vs. Brownfield#

Non è un termine tecnico, ma è utile per comprendere due scenari diversi nello sviluppo di soluzioni di network automation:

  • Gli ambienti Brownfield esistono già con sistemi legacy, processi manuali, configurazioni inconsistenti e conoscenza tribale. Più difficili perché si sta automatizzando una complessità che non era mai stata pensata per essere automatizzata: design inconsistenti, dati mancanti, tecnologie legacy, abitudini umane e vincoli del traffico in produzione. Ma è l’ambiente più comune.
  • Gli ambienti Greenfield sono costruiti da zero con un design automation-first. Puoi implementare tutti i principi in modo pulito: version control dal primo giorno, intent dichiarativo, modelli di dati puliti, testing completo. Ideale ma raro.

Approfondiamo perché gli ambienti brownfield sono così complicati…

  • Design di rete inconsistenti (o se era consistente, non è più completamente implementato) che si riducono a un insieme di eccezioni.
  • Mancanza di dati puliti e affidabili. La rete stessa o qualche foglio di calcolo obsoleto sono i riferimenti.
  • Alcuni dispositivi di rete di vendor e generazioni diverse non supportano interfacce di network management moderne (oltre alle CLI), limitando l’implementazione di approcci dichiarativi.
  • Cultura operativa e paura del cambiamento. Non dimenticare che le persone vengono prima, e devi guadagnare la fiducia prima dell’adozione.
  • La network automation deve coesistere con il traffico in produzione senza un cutover pulito. Il margine di errore è minimo.

Tuttavia, ci sono ancora speranze in questi casi. I seguenti tre approcci facilitano l’avvio in questi scenari:

  1. Approccio greenfield parziale: Automatizza la nuova infrastruttura mentre si esegue gradualmente il refactoring dei sistemi legacy. Questo mostra progressi senza partire dalla massima complessità.
  2. Selezione incrementale dei target: Concentrati sulle parti della rete più facili da automatizzare e che forniscono quick win:
    • Aggiunta di configuration drift e remediation per alcune funzionalità di management (AAA, NTP, SNMP)
    • Automazione del provisioning delle interfacce per un singolo tipo di dispositivo
    • Standardizzazione di un singolo sottosistema prima di espandersi
  3. Costruire momentum: Ogni piccola vittoria dimostra il valore della network automation e costruisce la fiducia per ottenere finanziamenti ed espandersi

2.3.4. Diversità dei Dispositivi e Astrazione dei Servizi#

Non tutti i dispositivi o servizi di rete funzionano allo stesso modo. Vendor, modelli e persino versioni software diverse hanno interfacce, capacità e limitazioni uniche. La tua network automation deve affrontare questa eterogeneità in modo strategico.

Due approcci principali:

  • Abbracciare la Network Automation Vendor-Specific: Scrivi network automation adattata alle capacità uniche di ogni vendor senza compromettere la riproducibilità. Pro: più semplice inizialmente, sfrutta i punti di forza del dispositivo. Contro: crea silos, più difficile da migrare se i requisiti cambiano.
  • Astrarlo: Crea un layer di astrazione vendor-agnostic che standardizza le operazioni comuni. Pro: portabilità, interfaccia unificata. Contro: maggiore complessità, potenziale perdita di capacità device-specific.

Best Practice: Approccio a Strati La maggior parte delle operazioni mature usa entrambi: driver vendor-specific alla base (un layer per tipo di dispositivo), poi un layer di astrazione comune sopra. Questo ti dà i vantaggi di entrambe le strategie.

Esempio reale: Costruire un’alternativa DMVPN I vendor di rete offrono DMVPN (Dynamic Multipoint VPN) per la scalabilità VPN hub-spoke. Un’alternativa è impostare molti semplici tunnel VPN point-to-point. Tuttavia, senza network automation questo è complicato (ed è la ragione per cui esiste il protocollo). Gestire migliaia di tunnel con la network automation è fattibile (e non estremamente complicato), e fornisce una scalabilità simile attraverso l’orchestrazione piuttosto che la sofisticazione del protocollo, poiché praticamente tutte le piattaforme supportano tunnel VPN di base. Hai sostituito una dipendenza da protocollo con un’astrazione di network automation: spesso un trade-off migliore.

Il principio chiave: separa i dettagli implementativi (come funzionano i dispositivi specifici) dall’obiettivo finale che vuoi raggiungere. Questo abilita l’indipendenza dal vendor e semplifica il ragionamento sul sistema.

2.3.5. La Fallacia degli Strumenti sopra il Design#

Sebbene gli strumenti siano essenziali, non sostituiscono un buon design. Un errore comune: acquistare uno strumento aspettandosi che risolva i problemi di network automation. Gli strumenti contano, ma amplificano l’architettura e il design esistenti. Una strategia di network automation ben progettata con uno strumento mediocre batte una strategia mal progettata con il miglior strumento disponibile.

Design e architettura sono strategia e devono venire prima. Gli strumenti sono dettagli implementativi. Investi tempo nella comprensione dei tuoi requisiti, nel design della tua architettura e nella definizione dei tuoi principi prima di selezionare gli strumenti. A volte un’architettura distribuita è appropriata. Altre volte una soluzione più semplice e capace si adatta meglio alle tue esigenze in termini di risultati versus complessità. Non esiste una formula unica, ma devi riconoscere e essere intenzionale nelle tue scelte.

Ricorda anche che gli strumenti non sono scatole magiche. Devi sempre portare la tua logica in essi. La personalizzazione e la configurazione domain-specific sono inevitabili.

Nel Capitolo 3, esploreremo un’architettura di riferimento che evidenzia i principali building block da considerare nella valutazione degli strumenti.

2.3.6. Build vs. Buy#

Una domanda strategica comune: dovresti acquistare una soluzione off-the-shelf, costruire network automation custom, o usare un approccio ibrido?

La regola semplice: compra quando puoi, costruisci quando devi. Controintuitivamente, costruire è spesso più costoso che comprare. Ma comprare ciò di cui hai bisogno non è sempre possibile.

Quando valuti la decisione:

  • Buy: Da usare quando un prodotto corrisponde strettamente alle tue esigenze, supporta la tua architettura e l’analisi costi/benefici è favorevole
  • Build: Da usare quando i tuoi requisiti sono unici, hai le competenze, o le soluzioni off-the-shelf non si adattano ai tuoi principi

Questa è fondamentalmente una decisione di design, non di procurement. Riguarda quanta personalizzazione e controllo hai realmente bisogno.

In pratica, la maggior parte delle organizzazioni usa un approccio ibrido: acquista componenti strategici (piattaforme di orchestrazione, sistemi CI/CD, storage dei dati) ma costruisce network automation domain-specific (template, workflow, logica di validazione). Devi possedere il layer domain-specific: le ricette generiche raramente producono i risultati di cui hai bisogno.

Quando valuti soluzioni open source, considera l’estensibilità. Spesso puoi riutilizzare il framework e costruire i tuoi layer personalizzati sopra: ad esempio, una data source per archiviare l’intent di rete che estende lo strumento core con modelli di dati personalizzati. Non dimenticare inoltre che con l’open source puoi comunque ottenere supporto ed edizioni enterprise per aggiungere reti di sicurezza quando necessario.

2.3.7. Governance della Network Automation#

Chi decide cosa viene automatizzato? Chi approva una modifica alla logica di network automation? Chi può autorizzare l’esecuzione di un job template su mille dispositivi in produzione? Queste domande raramente hanno risposte tecniche chiare, ma devono trovare risposta a livello organizzativo prima che la network automation raggiunga una scala significativa.

Una network automation non governata introduce una classe di rischio diversa rispetto alle operazioni manuali. Un singolo network engineer che commette un errore manuale interessa un dispositivo o una sessione. Un network engineer che lavora sull’automazione e commette un errore in un template di playbook può interessare ogni dispositivo in scope simultaneamente. Il blast radius scala con la capacità della network automation.

La governance in questo contesto significa definire quattro cose:

  • Confini di scope: quali operazioni sono idonee alla network automation e quali richiedono esecuzione umana indipendentemente dalla maturità della network automation. Le modifiche alle policy BGP, le modifiche ai protocolli di routing, o gli aggiornamenti delle policy di sicurezza potrebbero rimanere sotto controllo umano anche quando il resto dello stack è automatizzato, non perché la network automation non possa eseguirle, ma perché le conseguenze di un errore sono abbastanza grandi da giustificare la presenza di un essere umano nel loop.

  • Processo di approvazione della logica: le modifiche alla logica di network automation (nuovi playbook, template modificati, modelli di dati aggiornati nella SoT) dovrebbero seguire un processo di revisione equivalente a una software code review. La disciplina qui rispecchia l’ingegneria del software: le modifiche al codice che gira in produzione richiedono revisione prima di raggiungerla. Il codice di network automation non è diverso.

  • Autorizzazione all’esecuzione: chi può attivare quale job, su quale scope, in quali condizioni. Questo si traduce direttamente nel controllo degli accessi basato sui ruoli nel layer di Execution (Capitolo 5) e nel layer di Presentation (Capitolo 8). Il modello di governance deve essere espresso nei controlli di accesso degli strumenti, non solo in un documento di policy.

  • Audit e accountability: la network automation deve produrre lo stesso audit trail che produce il change management manuale. Un evento di esecuzione deve essere tracciabile a un change ticket, un approvatore e una versione specifica della logica di network automation che è stata eseguita. Questo non è opzionale negli ambienti regolamentati.

La governance non è burocrazia fine a se stessa. È il meccanismo attraverso cui le organizzazioni estendono la fiducia alla network automation in modo incrementale. Iniziare con operazioni a basso rischio, reversibili e ben comprese ed espandere lo scope man mano che la network automation guadagna una track record è più efficace che bloccarla completamente o deployarla senza guardrail.

2.3.8. Perché Questi Principi Sono Importanti: Imparare dai Fallimenti#

La network automation amplifica qualunque cosa le venga fornita. Processi puliti e ben progettati diventano più efficienti e affidabili. Ma anche un design scadente, dati errati o logica difettosa scalano, creando problemi più grandi più velocemente.

Il Case Study dell’Outage di Meta

Nell’ottobre 2021, Meta (ex Facebook) ha subito un outage globale della rete che ha messo offline i loro sistemi per ore. Cosa l’ha causato? La network automation ha amplificato una misconfiguration. Durante uno spostamento di traffico di routine, i sistemi automatizzati hanno apportato modifiche globali basate su una validazione incompleta delle policy. La configurazione si è propagata in cascata attraverso la rete, causando un single point of failure che si è diffuso globalmente.

La causa principale era una modifica errata della configurazione sui router backbone, che ha interrotto la comunicazione tra i data center. Questo guasto a cascata ha bloccato i servizi globalmente e ha anche impattato gli strumenti interni, complicando la diagnosi e la risoluzione. Meta ha chiarito che il problema non era dovuto ad attività malevole e nessun dato utente è stato compromesso. Tuttavia, l’outage ha evidenziato lacune presumibilmente critiche nella loro strategia di network automation:

  • Nessuna idempotency: Modifiche applicate senza verificare lo stato attuale
  • Nessuna transazionalità: Alcuni dispositivi hanno ricevuto la modifica, altri no (fallimento parziale)
  • Testing insufficiente: Lo scenario non è stato intercettato in pre-produzione
  • Nessuna capacità dry-run: Le modifiche sono state applicate senza anteprima o validazione
  • Versioning inadeguato: Impossibilità di identificare e ripristinare rapidamente la modifica problematica
  • Observability insufficiente: Impossibilità di rilevare il guasto abbastanza velocemente
  • Nessuna degradazione controllata: Le modifiche si sono propagate in cascata globalmente senza contenimento del blast radius
  • Responsabilità poco chiare: Nessuna gerarchia decisionale chiara per la network automation

Mappatura sui Principi: Ognuno dei nostri sei principi di design fondamentali affronta direttamente uno di questi fallimenti. Questo dimostra che non sono optional nice-to-have: sono salvaguardie essenziali.

La Lezione: Non automatizzare il caos sperando di risolverlo in seguito. Invece:

  1. Inizia con processi che comprendi e puoi validare
  2. Automatizza in modo incrementale, imparando da ogni passo
  3. Tratta ogni fallimento della network automation come un’opportunità di apprendimento
  4. Incorpora salvaguardie: rate limit, meccanismi di rollback, observability, contenimento del blast radius
  5. Separa le responsabilità così che i fallimenti in un’area non si propaghino globalmente

Nota come questo si colleghi all’approccio Persone, Processo e Tecnologia introdotto nel Capitolo 1.

I principi che abbiamo esplorato (Intent-Driven, Idempotency, Transactional, Versioning, testabilità e capacità Dry Run) affrontano direttamente questi modi di fallire. Non sono funzionalità opzionali; sono salvaguardie essenziali che devono essere incorporate fin dall’inizio.

2.4. Principi di Ingegneria del Software#

Oltre ai principi di design specifici del networking, i principi più ampi dell’ingegneria del software svolgono un ruolo cruciale nella costruzione di sistemi di network automation manutenibili e scalabili. Se vieni da un background di ingegneria del software, riconoscerai la maggior parte di questi; il valore qui sta nel vedere come si applicano specificamente alla network automation.

Non tutti e dodici hanno lo stesso peso in questo dominio. Quattro affrontano modi di fallire specifici della network automation su infrastrutture critiche: il Principio del Minimo Stupore (una network automation che si comporta in modo inaspettato distrugge la fiducia operativa stabilita nella sezione 2.1 prima che possa consolidarsi), la Programmazione Difensiva e Robusta (le reti falliscono in modi parziali e non deterministici che la network automation deve anticipare per design, non gestire come eccezioni), il Fail Fast, Fail Visible (il rilevamento precoce dei guasti contiene il blast radius prima che si scala tra i dispositivi) e la Separation of Concerns (il principio strutturale che il framework NAF nel Capitolo 3 istanzia direttamente — separare intent, logica di esecuzione e presentation non è una buona pratica generica qui, è la struttura specifica che mantiene i building block indipendentemente evolvibili). Gli altri otto principi sono igiene software standard: corretti, importanti e vale la pena conoscerli, ma non la ragione per cui la network automation specificamente fallisce o ha successo.

Li organizziamo in due categorie ispirandoci alle opere di Robert C. Martin “Clean Code” e “Clean Architecture”:

  • Principi di Clean Code: Come scrivere logica di network automation leggibile, manutenibile e corretta.
  • Principi di Clean Architecture: Come strutturare i sistemi affinché i componenti rimangano indipendenti, testabili ed evolvibili.

Concentrandosi sull’applicazione alla network automation, puoi trovare buoni esempi di questi principi in questa serie di blog di Network to Code di Ken Celenza.

2.4.1. Principi di Clean Code#

In questa sezione, il focus è su come vengono costruiti i componenti software.

Scrivi Codice per chi lo Legge

Il codice che scrivi verrà letto molte volte in futuro: da te stesso (durante il debugging) o da altri. E probabilmente non avranno il tuo contesto originale. Esprimi chiaramente la tua intenzione nel codice attraverso nomi significativi, commenti e struttura (non abusare dei commenti; usali con attenzione). Il codice di network automation non è solo istruzioni per le macchine; è una forma di documentazione per gli esseri umani.

DRY – Don’t Repeat Yourself

Evita di duplicare la logica nella tua codebase di network automation. Estrai invece i pattern comuni in template, funzioni o workflow riutilizzabili.

Invece di scrivere logica di configurazione device-specific in dieci playbook diversi, crea un template condiviso con variabili per le differenze. Questo riduce i bug e rende gli aggiornamenti più semplici. Questo principio si applica anche ai dati: usa strutture dati appropriate che sfruttino l’ereditarietà e il polimorfismo per creare modelli di dati più scalabili e riutilizzabili.

Quando violi il DRY, una correzione in un posto richiede correzioni in altri cinque, e inevitabilmente ne dimenticherai una.

Single Responsibility Principle (SRP)

Ogni modulo, funzione o workflow dovrebbe avere un solo motivo per cambiare. Nella network automation, questo significa:

  • Un motore di rendering dei template di configurazione non dovrebbe gestire anche la device discovery
  • Un workflow di validazione non dovrebbe anche eseguire modifiche

Quando ogni componente ha una singola responsabilità, i fallimenti sono isolati, il testing è più semplice e le modifiche sono meno rischiose. Ovviamente, ci sarà una funzione di composizione (o orchestrazione) per connettere tutte queste funzioni insieme.

Fail Fast, Fail Visible

Rileva i problemi il prima possibile e rendili visibili chiaramente. Nella network automation:

  • Valida i dati immediatamente all’input (non aspettare fino al deployment)
  • Rendi l’output del Dry Run esplicito e ovvio
  • Registra i fallimenti con il contesto completo, non con codici di errore vaghi
  • Avvisa immediatamente gli operatori quando qualcosa va storto

Intercettare i problemi presto riduce il blast radius e il tempo di risposta.

Sicurezza

Crittografia, autenticazione, minimo privilegio e audit trail devono essere incorporati nei sistemi di network automation fin dall’inizio, non aggiunti in seguito.

Nella network automation: ogni modifica dovrebbe essere verificabile, le credenziali non dovrebbero mai essere hardcoded e il controllo degli accessi dovrebbe seguire il principio del minimo privilegio. Un singolo sistema di network automation con accesso completo alla rete è un disastro di sicurezza in attesa di accadere.

Approfondiremo le considerazioni sulla sicurezza e la compliance nel Capitolo 12.

Principio del Minimo Stupore

La network automation dovrebbe comportarsi nel modo in cui gli utenti si aspettano. Un comportamento sorprendente o controintuitivo erode la fiducia.

Ad esempio, se un task di network automation si chiama “deploy_interface”, gli operatori si aspettano che crei un’interfaccia, non che ne elimini una. Un comportamento inaspettato frustra gli utenti e causa errori.

Programmazione Difensiva e Robusta

Incorpora retry, pattern Circuit Breaker, Compensation Logic e meccanismi di fallback. I sistemi distribuiti falliscono. Progetta per questo piuttosto che contro di esso. Se un dispositivo è temporaneamente irraggiungibile, riprova con backoff esponenziale invece di fallire immediatamente. Se una modifica fallisce a metà, avere un piano di rollback.

Questi pattern appaiono concretamente nel Capitolo 7 (Orchestration), dove il pattern di compensazione Saga gestisce i fallimenti parziali del workflow, e la logica di retry/backoff è incorporata nella funzionalità di resilienza.
“Sii conservativo in ciò che invii, sii liberale in ciò che accetti.” Legge di Postel (RFC 761)

Nella network automation:

  • Invio conservativo: Assicurati che i dati che invii alle API o ai dispositivi rispettino schemi e contratti rigorosi
  • Accettazione liberale: Sii pronto a gestire variazioni (es. attributi come interi o stringhe con conversione) per massimizzare l’interoperabilità con diverse versioni di sistema

Questo principio fa da ponte tra il clean code e l’architettura. Influenza sia come scrivi la logica di integrazione che come strutturi le interfacce di sistema.

2.4.2. Principi di Clean Architecture#

Esploriamo ora i principi che governano come i componenti di una soluzione di network automation si combinano.

KISS – Keep It Simple, Stupid

Più semplice è più facile da capire, testare e mantenere. Evita l’over-engineering in design, implementazione e architettura. La semplicità riduce i bug, aumenta la manutenibilità, migliora la leggibilità e rende i sistemi più facili da estendere o debuggare.

Semplice non significa semplicistico. Significa scegliere l’approccio più diretto che soddisfi i requisiti senza over-engineering o aggiungere astrazioni premature.

Nella network automation, questo significa preferire approcci Declarative semplici rispetto a script imperativi complessi (quando possibile), privilegiando chiarezza, componenti piccoli e componibili, comportamento prevedibile e soluzioni facilmente comprensibili da altri (incluso il tuo io futuro).

Separation of Concerns

Separa chiaramente dati (configurazione), logica (workflow) e presentation (API/UI). Questo previene il tight coupling e abilita l’evoluzione indipendente di ogni layer.

Nella network automation:

  • Layer dati: Network intent archiviato in forma strutturata
  • Layer logico: Motori di network automation e regole di validazione
  • Layer di presentation: API, CLI, dashboard per gli operatori

Questa separazione ti permette di cambiare come gli operatori interagiscono con la network automation senza impattare la logica sottostante. Questa separazione si mappa direttamente sui building block del NAF: il layer dati è la Source of Truth (Capitolo 4), il layer logico comprende Execution (Capitolo 5), Observability (Capitolo 6) e Orchestration (Capitolo 7), e il layer di Presentation è il Capitolo 8. Il Capitolo 3 introduce il framework NAF completo.

Observability

La network automation deve essere strumentata per misurare il proprio comportamento, rilevare i guasti e attivare azioni correttive. Non puoi ottimizzare ciò che non puoi misurare. Traccia sia metriche tecniche che orientate al business (es. ROI delle iniziative di network automation).

Nel Capitolo 6, tratteremo i diversi tipi di dati di observability che ci interessano nel networking: metriche, log, trace, network flow, alert (e molti altri!), e come sfruttarli per fornire informazioni utili a tutti i livelli.

Senza observability, stai volando alla cieca. Non saprai se la network automation funziona correttamente o sembra solo funzionare. Ricorda: anche i sistemi di network automation falliscono e hanno bisogno di monitoring. Strumenta i tuoi strumenti di network automation in modo tanto approfondito quanto strumenti la rete.

Estensibilità

Progetta pensando al futuro. Nuovi vendor, nuove tecnologie e nuovi requisiti arriveranno. L’architettura dovrebbe consentirlo senza richiedere riscritture complete.

In pratica: usa architetture a plugin per i driver vendor-specific, evita assunzioni hardcoded sulla topologia di rete e mantieni le interfacce stabili mentre le implementazioni evolvono.

Coupling Minimo, Coesione Massima

Definisci contratti chiari per come i sistemi comunicano: schemi, regole di validazione e policy di backward-compatibility. Questi contratti consentono l’evoluzione indipendente dei componenti.

Nella network automation, se il tuo sistema di orchestrazione parla ai tuoi driver dei dispositivi attraverso una REST API ben definita, entrambi i layer possono evolvere indipendentemente finché il contratto API viene mantenuto.

Affronta sempre ogni sistema con un’API-First Design: progetta prima le API (non le implementazioni). Questo garantisce che i sistemi possano essere sviluppati indipendentemente e sostituiti senza rompere gli altri componenti.


Questi principi avanzati verranno esplorati più in profondità nei capitoli successivi mentre discutiamo di scaling della network automation in organizzazioni grandi (e più piccole). Per ora, comprendi che questi principi completano i principi di design che abbiamo esplorato in precedenza: insieme, formano le fondamenta per una network automation affidabile, manutenibile e scalabile.

Questo capitolo ha stabilito che la fiducia è la fondamenta di una network automation vincente. La fiducia emerge da quattro qualità fondamentali: Predictable, Reliable, Usable e Understandable.

Queste qualità sono supportate da sei principi di design fondamentali:

  1. Intent-Driven: Definisci cosa vuoi ottenere prima di come ottenerlo
  2. Idempotente: Le esecuzioni ripetute producono risultati coerenti
  3. Transazionale: Le modifiche si completano interamente o falliscono in modo sicuro, mai parzialmente
  4. Versionato: Traccia tutte le modifiche con cronologia completa e audit trail
  5. Testabile: Valida il comportamento prima del deployment in produzione
  6. Dry-Run Friendly: Anteprima delle modifiche prima dell’esecuzione

Oltre a questi principi fondamentali, abbiamo esplorato pattern di decisione architetturale (dichiarativo vs. imperativo, greenfield vs. brownfield, astrazione dei dispositivi) e principi di ingegneria del software (clean code e clean architecture) che operazionalizzano questi pattern in sistemi reali.

Questi principi non sono teoria astratta: hanno implementazioni concrete negli strumenti e framework che utilizzerai. Nel resto di questo libro, vedremo come il pensiero architetturale (Capitolo 3) applica questi principi a sistemi più grandi, e come i building block (Capitoli 4–9) li operazionalizzano.

I punti chiave:

  • Inizia con i principi, non con gli strumenti
  • Progetta per risultati Predictable, non per la complessità
  • Misura e migliora continuamente.

Quando lo fai in modo coerente, la fiducia segue naturalmente, e con la fiducia arriva la capacità di scalare la network automation in tutta la tua organizzazione.

Ora comprendi i principi che rendono la network automation affidabile. Nel Capitolo 3 (Architectural Thinking), vedremo come strutturare questi principi in sistemi scalabili. Imparerai come progettare una network automation che cresce con la tua organizzazione senza diventare ingestibile: una visione pratica e architetturale di come applicare sistematicamente i principi che hai appreso qui.

💬 Found something to improve? Send feedback for this chapter