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; password
, server
, 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 🙂