OpenSwitch a Ansible automatizace prakticky (4): testování a životní cyklus sítě s Ansible

Posledně jsme si nastavili naší virtuální OpenSwitch leaf-spine topologii a vybudovali jsme BGP L3 fabric. Dnes si ukážeme více z životního cyklu s použitím Ansible – otestování sítě, vrácení odchylek do požadovaného stavu sítě a rolování změn.

Jste líní číst? Mrkněte na video:

Playbook pro testování sítě

Ansible můžete použít i pro testování, že síť funguje. Můžete například iniciovat ping z rlzných prvků na jiné prvky a zjišťovat, jestli prochází. Můžete kontrolovat směrovací tabulky a ujišťovat se, že v nich není nějaký problém (třeba chybějící default route). My si pro studijní účely zkusíme něco jednoduché, ale účinného – budeme analyzovat BGP peering. V zásadě chci pouze vytisknout pro každý prvek informaci o tom, jestli všichni jeho peerové jsou estabilished nebo ne (a pokud ne, dát mi o tom vědět). Určitě by se to dalo dělat mnohem chytřeji, ale pro pochopení konceptu to asi stačí.

Prohlédněte si test-fabric.yml Playbook:

---
- name: Configure hostname and interfaces
  hosts: all
  remote_user: root
  gather_facts: no
  vars_files:
    - vars/topology.yml
    - vars/connections.yml

  tasks:
    - name: Get BGP peering information
      connection: local
      ops_facts:
        provider: "{{ ops_rest_provider }}"
        endpoints:
          - "/system/vrfs/vrf_default/bgp_routers/{{item.0.as_number}}/bgp_neighbors/{{item.1.address}}"
      register: rest_result
      with_subelements:
        - "{{switches[inventory_hostname].ops_vrfs.0.bgp_routers}}"
        - "neighbors"
      ignore_errors: True

    - name: Prepare output
      set_fact:
        peer: "Peering to {{item.item.1.address}} is {{item.ansible_facts.endpoints.0.status.status.bgp_peer_state}}\n"
      register: peers
      with_items: "{{rest_result.results}}"

    - name: Transform output
      set_fact: peer_set="{{ peers.results | map(attribute='ansible_facts.peer') | list }}"

    - name: Report switches with failed neighbors
      fail: msg="{{item}}"
      when: "'Established' not in item"
      with_items: "{{peer_set}}"

V zásadě všechno se odehrálo v jednom jediném tasku jménem „Get BGP peering information“. To ostatní je jen způsob jak to v nějaké rozumně čitelné formě zobrazit a vyhodnocovat. Jak to děláme? Používá se Ansible modul ops_facts, který si umí šáhnout do konfigurační databáze OpenSwitch, která je v jeho samém srdci. Tam totiž nenajdete jen informace konfiguračního charakteru, ale také state jako je směrovací tabulka nebo právě stav BGP peeringu. Stačí se tedy podívat na správné místo a je to.

Spousťte testovací Playbook a podívejte se na výsledek.

$ ansible-playbook -i hosts test-fabric.yml

PLAY [Configure hostname and interfaces] ***************************************

TASK [Get BGP peering information] *********************************************
ok: [leaf1] => (item=({u'router_id': u'192.168.0.1', u'as_number': 65001, u'networks': [u'192.168.0.1/32']}, {u'remote_as': 65101, u'address': u'10.1.0.2'}))
ok: [leaf2] => (item=({u'router_id': u'192.168.0.2', u'as_number': 65002, u'networks': [u'192.168.0.2/32']}, {u'remote_as': 65101, u'address': u'10.1.1.2'}))
ok: [spine2] => (item=({u'router_id': u'192.168.1.2', u'as_number': 65102, u'networks': [u'192.168.1.2/32']}, {u'remote_as': 65001, u'address': u'10.2.0.1'}))
ok: [leaf3] => (item=({u'router_id': u'192.168.0.3', u'as_number': 65003, u'networks': [u'192.168.0.3/32']}, {u'remote_as': 65101, u'address': u'10.1.2.2'}))
ok: [spine1] => (item=({u'router_id': u'192.168.1.1', u'as_number': 65101, u'networks': [u'192.168.1.1/32']}, {u'remote_as': 65001, u'address': u'10.1.0.1'}))
ok: [leaf2] => (item=({u'router_id': u'192.168.0.2', u'as_number': 65002, u'networks': [u'192.168.0.2/32']}, {u'remote_as': 65102, u'address': u'10.2.1.2'}))
ok: [leaf1] => (item=({u'router_id': u'192.168.0.1', u'as_number': 65001, u'networks': [u'192.168.0.1/32']}, {u'remote_as': 65102, u'address': u'10.2.0.2'}))
ok: [leaf3] => (item=({u'router_id': u'192.168.0.3', u'as_number': 65003, u'networks': [u'192.168.0.3/32']}, {u'remote_as': 65102, u'address': u'10.2.2.2'}))
ok: [spine2] => (item=({u'router_id': u'192.168.1.2', u'as_number': 65102, u'networks': [u'192.168.1.2/32']}, {u'remote_as': 65002, u'address': u'10.2.1.1'}))
ok: [spine1] => (item=({u'router_id': u'192.168.1.1', u'as_number': 65101, u'networks': [u'192.168.1.1/32']}, {u'remote_as': 65002, u'address': u'10.1.1.1'}))
ok: [spine1] => (item=({u'router_id': u'192.168.1.1', u'as_number': 65101, u'networks': [u'192.168.1.1/32']}, {u'remote_as': 65003, u'address': u'10.1.2.1'}))
ok: [spine1] => (item=({u'router_id': u'192.168.1.1', u'as_number': 65101, u'networks': [u'192.168.1.1/32']}, {u'remote_as': 65004, u'address': u'10.1.3.1'}))
ok: [leaf4] => (item=({u'router_id': u'192.168.0.4', u'as_number': 65004, u'networks': [u'192.168.0.4/32']}, {u'remote_as': 65101, u'address': u'10.1.3.2'}))
ok: [spine2] => (item=({u'router_id': u'192.168.1.2', u'as_number': 65102, u'networks': [u'192.168.1.2/32']}, {u'remote_as': 65003, u'address': u'10.2.2.1'}))
ok: [leaf4] => (item=({u'router_id': u'192.168.0.4', u'as_number': 65004, u'networks': [u'192.168.0.4/32']}, {u'remote_as': 65102, u'address': u'10.2.3.2'}))
ok: [spine2] => (item=({u'router_id': u'192.168.1.2', u'as_number': 65102, u'networks': [u'192.168.1.2/32']}, {u'remote_as': 65004, u'address': u'10.2.3.1'}))

TASK [Prepare output] **********************************************************
...
TASK [Transform output] ********************************************************
ok: [spine2]
ok: [leaf2]
ok: [spine1]
ok: [leaf3]
ok: [leaf1]
ok: [leaf4]

TASK [Report switches with failed neighbors] ***********************************
skipping: [spine1] => (item=Peering to 10.1.0.1 is Established
)
skipping: [spine2] => (item=Peering to 10.2.0.1 is Established
)
skipping: [spine2] => (item=Peering to 10.2.1.1 is Established
)
skipping: [spine1] => (item=Peering to 10.1.1.1 is Established
)
skipping: [spine2] => (item=Peering to 10.2.2.1 is Established
)
skipping: [spine2] => (item=Peering to 10.2.3.1 is Established
)
skipping: [spine1] => (item=Peering to 10.1.2.1 is Established
)
skipping: [leaf1] => (item=Peering to 10.1.0.2 is Established
)
skipping: [leaf1] => (item=Peering to 10.2.0.2 is Established
)
skipping: [spine1] => (item=Peering to 10.1.3.1 is Established
)
skipping: [leaf2] => (item=Peering to 10.1.1.2 is Established
)
skipping: [leaf2] => (item=Peering to 10.2.1.2 is Established
)
skipping: [leaf3] => (item=Peering to 10.1.2.2 is Established
)
skipping: [leaf3] => (item=Peering to 10.2.2.2 is Established
)
skipping: [leaf4] => (item=Peering to 10.1.3.2 is Established
)
skipping: [leaf4] => (item=Peering to 10.2.3.2 is Established
)

PLAY RECAP *********************************************************************
leaf1                      : ok=3    changed=0    unreachable=0    failed=0
leaf2                      : ok=3    changed=0    unreachable=0    failed=0
leaf3                      : ok=3    changed=0    unreachable=0    failed=0
leaf4                      : ok=3    changed=0    unreachable=0    failed=0
spine1                     : ok=3    changed=0    unreachable=0    failed=0
spine2                     : ok=3    changed=0    unreachable=0    failed=0 

Všechno je v pořádku.

Životní cyklus sítě

Pojďme teď do sítě neobratně zasáhnout – připojíme se do jednoho z prvků a něco zkazíme, konkrétně nastavíme špatně AS number u neighbor.

$ docker exec -ti leaf1 vtysh
leaf1# conf t
leaf1(config)# router bgp 65001
leaf1(config-router)# neighbor 10.1.0.2 remote-as 65999
leaf1(config-router)# end
leaf1# exit

Otestujme znovu síť.

$ ansible-playbook -i hosts test-fabric.yml

PLAY [Configure hostname and interfaces] ***************************************

TASK [Report switches with failed neighbors] ***********************************
skipping: [spine2] => (item=Peering to 10.2.0.1 is Established
)
skipping: [spine2] => (item=Peering to 10.2.1.1 is Established
)
skipping: [leaf2] => (item=Peering to 10.1.1.2 is Established
)
skipping: [spine2] => (item=Peering to 10.2.2.1 is Established
)
skipping: [leaf2] => (item=Peering to 10.2.1.2 is Established
)
skipping: [spine2] => (item=Peering to 10.2.3.1 is Established
)
skipping: [leaf3] => (item=Peering to 10.1.2.2 is Established
)
failed: [spine1] (item=Peering to 10.1.0.1 is OpenSent
) => {"failed": true, "item": "Peering to 10.1.0.1 is OpenSent\n", "msg": "Peering to 10.1.0.1 is OpenSent\n"}
skipping: [leaf3] => (item=Peering to 10.2.2.2 is Established
)
skipping: [spine1] => (item=Peering to 10.1.1.1 is Established
)
skipping: [spine1] => (item=Peering to 10.1.2.1 is Established
)
skipping: [leaf4] => (item=Peering to 10.1.3.2 is Established
)
skipping: [spine1] => (item=Peering to 10.1.3.1 is Established
)
failed: [leaf1] (item=Peering to 10.1.0.2 is OpenSent
) => {"failed": true, "item": "Peering to 10.1.0.2 is OpenSent\n", "msg": "Peering to 10.1.0.2 is OpenSent\n"}
skipping: [leaf4] => (item=Peering to 10.2.3.2 is Established
)
skipping: [leaf1] => (item=Peering to 10.2.0.2 is Established
)

NO MORE HOSTS LEFT *************************************************************
	to retry, use: --limit @test-fabric.retry

PLAY RECAP *********************************************************************
leaf1                      : ok=3    changed=0    unreachable=0    failed=1
leaf2                      : ok=3    changed=0    unreachable=0    failed=0
leaf3                      : ok=3    changed=0    unreachable=0    failed=0
leaf4                      : ok=3    changed=0    unreachable=0    failed=0
spine1                     : ok=3    changed=0    unreachable=0    failed=1
spine2                     : ok=3    changed=0    unreachable=0    failed=0

Hmm, to není dobré. Spusťme tedy znova Playbook na vybudování fabric. Ansible má vlastnost idempotency, takže ho může spouštět kolikrát chceme bez ohledu na to, jaký je aktuální stav sítě. Ansible inteligentně zajistí dosažení požadovaného stavu.

Šetřeme místo a ukažme si jen příkaz na spuštění Playbooku.

$ ansible-playbook -i hosts build-fabric.yml

Síť se nám opravila. Můžete znovu zkusit test-fabric.yml Playbook, dopadne dobře (jen BGPku dejte nějaký čas).

Dnes jsme si ukázali jak s Ansible můžeme držet principy desired state. Je jedno do jakého stavu se síť dostane. Spuštěním Playbooku ji dostaneme vždy do stavu požadovaného (mimochodem asi vám to ušlo došlo takže ano – out-of-band management síť je téměř nutná a v datovém centru to beru jako zásadně dobrý nápad i pro tradiční ovládání). Také jsme si předvedli, že Ansible dokáže také testovat, že síť funguje. Příště to spojíme dohromady do Continuous Integration/Delivery.

Similar posts
  • Moderní 10G v datovém centru s novou ... HPE tento týden oznámilo evoluční vývoj portfolia v oblasti data center 1U prvků s 10G/40G/100G technologií, konkrétně novou řadu 5940. Co je nového? Hardwarové vlastnosti Prvky přichází s novou generací 10/40/100 čipů, které umožnily mít nově prvky se 100G uplinky (a to hned šesti) a také přináší podporou nových vlastností jako je směrování VXLAN (předchozí [...]
  • OpenSwitch v GNS3 – chcete GUI ... GNS3 verze 1.5 Pokud neznáte GNS3, jde o velmi dobrý síťový simulátor. Narozdíl od jiných řešení, o kterých jsem na netSvět už psal (Docker, shell skript, Mininet), je zaměřený především na síťaře, kteří chtějí pracovat s virtuální sítí a přizpůsobuje se jejich pohodlí. Do CI/CD pipeline se tedy moc nehodí, ale za to má výborné [...]
  • OpenSwitch a Ansible automatizace pra... Minule jsme napojili naši virtuální topologii na Ansible a spustili náš první testovací Playbook. Dnes provodeme automatizovanou konfiguraci L3 fabric a otestujeme síť. Příprava konfiguračních podkladů Pro zprovoznění L3 fabric potřebujeme Loopback adresu, IP adresy na jednotlivých spojeních mezi prvky a nastavení BGP (autonomní systémy, peering). V našem Ansible prostředí si vytvoříme jeden YAML soubor, [...]
  • OpenSwitch a Ansible automatizace pra... V minulém díle jsme si rozjeli Lead-Spine OpenSwitch topologii s využitím Dockeru a skript nám vygeneroval také hosts file pro Ansible. Dnes se vyzkoušíme napojení na Ansible 2.1. Příprava Ansible a vašeho VM První co potřebujeme udělat je nainstalovat Ansible minimálně ve verzi 2.1. Postup najdete zde: http://docs.ansible.com/ansible/intro_installation.html Dále vyřešíme nastavení SSH klienta v naší [...]
  • L3 a kontejnery bez overlay: Project ... Část 6 z celkových 6 v seriálu L3 a kontejnery bez overlay: Project Calico praktickyL3 a kontejnery bez overlay: Project Calico praktickyL3 a kontejnery bez overlay: Project Calico prakticky (1) – architekturaL3 a kontejnery bez overlay: Project Calico prakticky (2) – rozjezdL3 a kontejnery bez overlay: Project Calico prakticky (3) – BGPL3 a kontejnery bez [...]

No Comments Yet

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *