top of page
Search
Brett Gianpetro

Netbox and Ansible, Redux

Historically we have adopted an approach to network automation with Netbox that favors a logic and templating layer in native Python and Ansible as a basic configuration pusher (see more details on this blog post). This methodology has its benefits, but a lot of situations favor (or even require) an Ansible-only approach. Something like this:




In order to determine if this approach was even feasible, we set out to create a POC with the following goals:


  • Build out enough configuration for a basic leaf/spine topology to have its connections IP'd, BGP sessions up, and Loopbacks originated

  • Where possible, use Ansible modules that are config abstractions and not raw config (e.g., eos_interfaces vs eos_config)


...and that's really it. We wanted to keep it simple because we knew from experience that getting the Ansible syntax right would be tricky (it's why we went to our native Python model in the first place).


Results

There are two primary components for the Ansible playbooks required to get this test off the ground: 1) the Netbox Lookup Queries and 2) the Arista EOS modules. After some extended tinkering we were able to get both functioning and get the POC completed. All of the code for this is available here. Below are a few notes.


Netbox Lookup Queries

One of the challenges we've had in the past with using Ansible is working with complex data structures. We've found it's difficult to look clean, readable, and intuitive. However, after some tinkering with the Ansible Netbox query, we were able to consistently pull the information we required. For example, in order to query all of the IP addresses associated with a device, we developed the following query:


dev_ips: "{{ query('netbox.netbox.nb_lookup', 'ip-addresses',
             api_endpoint=nb_api_endpoint,
             api_filter='device=' ~ inventory_hostname, 
             token=nb_api_token) }}"

The primary obstacle we ran into while crafting these queries was the sort of variable/template rendering inception that happens as a result of running an Ansible playbook. For example, can you spot which portions of that query are already defined as Ansible variables? If you guessed nb_api_endpoint, inventory_hostname, and nb_api_token you would be correct! But generally this doesn't seem terribly intuitive or readable. Perhaps there is a better way? If you know something, leave us a comment!


Ansible EOS Modules

Recent Ansible network modules have evolved beyond basic configuration pushers and have abstracted the device configuration away in favor of the module's parameters. This is a nice trend because it reinforces idempotency and consistency. For our use case we were using Arista EOS modules, but the same module types and methodology is consistent across all the network operating systems that have Ansible modules. For this POC we were using the eos_interfaces, eos_l3_interfaces, and eos_bgp_global modules. Building on our example above where we query Netbox for a device's IP addresses and assign it to a variable named "dev_ips", we use the following task to assign the IP addresses:


    
- name: Configure IP Addresses
  arista.eos.eos_l3_interfaces:
    config:
      - name: "{{ item.value.assigned_object.name }}"
        ipv4:
        - address: "{{ item.value.address }}"
  loop: "{{ dev_ips }}"
  loop_control:
    label: "{{inventory_hostname}}/{{item.value.assigned_object.name }}"

Essentially this loops through a device's IP addresses and then configures the IP using the assigned interface name.


Conclusion

Although this is a super basic topology and contrived use case, we believe this approach definitely has a lot of potential. Using Ansible alone instead of a custom Python layer could be significantly easier to deploy and manage, and using the native Ansible modules instead of raw configurations is definitely more in line with the Network as Code methodology. We will continue to evolve this example with more data and custom requirements and update you here on the blog. Thanks for reading!


151 views0 comments

Recent Posts

See All

Comments


bottom of page