8) SDN & Réseaux modernes
SDN (ACI, NSX-T), fabrics EVPN/VXLAN & SRv6, SD-WAN/SASE, **Automation** (Ansible/Nornir/Netmiko), **IaC/NaC** (Terraform, GitOps), **APIs & modèles** (NETCONF/RESTCONF/gNMI/YANG), **tests/validation** (Batfish, pyATS, NAPALM), **CNI/Service Mesh** (Calico, Cilium, Istio), **orchestration** (NSO, Apstra, DNAC), **lab** (containerlab, EVE-NG).
EVPN/VXLAN ACI NSX-T DFW SD-WAN/SASE Ansible/Nornir Terraform NETCONF/gNMI Batfish/pyATS
Concepts SDN — Underlay/Overlay, Intent, Policy
Underlay
- IP Fabric L3 (IS-IS/OSPF/BGP), **ECMP**, Leaf/Spine.
- MTU 9216 pour VXLAN, BFD/GR/FRR pour convergence.
Overlay
- Encap VXLAN/Geneve, **VTEP/TEP**.
- Plan de contrôle **EVPN** (vs flood&learn).
Intent/Policy
- Déclaratif → compilation → déploiement.
- Politique L4-L7, micro-seg, service insertion.
Leaf/Spine (Underlay L3) ── ECMP ──> Leaf(VTEP)
│ │
└── Controller (APIC/NSX/…) <──────┘ ← Intent → Compile → Push (NETCONF/REST/API)
| Critère | ACI | NSX-T | EVPN/VXLAN DC |
|---|---|---|---|
| Contrôle | APIC | NSX Manager/Policy | BGP EVPN distribué |
| Sécurité | Contracts | DFW (L3–L7) | ACL/SGT (selon vendor) |
| Intégration L4-7 | Service Graphs | LB/NAT/IDS | Externe/Cloud |
| Portée | Physique+Virtuel | Virtuel/Edge | Physique |
# Règles de design (résumé)
- Leaf/Spine: Spine=stateless, Leaf=policy/VTEP, oversub ≤ 3:1
- EVPN: Route Type-2(MAC/IP), Type-3(IMET), Type-5(IP Prefix L3VNI)
- Anycast GW: SVI identique (MAC/IP) sur tous les leafs d’un VRF
- MTU: Underlay 9216, Overlay 8950+, hôte 9000
# Glossaire rapide
EVPN RT2/RT3/RT5 | VTEP | L3VNI | DFW | Contract | L3Out | SR Policy | SID | TI-LFA
Cisco ACI — Modèle objet, Contracts, L3Out, API & Terraform
| Objet | Rôle | Notes |
|---|---|---|
| Tenant | Isolation | Multi-projets |
| VRF | Routage | Multi-VRF |
| BD | L2 Domain | ARP Flood/Subnets |
| EPG | Endpoints | Port/VLAN/VMM |
| Contract | Politique | Filters + L4-7 |
| L3Out | Ext | BGP/OSPF |
# APIC REST — créer Tenant/BD/EPG (extraits)
POST https://apic/api/mo/uni/tn-Demo.json
{ "fvTenant": { "attributes": { "name": "Demo" } } }
POST https://apic/api/mo/uni/tn-Demo/BD-bd10.json
{ "fvBD": { "attributes": { "name": "bd10" }, "children":[
{ "fvSubnet": { "attributes": { "ip": "10.10.10.1/24" } } }
] } }
POST https://apic/api/mo/uni/tn-Demo/ap-App/epg-Web.json
{ "fvAEPg": { "attributes": { "name": "Web" } } }
# Terraform ACI — tenant + VRF + BD + EPG
provider "aci" { url="https://apic" username="admin" password="***" insecure=true }
resource "aci_tenant" "demo" { name = "Demo" }
resource "aci_vrf" "vrf" { tenant_dn = aci_tenant.demo.id name="PROD" }
resource "aci_bridge_domain" "bd" { tenant_dn=aci_tenant.demo.id name="BD10" arp_flood="yes" }
resource "aci_application_profile" "app" { tenant_dn=aci_tenant.demo.id name="App" }
resource "aci_application_epg" "web" { application_profile_dn=aci_application_profile.app.id name="Web" }
# Diag rapides
show endpoint ip 10.10.10.5
contract hit-counts | fabric node health | faults | atomic counters
VMware NSX-T — T0/T1, Segments, DFW, LB, Federation
- Segments Geneve, T1 DR (distribué), T0 Edge GW (NAT, eBGP/OSPF, LB).
- Edge Nodes/Clusters, Transport Zones, Uplinks, Federation (multi-site).
VM <─ DFW (L3–L7) ─> T1 (DR) ─> T0 (SR) ─> Edge/L3 ext (BGP/OSPF)
# DFW Rule (Policy API pseudo)
POST /policy/api/v1/infra/domains/default/security-policies/WEB/rules/allow-http
{ "action":"ALLOW","services":["TCP-80"],"source_groups":["SG-Web"],"destination_groups":["SG-App"] }
# Terraform NSX-T — segment & DFW
provider "nsxt" { host="nsx-mgr" username="admin" password="***" allow_unverified_ssl=true }
resource "nsxt_policy_segment" "web" { display_name="seg-web"
transport_zone_path="/infra/..." subnet { cidr="10.10.10.0/24" } }
resource "nsxt_policy_security_policy" "pol" { display_name="WEB" }
resource "nsxt_policy_security_rule" "http" {
security_policy_path = nsxt_policy_security_policy.pol.path
action="ALLOW"
services=["/infra/services/HTTP"]
source_groups=["/infra/domains/default/groups/SG-Web"]
destination_groups=["/infra/domains/default/groups/SG-App"]
}
EVPN/VXLAN — VTEP, Anycast GW, RT 2/3/5, MLAG/vPC
- RT-2 (MAC/IP), RT-3 (IMET), RT-5 (IP Prefix L3VNI).
- Anycast GW sur leafs (SVI même MAC/IP), MLAG/vPC hôtes.
- “suppress-arp”, ARP-glean, ND proxy en L3VNI.
# Arista EOS (extraits)
router bgp 65001
neighbor SPINE peer-group
address-family evpn
neighbor SPINE activate
vlan 10
vxlan vlan 10 vni 1010
interface Vxlan1
vxlan source-interface Loopback0
vxlan vlan 10 vni 1010
vxlan vrf PROD vni 5000
! Cisco NX-OS (extraits)
feature nv overlay
feature bgp
router bgp 65001
address-family l2vpn evpn
vlan 10
vn-segment 1010
interface nve1
source-interface loopback0
member vni 1010
suppress-arp
# Checks essentiels
- MTU path (host <-> leaf) | ECMP OK | BGP EVPN adj up
- VRF ↔ L3VNI mapping | SVI anycast doublé | ARP/ND counters
Segment Routing — SR-MPLS & SRv6 (SIDs, TI-LFA, SR Policy)
SID types (SRv6):
- Node-SID: End (endpoint)
- Adj-SID: Liens/Adjacences
- Service-SID: End.DX6/End.DT46 (L3/L2VPN)
# SR Policy (pseudo CLI)
segment-routing
policy AppA
color 100 end-point 2001:db8::1
candidate-path preference 200 explicit segment-list SL1
!
segment-list SL1
index 10 sid 2001:db8:1::
index 20 sid 2001:db8:2::
# TI-LFA: backup immédiat par segments pré-calculés
# KPI: convergence < 50ms, couverture topologique > 98%
SD-WAN & SASE — vManage/vSmart/vBond, App-Aware, ZTNA/CASB
- vManage (mgmt), vSmart (policy), vBond (orchestration).
- Overlay IPsec, DIA, App-Aware routing, segmentation VPN.
# App policy (pseudo)
match app = "Office365" then prefer link MPLS; fallback DIA; SLA jitter < 30ms
# SASE/Zero Trust
ZTNA agent/app, SWG, DNS Security, CASB, DLP, RBI
Automation — Ansible, Nornir, Netmiko (Inventaires, Jinja2, Vault)
# Ansible — VLAN + port access (ios)
- hosts: access
gather_facts: no
vars: { vlan_id: 10, vlan_name: USERS }
tasks:
- ios_vlans: { config: [{ vlan_id: "", name: "" }], state: merged }
- ios_interfaces:
config: [{ name: "Gi1/0/10", description: "User", mode: access, access: { vlan: "" } }]
state: merged
! Jinja2 — SVI avec helpers
interface Vlan
ip address
no shut
# Nornir + Netmiko (Python)
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_config
nr = InitNornir(config_file="config.yaml")
r = nr.run(task=netmiko_send_config, config_commands=["hostname LAB-SW"])
print(r)
# hosts.yaml (inventaire)
access:
hosts:
sw1: { hostname: 10.0.0.11, platform: ios }
sw2: { hostname: 10.0.0.12, platform: ios }
Terraform — Providers Réseau, Modules, CI/CD & Policy as Code
| Provider | Ressources | Cas d’usage |
|---|---|---|
| aci | tenant/vrf/bd/epg/contract | ACI intent |
| nsxt | segment/t0-t1/dfw/lb | NSX-T réseau & sécu |
| aws/azurerm/google | vpc/vnet, routes, vpn | Hybrid/multi-cloud |
| panos/cvp/junos | FW/CloudVision/Junos | Sécu & DC autom. |
# Module segment NSX
module "seg_web" { source="./modules/nsx_segment" name="web" cidr="10.10.10.0/24" }
# GitHub Actions — plan/apply
on: [pull_request, push]
jobs:
tf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init && terraform validate && terraform plan -out=plan.out
- if: github.ref == 'refs/heads/main'
run: terraform apply -auto-approve plan.out
# OPA/Rego — policy (exemple conceptuel)
package net.policy
deny[msg] { input.vlan.id < 10; msg := "VLAN réservé" }
Network-as-Code & GitOps — Intent, Données, Pipelines, DRIFT
repo/
├─ inventory/ (yaml)
├─ intent/ (sites, vlans, policies)
├─ templates/ (jinja)
├─ playbooks/
├─ modules/terraform/
├─ tests/ (batfish, pyats)
└─ .github/workflows/ci.yml
# intent/sites/paris.yaml
site: paris
vlans:
- { id: 10, name: "USERS", gw: "10.10.10.1/24" }
- { id: 20, name: "VOICE", gw: "10.10.20.1/24" }
contracts:
- { name: "web", src: "EPG-Web", dst: "EPG-App", ports: [80,443] }
# Pipeline
1) Lint YAML/Jinja + sécurité secrets
2) Build configs (Ansible/Jinja) + validations (Batfish)
3) Plan Terraform (NSX/ACI) — approval requis
4) Déploiement fenêtré + post-checks (pyATS)
# .pre-commit-config.yaml (extrait)
- repo: https://github.com/adrienverge/yamllint
rev: v1.35.1
hooks: [{ id: yamllint }]
- repo: https://github.com/zricethezav/gitleaks
rev: v8.18.0
hooks: [{ id: gitleaks }]
APIs & Modèles — NETCONF/RESTCONF, gNMI/OpenConfig, YANG
<rpc><edit-config>... (NETCONF, ietf-interfaces)</edit-config></rpc>curl -u admin:*** -H "Content-Type: application/yang-data+json" \
-X POST https://router/restconf/data/Cisco-IOS-XE-native:native/vlan \
-d '{ "Cisco-IOS-XE-vlan:vlan-list":[{ "id":10, "name":"USERS"}] }'
# gNMI Set (OpenConfig pseudo)
updates:
- path: /interfaces/interface[name=Eth1]/config/description
val: "Uplink to Spine1"
Validation & Tests — Batfish, pyATS/Genie, NAPALM, SuzieQ
# Batfish — assertions (pseudo)
assert reachability(src="EPG-Web", dst="EPG-App", permit=True, via="Contract:Web")
assert no_unintended_acl_drops()
# pyATS testbed + sanity
testbed:
devices: { sw1: { os: iosxe, connections: { cli: {protocol: ssh, ip: 10.0.0.11}}}}
# Tests: interface up, err < seuil, route présent
# NAPALM
from napalm import get_network_driver
d = get_network_driver("ios")("10.0.0.11","u","p"); d.open()
print(d.get_interfaces_counters()["Gig1"])
# SuzieQ
sq poller add --source iosxe --address 10.0.0.11
sq show interfaces --columns='hostname,ifname,state,mtu'
CNI & Service Mesh — Calico, Cilium (eBPF), Istio & Gateway API
| CNI | Mécanisme | Atouts | Notes |
|---|---|---|---|
| Calico | BGP/encap/VXLAN | Simple, scalable | NetworkPolicy |
| Cilium | eBPF | Perf, L7 aware | Hubble/observability |
# Calico policy (extrait)
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
spec: { selector: "app == 'web'", ingress: [{ action: Allow, protocol: TCP, destination: { ports: [80,443] }}] }
# Istio — Gateway API (extrait YAML)
kind: HTTPRoute
spec: { hostnames: ["app.example.com"], rules: [{ matches:[{path:{type: PathPrefix, value:"/"}}], backendRefs:[{ name:"app-svc", port:80 }]}]}
Lab — containerlab / EVE-NG : EVPN, NSX, ACI, SD-WAN
# clab.yml — mini fabric EVPN
name: evpn-lab
topology:
nodes:
l1: { kind: linux, image: frrouting/frr }
s1: { kind: linux, image: frrouting/frr }
links:
- endpoints: ["l1:eth1","s1:eth1"]
# EVE-NG — note
Importer images (vEOS, NX-OSv9k, vSRX, CSR1000v) + topologie Leaf/Spine + EVPN
# CI rapide
docker compose run --rm tests pyats run job sanity_job.py
