The Inside Playbook. Network functions in the new Ansible Engine 2.9

The Inside Playbook. Network functions in the new Ansible Engine 2.9

The upcoming release of Red Hat Ansible Engine 2.9 has some impressive improvements, some of which are described in this article. As always, we've been developing Ansible Network enhancements in the open with community support. Join - take a look at issue board on GitHub and study the development plan for release of Red Hat Ansible Engine 2.9 on the wiki page for Ansible Network.

As we recently announced, Red Hat Ansible Automation Platform now includes Ansible Tower, Ansible Engine, and all Ansible Network content. Now most of the popular networking platforms are implemented through Ansible modules. For example:

  • Arista EOS
  • Cisco IOS
  • Cisco IOS XR
  • Cisco NX-OS
  • Juniper Junos
  • VyOS

For a complete list of platforms that are fully supported by Red Hat through the Ansible Automation subscription, published here.

What have we learned

In the last four years, we have learned a lot about the development of a network automation platform. We also learned about How platform artifacts are used in playbooks and Ansible roles by end users. And here's what we found out:

  • Organizations are automating devices from not one, but many vendors.
  • Automation is not only a technical phenomenon, but also a cultural one.
  • Network automation at scale is more difficult than it looks because of the fundamental architectural design principles of automation.

When we discussed our long-term development plans over a year ago, our corporate clients asked for the following:

  • Fact gathering needs to be better standardized and aligned with the automation workflow for any device.
  • Updating configurations on the device also needs to be standardized and aligned so that Ansible modules handle the second half of the cycle after facts are gathered.
  • Strict and supported methods are needed to convert device configuration to structured data. On this basis, the source of truth can be moved from the network device.

Fact improvements

Gathering facts from network devices with Ansible often happens at random. Web platforms are equipped with fact-gathering capabilities to varying degrees, but they have little or no functionality for parsing and standardizing the representation of data in key-value pairs. Read post Ken Celenza on how difficult and painful it can be to analyze and standardize factual data.

You may have noticed how we worked on the Ansible Network Engine role. Naturally, 24k downloads later, the Network Engine role has quickly become one of the most popular Ansible roles in Ansible Galaxy for network automation scenarios. Before we ported a lot of this to Ansible 2.8 to prepare for what Ansible 2.9 will need, this Ansible role provided the first set of tools to help with command parsing, command management, and data collection for network devices.

If you're good at using Network Engine, this is a very efficient way to collect, parse, and standardize fact data for Ansible use. The disadvantage of this role is that you need to create a whole bunch of parsers for each platform and for all network activity. To understand how difficult it is to build, ship, and maintain parsers, take a look at 1200+ parsers from the guys from Cisco.

In a nutshell, getting facts from devices and normalizing them into key-value pairs is very important for large-scale automation, but this is difficult to achieve when you have many vendors and network platforms.

Every network fact module in Ansible 2.9 can now parse network device configuration and return structured data—without additional libraries, Ansible roles, or custom parsers.

Starting with Ansible 2.9, every time an updated network module is released, the fact module is improved to provide data about this configuration section. That is, the development of facts and modules now occurs at the same pace, and they will always have a common data structure.

The resource configuration on a network device can be retrieved and converted to structured data in two ways. In both ways, you can collect and transform a specific list of resources using a new keyword gather_network_resources. The resource names match the module names, which is very handy.

During fact gathering:

Using the keyword gather_facts it is possible to retrieve the current device configuration at the beginning of the playbook and then use it throughout the entire playbook. Specify the individual resources to retrieve from the device.

- hosts: arista
  module_defaults:
    eos_facts:
      gather_subset: min
      gather_network_resources:
      - interfaces
  gather_facts: True

You might have noticed something new in these examples, namely − gather_facts: true now available for native fact gathering for network devices.

Using the network facts module directly:

- name: collect interface configuration facts
  eos_facts:
    gather_subset: min
    gather_network_resources:
    - interfaces

The playbook returns the following facts about the interface:

ansible_facts:
   ansible_network_resources:
      interfaces:
      - enabled: true
        name: Ethernet1
        mtu: '1476'
      - enabled: true
        name: Loopback0
      - enabled: true
        name: Loopback1
      - enabled: true
        mtu: '1476'
        name: Tunnel0
      - enabled: true
        name: Ethernet1
      - enabled: true
        name: Tunnel1
      - enabled: true
        name: Ethernet1

Notice how Ansible retrieves the native configuration from the Arista device and converts it into structured data to use as standard key-value pairs for subsequent tasks and operations.

Interface facts can be added to Ansible stored variables and used immediately or later as input to a resource module eos_interfaces without further processing or transformation.

Resource Modules

So, we have extracted the facts, normalized the data, fit them into a standardized internal schema of the data structure, and we have a ready source of truth. Hooray! This is great, of course, but we still need to somehow convert the key-value pairs back to the specific configuration that the specific device platform expects. We now need platform-specific modules to meet these new fact-gathering and normalization requirements.

What is a resource module? You can think of device configuration sections as resources provided by that device. Network resource modules are intentionally limited to a single resource, and they can be stacked like bricks to set up complex network services. As a result, the requirements and specification for the resource module are naturally simplified because the resource module can read и configure a specific network service on a network device.

To explain what a resource module does, let's look at an example playbook that shows an idempotent operation using the new network resource facts and the module eos_l3_interface.

- name: example of facts being pushed right back to device.
  hosts: arista
  gather_facts: false
  tasks:
  - name: grab arista eos facts
    eos_facts:
      gather_subset: min
      gather_network_resources: l3_interfaces

  - name: ensure that the IP address information is accurate
    eos_l3_interfaces:
      config: "{{ ansible_network_resources['l3_interfaces'] }}"
      register: result

  - name: ensure config did not change
    assert:
      that: not result.changed

As you can see, the data collected from the device is transferred directly to the corresponding resource module without conversion. On startup, the playbook retrieves the values ​​from the device and compares them to what is expected. In this example, the values ​​returned are as expected (that is, configuration deviations are checked) and a message is displayed to indicate if the configuration has changed.

The ideal way to detect configuration deviation is to store the facts in Ansible stored variables and use them periodically along with the resource module in validation mode. This is a simple method to see if someone has changed the values ​​manually. In most cases, organizations allow manual changes and configuration, although many operations are performed through Ansible Automation.

How are the new resource modules different from the previous ones?

For the network automation engineer, there are 3 main differences between resource modules in Ansible 2.9 and previous versions.

1) For a specific network resource (which can also be thought of as a configuration section), modules and facts will evolve on all supported network operating systems at the same time. We think that if Ansible supports resource configuration on one network platform, we should support it everywhere. This simplifies the use of resource modules because a network automation engineer can now configure a resource (such as LLDP) on all network operating systems with native and supported modules.

2) Resource modules now include a state value.

  • merged: config merged with provided config (default);
  • replaced: the resource configuration will be replaced with the provided configuration;
  • overridden: the resource configuration will be replaced with the provided configuration; extra resource instances will be removed;
  • deleted: resource configuration will be deleted/restored by default.

The Inside Playbook. Network functions in the new Ansible Engine 2.9

3) Resource modules now include stable return values. When the network resource module has made (or proposed) the necessary changes to the network device, it returns the same key-value pairs to the playbook.

  • before: configuration on the device as structured data before the task;
  • after: if the device has changed (or may change if check mode is used), the resulting configuration will be returned as structured data;
  • commands: any configuration commands run on the device to bring it to the desired state.

The Inside Playbook. Network functions in the new Ansible Engine 2.9

The Inside Playbook. Network functions in the new Ansible Engine 2.9

What does all of this mean? Why is it important?

There are many complex concepts covered in this post, but we hope that in the end you will have a better understanding of what enterprise clients are asking for fact gathering, data normalization, and loop configuration for an automation platform. But why do they need these improvements? Many organizations are now engaged in digital transformation to make their IT environments more agile and competitive. For better or worse, many network engineers become network developers out of self-interest or at the behest of executives.

Organizations are realizing that automating individual network patterns does not solve the problem of silos and improves efficiency only up to a point. The Red Hat Ansible Automation Platform provides strong and normative resource data models to programmatically manage underlying data on a network device. That is, users are gradually moving away from individual configuration methods in favor of more modern methods with a focus on technologies (for example, IP addresses, VLANs, LLDP, etc.) and not on a specific vendor implementation.

Does this mean that the days of reliable and proven command and configuration modules are numbered? In no case. The expected network resource modules will not be applicable in all cases and not for every vendor, so the command and configuration modules will still be needed by network engineers for certain implementations. The purpose of resource modules is to simplify large Jinja templates and normalize raw device configurations into a structured JSON format. With resource modules, it will be easier for existing networks to translate their configuration into structured key-value pairs, which will provide a readable source of truth. By using structured key-value pairs, you can move from running configurations on each device to working with independent structured data and bring networks to the fore in an infrastructure-as-code approach.

What resource modules will appear in Ansible Engine 2.9?

Before we go into detail about what will happen in Ansible 2.9, let's remember how we divided the whole scope of work.

We have identified 7 categories and assigned certain network resources to each:

The Inside Playbook. Network functions in the new Ansible Engine 2.9

Note: Resources in bold were planned and implemented in Ansible 2.9.
Based on feedback from enterprise customers and the community, it was logical to first tackle those modules related to network topology protocols, virtualization, and interfaces.
The following resource modules are developed by the Ansible Network team and correspond to the platforms supported by Red Hat:

The Inside Playbook. Network functions in the new Ansible Engine 2.9

The following modules are developed by the Ansible community:

  • exos_lldp_global - from Extreme Networks.
  • nxos_bfd_interfaces - from Cisco
  • nxos_telemetry - from Cisco

As you can see, the concept of resource modules fits into our platform-focused strategy. That is, we include the necessary features and functions in Ansible itself to support standardization in the development of network modules, and also simplify the work of users at the level of roles and Ansible playbooks. To expand the development of resource modules, the Ansible team has released the Module Builder tool.

Plans for Ansible 2.10 and Beyond

After the release of Ansible 2.9, we will be working on the following set of resource modules for Ansible 2.10, which can be used to further configure network topology and policy, for example ACL, OSPF and BGP. The development plan can still be adjusted, so if you have comments, please let us know in Ansible Network community.

Resources and getting started

Ansible Automation Platform press release
Ansible Automation Blog
The Future of Content Delivery in Ansible
Reflections on changing the structure of an Ansible project

Source: habr.com

Add a comment