Come annunciato vi presentiamo la seconda parte dell’articolo sulla configurazione della rete con RHEL7/CentOS7 con nmcli, la command line interface di Network Manager. Il un post recente abbiamo anche mostrato uno script che fa uso si nmcli per semplificare alcuni processi di creazione di connessioni ethernet, team e bridge. Proprio di queste ultime due parleremo in questo blogpost, nello specifico tratteremo la configurazione di connessioni bridge e team in nmcli. Vedremo poi come monitorarle e analizzare i relativi file di configurazione.
Fino a tempi molto recenti nmcli era considerato inidoneo alla gestione di configurazioni più avanzate. Se, ad esempio, avessimo dovuto creare una connessione bridge avremmo dovuto interrompere e disabilitare il servizio NetworkManager e procedere alla configurazione manuale editando in /etc/sysconfig/network-scripts/ i nostri file ifcfg-*. Ora possiamo creare la nostra connessione bridge con nmcli in pochissimi semplici passi.
Iniziamo dalle connessioni bridge. Un network bridge che è un data link layer device che inoltra pacchetti in più network in base al loro MAC address. Questa pratica permette di segmentare una rete in modo logico ed efficiente. Il bridge analizza ogni singolo pacchetto e in base al MAC address di destinazione lo ruota in modo corretto. In Linux possiamo creare software bridge per emulare i bridge hardware. L’uso più comune che se ne fa è nell’ambito della virtualizzazione dove è necessario condividere un NIC hardware tra più NIC virtuali.
Nell’esempio seguente realizzeremo un software bridge utilizzando due NIC eth1 ed eth2 ed un software bridge br0 che smisterà il traffico sui due device.
Per prima cosa andremo a creare il network bridge br0 tramite il seguente comando:
nmcli con add type bridge con-name br0 ifname br0 |
In questo esempio abbiamo scelto di non dare alla connessione un ip statico. Se avessimo voluto un indirizzo IPv4 statico avremmo potuto utilizzare un comando del genere:
nmcli con add type bridge con-name br0 ifname br0 ip4 192.168.127.155/24 gw4 192.168.127.1 |
Successivamente andremo a creare i nostri bridge-slave:
nmcli con add type bridge-slave con-name br0-slave1 ifname eth1 master br0 nmcli con add type bridge-slave con-name br0-slave2 ifname eth2 master br0 |
Verifichiamo lo stato delle nostre connessioni con il comando
nmcli con show |
Supponendo di aver scelto per il DHCP andiamo a vedere quale indirizzo IP è stato assegnato al nostro bridge:
ip addr show |
Possiamo vedere anche i due device slave che sono ancora link attivi ma non hanno un IP assegnato.
Osserviamo ora i file di configurazione delle nostre connessioni, cominciando dal file /etc/sysconfig/network-scripts/ifcfg-br0:
DEVICE=br0 STP=yes BRIDGING_OPTS=priority=32768 TYPE=Bridge BOOTPROTO=dhcp DEFROUTE=yes PEERDNS=yes PEERROUTES=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_PEERDNS=yes IPV6_PEERROUTES=yes IPV6_FAILURE_FATAL=no NAME=br0 UUID=d1fa7bb2-5b43-4e0c-b819-a25d8cc4e3cb ONBOOT=yes |
Questo è il file di configurazione esattamente come è stato generato da Network Manager. In particolare la direttiva TYPE=Bridge specifica che si tratta di una connessione bridge.
Con il tool brctl possiamo studiare meglio il nostro nuovo software bridge:
brctl show br0 |
Oltre ai due slave device che abbiamo dato a br0 come porte possiamo leggere anche il bridge id di br0.
Ricordiamo che il bridge id è un campo di 8 byte composto da due parti: i primi due byte corrispondono alla bridge priority mentre i successivi 6 byte corrispondono al mac address.
In modo molto simile andremo a creare una connessione team tramite Network Manager. Una connessione team permette di aggregare due device assieme in modo simile al network bonding e facendo si che due o più network device si comportino come un’unica interfaccia. Strumento da applicare soprattutto in contesti dove sono richieste high availability e fault tolerance oppure, semplicemente dove è richiesto un output più elevato.
Ambedue i metodi aggregano device a layer 2 dello stack. La differenza sostanziale tra il bonding e il teaming è che il primo avviene soprattuto in kernel space rendendone il controllo leggermente più limitato mentre il network teaming implementa un piccolo kernel driver mentre fornisce una serie di tools in user space per la configurazione. Il driver espone una API (Team Netlink API) che viene utilizzata dalle applicazioni user-space per la configurazione dello stesso. Viene inoltre fornito un demone, teamd che controlla le istanze del Team driver che girano in kernel-space.
Comprendere a fondo la gestione del network teaming va ben al di là dell’apprendimento dei comandi di Network Manager. Per proseguire con questa guida è fondamentale conoscere, oltre al demone teamd, alcuni strumenti come teamdctl e teamnnl, che fanno parte delle succitate applicazioni user-space che colloquiano con il driver in kernel-space. Inoltre è necessario introdurre il concetto di runner, porzioni di codice in formato JSON lette dal demone teamd che implementano le varie logiche di aggregazione e/o backup che andremo a vedere: round-robin, active backup, broadcast, load balance, lacp.
Andiamo a testare una sempliece configurazione: in questo esempio utilizzeremo per il runner il metodo activebackup. In questo caso agganceremo due device eth0 e eth1 al nostro nuovo network team che chiameremo team0. Poiché il runner method è, appunto, activebackup, uno solo dei nostri due device sarà quello effettivamente attivo mentre l’altro resterà in attesa di prenderne il posto nel caso in cui il primo cada o venga disattivato.
Tramite nmcli andreamo a creare per prima cosa il device team0:
nmcli con add type team con-name team0 ifname team0 config '{"runner": {"name": "activebackup"}}' |
Abbiamo specificato il tipo di connessione come team, il nome della connessione e l’interfaccia come team0 e, tramite l’opzione config abbiamo specificato il runner in formato JSON. Questo è un esempio molto semplice di runner: se ne possono trovare di più complessi nella directory /usr/share/doc/teamd-1.15/example_configs.
Una volta creato il network device possiamo assegnargli subito un indirizzo ip statico:
nmcli con mod team0 ipv4.addresses 192.168.127.180/24 nmcli con mod team0 ipv4.method manual |
Passiamo ora alla creazione dei team slave device che saranno associati a eth0 e eth1:
nmcli con add type team-slave con-name team0-port1 ifname eth0 master team0 nmcli con add type team-slave con-name team0-port2 ifname eth1 master team0 |
Ora i due device eth0 e eth1 sono connessi al network team. Possiamo constatare con il seguente comando ps o con top che il demone teamd è ora attivo e che ha caricato il runner che abbiamo passato tramite nnmcli.
Il comando teamdctl ci permette di compiere varie operazioni di monitoraggio e configurazione sul nostro device. Ad esempio possiamo monitorare lo stato e verificare quale delle due interfacce è al momento attiva:
teamdctl team0 state |
Si può vedere che al momento la porta attiva è agganciata al device eth1. Proviamo ora a disattivarla e verifichiamo se la connessione rimane attiva:
nmcli dev dis eth1 teamdctl team0 state |
Come possiamo vedere dall’output la connessione è stata spostata sulla porta attiva eth2 mentre non c’è più traccia della porta eth1 che abbiamo disabilitato. Riattiviamo nuovamente e verifichiamo lo stato della connessione:
nmcli dev con eth1 teamdctl team0 state |
Di nuovo vediamo attivi tutte e due le porte mentre la porta attiva è ora rimasta eth2, questo almeno fino al prossimo evento di disservizio di eth2 che farà tornare attiva eth1.
Per visualizzare un dump completo della configurazione del team:
teamdctl team0 config dump |
Nella sezione “ports” sono definite le porte e per ognuna di essere è impostato un “link_watch” ovvero il methodo utilizzato da teamd per verificare lo stato delle porte. In questo caso il link_watch predefinito è “eththool”.
Nella directory /etc/sysconfig/network-scripts troveremo tre nuovi file generati da Network Manager. Il file ifcfg-team0, e i file ifcfg-team0-port1 e ifcfg-team0-port2, associati rispettivamente alle interfacce eth0 ed eth1.
Il file ifcfg-team0 si presenterà così:
DEVICE=team0 TEAM_CONFIG="{\"runner\": {\"name\": \"activebackup\"}}" DEVICETYPE=Team BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no NAME=team0 UUID=a75ed4c4-20a2-4fc0-a112-d084262d5882 ONBOOT=yes IPADDR=192.168.127.180 PREFIX=24 IPV6_PEERDNS=yes IPV6_PEERROUTES=yes |
Si può notare la voce relativa al runner configurato. Si può modificare il runner anche agendo direttamente sul file ifcfg-team0.
Possiamo ad esempio modificare il runner da activebackup a loadbalance. Impostare il runner a loadbalance fa si che il carico del traffico venga suddiviso su ambedue le intefacce.
Dopo aver modificato e salvato il file è necessario eseguire aggiornare la configurazione di NetWorkManager e dell’interfaccia con i comandi:
nmcli con reload nmcli con down team0 && nmcli con up team0 |
Network Manager (e la sua CLI) se usati correttamente possono essere degli strumenti utili e rendere più facile il lavoro di un sysadmin su una macchina RHEL o CentOS. Ci auguriamo che questi articoli siano lo spunto per approfondire maggiormente l’argomento!