Od ręcznej konfiguracji do Network as Code – zmiana paradygmatu
Tradycyjne zarządzanie siecią: SSH, CLI i kopiuj-wklej
Klasyczny sposób pracy inżyniera sieci wygląda podobnie w większości organizacji: logowanie po SSH na router czy przełącznik, kilka komend w CLI, szybki zapis konfiguracji i przejście do następnego urządzenia. Nierzadko zmiany są przygotowywane w notatniku lub Excelu, a potem ręcznie przenoszone do urządzeń. Jeśli sieć liczy kilkanaście urządzeń, daje się to jeszcze jakoś utrzymać. Przy kilkudziesięciu lub kilkuset – chaos jest tylko kwestią czasu.
Manualna konfiguracja opiera się zwykle na intuicji i pamięci administratora. Ktoś pamięta, że „na oddziale X VLAN 30 to goście”, ktoś inny wie, że „na tym routerze jest nietypowy NAT, lepiej go nie ruszać”. Dokumentacja, jeśli istnieje, bywa przeterminowana. Takie środowisko jest bardzo wrażliwe na rotację pracowników: odejście jednej kluczowej osoby potrafi sparaliżować możliwość wprowadzania zmian.
Ręczne podejście ma jeszcze jedną cechę: jest trudne do odtworzenia. Jeśli trzeba zbudować podobną konfigurację dla innej lokalizacji, najczęściej kopiuje się fragmenty z istniejącego urządzenia i modyfikuje „na oko”. W efekcie powstają drobne różnice, które później trudno wytropić, gdy coś nie działa tak samo w dwóch oddziałach.
Główne problemy: brak historii, niespójność i konfiguracje śmieciowe
Manualne zarządzanie konfiguracją sieci generuje konkretne, powtarzalne problemy:
- Brak rzetelnej historii zmian – nawet jeśli logi syslog częściowo pokazują, kto wykonał jaką komendę, nie ma prostego porównania „przed i po” ani szybkiego sposobu przywrócenia poprzedniej wersji konfiguracji.
- Niespójność konfiguracji – podobne urządzenia w różnych lokalizacjach mają delikatnie inne polityki ACL, odrobinę inne QoS lub inny sposób numeracji interfejsów. W małej skali to nie przeszkadza, w większej – powoduje trudne do diagnozowania anomalie.
- „Konfiguracje śmieciowe” – po kolejnych zmianach w konfiguracji pozostają nieużywane ACL-e, route-mapy, access-listy, nieużywane VLAN-y. Trudno ocenić, co można bezpiecznie usunąć. W efekcie konfiguracje puchną i stają się coraz mniej czytelne.
- Brak spójnych standardów – nazewnictwo interfejsów, opis portów, struktura ACL czy sposób definiowania VRF-ów zmienia się w zależności od osoby wprowadzającej zmiany i momentu w historii sieci.
W konsekwencji wdrażanie nowych funkcji lub urządzeń staje się coraz bardziej ryzykowne. Im więcej długów technicznych w konfiguracji, tym większa szansa, że niewielka modyfikacja doprowadzi do poważnej awarii.
Network as Code w praktyce: traktowanie konfiguracji jak kodu
Network as Code oznacza przesunięcie zarządzania siecią do świata znanego z programowania i DevOps. Konfiguracje urządzeń nie są już „tym, co siedzi na routerze”, ale stają się kodem przechowywanym w repozytorium (np. Git), z pełną historią zmian, wersjonowaniem i procesem przeglądu.
Fundamentem jest założenie, że repozytorium jest źródłem prawdy. To, co jest w Git, definiuje docelowy stan sieci. Urządzenia powinny być konfigurowane w sposób automatyczny, tak aby odzwierciedlały ten stan. Zmiana w sieci to zmiana w repozytorium, a nie bezpośrednia komenda na routerze. Nawet jeśli w pewnych sytuacjach trzeba wykonać ręczną korektę, docelowo i tak powinna zostać odzwierciedlona w repozytorium.
Network as Code łączy kilka elementów: automatyzację (Ansible, Terraform, Nornir), zarządzanie wersjami (Git), proces CI/CD (testy i automatyczne wdrażanie) oraz dobre praktyki inżynierskie (przeglądy kodu, standardy, dokumentację blisko kodu). Największy zysk pojawia się wtedy, gdy te elementy działają razem, a zmiany w sieci mają swój pełny cykl życia w systemach do zarządzania kodem.
Skrypty do sieci a świadome Network as Code
Wiele zespołów sieciowych używa skryptów – prostych plików Python, procedur Expect czy „one-linerów” w Bashu – do masowej zmiany haseł, dodania VLAN-u na wielu przełącznikach czy aktualizacji opisu portów. To często pierwszy krok do automatyzacji, ale nie jest to jeszcze Network as Code w pełnym znaczeniu.
Różnica polega na tym, że:
- Skrypty zwykle opisują co zrobić (imperatywne polecenia), ale nie definiują pełnego, docelowego stanu sieci. Są jednorazowe, trudne do ponownego użycia i niekoniecznie spięte z procesem zarządzania zmianą.
- Network as Code dąży do deklaratywnego opisu stanu: np. „ten router ma mieć takie interfejsy i takie trasy statyczne, a te ACL-e mają mieć konkretną listę reguł”. Narzędzia odpowiadają za doprowadzenie urządzeń do tak opisanego stanu oraz za weryfikację, czy się to udało.
W praktyce oznacza to przejście z myślenia „napiszę skrypt, który doda te trzy komendy” do „zdefiniuję szablon konfiguracji routera WAN, a skrypt wygeneruje i zastosuje pełną konfigurację zgodnie z danymi inwentarzowymi”. To zmiana paradygmatu, która na początku wymaga od inżynierów sieci trochę innego podejścia do pracy, ale daje znacznie większą powtarzalność.
Mały przykład: repozytorium Git porządkuje konfiguracje małej sieci
Wyobraź sobie firmę z kilkunastoma oddziałami: w każdym router VPN, kilka przełączników dostępowych, jeden kontroler Wi-Fi. Dotychczas każdą zmianę wprowadza się ręcznie. Po kilku latach konfiguracje tych samych typów urządzeń różnią się detalami, a nikt nie jest w stanie szybko powiedzieć, która lokalizacja ma jakie ACL-e.
Pierwszy krok w stronę Network as Code może być zaskakująco prosty:
- zrzucenie aktualnych konfiguracji wszystkich urządzeń do plików tekstowych,
- umieszczenie ich w repozytorium Git z czytelną strukturą katalogów,
- od tej pory – każda zmiana najpierw w pliku, commit, opis, a dopiero potem wdrożenie na urządzenia (nawet jeszcze ręczne).
Nawet bez pełnej automatyzacji wdrażania, samo przechowywanie konfiguracji w Git daje natychmiastowe korzyści: historię zmian, łatwe porównanie wersji, możliwość przywrócenia poprzedniej konfiguracji, lepszą współpracę w zespole. To często moment, w którym widać, że podejście „jak do kodu” jest dla sieci po prostu bardziej efektywne.
Fundamenty – Git, IaC i GitOps w kontekście sieci
Git w praktyce inżyniera sieci
Git to rozproszony system kontroli wersji, dominujący standard w świecie programistów. W kontekście Network as Code zastępuje „folder z backupami konfigów” i pojedyncze pliki Word/Excel. Kluczowe pojęcia:
- Commit – migawka zmian. Każdy commit zawiera informację, jakie linie konfiguracji doszły, zostały usunięte lub zmodyfikowane. Zawiera też opis tekstowy („message”), w którym można wyjaśnić cel zmiany.
- Branch – gałąź rozwoju. Zmiany w sieci można przygotowywać w oddzielnych branchach (np.
feature/new-site-krakow) i dopiero po przetestowaniu łączyć z główną gałęzią (np.main). - Tag – etykieta przypisana do konkretnego commita. Można oznaczać nimi „wydania” konfiguracji, np.
2024-05-rollout-vlan-standardization.
Dla inżyniera sieci Git staje się narzędziem do:
- porównywania konfiguracji pomiędzy lokalizacjami i w czasie,
- śledzenia, kto i dlaczego zmodyfikował dany fragment,
- wprowadzania zmian w bezpieczniejszy, kontrolowany sposób (branch + pull request),
- automatycznego wyzwalania pipeline’ów CI/CD po każdej zmianie w plikach.
Przy niewielkiej praktyce Git przestaje być „narzędziem dla programistów”, a zaczyna po prostu wspierać codzienną pracę z konfiguracją.
Infrastructure as Code w sieciach: deklaratywnie vs imperatywnie
Infrastructure as Code (IaC) zakłada opisywanie infrastruktury (serwery, sieci, usługi) w formie plików tekstowych, które można versionować, testować i automatycznie wdrażać. W przypadku sieci kluczowa jest różnica między dwoma podejściami:
- Imperatywne – „jak wykonać zmianę”: sekwencja komend typu
interface Gi0/1,switchport access vlan 20. Typowe dla ręcznego CLI i prostych skryptów. - Deklaratywne – „jaki ma być efekt”: opis, że hosty w danym oddziale mają mieć VLAN 20 jako sieć użytkowników, VLAN 30 jako sieć gościnna, a ruch z VLAN 30 ma być filtrowany według zdefiniowanej polityki. Narzędzie samo generuje odpowiednie komendy.
W praktyce dużo rozwiązań Network as Code łączy oba style. Często szablony konfiguracji są w dużej mierze deklaratywne, ale pewne sekwencje zmian nadal wymagają imperatywnej logiki (np. migracja BGP bez przerwy w ruchu). Kluczowe jest jednak, aby źródłem prawdy był opis stanu, a nie pojedyncze skrypty.
Popularne narzędzia IaC dla sieci (Ansible, Terraform, Nornir) przechowują definicje sieci w postaci plików YAML, HCL lub Python. Samo zapisanie konfiguracji w takich formatach nie wystarcza – sedno IaC to powtarzalność i przewidywalność. Jeśli ten sam opis zostanie zastosowany jutro lub za miesiąc, efekt ma być spójny.
GitOps dla sieci: repozytorium jako źródło prawdy
GitOps rozwija idee IaC o konkretną praktykę operacyjną. Zakłada, że Git jest jedynym źródłem prawdy na temat tego, jak ma wyglądać infrastruktura, a zmiany stanu są wykonywane wyłącznie poprzez zmiany w repozytorium. Dla sieci oznacza to kilka ważnych zasad:
- Nie ma „tajnych” zmian na urządzeniu, które nie zostały odzwierciedlone w repozytorium. Jeśli ktoś z konieczności naprawił coś ręcznie, musi później wprowadzić tę zmianę do Git.
- Wdrożenia są ciągłe: każda zmiana w repo wyruchamia pipeline, który testuje i w razie akceptacji wdraża konfigurację.
- Repozytorium odzwierciedla aktualny stan oczekiwany. Jeśli rzeczywisty stan urządzeń odbiega, pipeline powinien to wykryć i zgłosić.
GitOps sprawdza się szczególnie dobrze w środowiskach, gdzie topologia i konfiguracja są zbliżone między lokalizacjami – np. sieci sklepów, punktów sprzedaży czy oddziałów banku. Standaryzacja pozwala budować szablony konfiguracji i minimalizuje liczbę wyjątków.
Konwencje repozytorium: struktura, nazewnictwo, segregacja
Źle zaprojektowane repozytorium szybko staje się śmietnikiem plików, w którym trudno cokolwiek znaleźć. Porządek w strukturze katalogów to fundament. Najczęściej spotykane podejścia:
- Per lokalizacja – korzeń repozytorium zawiera katalogi oddziałów (np.
sites/warszawa,sites/krakow), a w nich pliki specyficzne dla danej lokalizacji. - Per rola urządzenia – katalogi typu
core,distribution,access,wan. - Per technologia – np.
bgp,ospf,acl,qos, jeśli konfiguracja jest mocno modularna. - Per klient/segment – w środowiskach MSP lub z wyraźnym podziałem biznesowym (np.
customers/bankX).
Dobrym kompromisem dla średniej organizacji jest kombinacja lokalizacja + rola, np. sites/warszawa/access, sites/warszawa/wan, sites/krakow/access. Dzięki temu łatwo znaleźć konkretny router czy przełącznik, ale można też objąć jednym wzrokiem wszystkie urządzenia warstwy dostępowej.
Poza strukturą katalogów warto ustalić standardy nazewnictwa plików (np. hostname-config.yaml, hostname-interfaces.yaml) oraz rozróżnić:
- pliki szablonów (np. w Jinja2),
- pliki zmiennych/inwentarza (YAML, CSV),
- pliki wygenerowane (gotowa konfiguracja, której zwykle nie commitujemy, chyba że pełni rolę archiwum).
Definiowanie stanu docelowego: szablony, inwentarz i zmienne
Żeby Network as Code działało na większą skalę, trzeba oddzielić logikę konfiguracji od danych specyficznych dla urządzeń i lokalizacji. Najczęściej odbywa się to przez:
Rozdział logiki i danych: praktyczny model
Rozsądny model dzieli repozytorium na trzy główne warstwy:
- Logika / szablony – opisują, jak ma wyglądać konfiguracja danego typu urządzenia (np. router WAN, przełącznik dostępowy), ale nie zawierają konkretnych IP czy nazw VLAN.
- Inwentarz – opisuje, jakie urządzenia są w sieci, gdzie stoją, jakimi mają nazwami i adresami zarządczymi (np.
inventory/hosts.yaml). - Dane biznesowe / zmienne – opisują wymagania funkcjonalne: jakie VLAN-y w danej lokalizacji, jaka przepustowość łącza, jakie prefiksy BGP, które porty są wykorzystywane.
Szablon przełącznika dostępowego może być jeden dla całej organizacji. Zmienia się jedynie zestaw zmiennych, które wchodzą do templatu, np.:
sites:
warszawa:
access:
sw1:
uplink_port: Gi1/0/48
user_vlans:
- id: 20
name: USERS
- id: 30
name: GUEST
management_ip: 10.10.0.11/24
krakow:
access:
sw1:
uplink_port: Gi1/0/48
user_vlans:
- id: 120
name: USERS_KRK
- id: 130
name: GUEST_KRK
management_ip: 10.20.0.11/24Szablon Jinja2 może potem wyglądać następująco:
{% for vlan in user_vlans %}
vlan {{ vlan.id }}
name {{ vlan.name }}
{% endfor %}
interface {{ uplink_port }}
description Uplink to distribution
switchport trunk allowed vlan {{ user_vlans | map(attribute="id") | join(",") }}Ten sam kod szablonu generuje różne konfiguracje w zależności od danych. Dzięki temu zmiana standardu (np. dodanie VLAN-u 40 dla IoT) wymaga modyfikacji zmiennych i ewentualnie jednego szablonu, a nie ręcznego dotykania setek plików konfiguracyjnych.
Wybór narzędzi – od prostych skryptów po platformy Network as Code
Kryteria wyboru narzędzia do automatyzacji sieci
Dobór narzędzia zależy od kilku twardych czynników. Najważniejsze z nich:
- Różnorodność producentów – jeśli sieć to głównie jeden vendor, wygodne bywają narzędzia lub platformy specyficzne (np. Cisco NSO, Juniper Apstra). Przy wielu dostawcach lepiej sprawdzają się narzędzia ogólne.
- Kompetencje zespołu – jeśli ludzie znają Ansible, szkoda to marnować; jeśli jest silny zespół Python, można śmiało sięgać po Nornir lub własne frameworki.
- Interfejsy urządzeń – telnet/SSH + CLI wymusza inne podejście niż bogate API w stylu NETCONF/RESTCONF czy gNMI. Warto najpierw inwentaryzować, jakie interfejsy udostępniają urządzenia.
- Skala i częstotliwość zmian – jeśli konfiguracje zmieniają się rzadko, proste playbooki Ansible wystarczą. Jeśli codziennie wchodzą setki zmian, warto myśleć o platformie, kolejce zadań i rozbudowanym monitoring-u.
Ansible – punkt startowy dla wielu zespołów
Ansible jest często pierwszym krokiem w stronę Network as Code, bo dobrze łączy prostotę z możliwościami. Przygotowuje się playbooki, które opisują, co ma zostać zrobione, oraz pliki inwentarza i zmiennych.
Typowy scenariusz dla sieci:
- inwentarz hostów w YAML (
inventory/hosts.yaml), - role Ansible dla poszczególnych typów urządzeń (
roles/router_wan,roles/access_switch), - moduły typu
ios_config,nxos_config,junos_configdo wgrywania zmian.
Przykładowy fragment playbooka aktualizującego bannery i dane kontaktowe na routerach WAN Cisco:
- name: Update WAN routers banners
hosts: wan_routers
gather_facts: no
vars_files:
- vars/global.yaml
tasks:
- name: Render banner template
template:
src: templates/banner.j2
dest: /tmp/{{ inventory_hostname }}-banner.cfg
- name: Apply banner configuration
ios_config:
src: /tmp/{{ inventory_hostname }}-banner.cfg
match: line
replace: linePlaybook można uruchamiać ręcznie lub z poziomu pipeline’u CI/CD; w obu przypadkach bazuje na tych samych plikach w Git i generuje przewidywalny efekt.
Terraform i providerzy sieciowi
Terraform jest kojarzony głównie z chmurą, ale coraz częściej ma zastosowanie w sieciach, zwłaszcza w integracji z SD-WAN, firewallami NGFW czy sieciami w chmurze (VPC, Transit Gateway, ExpressRoute/Direct Connect).
Na poziomie praktyki:
- definiuje się zasoby typu „VPN site”, „BGP peer”, „firewall policy” w HCL,
- używa się providerów producentów (np. Cisco, Palo Alto, F5) lub community,
- Terraform zarządza zależnościami i stanem wdrożenia.
Przykładowy fragment definiujący prosty tunel VPN site-to-site w usłudze firewallowej może wyglądać tak:
resource "vendor_vpn_tunnel" "site_warszawa" {
name = "site-warszawa"
local_cidr = "10.10.0.0/16"
remote_cidr = "10.100.0.0/16"
preshared_key = var.vpn_psk
ike_profile = "standard_ike"
ipsec_profile = "standard_ipsec"
}Plusem jest silne wsparcie dla planowania zmian: terraform plan pokazuje, co się stanie, zanim zostanie wykonane terraform apply. W sieci daje to dodatkową warstwę kontroli – pipeline może blokować wdrożenie, jeśli plan jest szerszy niż oczekiwano.
Nornir, Netmiko i własne frameworki w Pythonie
Dla zespołów komfortowo czujących się w Pythonie naturalnym kierunkiem jest Nornir oraz biblioteki typu Netmiko, Paramiko czy NAPALM. To elastyczne podejście, które pozwala budować dokładnie taką logikę, jakiej brakuje w gotowych narzędziach.
Nornir oddziela inwentarz, zadania i pluginy wykonywane dla urządzeń. Przykładowe zadanie:
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_config
from nornir_jinja2.plugins.tasks import template_file
nr = InitNornir(config_file="config.yaml")
def deploy_access_switch(task):
r = task.run(
task=template_file,
template="access_switch.j2",
path="templates",
)
cfg = r.result.splitlines()
task.run(
task=netmiko_send_config,
config_commands=cfg
)
nr.run(task=deploy_access_switch, groups=["access_switches"])Takie podejście daje możliwość wplecenia bardzo specyficznych warunków (np. „jeśli na porcie jest aktywny STP loop guard, zmień kolejność komend”), ale wymaga większej dyscypliny wpisania tego w zasady IaC i GitOps, aby nie skończyć z zawiłym, nieudokumentowanym kodem.
Dedykowane platformy Network as Code
Dla większych środowisk i organizacji, które wolą gotowy produkt niż budowanie wszystkiego samodzielnie, pojawiły się platformy skupione na automatyzacji sieci: Cisco NSO, Itential, Glueware, Apstra i inne. Łączy je kilka cech:
- modelowanie usług sieciowych (np. „site”, „MPLS VPN”, „L2VPN”) zamiast pojedynczych komend,
- wsparcie dla wielu vendorów poprzez adaptery,
- graficzne interfejsy i API do automatyzacji,
- często wbudowane mechanizmy walidacji i dry-run.
Takie platformy dobrze sprawdzają się, gdy sieć jest duża, a procesy formalne (change management, audyt) są rozbudowane. Wymagają jednak świadomej integracji z Git: szablony, definicje usług i polityk powinny nadal być przechowywane w repozytorium, a platforma powinna konsumować konfigurację z Git lub eksportować ją do niego.

Projekt repozytorium konfiguracji sieci – wzorce i praktyka
Podział repozytoriów: monorepo czy wiele repo?
Jedno z pierwszych pytań brzmi: trzymać wszystko w jednym repozytorium (monorepo), czy rozdzielić konfigurację na kilka mniejszych?
Monorepo ma sens, gdy:
- zespół jest niewielki i pracuje nad całą siecią,
- narzędzia i pipeline’y są wspólne dla wszystkich segmentów,
- sieć jest spójnie zarządzana (jedne standardy, jeden zespół change management).
Wiele repozytoriów sprawdza się, gdy:
- są niezależne domeny odpowiedzialności (np. „DC”, „WAN”, „retail branches”),
- część konfiguracji jest poufna (np. konfiguracje klientów w MSP),
- różne zespoły używają innych narzędzi czy pipeline’ów.
Rozdział można poprowadzić po domenach technicznych (DC vs WAN), po obszarach biznesowych (klienci, segmenty) albo po krytyczności (sieć produkcyjna vs lab). Niezależnie od wyboru warto wymusić spójne konwencje nazewnictwa i struktury, tak aby inżynier mógł łatwo przenosić się między repozytoriami.
Warstwy konfiguracji: globalna, per region, per site
Konfiguracja sieci zwykle wynika z kilku poziomów polityk. Dobry projekt repozytorium powinien to odzwierciedlać. Można wyróżnić co najmniej trzy warstwy:
- Globalna – zasady obowiązujące wszędzie: standardy haseł, bannery, globalne parametry SNMP, NTP, AAA.
- Regionalna – parametry zależne od regionu / kraju: serwery syslog, DNS, lokalne prefiksy, wymagania prawne.
- Site-specific – szczegóły konkretnej lokalizacji: adresacja, nazwy VLAN, numery portów dla uplinków.
Przekłada się to na strukturę, np.:
config/
global/
ntp.yaml
aaa.yaml
snmp.yaml
regions/
eu/
dns.yaml
syslog.yaml
us/
dns.yaml
syslog.yaml
sites/
warszawa/
vlans.yaml
wan.yaml
krakow/
vlans.yaml
wan.yamlSzablony mogą łączyć dane z kilku warstw: np. konfiguracja routera w Warszawie powstaje z global/* + regions/eu/* + sites/warszawa/*. Taki układ ułatwia wprowadzanie globalnych zmian bez grzebania w plikach każdej lokalizacji.
Oddzielenie danych wrażliwych
Hasła, klucze prywatne, pre-shared keys do VPN czy dane dostępowe do API nie powinny lądować w repozytorium w formie jawnej. Do ich przechowywania używa się:
- Ansible Vault,
- mechanizmów CI/CD (sekrety w GitLab CI, GitHub Actions, Jenkins credentials),
- zewnętrznych sejfów (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault).
Praktyczny model to przechowywanie w repozytorium referencji do sekretów (np. identyfikatorów w sejfie), a nie samych wartości. Pipeline pobiera wartości w czasie wykonywania, wstrzykuje do procesu templating-u, ale nie zapisuje ich w plikach outputu commitowanych do Git.
Repozytorium „tylko do odczytu” vs repo „operacyjne”
W wielu firmach istnieje już repozytorium z backupami konfiguracji. Można je:
- pozostawić jako archiwum „read-only” – dla historii i szybkich porównań,
- założyć osobne repo „operacyjne” – w którym znajdują się definicje stanu docelowego, szablony i dane inwentarza.
Różnica jest istotna: repo archiwalne odzwierciedla to, co jest, a repo operacyjne – to, co ma być. Pipeline może okresowo porównywać oba światy i raportować rozjazdy (dryft konfiguracji), co pomaga wychwycić „ciche” ręczne zmiany na urządzeniach.
Budowa pipeline’u CI/CD dla konfiguracji sieci
Ogólny przepływ: od commita do wdrożenia
Pipeline CI/CD dla sieci można podzielić na kilka kroków logicznych:
- Walidacja syntaktyczna – sprawdzenie, czy pliki YAML/HCL/JSON są poprawne, czy nie ma literówek w kluczach, czy struktura jest spójna.
- Linting i reguły stylu – wymuszenie konwencji: nazwy VLAN, standardowe opisy interfejsów, brak zabronionych komend.
- Generowanie konfiguracji – wyrenderowanie szablonów do postaci gotowych configów dla poszczególnych urządzeń.
- Testy logiki – analiza gotowych konfiguracji, np. wyszukiwanie niepożądanych patternów, sprawdzanie spójności routingu.
- Dry-run / pre-check – opcjonalne porównanie z aktualnym stanem urządzeń (co się zmieni), ewentualnie symulacja w labie.
- Wdrożenie – wykonanie zmian na urządzeniach, najczęściej etapami.
- CI – weryfikacja zmiany: linting, generowanie konfiguracji, testy logiki, ewentualnie uruchomienie symulacji (np. w EVE-NG, labie wirtualnym, digital twin).
- CD do środowiska testowego: automatyczne wdrożenie na labie lub niewielkiej, kontrolowanej grupie urządzeń (canary).
- CD do produkcji: wdrożenie na produkcji, zwykle z dodatkowymi blokadami (manualne zatwierdzenie, okna serwisowe, powiadomienia).
- Batch – wdrożenie na grupy urządzeń (np. po 5–10), z kontrolą po każdej paczce.
- Canary – najpierw pojedyncze urządzenie lub mała lokalizacja „pilotażowa”, dopiero potem reszta.
- Blue/Green – alternatywna ścieżka ruchu (np. drugi zestaw routerów, drugi VRF) przygotowana z wyprzedzeniem, przełączenie ruchu po weryfikacji.
- zgłoszenie zmiany (ticket) zawiera referencję do brancha / MR-a w Git,
- pipeline weryfikuje, czy numer zgłoszenia jest obecny w opisie commita lub MR-a,
- wdrożenie produkcyjne (stage
deploy_prod) jest dostępne tylko, jeśli okno serwisowe jest otwarte (np. flaga w systemie change, zmienna środowiskowa, parametr w pipeline trigger). - pipeline przed wdrożeniem pobiera i archiwizuje aktualną konfigurację urządzeń,
- w repozytorium jest utrzymywany katalog z „golden config” lub referencją do commitów oznaczonych jako stabilne,
- istnieje playbook / job „rollback” przyjmujący jako parametr identyfikator wersji do przywrócenia.
- yamllint – składnia i spójność stylu plików YAML,
- ansible-lint – dobre praktyki w playbookach i rolach,
- tflint i checkov – analiza modułów Terraform,
- własne skrypty Python/Go sprawdzające nazewnictwo, zakresy adresacji, spójność tagów.
- czy każda sieć VLAN ma przypisany opis,
- czy żaden interfejs uplink nie jest przypadkowo w trybie access,
- czy nie ma nakładających się prefiksów IP,
- czy trasy statyczne nie wskazują na „czarne dziury”.
Rozbicie pipeline’u na etapy i środowiska
Nawet jeśli w sieci nie ma klasycznego podziału na „dev / test / prod”, pipeline powinien mieć wyraźne etapy oraz możliwość kierowania zmian do różnych środowisk. Typowy schemat:
Przepływ w narzędziach typu GitLab CI / GitHub Actions / Jenkins można udokumentować jako serię jobów i stage’y. Przykładowo w GitLab CI:
stages:
- validate
- generate
- test
- deploy_lab
- deploy_prod
validate:lint:
stage: validate
script:
- yamllint config/
- ansible-lint playbooks/
only:
- merge_requests
generate:configs:
stage: generate
script:
- ansible-playbook generate_configs.yaml
artifacts:
paths:
- out/configs/
only:
- merge_requests
deploy:lab:
stage: deploy_lab
script:
- ansible-playbook deploy.yaml -i inventory/lab.yaml
when: manual
only:
- main
deploy:prod:
stage: deploy_prod
script:
- ansible-playbook deploy.yaml -i inventory/prod.yaml --limit "@batch1"
when: manual
only:
- tagsTaki podział wymusza porządek: każda zmiana musi przejść walidację, wygenerować gotowe konfiguracje (do wglądu reviewerów), przejść testy, a dopiero potem może być wdrożona – najpierw w labie, a potem na produkcji.
Strategie wdrożeń: batch, canary, blue/green
Zmiany sieciowe rzadko są kompletnie bezpieczne. Pipeline powinien więc wspierać kilka modeli wdrożeń:
Model wdrożenia można zakodować w zmiennych pipeline’u albo w metadanych repozytorium. Przykład prostego podziału na paczki w Ansible (tagi hostów używane jako „batch”):
- name: Deploy config in batches
hosts: all
serial: 5
tasks:
- name: Push configuration
ios_config:
src: "out/configs/{{ inventory_hostname }}.cfg"serial: 5 powoduje wdrażanie na pięciu hostach jednocześnie. Po każdej paczce można dodać task wykonujący testy kontrolne (np. sprawdzenie reachability między kluczowymi punktami). W przypadku narzędzi typu Nornir analogiczną logikę można zaimplementować poprzez filtrowanie inwentarza i sekwencyjne uruchamianie zadań na mniejszych podzbiorach.
Integracja z change management i kalendarzem zmian
W organizacjach objętych formalnym change management-em pipeline nie może żyć w próżni. Powinien być sklejony z procesem zgłoszeń i oknami serwisowymi. Typowy model:
Praktyczny mechanizm to proste wyrażenie regularne w regułach pipeline’u, które wymusza numer zgłoszenia, oraz integracja z API systemu ticketowego. Jeśli bilet jest w stanie „approved”, pipeline może odblokować zadanie wdrożeniowe.
Rollback i „bezpieczny punkt powrotu”
Automatyzacja bez dobrze przemyślanego rollbacku jest ryzykowna. W sieci rollback nie zawsze oznacza wycofanie pojedynczego commita – czasem wymaga przywrócenia poprzedniej, znanej-dobrej konfiguracji. Warto ustalić kilka zasad:
Przykładowy fragment playbooka Ansible realizującego szybki rollback do ostatniego backupu:
- name: Rollback to last known-good config
hosts: affected_devices
gather_facts: no
tasks:
- name: Load last backup
slurp:
src: "backups/{{ inventory_hostname }}/latest.cfg"
register: backup_cfg
- name: Apply backup configuration
ios_config:
lines: "{{ backup_cfg['content'] | b64decode | splitlines() }}"
replace: runningW środowiskach o wyższej złożoności rollback często oznacza nie tylko cofnięcie konfiguracji na urządzeniach, ale też korektę danych w inwentarzu (np. przywrócenie poprzedniego przypisania VLAN-ów czy polityk). Wtedy sensownie jest traktować rollback jako osobny scenariusz w Git – np. branch rollback/<ticket> przywracający spójny zestaw danych, a dopiero potem pipeline wdrażający go na urządzenia.
Testowanie konfiguracji sieci w procesie CI – od lintingu do walidacji stanu
Linting plików danych i szablonów
Pierwsza linia obrony przed błędami to linting. Dotyczy on zarówno plików danych (YAML, JSON, HCL), jak i szablonów (Jinja2, Nornir, moduły Terraform). Przykładowy zestaw narzędzi:
Lintery łatwo wpiąć w pipeline jako szybkie joby – wykonują się w kilka–kilkanaście sekund i natychmiast wychwytują literówki, zduplikowane wpisy, brakujące pola.
Testy generowanych konfiguracji (static analysis)
Sam fakt, że konfiguracja się generuje, nie gwarantuje, że jest poprawna merytorycznie. Kolejny krok to analiza wygenerowanych plików pod kątem reguł biznesowych i technicznych. Przykłady sprawdzeń:
Część reguł można zakodować jako prosty parser linii konfiguracyjnych, część – jako analizę modelu (przetwarzanie struktur danych przed templatingiem). Przykładowy test w Pytest, który weryfikuje, że każdy router w regionie ma zdefiniowane minimum dwa serwery NTP:
import yaml
from pathlib import Path
def load_site_config(site_path):
with open(site_path / "ntp.yaml") as f:
return yaml.safe_load(f)
def test_ntp_servers_minimum_two():
sites_dir = Path("config/sites")
for site in sites_dir.iterdir():
if not site.is_dir():
continue
cfg = load_site_config(site)
servers = cfg.get("ntp_servers", [])
assert len(servers) >= 2, f"Site {site.name} has less than 2 NTP servers"Takie testy można uruchamiać w CI zawsze, gdy zmieniają się pliki konfiguracyjne lub szablony. W razie naruszenia reguły pipeline się zatrzymuje, a autor zmian dostaje jasny komunikat.
Walidacja stanu w labie lub digital twin
Static analysis ma swoje granice – nie wykryje np. problemów z konwergencją routingu czy zjawisk typu asymetryczny routing. Dlatego w bardziej zaawansowanych wdrożeniach warto używać labu (fizycznego lub wirtualnego) albo rozwiązań digital twin do uruchomienia konfiguracji i przeprowadzenia testów.
Scenariusz może wyglądać tak:
- Pipeline buduje obraz labu (np. EVE-NG, CML, GNS3) z odpowiednimi wirtualnymi urządzeniami.
- Na urządzenia trafia wygenerowana konfiguracja.
- Uruchamiane są testy funkcjonalne – np. skrypty wykorzystujące
pytest+paramiko/napalm, które logują się do routerów i sprawdzają stan BGP, OSPF, ACL. - Wyniki wracają do CI jako raport.
Przykładowy prosty test stanu BGP z użyciem NAPALM:
from napalm import get_network_driver
def test_bgp_sessions_up(host, username, password):
driver = get_network_driver("ios")
with driver(hostname=host, username=username, password=password) as device:
bgp_neighbors = device.get_bgp_neighbors()
for peer, data in bgp_neighbors.get("global", {}).get("peers", {}).items():
assert data["is_up"], f"BGP session to {peer} on {host} is down"Takie testy nie muszą obejmować całej sieci – wystarczy reprezentatywna topologia. Kluczowe, aby testowane były krytyczne ścieżki ruchu (np. połączenia do systemów finansowych, interfejsy do partnerów).
Porównanie planu zmian z rzeczywistością (pre-check)
Ostatnia linia obrony przed wdrożeniem na produkcji to pre-check: porównanie aktualnego stanu z planem oraz oszacowanie, jakie komendy faktycznie zostaną wprowadzone. Mechanizmy zależą od narzędzia:
- w Ansible można użyć
check_modei modułów wspierających diff, - Terraform udostępnia
terraform plan, którego wynik można analizować automatycznie, - niektóre platformy NaC mają wbudowane „dry-run” pokazujące różnice linii konfiguracyjnych.
Pre-check można rozszerzyć o logikę biznesową. Jeśli np. plan przewiduje usunięcie więcej niż określonego procentu reguł ACL na firewallu lub modyfikację zbyt wielu interfejsów uplink, pipeline może wymusić dodatkową akceptację lub całkowicie zablokować wdrożenie.
Zmiana w sieci jako pull request – workflow pracy zespołu
Model pracy: Git jako źródło prawdy
Jeśli Git ma być źródłem prawdy dla konfiguracji sieci, cała praca nad zmianami musi przechodzić przez pull requesty (PR/MR). Bez tego szybko wrócą „szybkie poprawki” robione ręcznie na CLI, których nikt nie odzwierciedli w repozytorium.
Podstawowy model:
- Inicjator zmiany tworzy branch od
main(lub innej gałęzi bazowej) i modyfikuje dane / szablony. - Uruchamia się pipeline CI (na merge request), który waliduje zmianę i generuje konfiguracje.
- Reviewerzy przeglądają zarówno diff w plikach źródłowych, jak i wygenerowaną konfigurację (np. dołączoną jako artefakt lub commit w osobnym katalogu).
- Po akceptacji i scaleniu pipeline wdraża zmianę zgodnie z ustalonym procesem (lab → produkcja).
Szablony PR-ów i checklisty
Aby utrzymać jakość zmian, dobrze jest narzucić minimalny standard informacji w PR. Template PR może zawierać:
- krótki opis celu zmiany,
- zakres: jakie lokalizacje / urządzenia są dotknięte (link do inwentarza),
- ryzyka i plan rollbacku (jeśli odbiega od standardu),
- link do zgłoszenia change w systemie ITSM,
- screeny / logi z pipeline’u CI (np. link do raportu testów w labie).
Checklisty w PR (tickboxy) pomagają wymusić dyscyplinę: „[ ] Zmiana przetestowana w labie”, „[ ] Zweryfikowany wpływ na monitoring”, „[ ] Zweryfikowane zależności routingu”. W dużych zespołach realnie zmniejsza to liczbę „niespodzianek” na produkcji.
Code review konfiguracji – na co patrzeć
Review zmian w konfiguracji sieci różni się nieco od code review w typowym projekcie programistycznym. Dobrze, aby reviewer skupił się na kilku aspektach:
- Spójność z architekturą – czy nowa konfiguracja nie łamie ustalonych standardów (np. inny sposób numeracji VLAN, niestandardowe prefiksy).
- Bezpieczeństwo – nowe ACL, reguły NAT, dostęp zdalny. Czy nie ma zbyt szerokich wyjątków typu
permit any any, czy nie są otwierane niepotrzebne porty. - Skalowalność – czy rozwiązanie będzie działać tak samo dobrze przy 5, 50 i 500 lokalizacjach, czy nie wprowadza „specjalnej logiki” dla jednego przypadku.
- Czytelność danych – czy nowe pola inwentarza / konfiguracji są opisane, czy nazwy są intuicyjne, czy nie dublują istniejących parametrów.
Najczęściej zadawane pytania (FAQ)
Co to jest Network as Code i czym różni się od zwykłej automatyzacji skryptami?
Network as Code to podejście, w którym konfiguracja sieci jest traktowana jak kod: przechowywana w repozytorium (np. Git), wersjonowana, przeglądana w pull requestach i wdrażana przez zautomatyzowany proces (CI/CD). Repozytorium staje się „źródłem prawdy” o stanie sieci, a urządzenia są jedynie odzwierciedleniem tego stanu.
Zwykłe skrypty sieciowe są najczęściej imperatywne („wykonaj te trzy komendy na wszystkich przełącznikach”) i jednorazowe. Network as Code dąży do deklaratywnego opisu: „te urządzenia mają mieć taki zestaw interfejsów, VLAN-ów i ACL-i”, a narzędzia odpowiadają za doprowadzenie konfiguracji do opisanego stanu i jego weryfikację.
Jak zacząć z Network as Code w małej lub średniej sieci?
Najprostszy start to zrzucić bieżące konfiguracje wszystkich urządzeń do plików tekstowych i umieścić je w repozytorium Git z czytelną strukturą katalogów (np. /sites/krakow/router1.cfg). Od tego momentu każdą zmianę wprowadzać najpierw w pliku, robić commit z opisem, a dopiero potem wdrażać ją na urządzeniu, nawet jeśli na początku ręcznie.
Dopiero kolejnym krokiem jest dołożenie automatyzacji: prosty playbook Ansible lub skrypt Nornir, który pobiera konfigurację z repozytorium i wysyła ją na urządzenia. Taki etapowy start pozwala oswoić zespół z Git i procesem przeglądu zmian, zanim pojawi się pełne CI/CD.
Jakie problemy rozwiązuje podejście Network as Code w porównaniu z ręczną konfiguracją?
Ręczne zarządzanie przez SSH i CLI prowadzi do powtarzalnych kłopotów: brak rzetelnej historii zmian, niespójne konfiguracje między lokalizacjami, „śmieciowe” ACL-e i VLAN-y, a także silne uzależnienie od pamięci pojedynczych administratorów. Im większa sieć, tym bardziej każde ręczne kliknięcie zwiększa ryzyko awarii.
Network as Code porządkuje ten chaos. Masz pełny diff „przed/po”, szybki rollback do poprzedniej wersji, standaryzację szablonów konfiguracji i znacznie prostsze porównywanie urządzeń między oddziałami. Dodatkowo łatwiej przejąć sieć po kimś innym, bo wiedza jest w repozytorium, a nie „w głowie jednego admina”.
Jaką rolę pełni Git w Network as Code dla sieci?
Git staje się centralnym narzędziem do zarządzania konfiguracją: przechowuje konfiguracje jako pliki tekstowe, pozwala śledzić, kto i kiedy coś zmienił, oraz umożliwia porównanie dwóch wersji tej samej konfiguracji lub konfiguracji z różnych lokalizacji. Commit to migawka zmian z opisem celu, branch to bezpieczne środowisko do przygotowania zmian, a tag może oznaczać „wydanie” konfiguracji.
Dodatkowo Git jest naturalnym punktem integracji z CI/CD: każda zmiana w repozytorium może automatycznie wyzwalać testy (linting, walidacja szablonów, testy suchych wdrożeń) i dopiero po ich przejściu uruchamiać proces wdrożenia konfiguracji na urządzeniach.
Jakie narzędzia najczęściej wykorzystuje się do Network as Code w sieciach?
W praktyce stosuje się kombinację kilku klas narzędzi. Do samego przechowywania i wersjonowania konfiguracji używany jest Git (GitLab, GitHub, Bitbucket). Do automatyzacji wdrożeń typowo wchodzi w grę Ansible, Terraform dla części sieci w chmurze lub Nornir/Netmiko/NAPALM dla bardziej „surowych” integracji z urządzeniami.
Nad tym wszystkim pracuje system CI/CD (np. GitLab CI, GitHub Actions, Jenkins), który po commitach uruchamia testy i proces wdrażania. Kluczem nie jest wybór jednego „magicznego” narzędzia, ale spójne spięcie ich tak, by zmiana w repozytorium zawsze oznaczała kontrolowaną zmianę w sieci.
Czy Network as Code ma sens przy kilku–kilkunastu urządzeniach?
Tak, nawet w małej sieci widać realne korzyści. Przy kilku routerach i przełącznikach samo posiadanie historii zmian w Git, możliwości szybkiego diff-a i prostego rollbacku potrafi oszczędzić wiele godzin szukania, „co ktoś zmienił wczoraj wieczorem”. Dodatkowo łatwo skopiować konfigurację sprawdzonej lokalizacji do kolejnej, zachowując spójność.
Pełne CI/CD nie musi być wdrażane od razu. W małym środowisku rozsądnym kompromisem jest: Git + szablony + półautomatyczne skrypty wdrażające (np. uruchamiane ręcznie), a dopiero później dołożenie pipeline’ów i testów. Dzięki temu podejście skalowalnie rośnie razem z siecią.
Jak uniknąć bałaganu w repozytorium z konfiguracjami sieciowymi?
Po pierwsze, ustalić jednolitą strukturę katalogów (np. podział na lokalizacje, typy urządzeń lub warstwy sieci) i trzymać się jej konsekwentnie. Po drugie, wprowadzić podstawowe standardy: konwencje nazewnicze plików, sposób opisywania commitów oraz minimalne wymagania do akceptacji merge requestów (np. obowiązkowa recenzja drugiej osoby przy zmianach w rdzeniu).
Pomaga też rozdzielenie danych od logiki: szablony konfiguracji (np. Jinja2) trzymane osobno od inwentarza (YAML/JSON z listą lokalizacji, adresacją, VLAN-ami). Taki podział ułatwia utrzymanie porządku i pozwala generować spójne konfiguracje dla wielu lokalizacji bez ręcznego kopiowania fragmentów.
Kluczowe Wnioski
- Ręczna konfiguracja (SSH, CLI, kopiuj-wklej) skaluje się słabo: przy kilkudziesięciu–kilkuset urządzeniach prowadzi do chaosu, zależności od „jednej głowy” i trudności w odtworzeniu konfiguracji w innych lokalizacjach.
- Typowe skutki manualnego podejścia to brak przejrzystej historii zmian, niespójne konfiguracje między oddziałami, nagromadzone „konfiguracje śmieciowe” oraz rozjazd standardów nazewniczych i strukturalnych.
- Network as Code traktuje konfigurację jak kod: repozytorium (np. Git) staje się jedynym źródłem prawdy, a urządzenia są automatycznie doprowadzane do stanu opisanego w plikach, zamiast być modyfikowane bezpośrednio w CLI.
- Sama automatyzacja skryptami to za mało: pojedyncze skrypty zwykle opisują sekwencję komend (podejście imperatywne), podczas gdy Network as Code stawia na deklaratywny opis docelowego stanu sieci i jego spójną realizację.
- Połączenie narzędzi automatyzacji (Ansible, Terraform, Nornir) z Git, procesami CI/CD, przeglądami zmian i standardami inżynierskimi pozwala zarządzać konfiguracją sieci tak samo świadomie, jak kodem aplikacji.
- Praktyczny pierwszy krok może być bardzo prosty: zrzucić konfiguracje wszystkich urządzeń do plików, umieścić je w Git z sensowną strukturą katalogów i wprowadzać zmiany najpierw w repozytorium, a dopiero potem na urządzeniach.
Bibliografia i źródła
- Network Programmability and Automation: Skills for the Next-Generation Network Engineer. O'Reilly Media (2017) – Automatyzacja sieci, Git, szablony konfiguracji, praktyki DevOps
- Infrastructure as Code: Managing Servers in the Cloud. O'Reilly Media (2016) – Paradygmat IaC, deklaratywne opisy stanu, wersjonowanie konfiguracji
- Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation. Addison-Wesley Professional (2010) – Zasady CI/CD, pipeline’y, automatyzacja wdrożeń i testów
- Ansible for Network Automation. Red Hat – Oficjalna dokumentacja Ansible dla automatyzacji konfiguracji urządzeń sieciowych






