Wybierz swój język

Podstawy automatyzacji z Ansible: Automatyzacja sieci

Ansible świetnie nadaje się do zarządzania konfiguracją urządzeń sieciowych. Dotyczy to zarówno prostych, jak i bardziej zaawansowanych zmian, które można przeprowadzać bezpośrednio lub za pośrednictwem różnych kontrolerów, jak Cisco NSO (Network Services Orchestrator), Cisco APIC (Application Policy Infrastructure Controller) dla ACI (Application Centric Infrastructure), Cisco Catalyst SD-WAN Manager i Cisco Meraki dla SD-WAN czy Cisco Catalyst Center dla SD-Access. W tym artykule skupimy się na bezpośredniej automatyzacji wybranych urządzeń sieciowych firmy Cisco Systems.

Kiedy używamy Ansible do zarządzania hostami z systemem operacyjnym z rodziny GNU/Linux, Ansible kopiuje moduł napisany w Python do zarządzanego hosta i na nim go uruchamia. Ma to dużą zaletę szczególnie, kiedy wykonanie zadań jest złożone i czasochłonne. Dzięki temu, system zarządzający nie jest prawie w ogóle obciążony i przy niewielkich zasobach może obsługiwać bardzo dużą ilość hostów. W przypadku automatyzacji sieci czy też urządzeń sieciowych wygląda to nieco inaczej, przynajmniej od środka, bo z punktu widzenia użytkowego czy też osoby korzystającej z automatyzacji, nic się nie zmienia.

Wynika to z kilku rzeczy. Moduł działający na hoście najczęściej działa bezpośrednio na jego plikach konfiguracyjnych. W przypadku urządzeń sieciowych, nie pracuje się bezpośrednio na plikach. Konfiguracja dostępna jest poprzez odpowiedni interfejs, jak CLI over SSH, XML over SSH, czy API over HTTP/HTTPS. Moduł działający na hoście tworzy dodatkowo różne katalogi i pliki, co nie jest często albo możliwe albo wydajne na urządzeniach sieciowych, ze względu na rodzaj stosowanych w nich pamięci. Moduł też potrzebuje do działania interpretatora Python, czego niestety większość starszych urządzeń sieciowych nie posiada. To prowadzi do tego, że najwygodniej jest wykonywać moduł Ansible lokalnie, a następnie nawiązywać połączenie poprzez udostępniany interfejs.

Ansible domyślnie nawiązuje połączenie SSH i próbuje wysłać w nim swój moduł do zdalnego węzła. Aby to zmienić, musimy użyć jednego z trzech typów dostępnych połączeń:

  • network_cli, które korzysta CLI over SSH (trwałe połączenie).
  • netconf, które korzysta z XML over SSH (trwałe połączenie).
  • httpapi, które korzysta z API over HTTP/HTTPS (trwałe połączenie).

Dawniej do tego celu był wykorzystywany typ połączenia "local", którym wskazywaliśmy Ansible, że moduł ma zostać uruchomiony lokalnie, a do węzła ma zostać nawiązywane połączenie w sposób określony wewnątrz słownika "provider". Niestety, nie odbywało się to w sposób wydajny, gdyż dla każdego zadania było na nowo otwierane i zamykane połączenie.

Obecnie nie zaleca się korzystania z typu połączenia "local".

Tak więc musimy tu zakładać, że moduł będzie wykonywał się bezpośrednio na węźle zarządzającym, a nie urządzeniach sieciowych czy też węzłach zarządzanych. Często, nawet będzie wysyłał jakieś polecenia do urządzeń sieciowych, czekał na odebrane informacje, po ich odebraniu wykonywał coś lokalnie, a następnie znowu coś do nich wysyłał. Dlatego przy dużej ilości urządzeń sieciowych, wymagane może być wykorzystanie większej ilości węzłów wykonawczych (ang. execution nodes) w ramach środowiska automatyzującego. Klastrami takich węzłów da się zarządzać z jednego miejsca w ramach Red Hat Ansible Automation Platform.


Dostępna jest bardzo duża ilość modułów Ansible do automatyzacji urządzeń sieciowych. Przy ich wyborze warto pamiętać o wspomnianej wcześniej idempotentności. Dlatego najlepiej wybierać w pierwszej kolejności moduły wyspecjalizowane do obsługi konkretnych zadań, a dopiero kiedy nie możemy takich znaleźć, korzystać z tych bardziej uniwersalnych, za pomocą których można zrobić prawie wszystko. O ile listę dostępnych modułów sieciowych można znaleźć w dokumentacji Ansible, to należy pamiętać o Red Hat Automation Hub, gdzie dostępne są dodatkowe moduły, role i całe kolekcje niedostępne w standardzie.

Dostęp do Red Hat Automation Hub można uzyskać po wykupieniu subskrypcji dla platformy Red Hat Ansible Automation.


Kilka sposobów na przyśpieszenie automatyzacji

Poszczególne zadania playbooka, dla każdego z węzłów wykonywane są sekwencyjnie, według kolejności ich ułożenia. Natomiast mogą być one wykonywane równolegle na wielu węzłach w tym samym czasie. To na ilu, zależne jest od konfiguracji - domyślnie 5. Do modyfikacji tego służy opcja "-f" lub "--fork" polecenia "ansible" i "ansible-playbook" albo parametr "forks" pliku "ansible.cfg". Parametr ten określa ilość równoległych procesów, jaka będzie dostępna do wykonywania zadań. W ten sposób główny proces dzieli się lub inaczej mówiąc rozwidla się (ang. fork) na wiele mniejszych.

Domyślnie, zanim Ansible zacznie wykonywać nowe zadanie na pierwszym z węzłów, czeka aż wszystkie pozostałe węzły zakończą wykonywania poprzedniego zadania. Nawet, kiedy pozostałe procesy są wolne i nic nie robią. To domyślne zachowanie wynika z domyślnego ustawienia parametru "strategy" na wartość "linear". Kiedy jakaś niewielka grupa urządzeń jest znacząco wolniejsza od reszty, warto rozważyć zmianę tego parametru. Po przestawieniu wartości parametru "strategy" na "free", Ansible będzie wykonywał kolejne zadania tak szybko, jak to możliwe. Czyli, jak tylko pojawią się wolne do użycia procesy. Nadal będzie wykonywał zadania w odpowiedniej kolejności, ale kiedy w ramach bieżącego zadania przestaną być potrzebne kolejne procesy, to zaczną się one zajmować obsługą kolejnych zadań na tych węzłach, które zakończyły już poprzednie zadanie. Dzięki temu, wykorzystanie dostępnych procesów jest efektywniejsze, co przekłada się na poprawę całościowej wydajności.

Dodatkowo, jeżeli zależy nam na wydajności, to powinniśmy unikać wydawania polecenia "show running-config".

Jest to jedno z najbardziej zasobożernych poleceń, jakie można wysłać do urządzenia sieciowego. Jego przetworzenie trwa na tyle długo, że odradzamy wykonywania poleceń na jego bazie na dużej ilości urządzeń sieciowych oraz używania go w playbookach.


Logowanie i backup konfiguracji urządzeń sieciowych

Przejdźmy teraz przez kilka przykładów wykorzystania Ansible do automatyzacji na urządzeniach sieciowych firmy Cisco Systems. Do tego celu wykorzystamy dwa przełączniki:

  • Cisco Nexus 3172TQ z oprogramowaniem Cisco NXOS (moduły Ansible z prefiksem "cisco.nxos.nxos_").
  • Cisco Catalyst 9300 z oprogramowaniem Cisco IOS-XE (moduły Ansible z prefiksem "cisco.ios.ios_").

O ile my będziemy wykonywać nasze zadania tylko na dwóch przełącznikach, to równie dobrze mogłoby być ich znacznie więcej. Kiedy mówimy o wykonaniu nawet dość prostych czynności na dużej ilości urządzeń i/lub za każdym razem, kiedy kreowana i usuwana jest jakaś usługa, to robienie ich ręcznie jest mało efektywne, czasochłonne oraz podatne na błędy i pominięcia.

Nasz plik inwentarza został nieco zmodyfikowany. Za pomocą zmiennej "ansible_network_os" wskazaliśmy systemy operacyjne, jakie są używane przez nasze urządzenia sieciowe. Użyliśmy także najprostszego sposobu logowania do nich, za pomocą użytkownika i jawnie podanego hasła. Należy jednak pamiętać, że Ansible umożliwia przechowywanie poufnych informacji, jak m.in. hasła w specjalnych pojemnikach poświadczeń, dzięki czemu nie są one dostępne w postaci jawnego tekstu.

W związku z tym, że naszym celem tutaj jest pokazanie, jak w najprostszy sposób zarządzać urządzeniami sieciowymi, a też tej metody nawiązywania połączenia jeszcze nie pokazywaliśmy, to właśnie tutaj z niej skorzystamy.

[msleczek@vm0-net projekt_A]$ cat inventory
[all:vars]
ansible_user=admin
ansible_ssh_pass=networkers.pl
ansible_connection=network_cli
ansible_become=no

[catalyst]
10.8.100.65 ansible_network_os=ios

[nexus]
10.8.100.66 ansible_network_os=nxos

[msleczek@vm0-net projekt_A]$

Do nawiązywania połączeń będziemy korzystać z metody "network_cli".

Zaczniemy od czegoś prostego ale bardzo użytecznego, czyli zebrania konfiguracji ze wszystkich urządzeń sieciowych. Do tego celu posłużymy się parametrem "backup" modułów "cisco.ios.ios_config" i "cisco.nxos.nxos_config".

[msleczek@vm0-net projekt_A]$ cat backup.yml
---
- hosts: catalyst
  gather_facts: no
  tasks:
  - name: IOS/IOS-XE Backup Configuration
    cisco.ios.ios_config:
      backup: yes

- hosts: nexus
  gather_facts: no
  tasks:
  - name: NXOS Backup Configuration
    cisco.nxos.nxos_config:
      backup: yes

[msleczek@vm0-net projekt_A]$ ansible-playbook backup.yml

PLAY [catalyst] ******************************************************************

TASK [IOS/IOS-XE Backup Configuration] *******************************************
changed: [10.8.100.65]

PLAY [nexus] *********************************************************************

TASK [NXOS Backup Configuration] *************************************************
changed: [10.8.100.66]

PLAY RECAP ***********************************************************************
10.8.100.65 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 
10.8.100.66 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

[msleczek@vm0-net projekt_A]$

Jeżeli nie wskażemy jawnie, gdzie mają być składowane kopie zapasowe oraz nie podamy nazw ich plików, to w katalogu bieżący Ansible utworzy katalog o nazwie "backup/" i w nim umieści konfiguracje z urządzeń sieciowych.

[msleczek@vm0-net projekt_A]$ ls -l backup
total 20
-rw-rw-r--. 1 msleczek msleczek 5535 Jun 12 13:05 10.8.100.65_config.2025-06-14@13:05:13
-rw-rw-r--. 1 msleczek msleczek 9962 Jun 12 13:05 10.8.100.66_config.2025-06-14@13:05:18
[msleczek@vm0-net projekt_A]$


Na rynku jest zbyt dużo sprzętu z szarego kanału, stąd koniecznie sprawdzaj, czy firma sprzedająca produkty firmy Cisco Systems lub Red Hat jest na 100% jej partnerem handlowym.

Sprawdzić można to w Cisco Partner Locator oraz Red Hat Partner Locator gdzie też jesteśmy.


Automatyzacja konfiguracji urządzeń sieciowych

W kolejnym przykładzie, na przełączniku Cisco Catalyst zabezpieczymy linie VTY, poprzez które odbywa się obsługa przełącznika. Będzie to możliwe tylko z dwóch adresów IP oraz tylko za pomocą SSH. Dodatkowo, wszyscy będą automatycznie wylogowywani po 15-minutach braku aktywności. Jeżeli doszło do zmiany w konfiguracji, to zostanie ona trwale zapisana.

Polecenia CLI dostępne w systemach Cisco IOS-XE oraz Cisco NXOS powiązane są z sekcją czy też inaczej kontekstem, w jakim się je wydaje. Oznacza to, że to samo polecenie może służyć do całkiem różnych rzeczy, a nawet mieć inną składnię, w zależności od tego, w jakim miejscu konfiguracji zostanie wydane. Polecenia, które chcemy wydać umieszcza się na liście "lines". Natomiast parametr "parents" umożliwia ustawienie stosownego kontekstu czy też inaczej sekcji, w jakiej zostaną one wydane.

Zdarza się też, że przed wydaniem poleceń chcemy usunąć jakieś poprzednie. Do tego celu służy parametr "before". W naszym przykładzie, pierw usuwamy całą listę ACL, a następnie tworzymy nową od zera.

Polecenia na liście "before" zostaną wydane tylko, jeżeli moduł musi wprowadzić zmiany.

Do weryfikacji tego służy parametr "match", który porównuje aktualną konfigurację z tym, co chcemy osiągnąć, w ramach danego kontekstu. Parametr ten może przyjmować wartości:

  • "none" - nie sprawdzamy nic w konfiguracji bieżącej, więc polecenia zawsze zostaną wprowadzone.
  • "strict" - sprawdza, czy w konfiguracji bieżącej żądane polecenia są w odpowiedniej kolejności.
  • "exact" - podobnie jak strict, ale dana sekcja nie może zawierać nic więcej.
  • "line" - sprawdza linia po linii każde polecenie z konfiguracją, jak jest, to nic nie robi, a jak nie, to je dodaje.

W naszym przykładzie został on ustawiony na "strict", co oznacza, że polecenia z listy "lines" będą sprawdzane nie tylko pod względem wystąpienia, ale też pozycji w jakiej powinny się znaleźć, co przy listach ACL jest kluczowe.

Podobna sytuacja ma miejsce dalej, gdzie dzięki zastosowaniu parametru "parents", polecenia z listy "lines", których celem jest zabezpieczenie linii VTY od 0 do 15, zostaną wprowadzone w trybie konfiguracji tych linii.

[msleczek@vm0-net projekt_A]$ cat configure_switches.yml 
---
- hosts: catalyst
  gather_facts: false
  tasks:
  - name: Create ACL
    cisco.ios.ios_config:
      match: strict
      before: no ip access-list extended MGMT-ACL
      parents: ip access-list extended MGMT-ACL
      lines:
      - permit ip host 10.8.232.120 any
      - permit ip host 10.8.100.100 any
  - name: Harden VTY lines
    cisco.ios.ios_config:
      parents:
      - line vty 0 15
      lines:
      - exec-timeout 15 0
      - transport input ssh
      - access-class MGMT-ACL in
  - name: Save Configuration
    cisco.ios.ios_config:
      save_when: changed

- hosts: nexus
  gather_facts: false
  tasks:
  - name: Configure hostname and domain name
    cisco.nxos.nxos_system:
      hostname: nx3172-lab
      domain_name: networkers.pl
  - name: Configure DNS Servers
    cisco,nxos.nxos_system:
      name_servers:
      - 1.1.1.1
      - 8.8.4.4
  - name: Banner MOTD
    cisco,nxos.nxos_banner:
      banner: motd
      text: "{{ lookup('ansible.builtin.file', 'banner.txt') }}"
      state: present
  - name: VLAN creation
    cisco.nxos.nxos_vlans:
      config:
      - vlan_id: 123
        name: ANSIBLE-123
        enabled: yes
        state: active
  - name: Save Configuration
    cisco.nxos.nxos_config:
      save_when: changed

[msleczek@vm0-net projekt_A]

Na przełączniku Cisco Nexus ustawimy hostname, nazwę domenową, serwery DNS, komunikat MOTD (Message Of The Day), jaki pojawia się w trakcie logowania oraz jeden VLAN. Ponadto, jeżeli konfiguracja uległa zmianie, to zostanie trwale zapisana.

[msleczek@vm0-net projekt_A]$ ansible-playbook configure_switches.yml

PLAY [catalyst] ****************************************************************************

TASK [Create ACL] **************************************************************************
changed: [10.8.100.65]

TASK [Harden VTY lines] ********************************************************************
changed: [10.8.100.65]

TASK [Save Configuration] ******************************************************************
changed: [10.8.100.65]

PLAY [nexus] *******************************************************************************

TASK [Configure hostname and domain name] **************************************************
changed: [10.8.100.66]

TASK [Configure DNS Servers] ***************************************************************
changed: [10.8.100.66]

TASK [Banner MOTD] *************************************************************************
changed: [10.8.100.66]

TASK [VLAN creation] ***********************************************************************
changed: [10.8.100.66]

TASK [Save Configuration] ******************************************************************
changed: [10.8.100.66]

PLAY RECAP *********************************************************************************
10.8.100.65     : ok=3  changed=3  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0 
10.8.100.66     : ok=5  changed=5  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

[msleczek@vm0-net projekt_A]$

Urządzeniami sieciowymi również można zarządzać za pomocą poleceń doraźnych (łac. ad-hoc). Dotyczy to zarówno wprowadzania zmian, jak i zbierania pewnych danych. To pierwsze może być przydatne przy zmianie hasła na dużej ilości urządzeń, a to drugie przy inwentaryzacji oraz weryfikacji stanu pewnych elementów i usług urządzenia. 

Do zbierania faktów z urządzeń sieciowych służą wyspecjalizowane moduły. Dla urządzeń z systemem Cisco IOS lub Cisco IOS-XE należy do tego celu stosować moduł "cisco.ios.ios_facts", a dla urządzeń z systemem Cisco NXOS moduł "cisco.nxos.nxos_facts".

[msleczek@vm0-net projekt_A]$ ansible -m cisco.ios.ios_facts catalyst -a "gather_subset=hardware"
10.8.100.65 | SUCCESS => {
    "ansible_facts": {
        "ansible_net_api": "cliconf",
        "ansible_net_filesystems": [
            "flash:"
        ],
        "ansible_net_filesystems_info": {
            "flash:": {
                "spacefree_kb": 8897616.0,
                "spacetotal_kb": 11087104.0
            }
        },
        "ansible_net_gather_network_resources": [],
        "ansible_net_gather_subset": [
            "default",
            "hardware"
        ],
        "ansible_net_hostname": "cat9300",
        "ansible_net_image": "flash:packages.conf",
        "ansible_net_iostype": "IOS",
        "ansible_net_memfree_mb": 1105641.8515625,
        "ansible_net_memtotal_mb": 1392644.6328125,
        "ansible_net_model": "C9300-48P",
        "ansible_net_python_version": "3.6.8",
        "ansible_net_serialnum": "FCW2248E156",
        "ansible_net_stacked_models": [
            "C9300-48P"
        ],
        "ansible_net_stacked_serialnums": [
            "FCW2248E156"
        ],
        "ansible_net_system": "ios",
        "ansible_net_version": "16.06.05",
        "ansible_network_resources": {},
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false
}
[msleczek@vm0-net projekt_A]$

Poniżej zobaczyć można baner MOTD, jaki ustawiliśmy na przełączniku Cisco Nexus:

[msleczek@vm0-net projekt_A]$ ansible -m cisco.nxos.nxos_command nexus -a "commands='show banner motd'"
10.8.100.66 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "stdout": [
        "W networkers.pl kupisz m.in. produkty:\n- Cisco Systems\n- Red Hat\n- LINBIT\n- Storware\n- VMware\n- Veeam\n- NextCloud\n- Collabora Online\n- ONLYOFFICE\n- SuperMicro\n\nZapraszamy do dzialu PRODUKTY i ROZWIAZANIA."
    ],
    "stdout_lines": [
        [
            "W networkers.pl kupisz m.in. produkty:",
            "- Cisco Systems",
            "- Red Hat",
            "- LINBIT",
            "- Storware",
            "- VMware",
            "- Veeam",
            "- NextCloud",
            "- Collabora Online",
            "- ONLYOFFICE",
            "- SuperMicro",
            "",
            "Zapraszamy do dzialu PRODUKTY i ROZWIAZANIA."
        ]
    ]
}
[msleczek@vm0-net projekt_A]$

Istnieje także możliwość wykorzystania szablonów Jinja2 do generowania konfiguracji, które następnie będą wysyłane do urządzeń sieciowych. Co fajne, to szablony Jinja2 są obsługiwane bezpośrednio przez moduły sieciowe, dzięki czemu nie jest potrzebne stosowanie pośrednio modułu "ansible.builtin.template".

Na koniec warto dodać, że w ramach Red Hat Automation Hub dostępne jest wiele gotowych roli, pluginów, modułów oraz kolekcji tworzonych przez różnych producentów rozwiązań sieciowych, które są dodatkowo weryfikowane i certyfikowane przez Red Hat. Przykładem może być bardzo dobrze dopracowany zestaw do automatyzacji Cisco ACI (Application Centric Infrastructure).

Zainteresowanych automatyzacją oraz orkiestracją sieci i jej usług na większą skalę, zachęcamy do zapoznania się z Cisco NSO (Network Services Orchestrator), który umożliwia kooperację z Red Hat Ansible Automation Platform oraz wprowadzanie wszelkich zmian w sposób atomowy w ramach całej infrastruktury sieciowej.


Zapraszamy do Ten adres pocztowy jest chroniony przed spamowaniem. Aby go zobaczyć, konieczne jest włączenie w przeglądarce obsługi JavaScript. zainteresowanych rozwiązaniami Red Hat, w tym w szczególności Red Hat Enterprise Linux, Red Hat Satellite, Red Hat OpenShift Container Platform, Red Hat Ansible Automation Platform oraz Red Hat OpenStack Platform. Jesteśmy partnerem firmy Red Hat i za naszym pośrednictwem można zakupić ich produkty na polskim rynku.


Przed kolejną porcją wiedzy zachęcamy do przećwiczenia i utrwalenia tej poznanej tutaj. Skorzystaj z naszych ćwiczeń!