F5 Ansible setup and playbook example

Introduction to F5 and Ansible automation

On this post we will describe how to automate the creation of F5 objects using Ansible. We will describe first the Ansible installation on a Linux Ubuntu system and then show you how to run a playbook. At Austral Tech our DevOps and F5 Specialists are experts automating stuff, so we wanted to share some of the magic with you :).

F5 users can automate and orchestrate using Ansible through a series of integrations with the F5 BIG-IP API-called modules. These modules leverage the full API support implemented on F5 BIG-IP hardware and virtual platforms.

Ansible F5 modules enable most common use cases, such as:

  • Automating the initial configurations on the BIG-IP like DNS, NTP etc.

  • Automation to Network the BIG-IP (VLANS, Self-Ips)

  • Automated deployment of HTTP and HTTPS applications

  • Managing Virtual-Servers, Pools, Monitors and other configuration objects

Ansible Installation

In case you still don’t have Ansible installed, we will describe the steps.

Log into the Ubuntu Server that will host Ansible and install the necessary repository with the commands:

sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update

Now you can proceed to the Ansible installation

sudo apt-get install ansible -y

Because Ansible requires a Python interpreter (in order to run its modules), we need to install Python as well. For that, issue the command:

sudo apt-get install python -y

Note: You may find Python already installed.

At this point, Ansible is installed and ready to go. You can verify it running:

 ansible --version

You should see an output like the following:

ansible 2.6.1
   config file = /etc/ansible/ansible.cfg
   configured module search path = [u'/home/nop/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
   ansible python module location = /usr/lib/python2.7/dist-packages/ansible
   executable location = /usr/bin/ansible
   python version = 2.7.14 (default, Sep 23 2017, 22:06:14) [GCC 7.2.0]

F5 Integration with Ansible

The latest Ansible versions include the necessary modules to work with F5 BIG-IP devices. The software compatibility matrix between BIG-IP devices and Ansible versions is shown below:

To check that the necessary Ansible modules for BIG-IP devices are indeed installed, run the following command:

 ansible-doc -l | grep bigip

You should see a long list of BIG-IP modules:

bigip_asm_policy                                     Manage BIG-IP ASM policies                                                                                                                        
bigip_command                                        Run arbitrary command on F5 devices                                                                                                               
bigip_config                                         Manage BIG-IP configuration sections                                                                                                              
bigip_configsync_action                              Perform different actions related to config-sync                                                                                                  
bigip_data_group                                     Manage data groups on a BIG-IP                                                                                                                    
bigip_device_connectivity                            Manages device IP configuration settings for HA on a BIG-IP                                                                                       
bigip_device_dns                                     Manage BIG-IP device DNS settings                                                                                                                 
bigip_device_group                                   Manage device groups on a BIG-IP                                                                                                                  
bigip_device_group_member                            Manages members in a device group                                                                                                                 
bigip_device_httpd                                   Manage HTTPD related settings on BIG-IP                                                                                                           
bigip_device_license                                 Manage license installation and activation on BIG-IP devices                                                                                      
bigip_device_ntp                                     Manage NTP servers on a BIG-IP                                                                                                                    
bigip_device_sshd                                    Manage the SSHD settings of a BIG-IP      
....


Installing python f5-sdk module

The integration between F5 and Ansible is a little different to the usual Ansible SSH integration. The way it works with F5 is that the BIG-IP devices expose their REST API and Ansible creates, deletes and modifies objects performing REST API calls, instead of running SSH commands locally on the F5. Because of this in order to have Ansible working with F5 BIG-IP you need to install the Python F5 SDK with this command:

sudo pip install f5-sdk

A successful installation will produce the following output:

Collecting f5-sdk
   Downloading https://files.pythonhosted.org/packages/77/d1/e7ae0356e83801349404333ca99babb42641e363dba536f695215c1bd55c/f5-sdk-3.0.21.tar.gz (156kB)
     100% |████████████████████████████████| 163kB 52kB/s 
 Collecting f5-icontrol-rest<2.0.0 (from f5-sdk)   Downloading https://files.pythonhosted.org/packages/e0/44/91979de0a81253d025a0814f16f53df46d3ed3edd5b9fd7181f28a9dd0bb/f5-icontrol-rest-1.3.13.tar.gz Requirement already satisfied: six<2.0.0 in /usr/lib/python2.7/dist-packages (from f5-sdk) Requirement already satisfied: requests<3,>=2.5.0 in /usr/local/lib/python2.7/dist-packages (from f5-icontrol-rest<2.0.0->f5-sdk)
 Installing collected packages: f5-icontrol-rest, f5-sdk
   Running setup.py install for f5-icontrol-rest … done
   Running setup.py install for f5-sdk … done
 Successfully installed f5-icontrol-rest-1.3.13 f5-sdk-3.0.21

The Ansible modules that we will use also requires to have the netaddr module installed, so proceed to install it with:

sudo pip install netaddr

A successful installation will produce the following output:

Collecting netaddr
   Downloading https://files.pythonhosted.org/packages/ba/97/ce14451a9fd7bdb5a397abf99b24a1a6bb7a1a440b019bebd2e9a0dbec74/netaddr-0.7.19-py2.py3-none-any.whl (1.6MB)
     100% |████████████████████████████████| 1.6MB 63kB/s 
 Installing collected packages: netaddr
 Successfully installed netaddr-0.7.19

It is important to note that you are installing these modules on the Linux machine where Ansible is running, you don’t install anything on the F5 devices themselves.

Now that we have the Ansible setup ready we will show you a playbook for creating F5 objects.

Running F5 BIG-IP playbook

For this post we are going to use the playbook from F5 Networks located at their git repository. We are going to analyse the playbook and explain what we are doing. We start with the first lines

---

- name: Create a VIP, pool and pool members
  hosts: all
  connection: local

This playbook will iterate over all hosts defined in our inventory. We only specified a single host (localhost) so that means that Ansible will connect to localhost to run the tasks.

For this simple example, we are not going to connect to the BIG-IP via our inventory information. For simplicity, we will be defining all that in the playbook itself.

connection: local is indicating Ansible that we will run the tasks locally. This can be confusing at first, but remember we are using the F5 REST API to connect to the F5 device. So when we say we run the playbook locally, it actually means, Ansible talks locally to the F5 SDK python module which sends the API REST calls to the F5 to perform the operations. The same thing applies to delegate_to keyword which you will see later in the playbook.

Set connection variables

As F5 Ansible modules communicate almost exclusively over the REST API of the F5 device, to facilitate a connection to the remote device, we need to specify these connection parameters.

The pattern we use for this is called a provider. You will typically see us define this with an Ansible fact called provider. Let’s see this below.

vars:
  provider:
    password: admin
    server: 1.1.1.1
    user: admin
    validate_certs: no
    server_port: 443

The above defines a new fact called provider. That fact is known as a dictionary and it itself includes some sub-keys; passwordserver, etc. You will need to change these parameters (user, password and server) with the information to connect to your F5 BIG-IP device.

The values of those sub-keys are variables (identifiable by their use of {{ and }}).

In the remaining tasks, you will see how the provider itself is passed to the task so that it can connect to the BIG-IP.

Add a pool

A pool represents a collection of resources. These resource typically deliver a service that is identical. By assigning them to a pool, the BIG-IP is able to distribute requests among them.

tasks:
  - name: Create a pool
    bigip_pool:
      provider: "{{ provider }}"
      lb_method: ratio-member
      name: web
      slow_ramp_time: 120
    delegate_to: localhost

If you have look at the playbook closely you may have noted the reserved word ‘delegate_to‘. ‘delegate_to’ runs the module locally. It must be used with F5 modules. Without it, the module will try to run on the BIG-IP and will fail. This is because none of the supporting python modules exist on the BIG-IP.

Add two pool members

Now you want to create the pool members in your BIG-IP configuration. Members represent where the traffic coming through a virtual server will eventually land. They could be physical gear, VMs, or other devices.

- name: Add members to pool
  bigip_pool_member:
    provider: "{{ provider }}"
    description: "webserver {{ item.name }}"
    host: "{{ item.host }}"
    name: "{{ item.name }}"
    pool: web
    port: 80
  with_items:
    - host: 10.10.10.10
      name: web01
    - host: 10.10.10.20
      name: web02
  delegate_to: localhost

Add a virtual server

Now that you created your pool and the nodes are members of that pool, you want to create a virtual IP address so that external requests go to the pool members.

The following example uses 172.16.10.108 as the external address, so you likely need to change it for your own environment.

- name: Create a VIP
  bigip_virtual_server:
    provider: "{{ provider }}"
    description: foo-vip
    destination: 172.16.10.108
    name: vip-1
    pool: web
    port: 80
    snat: Automap
    profiles:
      - http
      - clientssl
  delegate_to: localhost


Running F5 BIG-IP playbook

Now that we have Ansible and the required modules installed and we have the playbook ready, we can finally proceed to create a pool, add two members to that pool, and assign a virtual server to serve requests to the members in the pool.

The information to connect to the BIG-IP device is in the playbook file itself, so for inventory we are just going to create an inventory file with the following data:

localhost

And we can finally run the playbook with the command

ansible-playbook -i inventory playbook.yaml

Which should produce the following output:

PLAY [Create a VIP, pool and pool members] *****************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create a pool] ***************************************************************************************************************************************************************************************
changed: [localhost -> localhost]

TASK [Add members to pool] *********************************************************************************************************************************************************************************
changed: [localhost -> localhost] => (item={u'host': u'10.10.10.10', u'name': u'web01'})
changed: [localhost -> localhost] => (item={u'host': u'10.10.10.20', u'name': u'web02'})

TASK [Create a VIP] ****************************************************************************************************************************************************************************************
changed: [localhost -> localhost]

PLAY RECAP *************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=3    unreachable=0    failed=0 

After the playbook have run, you should be able to see the Virtual Server, pool and associate pool members on the F5 GUI

So that concludes our introduction to F5 and Ansible automation. We hope it helps you on your automation endeavours 🙂