목차

  1. 테스트 구성
  2. Ansible 플레이북 디렉터리 구조 설정
  3. Ansible NX-OS 변수 개요
  4. Ansible 설정 파일 / 전역 변수 파일 생성
  5. Ansible 호스트 변수 및 역할 변수 파일 생성
  6. 스파인 역할 작업 파일 생성
  7. 리프 역할 작업 파일 생성
  8. Ansible 호스트 파일 생성
  9. 메인 Ansible 플레이북 생성
  10. Ansible 플레이북 실행
  11. 동작 확인

 

 

테스트 구성

이번 실습은 Ansible을 통해서 Cisco Nexus 장비에 설정을 배포하는 실습을 진행하겠습니다.

환경

 - 가상화 장비 (N9K-C9300v)

 - nxos 10.5.2.F

 

설정 범위

- Hostname

- loopback interface

- enable feature

- OSPF

- BGP

 

Ansible 플레이북 디렉터리 구조 설정

 

 

서버에 접속하여 Playbooks 디렉토리를 생성 -> 새로 생성된 Playbooks 디렉토리로 이동 -> NXOS 플레이북을 저장할 Ansible-NXOS라는 디렉토리를 생성하고 해당 디렉토리로 이동 -> group_vars, host_vars, roles 디렉토리 생성

mkdir Playbooks
cd Playbooks
mkdir Ansible-NXOS
cd Ansible-NXOS
mkdir group_vars
mkdir host_vars
mkdir roles

 

 

Ansible Galaxy를 사용하여 roles 디렉터리 내에 역할을 생성할 것입니다. Ansible Galaxy는 역할을 다운로드하거나 생성하기 위한 공식 커뮤니티 도구입니다.

cd roles
ansible-galaxy init spine
ansible-galaxy init leaf

 

 

리프 디렉터리와 스파인 디렉터리가 동일한 구조를 공유하는 것을 확인할 수 있습니다. 

`defaults`와 `vars` 디렉터리에는 tasks에서 사용할 변수들이 저장되고, 태스크 자체는 `tasks` 디렉터리 안에 저장됩니다.
디렉터리 아래에 ".yml" 파일이 있는 것을 볼 수 있습니다 플레이북은 YAML이라는 간단한 마크업 언어로 작성됩니다.

*명령어 "tree"

 

 

Ansible NX-OS 변수 개요

 

 

1) 기존 Ansible 네트워크 모듈인 nxos_config와 nxos_pim_rp_address

2) 변수와 변수 사용 방법.
각 네트워크 모듈에 대한 문서에는 모듈의 기능에 대한 개요와 매개변수 또는 키 표가 포함되어 있습니다. 표로 정리된 매개변수는 사용자가 모듈이 작업을 수행하는 데 필요한 필수 매개변수, 선택 사항 매개변수 및 매개변수의 기본값을 확인할 수 있도록 합니다.

위와 같은 형식이니 알고 넘어가면 좋습니다.

 

Ansible 설정 파일 / 전역 변수 파일 생성

 

 

Ansible 파일 생성을 위해 Ansible-NXOS 디랙토리로 이동합니다.

 

 

호스트 키 검사를 비활성화하는 ansible.cfg 파일을 생성하겠습니다.

touch ansible.cfg
cat <<EOF >> ansible.cfg
[defaults]
host_key_checking = False

EOF

 

 

모든 Node에 동일하게 적용할 내용을 all 파일로 관리합니다. ansible_connection과 nxos_provider에 대한 내용을 생성하겠습니다. 이 파일은 키/값 쌍으로 구성되며, group_vars/all은 모든 장치에 적용되는 범용 변수를 저장하는 위치입니다.

touch group_vars/all
cat <<EOF >> group_vars/all
---

ansible_connection: httpapi
ansible_httpapi_use_ssl: yes
ansible_httpapi_validate_certs: no
ansible_network_os: nxos
ansible_user: admin
ansible_httpapi_pass: admin
EOF

** ansible_connection: httpapi / ansible_httpapi_use_ssl: yes 두 명령어로 인해 SSH가 아닌 HTTPS로 통신

** Cisco 권장사항이 HTTPS를 통한 NX-API를 사용하는 것이기 때문에 api로 실습

 

Ansible 호스트 변수 및 역할 변수 파일 생성

 

 

각 역할에 대해 장치별로 사용할 변수와 해당 역할에 지정된 모든 장치에서 공통으로 사용할 변수를 생성해야 합니다. 장치별 변수는 각 장치의 `host_vars` 디렉터리에 정의됩니다. 

 

# 장치별 변수 생성

Spine1 yaml 파일

더보기

touch host_vars/10.202.32.111.yml
cat <<EOF >> host_vars/10.202.32.111.yml
---
# vars file for Spine1

router_id: 10.202.32.111

loopbacks:
  - { interface: loopback0, addr: 10.0.0.111, mask: 32 }
  - { interface: loopback1, addr: 1.1.1.1, mask: 32 }
EOF

Spine2 yaml 파일

더보기

touch host_vars/10.202.32.112.yml
cat <<EOF >> host_vars/10.202.32.112.yml
---
# vars file for Spine2

router_id: 10.202.32.112

loopbacks:
  - { interface: loopback0, addr: 10.0.0.112, mask: 32 }
  - { interface: loopback1, addr: 1.1.1.1, mask: 32 }
EOF

Leaf1 yaml 파일

더보기

touch host_vars/10.202.32.101.yml
cat <<EOF >> host_vars/10.202.32.101.yml
---
# vars file for Leaf1

router_id: 10.202.32.101

loopbacks:
  - { interface: loopback0, addr: 10.0.0.101, mask: 32 }
  - { interface: loopback1, addr: 2.2.2.1, mask: 32 }
EOF

Leaf2 yaml 파일

더보기

touch host_vars/10.202.32.102.yml
cat <<EOF >> host_vars/10.202.32.102.yml
---
# vars file for Leaf2

router_id: 10.202.32.102

loopbacks:
  - { interface: loopback0, addr: 10.0.0.102, mask: 32 }
  - { interface: loopback1, addr: 2.2.2.2, mask: 32 }
EOF

 

모든 장치에서 공통으로 사용할 변수는 각각 `roles/spine/vars/main.yml`과 `roles/leaf/vars/main.yml`에 정의

 

# 장치 역할 변수 생성

 

Ansible Spine 역할 변수 :

아래 YAML 코드를 Spine 역할 변수 디렉터리의 main.yml 파일로 생성.

이 변수들은 VXLAN, EVPN, OSPF, BGP, PIM와 같은 패브릭 공통 설정에 사용됩니다. 각 변수는 키/값 쌍으로 이루어진 딕셔너리이거나, 딕셔너리 목록을 포함하는 딕셔너리라는 점을 기억하세요.

Ansible Spine 역할 변수

더보기

touch roles/spine/vars/main.yml
cat <<EOF >> roles/spine/vars/main.yml

features:
  - { feature: bgp }
  - { feature: pim }
  - { feature: ospf }

ospf_process_id: UNDERLAY

ospf_area: 0

asn: 65001

address_families:
  - { afi: l2vpn, safi: evpn }

bgp_neighbors:
  - { remote_as: 65001, neighbor: 10.0.0.101, update_source: Loopback0 }
  - { remote_as: 65001, neighbor: 10.0.0.102, update_source: Loopback0 }

rp_address: 1.1.1.1
EOF

 

Ansible 리프 역할 변수 :

아래 YAML 파일을 리프 역할 변수 디렉터리의 main.yml 파일로 생성합니다.

 여기에 있는 변수들은 VXLAN, EVPN, OSPF, BGP, PIM, SVI, VRF와 특정 VNI에 매핑된 VLAN과 같은 VXLAN 매개변수 등 특정 기능에 사용됩니다. 각 변수는 키/값 쌍으로 이루어진 딕셔너리이거나, 딕셔너리 목록을 포함하는 딕셔너리라는 점을 기억하세요.

Ansible 리프 역할 변수

더보기

touch roles/leaf/vars/main.yml
cat <<EOF >>roles/leaf/vars/main.yml

features:
  - { feature: bgp }
  - { feature: interface-vlan }
  - { feature: ospf }
  - { feature: pim }
  - { feature: vnseg_vlan } 

ospf_process_id: UNDERLAY

ospf_area: 0

asn: 65001

address_families:
  - { afi: l2vpn, safi: evpn }
  - { afi: ipv4, safi: unicast }

bgp_neighbors:
  - { remote_as: 65001, neighbor: 10.0.0.111, update_source: Loopback0 }
  - { remote_as: 65001, neighbor: 10.0.0.112, update_source: Loopback0 }

rp_address: 1.1.1.1

vlans_l2vni:
  - { vlan_id: 11, vni_id: 10011, addr: 10.0.11.1, mask: 24, mcast_grp: 239.0.0.11, vrf: Tenant-1 }
  - { vlan_id: 12, vni_id: 10012, addr: 10.0.12.1, mask: 24, mcast_grp: 239.0.0.12, vrf: Tenant-1 }
  - { vlan_id: 13, vni_id: 10013, addr: 10.0.13.1, mask: 24, mcast_grp: 239.0.0.13, vrf: Tenant-1 }
  - { vlan_id: 14, vni_id: 10014, addr: 10.0.14.1, mask: 24, mcast_grp: 239.0.0.14, vrf: Tenant-1 }
  - { vlan_id: 15, vni_id: 10015, addr: 10.0.15.1, mask: 24, mcast_grp: 239.0.0.15, vrf: Tenant-1 }

vlans_l3vni:
  - { vlan_id: 10, vni_id: 10000, vrf: Tenant-1 }

vrfs:
  - { vrf: Tenant-1, vni_id: 10000, afi: ipv4, safi: unicast }
EOF

 

스파인 역할 작업 파일 생성

 

 

아래의 모든 작업을 수행하려면 roles/spine/tasks/에 있는 main.yml 파일을 편집해야 합니다.

시작 전 Ansible의 기능인 루프를 소개합니다. `loop`는 리스트를 순회하는 데 사용됩니다. roles/spine/vars/main.yml 파일에서 변수를 생성할 때, 많은 변수가 리스트로 구성했습니다.

`loop`를 사용하면 리스트를 순회하면서 `item.subkey`를 통해 해당 서브키 위치의 값을 참조하여 키(또는 서브키)를 처리할 수 있습니다.
tasks main.yml 파일을 작성하는 과정에서 타이핑을 줄이고 작업을 반복하기 위해 loop 함수를 자주 사용하게 될 것입니다.

 

아래의 nxos_interfaces 및 nxos_l3_interfaces 태스크를 roles/spine/tasks/main.yml 파일에 추가합니다. 이렇게 하면 host_vars에 정의된 루프백 변수를 사용하여 iBGP EVPN 피어링에 사용되는 루프백과 NVE 인터페이스의 소스를 각각 구성할 수 있습니다.

-   name: CONFIGURE LOOPBACK INTERFACES
    cisco.nxos.nxos_interfaces:
        config:
        -   name: "{{ item.interface }}"
            enabled: true
    loop: "{{ loopbacks }}"

-   name: CONFIGURE INTERFACE IP ADDR
    cisco.nxos.nxos_l3_interfaces:
        config:
        -   name: "{{ item.interface }}"
            ipv4:
            -   address: "{{ item.addr }}/{{ item.mask }}"
    loop: "{{ loopbacks }}"

아래의 nxos_ospf_vrf 및 nxos_ospf_interfaces 태스크를 roles/spine/tasks/main.yml 파일에 추가합니다. 이 태스크는 roles/spine/vars/main.yml에 있는 변수를 사용하며, 이전 태스크에서 생성한 루프백 인터페이스의 OSPF 인터페이스 매개변수를 Python에서 생성한 OSPF 프로세스로 구성하는 데 사용됩니다.

-   name: ASSOCIATE INTERFACES WITH OSPF PROCESS
    cisco.nxos.nxos_ospf_interfaces:
        config:
        -   name: "{{ item.interface }}"
            address_family:
            -   afi: ipv4
                processes:
                -   process_id: "{{ ospf_process_id }}"
                    area:
                        area_id: "{{ ospf_area }}"
    loop: "{{ loopbacks }}"

아래의 nxos_pim_interface 태스크를 roles/spine/tasks/main.yml 파일에 추가합니다. 이렇게 하면 host_vars에 정의된 루프백 변수를 사용하여 PIM 프로세스에 루프백을 구성할 수 있습니다.

-   name: CONFIGURE PIM INTERFACES
    cisco.nxos.nxos_pim_interface:
        interface: "{{ item.interface }}"
        sparse: true
    loop: "{{ loopbacks }}"

아래의 nxos_evpn_global, nxos_bgp_global, nxos_bgp_neighbor_address_family 태스크를 roles/spine/tasks/main.yml 파일에 추가합니다. 이 태스크들은 roles/spine/vars/main.yml에 정의된 BGP 변수를 사용하여 프로세스를 구성합니다.

-   name: ENABLE NV OVERLAY EVPN
    cisco.nxos.nxos_evpn_global:
        nv_overlay_evpn: true

-   name: CONFIGURE BGP ASN AND ROUTER ID
    cisco.nxos.nxos_bgp_global:
        config:
            as_number: "{{ asn }}"
            router_id: "{{ router_id }}"
            neighbors:
            -   neighbor_address: "{{ item.neighbor }}"
                remote_as: "{{ item.remote_as }}"
                update_source: "{{ item.update_source }}"
        state: merged
    loop: "{{ bgp_neighbors }}"

-   name: CONFIGURE BGP NEIGHBORS
    cisco.nxos.nxos_bgp_neighbor_address_family:
        config:
            as_number: "{{ asn }}"
            neighbors:
            -   neighbor_address: "{{ item.neighbor }}"
                address_family:
                -   afi: l2vpn
                    safi: evpn
                    send_community:
                        both: true
                    route_reflector_client: true
    loop: "{{ bgp_neighbors }}"

아래의 nxos_config 태스크를 roles/spine/tasks/main.yml 파일에 추가합니다. 이 태스크는 nxos_config 모듈의 save 매개변수를 사용하여 구성을 저장하는 데 사용됩니다.

-   name: SAVE RUN CONFIG TO STARTUP CONFIG
    cisco.nxos.nxos_config:
        save_when: always

통합 컨피그

더보기

[admin@localhost Ansible-NXOS]$ vi roles/spine/tasks/main.yml
---
#SPDX-License-Identifier: MIT-0
# tasks file for spine


-   name: ENABLE FEATURES
    cisco.nxos.nxos_feature:
        feature: "{{item.feature }}"
    loop: "{{ features }}"

-   name: ENABLE FEATURES
    cisco.nxos.nxos_config:
        lines: "feature nv overlay"

-   name: CONFIGURE LOOPBACK INTERFACES
    cisco.nxos.nxos_interfaces:
        config:
        -   name: "{{ item.interface }}"
            enabled: true
    loop: "{{ loopbacks }}"

-   name: CONFIGURE INTERFACE IP ADDR
    cisco.nxos.nxos_l3_interfaces:
        config:
        -   name: "{{ item.interface }}"
            ipv4:
            -   address: "{{ item.addr }}/{{ item.mask }}"
    loop: "{{ loopbacks }}"

-   name: ASSOCIATE INTERFACES WITH OSPF PROCESS
    cisco.nxos.nxos_ospf_interfaces:
        config:
        -   name: "{{ item.interface }}"
            address_family:
            -   afi: ipv4
                processes:
                -   process_id: "{{ ospf_process_id }}"
                    area:
                        area_id: "{{ ospf_area }}"
    loop: "{{ loopbacks }}"

-   name: CONFIGURE PIM INTERFACES
    cisco.nxos.nxos_pim_interface:
        interface: "{{ item.interface }}"
        sparse: true
    loop: "{{ loopbacks }}"

-   name: ENABLE NV OVERLAY EVPN
    cisco.nxos.nxos_evpn_global:
        nv_overlay_evpn: true

-   name: CONFIGURE BGP ASN AND ROUTER ID
    cisco.nxos.nxos_bgp_global:
        config:
            as_number: "{{ asn }}"
            router_id: "{{ router_id }}"
            neighbors:
            -   neighbor_address: "{{ item.neighbor }}"
                remote_as: "{{ item.remote_as }}"
                update_source: "{{ item.update_source }}"
        state: merged
    loop: "{{ bgp_neighbors }}"

-   name: CONFIGURE BGP NEIGHBORS
    cisco.nxos.nxos_bgp_neighbor_address_family:
        config:
            as_number: "{{ asn }}"
            neighbors:
            -   neighbor_address: "{{ item.neighbor }}"
                address_family:
                -   afi: l2vpn
                    safi: evpn
                    send_community:
                        both: true
                    route_reflector_client: true
    loop: "{{ bgp_neighbors }}"

-   name: SAVE RUN CONFIG TO STARTUP CONFIG
    cisco.nxos.nxos_config:
        save_when: always

[admin@localhost Ansible-NXOS]$

 

리프 역할 작업 파일 생성

 

 

스파인과 동일하게 roles/leaf/tasks/main.yml 파일을 수정하여 VLAN, VRF, VXLAN, EVPN 등과 설정을 생성합니다.

통합 컨피그

더보기

[admin@localhost Ansible-NXOS]$ vi roles/leaf/tasks/main.yml
---
#SPDX-License-Identifier: MIT-0
# tasks file for leaf

-   name: ENABLE FEATURES
    cisco.nxos.nxos_feature:
        feature: "{{item.feature }}"
    loop: "{{ features }}"

-   name: ENABLE FEATURES
    cisco.nxos.nxos_config:
        lines: "feature nv overlay"

-   name: CONFIGURE LOOPBACK INTERFACES
    cisco.nxos.nxos_interfaces:
        config:
        -   name: "{{ item.interface }}"
            enabled: true
    loop: "{{ loopbacks }}"

-   name: CONFIGURE INTERFACE IP ADDR
    cisco.nxos.nxos_l3_interfaces:
        config:
        -   name: "{{ item.interface }}"
            ipv4:
            -   address: "{{ item.addr }}/{{ item.mask }}"
    loop: "{{ loopbacks }}"

-   name: ASSOCIATE INTERFACES WITH OSPF PROCESS
    cisco.nxos.nxos_ospf_interfaces:
        config:
        -   name: "{{ item.interface }}"
            address_family:
            -   afi: ipv4
                processes:
                -   process_id: "{{ ospf_process_id }}"
                    area:
                        area_id: "{{ ospf_area }}"
    loop: "{{ loopbacks }}"

-   name: CONFIGURE PIM INTERFACES
    cisco.nxos.nxos_pim_interface:
        interface: "{{ item.interface }}"
        sparse: true
    loop: "{{ loopbacks }}"

-   name: ENABLE NV OVERLAY EVPN
    cisco.nxos.nxos_evpn_global:
        nv_overlay_evpn: true

-   name: CONFIGURE BGP ASN, ROUTER ID, AND NEIGHBORS
    cisco.nxos.nxos_bgp_global:
        config:
            as_number: "{{ asn }}"
            router_id: "{{ router_id }}"
            neighbors:
            -   neighbor_address: "{{ item.neighbor }}"
                remote_as: "{{ item.remote_as }}"
                update_source: "{{ item.update_source }}"
        state: merged
    loop: "{{ bgp_neighbors }}"

-   name: CONFIGURE BGP NEIGHBOR AFI, SAFI, COMMUNITY, and RR
    cisco.nxos.nxos_bgp_neighbor_address_family:
        config:
            as_number: "{{ asn }}"
            neighbors:
            -   neighbor_address: "{{ item.neighbor }}"
                address_family:
                -   afi: l2vpn
                    safi: evpn
                    send_community:
                        both: true
                    route_reflector_client: true
    loop: "{{ bgp_neighbors }}"

-   name: CONFIGURE VLAN TO VNI MAPPING
    cisco.nxos.nxos_vlans:
        config:
        -   vlan_id: "{{ item.vlan_id }}"
            mapped_vni: "{{ item.vni_id }}"
    with_items:
    - "{{ vlans_l2vni }}"
    - "{{ vlans_l3vni }}"

-   name: CONFIGURE TENANT VRFs
    cisco.nxos.nxos_vrf:
        vrf: "{{ item.vrf }}"
        vni: "{{ item.vni_id }}"
        rd: auto
        state: present
    loop: "{{ vrfs }}"

-   name: CONFIGURE TENANT VRFs (cont'd)
    cisco.nxos.nxos_vrf_af:
        vrf: "{{ item.vrf }}"
        afi: ipv4
        route_target_both_auto_evpn: true
        state: present
    loop: "{{ vrfs }}"

-   name: CONFIGURE VXLAN VTEP NVE INTERFACE
    cisco.nxos.nxos_interfaces:
        config:
        -   name: nve1
            enabled: true
        state: merged

-   name: CONFIGURE VXLAN VTEP NVE INTERFACE FOR EVPN CONTROL PLANE
    cisco.nxos.nxos_vxlan_vtep:
        interface: nve1
        host_reachability: true
        source_interface: Loopback1
        state: present

-   name: CONFIGURE VXLAN VTEP NVE INTERFACE L2VNI MAPPING
    cisco.nxos.nxos_vxlan_vtep_vni:
        interface: nve1
        vni: "{{ item.vni_id }}"
        #ingress_replication: bgp
        multicast_group: "{{ item.mcast_grp }}"
        #suppress_arp: true
    loop: "{{ vlans_l2vni }}"

-   name: CONFIGURE VXLAN VTEP NVE INTERFACE L3VNI MAPPING
    cisco.nxos.nxos_vxlan_vtep_vni:
        interface: nve1
        vni: "{{ item.vni_id }}"
        assoc_vrf: true
    loop: "{{ vlans_l3vni }}"

-   name: CONFIGURE L2 EVPN VRFs
    cisco.nxos.nxos_evpn_vni:
        vni: "{{ item.vni_id }}"
        route_distinguisher: auto
        route_target_both: auto
    loop: "{{ vlans_l2vni }}"

-   name: CONFIGURE TENANT VRFs UNDER BGP PROCESS
    cisco.nxos.nxos_bgp_address_family:
        config:
            as_number: "{{ asn }}"
            address_family:
            -   afi: "{{ item.afi }}"
                safi: "{{ item.safi }}"
                vrf: "{{ item.vrf }}"
                advertise_l2vpn_evpn: true
    loop: "{{ vrfs }}"

-   name: CONFIGURE ANYCAST GW MAC
    cisco.nxos.nxos_overlay_global:
        anycast_gateway_mac: "1234.5678.9000"

-   name: SAVE RUN CONFIG TO STARTUP CONFIG
    cisco.nxos.nxos_config:
        save_when: always

[admin@localhost Ansible-NXOS]$

 

 

Ansible 호스트 파일 생성

 

 

지금까지 Ansible 설치를 완료하고 플레이북 디랙토리를 설정하고 역할(Role), 작업(Task) 구성을 완료했습니다

이제 실제 자동화 배포를 수행하기 위한 마지막 단계로, VXLAN EVPN 패브릭 배포를 위해 Ansible이 관리할 대상 장비를 정의하는 호스트 파일(Inventory) 과 전체 실행 순서를 정의하는 메인 플레이북을 작성해야 합니다.

 

먼저 Ansible이 제어할 Nexus 스위치 정보를 등록하기 위한 호스트 파일을 생성해보겠습니다. 인벤토리 파일에는 Ansible이 관리할 장비(호스트) 목록을 정의합니다. 단순히 장비 목록만 나열할 수도 있으며, 대괄호([])를 사용해 그룹을 생성하고 장비를 그룹별로 분류할 수도 있습니다.

이러한 그룹 기능을 활용하면 Spine, Leaf, Server 등 역할별로 장비를 구분하여 관리할 수 있으며, 특정 그룹에 대해서만 플레이북을 실행하는 등 보다 효율적인 자동화가 가능합니다.

cat <<EOF >> hosts
# hosts file for Ansible playbook

[spine]
10.202.32.111
10.202.32.112

[leaf]
10.202.32.101
10.202.32.102

EOF

 

메인 Ansible 플레이북 생성

 

 

플레이북은 Ansible에서 자동화 작업을 정의하는 핵심 구성 요소로, 하나 이상의 장비에 대한 설정 및 운영 작업을 수행하는 플레이와 작업의 집합입니다. Ansible은 효율적인 관리와 재사용을 위해 역할(Role) 기반의 디렉터리 구조를 사용하는 것을 권장합니다.

cat <<EOF >> site.yml
---
# main playbook

- hosts: spine
  roles:
    - role: spine

- hosts: leaf
  roles:
    - role: leaf
EOF

 

Ansible 플레이북 실행

 

 

드디어 실행입니다. 실행 명령어는 ansible-playbook -i hosts site.yml -vvv 입니다.

-vvv 옵션으로 작업간 상세정보를 보여주는 옵션입니다

정상적으로 실행된 모습이다 ㅎ-ㅎ

사실 중간에 에러가 한번 발생했는데 마지막에 정리하고 다음으로 컨피그가 잘 적용 되었는지 확인해보겠습니다.

 

동작 확인

 

BGP 설정이 잘 들어간 모습

 

작업간 특이로그 없음

 

패킷 덤프 HTTPS로 암호화되어 통신되는 모습 (기본은 SSH 통신)

 

이슈사항

 

플레이북을 처음 실행 시켰을 때 아래 에러가 발생했습니다.

더보기

[admin@localhost Ansible-NXOS]$ ansible-playbook -i hosts site.yml -vvv

ansible-playbook [core 2.21.0]

  config file = /home/admin/Playbooks/Ansible-NXOS/ansible.cfg

  configured module search path = ['/home/admin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']

  ansible python module location = /usr/local/lib/python3.12/site-packages/ansible

  ansible collection location = /home/admin/.ansible/collections:/usr/share/ansible/collections

  executable location = /usr/local/bin/ansible-playbook

  python version = 3.12.13 (main, Apr 16 2026, 00:00:00) [GCC 14.3.1 20251022 (Red Hat 14.3.1-4)] (/usr/bin/python3)

  jinja version = 3.1.6

  pyyaml version = 6.0.1 (with libyaml v0.2.5)

Using /home/admin/Playbooks/Ansible-NXOS/ansible.cfg as config file

host_list declined parsing /home/admin/Playbooks/Ansible-NXOS/hosts as it did not pass its verify_file() method

script declined parsing /home/admin/Playbooks/Ansible-NXOS/hosts as it did not pass its verify_file() method

auto declined parsing /home/admin/Playbooks/Ansible-NXOS/hosts as it did not pass its verify_file() method

Parsed /home/admin/Playbooks/Ansible-NXOS/hosts inventory source with ini plugin

Skipping callback 'minimal', as we already have a stdout callback.

Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: site.yml ********************************************************************************************************************

2 plays in site.yml

PLAY [spine] **************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************

task path: /home/admin/Playbooks/Ansible-NXOS/site.yml:4

redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi

redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi

redirecting (type: httpapi) ansible.builtin.nxos to cisco.nxos.nxos

redirecting (type: httpapi) ansible.builtin.nxos to cisco.nxos.nxos

redirecting (type: modules) ansible.builtin.nxos_facts to cisco.nxos.nxos_facts

<10.202.32.111> ESTABLISH LOCAL CONNECTION FOR USER: admin

<10.202.32.111> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e `"&& mkdir "` echo /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.841656-26708-73467771251708 `" && echo ansible-tmp-1781670901.841656-26708-73467771251708="` echo /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.841656-26708-73467771251708 `" )'

redirecting (type: modules) ansible.builtin.nxos_facts to cisco.nxos.nxos_facts

<10.202.32.112> ESTABLISH LOCAL CONNECTION FOR USER: admin

<10.202.32.112> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e `"&& mkdir "` echo /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.8563075-26709-225276323680481 `" && echo ansible-tmp-1781670901.8563075-26709-225276323680481="` echo /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.8563075-26709-225276323680481 `" )'

redirecting (type: modules) ansible.builtin.nxos_facts to cisco.nxos.nxos_facts

redirecting (type: modules) ansible.builtin.nxos_facts to cisco.nxos.nxos_facts

Using module file /usr/local/lib/python3.12/site-packages/ansible_collections/cisco/nxos/plugins/modules/nxos_facts.py

<10.202.32.111> PUT /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/tmpuw8_5z6p TO /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.841656-26708-73467771251708/AnsiballZ_nxos_facts.py

<10.202.32.111> EXEC /bin/sh -c 'chmod u+rwx /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.841656-26708-73467771251708/ /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.841656-26708-73467771251708/AnsiballZ_nxos_facts.py'

Using module file /usr/local/lib/python3.12/site-packages/ansible_collections/cisco/nxos/plugins/modules/nxos_facts.py

<10.202.32.112> PUT /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/tmp124e0zc5 TO /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.8563075-26709-225276323680481/AnsiballZ_nxos_facts.py

<10.202.32.112> EXEC /bin/sh -c 'chmod u+rwx /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.8563075-26709-225276323680481/ /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.8563075-26709-225276323680481/AnsiballZ_nxos_facts.py'

<10.202.32.111> EXEC /bin/sh -c '/usr/bin/python3 /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.841656-26708-73467771251708/AnsiballZ_nxos_facts.py'

<10.202.32.112> EXEC /bin/sh -c '/usr/bin/python3 /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.8563075-26709-225276323680481/AnsiballZ_nxos_facts.py'

<10.202.32.112> EXEC /bin/sh -c 'rm -f -r /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.8563075-26709-225276323680481/ > /dev/null 2>&1'

[WARNING]: Deprecation warnings can be disabled by setting `deprecation_warnings=False` in ansible.cfg.

[DEPRECATION WARNING]: Importing 'to_text' from 'ansible.module_utils._text' is deprecated. This feature will be removed from ansible-core version 2.24. Use ansible.module_utils.common.text.converters instead.

[ERROR]: Task failed: Action failed: The following modules failed to execute: ansible.legacy.nxos_facts.

Task failed: Action failed.

<<< caused by >>>

The following modules failed to execute: ansible.legacy.nxos_facts.

+--[ Sub-Event 1 of 1 ]---

|

| Could not connect to https://10.202.32.112:443/ins: [Errno 111] 연결이 거부됨

|

+--[ End Sub-Event ]---

fatal: [10.202.32.112]: FAILED! => {

    "ansible_facts": {},

    "changed": false,

    "failed_modules": {

        "ansible.legacy.nxos_facts": {

            "changed": false,

            "deprecations": [

                {

                    "collection_name": "ansible.builtin",

                    "deprecator": {

                        "resolved_name": "ansible.builtin",

                        "type": null

                    },

                    "msg": "Importing 'to_text' from 'ansible.module_utils._text' is deprecated.",

                    "version": "2.24"

                }

            ],

            "exception": "(traceback unavailable)",

            "failed": true,

            "warnings": []

        }

    },

    "msg": "The following modules failed to execute: ansible.legacy.nxos_facts."

}

<10.202.32.111> EXEC /bin/sh -c 'rm -f -r /home/admin/.ansible/tmp/ansible-local-26703hyegwp_e/ansible-tmp-1781670901.841656-26708-73467771251708/ > /dev/null 2>&1'

[ERROR]: Task failed: Action failed: The following modules failed to execute: ansible.legacy.nxos_facts.

Task failed: Action failed.

<<< caused by >>>

The following modules failed to execute: ansible.legacy.nxos_facts.

+--[ Sub-Event 1 of 1 ]---

|

| Could not connect to https://10.202.32.111:443/ins: [Errno 111] 연결이 거부됨

|

+--[ End Sub-Event ]---

fatal: [10.202.32.111]: FAILED! => {

    "ansible_facts": {},

    "changed": false,

    "failed_modules": {

        "ansible.legacy.nxos_facts": {

            "changed": false,

            "deprecations": [

                {

                    "collection_name": "ansible.builtin",

                    "deprecator": {

                        "resolved_name": "ansible.builtin",

                        "type": null

                    },

                    "msg": "Importing 'to_text' from 'ansible.module_utils._text' is deprecated.",

                    "version": "2.24"

                }

            ],

            "exception": "(traceback unavailable)",

            "failed": true,

            "warnings": []

        }

    },

    "msg": "The following modules failed to execute: ansible.legacy.nxos_facts."

}

PLAY RECAP ****************************************************************************************************************************

10.202.32.111              : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

10.202.32.112              : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

[admin@localhost Ansible-NXOS]$

 

확인결과 Managed node. 즉, Leaf 스위치에서 nx-api기능이 비활성화 되어있어 TCP RST 메세지가 발생했었고 장비에 접속하여 기능을 활성화한 다음 실행하니 정상 동작했습니다.

 

 

이상입니다.

감사합니다.

+ Recent posts