Ansible: Interaktionen mit Cisco IOS-Geräten

Ansible kann auf Mehrere Arten mit Cisco-Devices zusammen arbeiten. Dieser Artikel beschreibt eine einfache und direkte Interaktion.
Natürlich muss Ansible sich auf dem Router oder Switch anmelden können.. Dazu wird der User auf dem Gerät (hier ist es ein Cisco 1921 Router) als privilegiertes Login angelegt.

username ansible privilege 15 password ansiblepwd

Der User ansible kann natürlich auch als ‘normaler’, also nicht-privilegierter User angelegt werden, jedoch müssen dann zusätzlich die Variablen

ansible_become=yes
ansible_become_method=enable
ansible_become_password=ena-PW_des_Routers

in der Variable-Sektion des Hosts-Files angelegt werden, damit Ansible in den enable-Modus wechseln kann.

Ausserdem wird in der entsprechenden Sektion angegeben welches Betriebssystem die Router verwenden, in diesem Fall ios.

Es bietet sich an, hier zwischen Router(n), Core-, Distributions und Access-Switches zu unterteilen, da diese Gruppen zwar untereinander ähnlich bis gleich konfiguriert werden, zwischen den Gruppen aber große Unterschiede vorhanden sind… Speziell Router und Firewalls sollte man sehr genau betracheten, da diese (neben Core-Switches) IP-Netze halten und entstrechend individuell konfiguriert werden müssen.

In diesem Beispiel hat die Gruppe Routers nur ein Mitglied,

[Router] 
172.16.199.2 

[Router:vars] 
ansible_user=ansible 
ansible_password=ansiblepwd
ansible_network_os=ios

Damit kann schon grundsätzlich auf den Router zugegriffen werden. Dazu folgt nun ein  einfaches Playbook:

--- 
- name: CiscoTest 
 hosts: 172.16.199.2 
 gather_facts: false 
 connection: network_cli 

 tasks: 
  - name: Set Interfaces 
    ios_command: 
        commands: 
           - conf t 
           - interface GigabitEthernet0/1.254 
           - description ClientB VLAN254 Ansible Test 
           - encapsulation dot1Q 254 
           - ip address 172.16.254.1 255.255.255.0 
           - ip helper-address 172.16.199.11 
           - ip helper-address 172.16.199.12 
           - end 
           - wr 

  - name: Show Interfaces 
    ios_command: 
       commands: 
           - sh ip int br 
    register: output 

  - name: Print Output 
    debug: 
      var: output.stdout_lines

Das Playbook heißt CiscoTest und wird direkt auf den Host 172.16.199.2 angewandt. Ein Sammeln von Informationen wird nicht gestartet (gather_facts ist false) und die Verbindung soll direkt auf das CLI des Routers gehen (connection=network_cli). Das Playbook enthält drei aufeinander folgende Aufgaben/Tasks. Der erste (Set Interfaces) baut auf dem Router das VLAN-Interface GigabitEthernet 0/1.254 auf und trunkt es per 802.1Q, IP-Adresse und IP-Helper weden zugewiesen, damit im Subnetz Clients auf die verfügbaren DHCP-Server geleitet werden können. Nun wird noch die Konfiguration auf dem Router gespeichert und der Task ist beendet.
Die Ausgaben auf dem CLI sind in diesem Fall irrelevant, da der Router nach den einzelnen Kommandeos nichts ausgibt.

Der zweite Task, Show Interfaces fasst alle Interfaces zusammen und es ist gleich zu sehen, ob die Konfiguration erfolgreich durchgeführt werden konnte. In diesem Fall ist die Ausgabe wichtig, daher wird sie über register in die Variable output gespeichert und im dritten Task, Print Output, angezeigt.

Die Ausführung des Playbooks zeigt dann Folgendes:

[user1@ansible playbooks]$ ansible-playbook ciscotest.yml  

PLAY [CiscoTest] ************************************************************************************************************************************************ 

TASK [Set Interfaces] ******************************************************************************************************************************************* 
ok: [172.16.199.2] 

TASK [Show Interfaces] ****************************************************************************************************************************************** 
ok: [172.16.199.2] 

TASK [Print Output] ********************************************************************************************************************************************* 
ok: [172.16.199.2] => { 
   "output.stdout_lines": [ 
       [ 
           "Interface                  IP-Address      OK? Method Status                Protocol", 
           "Embedded-Service-Engine0/0 unassigned      YES NVRAM  administratively down down    ", 
           "GigabitEthernet0/0         172.16.199.2    YES NVRAM  up                    up      ", 
           "GigabitEthernet0/1         172.16.200.1    YES NVRAM  down                  down    ", 
           "GigabitEthernet0/1.1       10.10.1.1       YES NVRAM  down                  down    ", 
           "GigabitEthernet0/1.10      172.16.210.1    YES NVRAM  down                  down    ", 
           "GigabitEthernet0/1.11      172.16.211.1    YES NVRAM  down                  down    ", 
           "GigabitEthernet0/1.20      172.16.220.1    YES NVRAM  down                  down    ", 
           "GigabitEthernet0/1.21      172.16.21.1     YES manual down                  down    ", 
           "GigabitEthernet0/1.100     10.10.100.1     YES NVRAM  down                  down    ", 
           "GigabitEthernet0/1.200     10.10.200.1     YES NVRAM  down                  down    ", 
           "GigabitEthernet0/1.254     172.16.254.1    YES manual down                  down    ", 
           "GigabitEthernet0/1.300     10.10.30.1      YES NVRAM  down                  down" 
       ] 
   ] 
} 

PLAY RECAP ****************************************************************************************************************************************************** 
172.16.199.2               : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0    

[user1@ansible playbooks]$

Das Recap zeigt, dass 3 Tasks erfolgreich auf dem Router durchgeführt wurden, was der router in seiner Konfigurationsdatei auch bestätigt.

r-test#sh run int gi0/1.254 
Building configuration... 

Current configuration : 212 bytes 
! 
interface GigabitEthernet0/1.254 
description ClientB VLAN254 Ansible Test 
encapsulation dot1Q 254 
ip address 172.16.254.1 255.255.255.0 
ip helper-address 172.16.199.11 
ip helper-address 172.16.199.12 
end