Dlaczego automatyzować sieć, nawet bez doświadczenia programistycznego
Codzienna rutyna administratora sieci a automatyzacja
Administrator sieci spędza zbyt dużo czasu na powtarzalnych zadaniach: kopiowaniu tych samych poleceń na kolejne urządzenia, ręcznym wklejaniu konfiguracji z notatnika, sprawdzaniu statusu interfejsów czy aktualizacji haseł. Każde takie zadanie osobno nie wygląda groźnie, ale w skali tygodnia potrafi zjeść wiele godzin.
Ręczne podejście oznacza też wyższe ryzyko błędu. Literówka w ACL, pominięty interfejs w VLAN-ie czy zły numer AS w BGP mogą wywołać problemy trudne do wychwycenia, bo konfiguracja powstawała „z palca” i nie ma jednego, powtarzalnego źródła prawdy.
Automatyzacja Ansible i prostym Pythonem przenosi ciężar pracy z ręcznego wykonywania komend na opisywanie, co ma być zrobione. Zamiast logować się na każde urządzenie i wklejać komendy, przygotowujesz plik z konfiguracją lub skrypt, który robi to za Ciebie, w ten sam sposób, za każdym razem.
Co daje automatyzacja sieci przy pomocy Ansible i Pythona
Szybkość wprowadzania zmian. Zmiana, która kiedyś zajmowała pół dnia, sprowadza się do uruchomienia jednego playbooka lub skryptu. W większych sieciach oszczędność czasu rośnie niemal liniowo z liczbą urządzeń.
Spójność konfiguracji. Te same szablony i zadania stosowane na wszystkich przełącznikach lub routerach eliminują różnice, które powstają przy ręcznym konfigurowaniu. To z kolei zmniejsza liczbę „dziwnych” problemów wynikających z drobnych rozbieżności.
Lepszy audyt i kontrola. Gdy konfiguracja jest zapisana jako pliki (infrastruktura jako kod), łatwiej prześledzić, kto i kiedy wprowadził daną zmianę. Systemy kontroli wersji (np. Git) pozwalają wrócić do poprzedniego stanu i obejrzeć historię.
Mniejszy stres przy zmianach. Zautomatyzowany proces jest powtarzalny. Jeśli playbook zadziałał na labie, jest duża szansa, że identycznie zadziała w produkcji. Ansible ma tryb „check mode”, a prosty Python może najpierw tylko zbierać informacje, zanim zacznie cokolwiek zmieniać.
Mit „muszę być programistą”, a praktyka pracy z Ansible i Pythonem
Wielu administratorów sieci zakłada, że automatyzacja wymaga pełnych umiejętności programistycznych. W rzeczywistości Ansible opiera się głównie na plikach YAML, czyli uporządkowanych listach i słownikach. Przypomina rozbudowaną, ale logiczną konfigurację – nie pełnoprawny kod.
Python w automatyzacji sieci też nie wymaga zaawansowanej wiedzy. W praktyce potrzebne są proste konstrukcje: pętle, warunki, odczyt plików i wywołanie kilku funkcji z bibliotek takich jak Netmiko czy NAPALM. To jest spokojnie w zasięgu osoby, która potrafi zrozumieć konfigurację routera z kilkuset liniami.
Kluczem nie jest „nauczyć się programować wszystko”, ale zbudować kilka małych narzędzi rozwiązujących konkretne problemy: zapisanie konfiguracji z wielu urządzeń, porównanie wersji OS, wdrożenie jednolitego banera czy NTP na wszystkich przełącznikach.
Przykład z życia: zmiana hasła na 20 przełącznikach
Przy podejściu ręcznym schemat wygląda tak: logujesz się na każdy przełącznik po SSH, przechodzisz do trybu konfiguracji, zmieniasz hasło, zapisujesz konfigurację, wylogowujesz się. Przy 20 urządzeniach, z przerwami i drobnymi pomyłkami, to łatwo ponad godzina pracy.
Z Ansible przygotowujesz jeden playbook, w którym w jednym miejscu definiujesz nowe hasło (najlepiej zaszyfrowane Ansible Vaultem). Wskazujesz grupę hostów „access-switches” i uruchamiasz zadanie. Całość trwa kilka minut, z pełnym logiem wykonania i informacją, czy gdzieś wystąpił błąd.
Takie proste doświadczenie mocno zmienia sposób myślenia o swojej pracy. Zamiast „20 razy to samo” robisz „raz dobrze przygotować, a potem wielokrotnie uruchomić”.
Minimalne podstawy, których potrzebuje administrator sieci
Fundamenty: terminal, SSH, praca z plikami
Automatyzacja sieci opiera się na pracy w terminalu. W praktyce oznacza to swobodne korzystanie z:
- logowania po SSH do urządzeń i serwerów (np. ssh user@host),
- podstawowych komend systemu Linux (ls, cd, cat, less, mkdir, rm, cp, mv),
- prostego edytora tekstu (nano, vim, VS Code z WSL),
- kopiowania plików (scp, sftp lub git clone / git pull).
Bez tego trudno płynnie poruszać się w świecie Ansible i Pythona. Na szczęście wszystko to można opanować w krótkich, praktycznych ćwiczeniach: tworzenie katalogu projektu, edycja pliku YAML, uruchomienie komendy, sprawdzenie wyników w logu.
Podstawy YAML, repozytoriów i wersjonowania konfiguracji
Ansible używa języka YAML do opisywania zadań i zmiennych. YAML to przejrzysta składnia oparta na wcięciach. Najważniejsze zasady:
- spójne wcięcia (najczęściej 2 spacje),
- listy oznaczone myślnikiem (-),
- klucze i wartości w formacie
klucz: wartość.
Przykład prostego fragmentu YAML:
routers:
- name: r1
ip: 10.0.0.1
- name: r2
ip: 10.0.0.2
Drugim filarem jest repozytorium, czyli miejsce, w którym trzymasz pliki projektu (playbooki, skrypty, szablony). Najczęściej będzie to repozytorium Git na serwerze (GitLab, GitHub) lub w katalogu współdzielonym. Dzięki wersjonowaniu łatwiej porównać zmianę sprzed tygodnia i w razie potrzeby przywrócić poprzednią wersję.
Ważnym nawykiem jest traktowanie konfiguracji sieci jako kodu – zamiast modyfikować „na żywym organizmie”, najpierw edytujesz plik, zapisujesz go w repozytorium, uruchamiasz playbook lub skrypt z tego pliku, a dopiero potem konfiguracja trafia na urządzenia.
Jednorazowy skrypt kontra powtarzalny proces
Jednorazowy skrypt robi „jeden strzał”: napisany szybko, często bez dokumentacji i walidacji, ratuje sytuację, ale za pół roku nikt nie pamięta, jak działał. Taki kod zazwyczaj trudno uruchomić ponownie, na przykład z uwagi na ścieżki absolutne czy zaszyte w środku wartości.
Powtarzalny proces to mały, ale uporządkowany projekt. Ma strukturę katalogów, plik z instrukcją (choćby kilka zdań w README), parametry przeniesione do plików YAML lub JSON i jasno wydzieloną część zmienną (dane) od stałej (logika). Można go uruchomić ponownie po miesiącu bez zgadywania.
Warto od początku celować w tę drugą formę. Nawet najmniejszy playbook Ansible czy krótki skrypt Python powinny mieć:
- osobny plik z danymi (lista urządzeń, hasła zaszyfrowane, parametry),
- krótki opis w komentarzu, co robią,
- wariant „tylko odczyt” przed wprowadzaniem zmian.
Jak się uczyć: krótkie sesje zamiast rzadkich „projektów”
Nauka automatyzacji jest skuteczniejsza w małych porcjach. Zamiast jednej, wielkiej akcji raz na kilka miesięcy, lepiej codziennie lub co drugi dzień poświęcić 20–30 minut na:
- uruchomienie jednego playbooka na labie,
- modyfikację prostego skryptu Python,
- dodanie nowej zmiennej w YAML i użycie jej w zadaniu.
Po kilku tygodniach takie drobne kroki złożą się na zestaw umiejętności wystarczający do realnych zadań w sieci produkcyjnej.

Przygotowanie bezpiecznego środowiska do nauki (lab)
Dlaczego nie testować automatyzacji na produkcji
Automatyzacja zwiększa zasięg zmian. Jednym poleceniem możesz dotknąć kilkunastu czy kilkudziesięciu urządzeń. To zaleta, ale i zagrożenie. Błąd w szablonie czy playbooku może powielić złą konfigurację wszędzie naraz.
Dlatego pierwsze kroki z Ansible i Pythonem należy wykonywać w odseparowanym laboratorium. Nawet jeśli czujesz się pewnie z konfiguracją pojedynczego routera, automatyczne wprowadzanie zmian to inna skala odpowiedzialności.
Bezpieczny lab pozwala na popełnianie błędów bez konsekwencji dla użytkowników. Można tam eksperymentować z kolejnymi wersjami skryptów i uczyć się czytać wyniki, zanim cokolwiek trafi do środowiska produkcyjnego.
Opcje labu: fizyczne urządzenia, wirtualki i emulatory
Najprostsze warianty środowiska testowego to:
- Stare lub zapasowe urządzenia fizyczne – kilka przełączników i routerów odłączonych od produkcji, połączonych w mini-sieć.
- GNS3 lub EVE-NG – popularne platformy do wirtualizacji routerów i przełączników różnych producentów, z możliwością integracji z Ansible i Pythonem.
- Emulatory producentów – wirtualne obrazy (np. vIOS, CSR1000v, vSRX, vMX, NX-OSv), często dostępne do celów labowych.
- Wirtualne routery Linux z FRRouting/Quagga – jeśli celem jest nauka routingu i ogólnej automatyzacji.
Ważne, by lab umożliwiał połączenie po SSH z maszyny, na której będzie zainstalowany Ansible i Python. Wtedy cała mechanika automatyzacji będzie w praktyce identyczna jak w produkcji.
Przykładowy scenariusz labowy dla automatyzacji sieci
Na początek wystarczy prosty topologia:
- 2–3 routery połączone w małą sieć z OSPF lub statycznym routingiem,
- 2–4 przełączniki z kilkoma VLAN-ami,
- jeden „serwer” z Linuxem (fizyczny lub VM) jako stacja z Ansible i Pythonem.
Taki lab pozwala przetestować typowe zadania:
- ustawienie banera logowania i serwerów NTP na wszystkich urządzeniach,
- zmianę adresów IP na interfejsach,
- konfigurację VLAN-ów i interfejsów trunk/access,
- aktualizację hasła administracyjnego na grupie przełączników.
W kolejnych etapach można dorzucić ACL, BGP, QoS czy zdalny syslog, ale nie ma sensu zaczynać od zbyt skomplikowanych scenariuszy.
Oddzielenie labu od produkcji i przełączanie kontekstów
W projektach Ansible kluczową rolę odgrywa inventory, czyli lista hostów. Najbezpieczniej jest od razu założyć osobne inwentarze dla labu i produkcji, na przykład:
inventories/lab/hosts.ymlinventories/prod/hosts.yml
Przy uruchamianiu playbooka zawsze jawnie wskazujesz, z którego inwentarza chcesz korzystać, np. -i inventories/lab/hosts.yml. Dodatkowo można użyć osobnych plików ansible.cfg dla labu i produkcji lub parametrów środowiskowych, aby ograniczyć ryzyko pomyłki.
Dobrym nawykiem jest też wyraźne oznaczanie nazw hostów. Przykładowo, w labie: r1-lab, sw1-lab, a w produkcji: r1-prod, sw1-core. W połączeniu z osobnymi inwentarzami daje to dodatkowy „bezpiecznik” w głowie.
Pierwsze kroki z Ansible dla administratora sieci
Ansible w sieciach: agentless i moduły sieciowe
Ansible to narzędzie do automatyzacji, które nie wymaga instalowania agentów na urządzeniach. Łączy się z nimi przez SSH lub API, wysyła komendy i analizuje odpowiedzi. Dla administratora sieci to duża zaleta – większość routerów i przełączników już ma SSH/NETCONF/REST.
Świat sieciowy w Ansible opiera się na modułach specyficznych dla producentów (np. cisco.ios.ios_config, arista.eos.eos_config, junipernetworks.junos.junos_config) albo na modułach ogólnych (ansible.netcommon). Moduły znają sposób wejścia do trybu konfiguracji, zapisania zmian czy pobrania danych.
Zamiast pisać skrytpy do logowania się i wysyłania komend, opisujesz w playbooku, co chcesz mieć w konfiguracji lub jakie komendy „show” uruchomić. Resztą zajmuje się silnik Ansible i moduły dostosowane do danego systemu operacyjnego.
Instalacja Ansible na Linux/WSL
Najbezpieczniejszą drogą jest użycie systemu Linux (np. Ubuntu) jako stacji roboczej lub WSL (Windows Subsystem for Linux) pod Windows. Ogólny schemat instalacji na Ubuntu:
- Aktualizacja pakietów:
sudo apt update - Instalacja Pythona i pip (jeśli brak):
sudo apt install python3 python3-pip -y - Instalacja Ansible, najlepiej z pip:
pip3 install ansible
Po instalacji sprawdzasz wersję:
Sprawdzenie działania Ansible i pierwsze połączenie SSH
Po instalacji szybko weryfikujesz, czy Ansible działa:
ansible --versionJeśli komenda zwróci wersję i ścieżki do modułów, można iść dalej. Kolejny krok to prosty test połączenia SSH do jednego z urządzeń w labie.
Tworzysz plik inwentarza, np. inventories/lab/hosts.yml:
all:
hosts:
r1-lab:
ansible_host: 10.0.0.11
ansible_user: admin
ansible_network_os: cisco.ios.ios
Następnie uruchamiasz moduł ping dla hostów sieciowych (moduł nie wysyła ICMP, tylko robi prostą operację przez SSH):
ansible all -i inventories/lab/hosts.yml -m ansible.netcommon.network_cli -c network_cliJeśli konfiguracja SSH i hasła jest poprawna, powinieneś zobaczyć status „ok” dla urządzenia. W razie błędów najpierw popraw połączenie SSH „ręcznie”, dopiero potem wracaj do Ansible.
Podstawowa struktura katalogów dla małego projektu sieciowego
Nawet mały projekt dobrze jest poukładać. Minimalny szkielet:
network-automation/
inventories/
lab/
hosts.yml
playbooks/
get-facts.yml
group_vars/
host_vars/
ansible.cfg
Plik ansible.cfg w katalogu projektu pozwala ustawić domyślny inwentarz i zachowanie połączeń. Prosty przykład:
[defaults]
inventory = inventories/lab/hosts.yml
host_key_checking = False
retry_files_enabled = False
[connection]
pipelining = True
Dzięki temu nie musisz za każdym razem podawać -i inventories/lab/hosts.yml, a konfiguracja projektu nie wpływa na inne katalogi.
Pierwszy playbook: odczyt faktów z urządzenia
Dobrym startem jest playbook, który niczego nie zmienia, tylko zbiera informacje z routera lub przełącznika. Np. z użyciem modułu ios_facts z kolekcji cisco.ios.
Instalacja kolekcji:
ansible-galaxy collection install cisco.iosProsty playbook w playbooks/get-facts.yml:
---
- name: Pobierz fakty z routerów labowych
hosts: r1-lab
gather_facts: no
connection: network_cli
tasks:
- name: Zbierz fakty z urządzenia
cisco.ios.ios_facts:
register: device_facts
- name: Wyświetl wersję IOS
debug:
msg: "Wersja systemu: {{ device_facts.ansible_facts.ansible_net_version }}"
Uruchomienie:
ansible-playbook playbooks/get-facts.ymlTo pierwszy moment, kiedy widzisz konkretny efekt: wersję systemu, hostname, informacje o interfejsach wyciągnięte automatycznie z urządzenia.
Konfiguracja poświadczeń i Ansible Vault
Hasła i klucze wygodniej trzymać w zmiennych niż wklejać do inwentarza. Najprostsza forma to plik w group_vars:
group_vars/
all.ymlansible_user: admin
ansible_password: "bardzo_tajne_haslo"
ansible_become: yes
ansible_become_method: enable
ansible_become_password: "haslo_enable"
Żeby nie przechowywać haseł w postaci jawnej, użyj ansible-vault:
ansible-vault encrypt group_vars/all.ymlPrzy uruchamianiu playbooka Ansible poprosi o hasło do Vaulta lub użyjesz pliku z hasłem. Dzięki temu pliki repozytorium mogą trafić do Gita bez obaw o wyciek haseł.
Tryb „check” i „diff” jako zabezpieczenie przed błędami
Przed pierwszym wprowadzeniem zmian dobrze jest zobaczyć, co Ansible zamierza zrobić. W tym celu służy tryb sprawdzający:
ansible-playbook playbooks/change-banner.yml --check --diffParametr --check powoduje „suchy bieg” – Ansible symuluje zmiany, ale ich nie wprowadza. --diff pokazuje różnice w konfiguracji (jeśli moduł je obsługuje). To mechanizm, który często ratuje przed nadpisaniem ręcznie zmodyfikowanej konfiguracji.

Podstawy playbooków Ansible pod sieci: od prostego zadania do roli
Struktura playbooka dla urządzeń sieciowych
Playbook dla sieci jest podobny do tego dla serwerów, ale zwykle ustawia się inne parametry połączeń. Szkielet z jednym zadaniem:
---
- name: Konfiguracja banera logowania
hosts: all
gather_facts: no
connection: network_cli
tasks:
- name: Ustaw baner MOTD
cisco.ios.ios_banner:
banner: motd
text: |
Dostep tylko dla upowaznionego personelu.
Wszystkie akcje sa logowane.
state: present
Tu od razu widać kilka elementów: nazwę playbooka, grupę hostów, sposób połączenia oraz listę zadań.
Grupy hostów i zmienne grupowe
Gdy lab się rozrośnie, pojawi się potrzeba rozdzielenia routerów i przełączników. W inwentarzu możesz zdefiniować grupy:
all:
children:
routers:
hosts:
r1-lab:
ansible_host: 10.0.0.11
r2-lab:
ansible_host: 10.0.0.12
switches:
hosts:
sw1-lab:
ansible_host: 10.0.0.21
sw2-lab:
ansible_host: 10.0.0.22
W katalogu group_vars możesz wtedy mieć różne pliki:
group_vars/routers.yml– zmienne wspólne dla routerów,group_vars/switches.yml– osobne parametry dla przełączników.
Playbook może wskazywać tylko wybraną grupę, np. hosts: routers, dzięki czemu zadania nie dotkną przełączników.
Szablony Jinja2 do generowania konfiguracji
Dla bardziej złożonych fragmentów konfiguracji (np. VLAN-y, BGP) wygodnie użyć szablonów Jinja2. Szablon to plik tekstowy z wstawkami w klamrach. Przykład prostego szablonu VLAN-ów templates/vlans.j2:
{% for vlan in vlans %}
vlan {{ vlan.id }}
name {{ vlan.name }}
{% endfor %}
Zmienne VLAN-ów definiujesz np. w host_vars/sw1-lab.yml:
vlans:
- id: 10
name: USERS
- id: 20
name: SERVERS
Playbook używający szablonu z modułem ios_config:
---
- name: Konfiguracja VLAN-ow ze wzorca
hosts: switches
gather_facts: no
connection: network_cli
tasks:
- name: Wygeneruj i zastosuj konfiguracje VLAN
cisco.ios.ios_config:
src: "templates/vlans.j2"
Ten wzorzec łatwo rozszerzać. Dodajesz VLAN do listy w YAML, odpalasz playbooka i konfiguracja pojawia się na przełączniku.
Od pojedynczego playbooka do roli
Gdy liczba zadań rośnie, pojedynczy plik playbooka staje się mało czytelny. Dużo wygodniejsze są role, czyli uporządkowany zestaw zadań, szablonów i zmiennych do jednego celu, np. „bazowa konfiguracja routera”.
Minimalna rola roles/base-router może wyglądać tak:
roles/
base-router/
tasks/
main.yml
templates/
base-config.j2
defaults/
main.yml
Przykładowy plik tasks/main.yml:
---
- name: Zastosuj bazowa konfiguracje routera
cisco.ios.ios_config:
src: "base-config.j2"
W defaults/main.yml możesz zdefiniować domyślne zmienne, np. NTP, serwer syslog, domenę:
---
ntp_servers:
- 192.0.2.1
- 192.0.2.2
domain_name: lab.local
logging_server: 192.0.2.10
Playbook korzystający z roli jest wtedy bardzo prosty:
---
- name: Bazowa konfiguracja routerow
hosts: routers
gather_facts: no
connection: network_cli
roles:
- base-router
Dzięki rolom nie kopiujesz tych samych zadań między playbookami. Projekty stają się modularne: jedna rola dla bazowej konfiguracji, druga dla OSPF, trzecia dla BGP i tak dalej.
Parametryzowanie ról dla różnych środowisk
Ta sama rola może pracować inaczej w labie i w produkcji. Różnice można wynieść do zmiennych inwentarza. Na przykład w inventories/lab/group_vars/routers.yml:
ntp_servers:
- 10.255.0.1
domain_name: lab.local
A w inventories/prod/group_vars/routers.yml:
ntp_servers:
- 172.16.0.10
- 172.16.0.11
domain_name: corp.local
Ten sam playbook i ta sama rola, inne dane – konfiguracja dopasowana do środowiska bez zmian w logice.
Wprowadzenie do Pythona w automatyzacji sieci (bez „bycia programistą”)
Zakres Pythona potrzebny administratorowi sieci
Do prostych automatyzacji wystarczy wąski zestaw umiejętności:
- uruchamianie skryptu:
python3 skrypt.py, - zmienne, listy, słowniki,
- instrukcje
if, pętlafor, - podstawowe operacje na plikach (odczyt/zapis tekstu, JSON, YAML),
- korzystanie z zewnętrznych bibliotek (Netmiko, NAPALM).
Nie trzeba znać wzorców projektowych, klas ani zaawansowanej składni. W praktyce większość skryptów sieciowych to kilkadziesiąt linijek.
Instalacja bibliotek sieciowych dla Pythona
Na tej samej maszynie, gdzie masz Ansible, zainstaluj Netmiko i NAPALM:
pip3 install netmiko napalmDobrą praktyką jest użycie wirtualnego środowiska Pythona, np. venv, żeby nie mieszać bibliotek systemowych z projektowymi:
python3 -m venv venv
source venv/bin/activate
pip install netmiko napalm
W każdym nowym terminalu przed pracą aktywujesz środowisko komendą source venv/bin/activate.
Prosty skrypt Python do wykonania komendy „show”
Najczęstsze zadanie na start: zalogować się na router i wykonać komendę show. Netmiko upraszcza to do kilku linijek kodu. Przykład scripts/show_version.py:
from netmiko import ConnectHandler
device = {
"device_type": "cisco_ios",
"host": "10.0.0.11",
"username": "admin",
"password": "bardzo_tajne_haslo",
}
with ConnectHandler(**device) as conn:
output = conn.send_command("show version")
print(output)
Skrypt uruchamiasz:
python3 scripts/show_version.pyTo odpowiednik ręcznego logowania się przez SSH, ale wynik od razu ląduje w pliku lub na ekranie. W dalszych krokach możesz dodać prostą analizę tekstu, np. wyszukanie wersji IOS.
Wydzielenie danych urządzeń do pliku YAML
Żeby nie trzymać adresów i haseł w środku skryptu, lepiej przenieść je do pliku YAML, np. devices.yml:
devices:
- name: r1-lab
host: 10.0.0.11
username: admin
password: bardzo_tajne_haslo
device_type: cisco_ios
- name: r2-lab
host: 10.0.0.12
username: admin
password: bardzo_tajne_haslo
device_type: cisco_ios
Skrypt z użyciem biblioteki PyYAML:
import yaml
from netmiko import ConnectHandler
with open("devices.yml") as f:
data = yaml.safe_load(f)
for dev in data["devices"]:
print(f"Polaczenie z {dev['name']} ({dev['host']})")
with ConnectHandler(
device_type=dev["device_type"],
host=dev["host"],
username=dev["username"],
password=dev["password"],
) as conn:
output = conn.send_command("show ip interface brief")
filename = f"outputs/{dev['name']}_interfaces.txt"
with open(filename, "w") as out:
out.write(output)
Taki skrypt przechodzi po liście urządzeń, wykonuje komendę i zapisuje wynik do osobnych plików. Struktura jest już bardziej zbliżona do narzędzia, które można uruchamiać cyklicznie.
NAPALM jako warstwa abstrakcji nad różnymi vendorami
NAPALM ujednolica sposób pracy z różnymi systemami (IOS, Junos, EOS). Zamiast pisać osobną logikę dla każdego producenta, korzystasz z jednego interfejsu. Przykład prostego skryptu pobierającego fakty:
Przykład użycia NAPALM do pobierania faktów z urządzenia
from napalm import get_network_driver
driver = get_network_driver("ios")
device = driver(
hostname="10.0.0.11",
username="admin",
password="bardzo_tajne_haslo",
)
device.open()
facts = device.get_facts()
interfaces = device.get_interfaces()
device.close()
print("Podstawowe informacje:")
for key, value in facts.items():
print(f"{key}: {value}")
print("nInterfejsy:")
for name, data in interfaces.items():
print(f"{name}: is_up={data['is_up']}, description={data['description']}")
Struktura zwracanych danych jest słownikowa, więc można ją łatwo zapisać do JSON lub przefiltrować. Ten sam skrypt, po zmianie typu sterownika np. na junos, będzie działał z Juniperem (przy spełnieniu wymagań transportu).
Zapisywanie danych z NAPALM do JSON
JSON dobrze współpracuje z innymi narzędziami (np. systemami CMDB, Elastic, narzędziami do raportów). Przykład rozszerzenia poprzedniego skryptu:
import json
from napalm import get_network_driver
driver = get_network_driver("ios")
device = driver(
hostname="10.0.0.11",
username="admin",
password="bardzo_tajne_haslo",
)
device.open()
facts = device.get_facts()
interfaces = device.get_interfaces()
device.close()
result = {
"facts": facts,
"interfaces": interfaces,
}
with open("outputs/r1-lab_napalm.json", "w") as f:
json.dump(result, f, indent=2)
Takie pliki można później porównywać, wersjonować w Gicie lub podawać do kolejnych skryptów kontrolnych.
Wywoływanie wielu urządzeń z NAPALM i prosty raport
Przykład skryptu, który przechodzi po liście urządzeń z YAML i buduje prosty raport o wersji systemu:
import yaml
from napalm import get_network_driver
with open("devices.yml") as f:
data = yaml.safe_load(f)
for dev in data["devices"]:
print(f"n=== {dev['name']} ({dev['host']}) ===")
driver = get_network_driver("ios")
device = driver(
hostname=dev["host"],
username=dev["username"],
password=dev["password"],
)
device.open()
facts = device.get_facts()
device.close()
print(f"Vendor: {facts.get('vendor')}")
print(f"Model: {facts.get('model')}")
print(f"OS version: {facts.get('os_version')}")
print(f"Serial: {facts.get('serial')}")
Taki raport często zastępuje ręczne przeklikiwanie się przez kilkanaście urządzeń przed planowaną aktualizacją.
Bezpieczne obchodzenie się z hasłami w skryptach Python
Najgorszy wariant to trzymanie haseł wprost w kodzie. Lepsze podejścia:
- odczyt hasła z zmiennej środowiskowej,
- użycie pliku YAML zaszyfrowanego Ansible Vault,
- interaktywne pytanie o hasło, jeśli skrypt uruchamiany jest ręcznie.
Przykład z wykorzystaniem zmiennej środowiskowej:
import os
from netmiko import ConnectHandler
password = os.environ.get("NET_PASSWORD")
if not password:
raise SystemExit("Brak zmiennej NET_PASSWORD")
device = {
"device_type": "cisco_ios",
"host": "10.0.0.11",
"username": "admin",
"password": password,
}
with ConnectHandler(**device) as conn:
print(conn.send_command("show hostname"))
W praktyce można połączyć to z managerem haseł lub mechanizmem CI/CD, który wstrzykuje zmienne środowiskowe tylko na czas zadania.

Proste skrypty Python + Netmiko/NAPALM do pracy z urządzeniami
Netmiko do wprowadzania konfiguracji liniowej
Dla krótkich zmian konfiguracyjnych (np. opis interfejsu, ACL na jednym porcie) Netmiko bywa szybsze niż przygotowywanie roli Ansible. Przykład aktualizacji opisu na interfejsie:
from netmiko import ConnectHandler
device = {
"device_type": "cisco_ios",
"host": "10.0.0.21",
"username": "admin",
"password": "bardzo_tajne_haslo",
}
commands = [
"interface GigabitEthernet0/1",
"description Uplink do rdzenia",
]
with ConnectHandler(**device) as conn:
output = conn.send_config_set(commands)
print(output)
Netmiko sam przechodzi w tryb konfiguracji, wysyła polecenia i wraca do trybu wykonywania.
Netmiko i obsługa wielu komend oraz zapis kopii konfiguracji
Przykład skryptu, który pobiera bieżącą konfigurację i zapisuje ją lokalnie jako kopię:
import os
from datetime import datetime
from netmiko import ConnectHandler
device = {
"device_type": "cisco_ios",
"host": "10.0.0.11",
"username": "admin",
"password": "bardzo_tajne_haslo",
}
backup_dir = "backups"
os.makedirs(backup_dir, exist_ok=True)
with ConnectHandler(**device) as conn:
hostname = conn.send_command("show running-config | include hostname").split()[1]
running = conn.send_command("show running-config")
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
filename = os.path.join(backup_dir, f"{hostname}_running_{timestamp}.cfg")
with open(filename, "w") as f:
f.write(running)
print(f"Zapisano kopie konfiguracji do {filename}")
Taki skrypt można zintegrować z cronem lub narzędziem orkiestrującym zadania i mieć codzienne backupy bez dodatkowego sprzętu.
Prosty „compliance check” w Pythonie
Częsty scenariusz: sprawdzenie, czy na wszystkich urządzeniach skonfigurowano np. serwery NTP i logging. Minimalny wariant opary na wyszukiwaniu linii w running-config:
import yaml
from netmiko import ConnectHandler
REQUIRED_LINES = [
"ntp server 192.0.2.1",
"logging host 192.0.2.10",
]
with open("devices.yml") as f:
data = yaml.safe_load(f)
for dev in data["devices"]:
print(f"n=== Sprawdzanie {dev['name']} ===")
with ConnectHandler(
device_type=dev["device_type"],
host=dev["host"],
username=dev["username"],
password=dev["password"],
) as conn:
running = conn.send_command("show running-config")
for line in REQUIRED_LINES:
if line in running:
print(f"[OK] {line}")
else:
print(f"[BRAK] {line}")
To nie jest idealny compliance w stylu narzędzi klasy enterprise, ale w małych środowiskach rozwiązuje 80% problemów.
NAPALM i wprowadzanie zmian z mechanizmem „diff”
NAPALM potrafi wgrać konfigurację w trybie „merge” lub „replace” i pokazać różnicę przed zatwierdzeniem. To bezpieczniejsze niż ślepe wysyłanie linii konfiguracyjnych.
from napalm import get_network_driver
driver = get_network_driver("ios")
device = driver(
hostname="10.0.0.11",
username="admin",
password="bardzo_tajne_haslo",
)
device.open()
device.load_merge_candidate(filename="configs/r1-lab_snmp.cfg")
diff = device.compare_config()
if diff:
print("Proponowane zmiany:")
print(diff)
confirm = input("Zatwierdzic zmiany? [y/N]: ").lower()
if confirm == "y":
device.commit_config()
print("Zmiany zatwierdzone.")
else:
device.discard_config()
print("Zmiany odrzucone.")
else:
print("Brak roznic, nic do zrobienia.")
device.close()
Taki schemat przypomina pracę na Junosie: najpierw przegląd różnic, potem świadome zatwierdzenie.
Łączenie Netmiko i NAPALM w jednym skrypcie
Typowy wzorzec: Netmiko do prostych komend typu „show”, NAPALM do szerszych zmian konfiguracyjnych. Przykład: najpierw szybka kontrola stanu BGP, potem ewentualne wgranie nowej polityki:
from netmiko import ConnectHandler
from napalm import get_network_driver
device_params = {
"host": "10.0.0.11",
"username": "admin",
"password": "bardzo_tajne_haslo",
}
# Szybki podglad stanu BGP przez Netmiko
with ConnectHandler(device_type="cisco_ios", **device_params) as conn:
bgp_summary = conn.send_command("show ip bgp summary")
print(bgp_summary)
if "Idle" in bgp_summary:
print("Sesja BGP w stanie Idle, przerwij lub wprowadz zmiany z ostroznoscia.")
exit(1)
# Zmiana polityki BGP przez NAPALM
driver = get_network_driver("ios")
device = driver(**device_params)
device.open()
device.load_merge_candidate(filename="configs/r1-lab_bgp_policy.cfg")
diff = device.compare_config()
if diff:
print("Zmiany BGP:")
print(diff)
confirm = input("Zatwierdzic zmiany? [y/N]: ").lower()
if confirm == "y":
device.commit_config()
else:
device.discard_config()
device.close()
Takie podejście daje szybki podgląd stanu przed i po zmianie, a jednocześnie korzysta z wygodnego mechanizmu „diff” z NAPALM.
Łączenie Ansible i Pythona w praktycznym workflow sieciowym
Generowanie danych wejściowych dla Ansible skryptem Python
Czasem dane o urządzeniach są w CSV, bazie danych lub API CMDB. Python dobrze nadaje się do ich przetworzenia do formatu zrozumiałego dla Ansible (inwentarz YAML lub JSON).
Przykład skryptu, który z pliku CSV tworzy plik hosts.yml dla Ansible:
import csv
import yaml
inventory = {"all": {"hosts": {}}}
with open("devices.csv") as f:
reader = csv.DictReader(f)
for row in reader:
name = row["name"]
inventory["all"]["hosts"][name] = {
"ansible_host": row["ip"],
"device_role": row["role"],
}
with open("hosts.yml", "w") as f:
yaml.dump(inventory, f, default_flow_style=False)
Skrypt można uruchamiać po każdej zmianie w CMDB, a Ansible zawsze będzie miało aktualny inwentarz.
Użycie modułu ansible.builtin.script do wywołania Pythona z playbooka
Ansible umożliwia uruchamianie skryptów lokalnych na maszynie „control node”. Dzięki temu można wpleść logikę Pythona w szerszy proces.
Przykładowy playbook, który przed konfiguracją urządzeń generuje raport Pythonem:
---
- name: Raport wstepny przed konfiguracja
hosts: localhost
gather_facts: no
tasks:
- name: Generuj raport Netmiko
ansible.builtin.script: "scripts/precheck_report.py"
- name: Konfiguracja routerow po prechecku
hosts: routers
gather_facts: no
connection: network_cli
roles:
- base-router
Skrypt precheck_report.py może korzystać z tego samego pliku devices.yml, którego używasz ręcznie. W ten sposób jedna logika analizy stanu jest używana zarówno interaktywnie, jak i w pipeline.
Ansible jako scheduler dla skryptów Python
Jeśli w środowisku jest już Ansible Tower/AWX lub inny scheduler, nie trzeba budować osobnej infrastruktury dla Pythona. Playbook może po prostu uruchamiać skrypty jako zadania.
Przykład prostej roli roles/run-python-scripts:
roles/
run-python-scripts/
tasks/
main.yml
---
# roles/run-python-scripts/tasks/main.yml
- name: Wykonaj skrypt zbierajacy dane
ansible.builtin.script: "scripts/collect_napalm_facts.py"
- name: Wykonaj skrypt compliance
ansible.builtin.script: "scripts/check_compliance.py"
Playbook uruchamiający rolę:
---
- name: Zadania Pythonowe z Ansible
hosts: localhost
gather_facts: no
roles:
- run-python-scripts
Całość można potem planować w Tower/AWX o dowolnych godzinach.
Python jako filtr niestandardowy w Ansible
Jeśli filtrów Jinja2 i wbudowanych funkcji nie wystarcza, można napisać własny filtr w Pythonie. To pozwala wykonywać bardziej złożone transformacje danych, zanim trafią do szablonów.
Struktura katalogu z filtrami:
plugins/
filter/
net_filters.py
Przykład prostego filtra, który usuwa interfejsy typu „Loopback” z listy:
# plugins/filter/net_filters.py
def exclude_loopbacks(interfaces):
return [i for i in interfaces if not i.startswith("Loopback")]
class FilterModule(object):
def filters(self):
return {
"exclude_loopbacks": exclude_loopbacks,
}
Użycie filtra w szablonie Jinja2:
{% for intf in interfaces | exclude_loopbacks %}
interface {{ intf }}
description Zarzadzanie
{% endfor %}
Taki filtr można łatwo rozbudować o inne reguły (np. wyłączenie portów według wzorca nazwy).
Python jako moduł Ansible (moduł akcji)
Jeśli dany typ zadania powtarza się w wielu playbookach, można go zamknąć w module Ansible napisanym w Pythonie. Wymaga to trochę więcej pracy, ale pozwala zyskać czystsze playbooki.
Prosty lokalny moduł, który zapisuje dane do pliku JSON:
library/
save_json.py
#!/usr/bin/python
from ansible.module_utils.basic import AnsibleModule
import json
def run_module():
module_args = dict(
path=dict(type="str", required=True),
data=dict(type="dict", required=True),
)
result = dict(changed=False)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True,
)
if module.check_mode:
module.exit_json(**result)
with open(module.params["path"], "w") as f:
json.dump(module.params["data"], f, indent=2)
result["changed"] = True
module.exit_json(**result)
def main():
run_module()
if __name__ == "__main__":
main()
Użycie modułu w playbooku:
Najczęściej zadawane pytania (FAQ)
Czy mogę automatyzować sieć Ansible i Pythonem, jeśli nie umiem programować?
Tak. Do podstawowej automatyzacji sieci nie są potrzebne pełne umiejętności programistyczne. Ansible opiera się na plikach YAML, które przypominają uporządkowaną konfigurację, a nie klasyczny kod.
W Pythonie w praktyce używa się prostych elementów: pętli, warunków, czytania plików i kilku funkcji z bibliotek sieciowych (np. Netmiko, NAPALM). Osoba, która swobodnie czyta konfigurację routera lub przełącznika, jest w stanie opanować ten poziom Pythona.
Od czego zacząć naukę automatyzacji sieci z Ansible i Pythonem?
Najpierw opanuj podstawy pracy w terminalu: SSH do urządzeń, podstawowe komendy Linuksa, edycję prostych plików tekstowych oraz kopiowanie plików (scp, sftp, git). Bez tego trudno będzie sprawnie uruchamiać playbooki i skrypty.
Kolejny krok to YAML i proste repozytorium Git: jeden katalog z playbookami, szablonami i plikami z danymi. Zacznij od jednego, bardzo prostego zadania, np. zebrania informacji „show version” z kilku urządzeń.
Jakie są realne korzyści z automatyzacji sieci dla małego środowiska?
Nawet przy kilkunastu urządzeniach zyskujesz czas i spójność konfiguracji. Zmiany, które ręcznie zajmowały godzinę, sprowadzają się do jednego uruchomienia playbooka, z powtarzalnym wynikiem.
Druga rzecz to kontrola: konfiguracja zapisana w plikach, wersjonowana w Git, daje historię zmian i łatwiejszy „rollback”. Znika też efekt „na tym switchu ktoś kiedyś coś dopisał z palca”.
Czy automatyzacja sieci jest bezpieczna? Jak uniknąć awarii?
Automatyzacja jest bezpieczna, jeśli zmiany najpierw testujesz w labie, a nie na produkcji. Błąd w szablonie może powielić złą konfigurację na wszystkich urządzeniach, więc środowisko testowe jest kluczowe.
Pomaga też ostrożny tryb pracy: tryb „check mode” w Ansible, skrypty Pythona zaczynające od samego odczytu (zbieranie konfiguracji, statusów) i dopiero później wykonywanie zmian. Do tego małe, częste wdrożenia zamiast jednej ogromnej modyfikacji.
Czym różni się „jednorazowy skrypt” od porządnego procesu automatyzacji?
Jednorazowy skrypt to często plik napisany „na szybko”, z zaszytymi na sztywno adresami, loginami i bez dokumentacji. Ratuje sytuację, ale po kilku miesiącach nikt nie pamięta, jak go uruchomić i czy jest jeszcze aktualny.
Powtarzalny proces ma prostą strukturę katalogów, osobne pliki z danymi (np. lista urządzeń, zmienne w YAML), krótki opis w README i rozdzielenie logiki od konfiguracji. Taki projekt można uruchomić po dłuższym czasie bez zgadywania.
Jak wygląda prosty, praktyczny przykład automatyzacji z Ansible?
Klasyczny przypadek to zmiana hasła na wielu przełącznikach. Zamiast logować się po kolei na każde urządzenie i ręcznie wpisywać te same komendy, przygotowujesz playbook, w którym w jednym miejscu definiujesz nowe hasło (zaszyfrowane Ansible Vaultem).
Następnie wskazujesz grupę hostów, np. „access-switches”, i uruchamiasz zadanie. Po kilku minutach masz zaktualizowane hasła, zapis logów i jasną informację, gdzie zmiana się nie udała.
Ile czasu dziennie przeznaczyć na naukę Ansible i Pythona jako administrator sieci?
W praktyce lepsze efekty daje 20–30 minut dziennie niż wielogodzinny „projekt” raz na kilka miesięcy. W takiej krótkiej sesji możesz uruchomić jeden playbook na labie, poprawić fragment skryptu lub dodać nową zmienną w YAML.
Po kilku tygodniach takich małych kroków zwykle da się już pisać własne proste playbooki i skrypty, które realnie oszczędzają czas w produkcyjnej sieci.
Najważniejsze wnioski
- Automatyzacja z Ansible i Pythonem usuwa ręczne „klepanie” tych samych komend na wielu urządzeniach, oszczędza godziny pracy tygodniowo i ogranicza literówki oraz pomyłki w konfiguracji.
- Wykorzystanie playbooków i skryptów daje spójną konfigurację w całej sieci, mniej „dziwnych” incydentów i czytelny log zmian, który można łatwo prześledzić i odtworzyć dzięki Gitowi.
- Automatyzacja zmniejsza stres przy wdrażaniu zmian: ten sam proces da się przetestować w labie, uruchomić w trybie „check” i dopiero potem zastosować w produkcji.
- Do startu nie trzeba być programistą – Ansible opiera się na prostym YAML, a w Pythonie wystarczą pętle, warunki i użycie gotowych bibliotek (Netmiko, NAPALM) do konkretnych zadań sieciowych.
- Największy efekt dają małe, praktyczne narzędzia: np. playbook do zmiany hasła na kilkudziesięciu przełącznikach czy skrypt zbierający konfiguracje z całej sieci jednym poleceniem.
- Podstawą pracy jest biegłość w terminalu i SSH oraz wygodna obsługa plików i edytora tekstu, bo cała automatyzacja kręci się wokół uruchamiania komend i edycji plików konfiguracyjnych.
- Konfiguracja traktowana jako kod (pliki YAML, repozytorium Git, wersjonowanie) zamienia jednorazowe „skrypty ratunkowe” w powtarzalny proces, który da się uruchamiać, rozwijać i audytować latami.






