Dig deeper into Ansible and F5 integration
Basics of Ansible and F5 integration were covered in a joint webinar held earlier in March 2017. To learn more about the integration and current F5 module support along with some use cases view the webinar .
We had another joint webinar in June 2017, which went into details on the integration. We spoke about how to F5 ansible modules (that will be part of upcoming Ansible 2.4 release) can be used to perfrom administrative tasks on the BIG-IP, make the BIG-IP ready for application deployment in weeks rather than in days. We also touched upon usage of F5 ansible iApps module to deploy applications on the BIG-IP.
The webinar's was very well received which ended with a great Q and A session. Some of the questions that came up were how do we create playbooks for different workflows, what are the best practices that F5 recommends, can we get a sample playbook etc. We will use this forum to answer some of the questions and dig deeper into the F5 and Ansible integration.
Now what really is a playbook, it is nothing but a collection of tasks that are to be performed sequentially on a system. Let us consider a use case where a customer has just purchased 20 BIG-IP’s and needs to get all of them networked and to a state where the BIG-IPs are ready to deploy applications. We can define a playbook which consists of tasks required to perform Day0 and Day1 configuration on the BIG-IPs.
Lets start with Day0, now networking the system consists of assigning it a NTP and DNS server address, assigning a hostname, making some ssh customizations etc., some of these settings are common to all the BIG-IPs. The common set of configurations can be defined using the concept of a ‘role’ in ansible. Let’s define a ‘onboarding’ role which will configure the common settings like NTP, DNS and SSHD settings.
PLAYBOOK FOR ONBOARDING
- name: Onboarding BIG-IP hosts: bigip gather_facts: false roles: - onboarding //playbook runs tasks defined in the ‘onboarding’ role
This play book will run against all the BIG-IP’s defined in the inventory host file
Example of inventory host file
[bigip] 10.192.73.218 10.192.73.219 10.192.73.220 10.192.73.221
The above playbook will run tasks specified in the 'onboarding' role in file main.yaml (playbooks/roles/onboarding/tasks/main.yaml)
- name: Configure NTP server on BIG-IP bigip_device_ntp: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" ntp_servers: "{{ ntp_servers }}" validate_certs: False delegate_to: localhost - name: Manage SSHD setting on BIG-IP bigip_device_sshd: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" banner: "enabled" banner_text: " {{ banner_text }}" validate_certs: False delegate_to: localhost - name: Manage BIG-IP DNS settings bigip_device_dns: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" name_servers: "{{ dns_servers }}" search: "{{ dns_search_domains }}" ip_version: "{{ ip_version }}" validate_certs: False delegate_to: localhost
Variables will be referenced from the main.yaml file under default directory for the ‘onboarding’ role (playbooks/roles/onboarding/default/main.yaml)
username: admin password: admin banner_text: "--------Welcome to Onboarding BIGIP----------" ntp_servers: - '172.27.1.1' - '172.27.1.2' dns_servers: - '8.8.8.8' - '4.4.4.4' dns_search_domains: - 'local' - 'localhost' ip_version: 4
The BIG-IP is now ready to deploy applications. One application is configuring the BIG-IP to securely load balance applications. This requires configuring the following on the BIG-IP
- Vlans
- Self-IPs
- Nodes/members (2)
- Pool (1)
- Assigning the nodes to the Pool
- Creating a HTTPS Virtual server
- Creating a redirect Virtual server, which will redirect all HTTP requests to the HTTPS virtual server (iRule is assigned to the virtual server to achieve this)
This playbook will be run individually for each BIG-IP since each will use different values for VLANS/Self IP’s/Virtual server address etc. The variables values for this playbook is defined inline and not in a separate file.
PLAYBOOK FOR APPLICATION DEPLOYMENT
- name: creating HTTPS application hosts: bigip tasks: - name: Configure VLANs on the BIG-IP bigip_vlan: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" validate_certs: False name: "{{ item.name }}" tag: "{{ item.tag }}" tagged_interface: "{{ item.interface }}" with_items: - name: 'External' tag: '10' interface: '1.1' - name: 'Internal tag: '11’ interface: '1.2' delegate_to: localhost - name: Configure SELF-IPs on the BIG-IP bigip_selfip: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" validate_certs: False name: "{{ item.name }}" address: "{{ item.address }}" netmask: "{{ item.netmask }}" vlan: "{{ item.vlan }}" allow_service: "{{item.allow_service}}" with_items: - name: 'External-SelfIP' address: '10.10.10.10' netmask: '255.255.255.0' vlan: 'External' allow_service: 'default' - name: 'Internal-SelfIP' address: '192.10.10.10' netmask: '255.255.255.0' vlan: 'Internal' allow_service: 'default' delegate_to: localhost - name: Create a web01.internal node //Creating Node1 bigip_node: server: "{{ inventory_hostname }}" user: "admin" password: "admin" host: "192.168.68.140" name: "web01.internal" validate_certs: False delegate_to: localhost - name: Create a web02.internal node //Creating Node2 bigip_node: server: "{{ inventory_hostname }}" user: "admin" password: "admin" host: "192.168.68.141" name: "web02.internal" validate_certs: False delegate_to: localhost - name: Create a web-pool //Creating a pool bigip_pool: server: "{{ inventory_hostname }}" user: "admin" password: "admin" lb_method: "ratio_member" monitors: http name: "web-pool" validate_certs: False delegate_to: localhost - name: Add http node to web-pool //Assigning members to a pool bigip_pool_member: description: "HTTP Webserver-1" host: "{{ item.host }}" name: "{{ item.name }}" user: "admin" password: "admin" pool: "web-pool" port: "80" server: "{{ inventory_hostname }}" validate_certs: False with_items: - host: "192.168.168.140" name: "web01.internal" - host: "192.168.68.141" name: "web02.internal" delegate_to: localhost - name: Create a virtual server //Create a HTTPS Virtual Server bigip_virtual_server: description: "Secure web application" server: "{{ inventory_hostname }}" user: "admin" password: "admin" name: "https_vs" destination: "10.10.20.120" port: 443 snat: "Automap" all_profiles: - http - clientssl pool: "web-pool" validate_certs: False delegate_to: localhost - name: Create a redirect virtual server //Create a redirect virtual server bigip_virtual_server: description: "Redirect Virtual server" server: "{{ inventory_hostname }}" user: "admin" password: "admin" name: "http_redirect" destination: "10.10.20.120" validate_certs: False port: 80 all_profiles: - http all_rules: //Attach an iRule to the Virtual server - _sys_https_redirect delegate_to: localhost
Bookmark this page if you are interested in learning more. We will be updating this blog with new F5 modules that are going to be supported with Ansible 2.4 release
- B_EarpAltocumulus
I cannot work out how many files are referenced here - would you be able to post the final config file(s)? It would make it much easier to understand. For me at least.
Could you add their locations at the top of the file so I could see how they all reference each other?
Thanks a lot...
- Payal_SRet. Employee
Sure I understand, I am using the concept of roles here which is Ansible best practice but it can get confusing.
To keep it simple have the variable file and the playbook in the same directory and then run the playbook ansible-playbook playbook-name.yaml
If your variable file name is say 'variable_file.yaml', then in your playbook you would reference the variable file as follows:
-
name: Onboarding BIG-IP hosts: bigip gather_facts: false vars_files:
- variable_file.yaml
..... .....
You can check out the following github as well for an example: https://github.com/payalsin/f5-ansible/blob/master/playbooks/onboarding-bigip.yml
Thanks
-
- B_EarpAltocumulus
Hi - thanks for that - so I followed your link and I think there are 2 files I need to download but I cannot be sure. I don't suppose you could upload the files with their locations hashed out at the top of the file so I can understand how they relate to each other? I tried to run the playbook but it says there is no password, and I looked at both the files and there is no password entry - so I am presuming there is a 3rd hidden file somewhere, but I am not sure what that is or how to reference it. Thanks :)
- Payal_SRet. Employee
Yes there is another file called the host file which needs to have information about the host you are trying to connect to.
"Ansible works against multiple systems in your infrastructure at the same time. It does this by selecting portions of systems listed in Ansible’s inventory, which defaults to being saved in the location /etc/ansible/hosts. You can specify a different inventory file using the -i option on the command line." - http://docs.ansible.com/ansible/latest/intro_inventory.html
Example of the host file for the above example:
[bigip]
[bigip:vars]
When the playbook is run it will look at the host file. As mentioned above default host file is placed at /etc/ansible/hosts BUT you can create your own host file as well and then reference that host file in your ansible.cfg.
Example of ansible.cfg
[defaults]
- __WIKKI___62134Nimbostratus
Hi Payal, I was looking at some Q&A in the ansible webinar, and found that there is a slack channel to discuss more devops related topic on F5.
It was mentioned f5-common-python.slack.com is the group that we can join. However I did not see any invitation link. Can you please let me know how to register for this slack group?
- B_EarpAltocumulus
Hi Payal. Still zero idea how all these files link together. I hate to sound like a broken record, but would you be able to put the name & path at the top of the file so we can see how they all link together, and also highlight any hidden files - I found a few the last time as you know - otherwise there is no way that you can tell how it works. :)
I am genuinely interested in following what you are putting down and have been hacking away at it for weeks, but because there is no way of understanding how all the files link together it is an impossible task.
I am sure that once we understand how the files all link together, and where the hidden files are that we can be up and running in no time!!
-
name: Onboarding BIG-IP
hosts: bigip
gather_facts: false
roles:
- onboarding //playbook runs tasks defined in the ‘onboarding’ role
[bigip] 10.192.73.218 10.192.73.219 10.192.73.220 10.192.73.221
-
name: Configure NTP server on BIG-IP bigip_device_ntp: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" ntp_servers: "{{ ntp_servers }}" validate_certs: False delegate_to: localhost
-
name: Manage SSHD setting on BIG-IP bigip_device_sshd: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" banner: "enabled" banner_text: " {{ banner_text }}" validate_certs: False delegate_to: localhost
-
name: Manage BIG-IP DNS settings bigip_device_dns: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" name_servers: "{{ dns_servers }}" search: "{{ dns_search_domains }}" ip_version: "{{ ip_version }}" validate_certs: False delegate_to: localhost
username: admin password: admin banner_text: "--------Welcome to Onboarding BIGIP----------" ntp_servers: - '172.27.1.1' - '172.27.1.2'
dns_servers: - '8.8.8.8' - '4.4.4.4' dns_search_domains: - 'local' - 'localhost' ip_version: 4
-
name: Onboarding BIG-IP
hosts: bigip
gather_facts: false
roles:
- Payal_SRet. Employee
Alright let's give this another try. Let's keep it real simple. Let's look at the three files to get this to work
1) The host file, which is be default placed at /etc/ansible/hosts (this file will have the IP Address of your bigip)
[bigip] 10.XX.XX.XX
2) The variable file is the same directory as your playbook, the values from this variable file will be substituted when the playbook is run
username: admin password: admin banner_text: "--------Welcome to Onboarding BIGIP----------" hostname: 'ansibleManaged-bigip.local' ntp_servers: - '172.27.1.1' - '172.27.1.2' dns_servers: - '8.8.8.8' - '4.4.4.4' dns_search_domains: - 'local' - 'localhost' ip_version: 4 bind_servers: - '192.168.2.1' - '192.168.2.2' vlan_information: - name: 'External' tag: '10' interface: '1.1' - name: 'Internal' tag: '11' interface: '1.2' selfip_information: - name: 'External-SelfIP' address: '10.168.68.5' netmask: '255.255.255.0' vlan: 'External' allow_service: 'default' - name: 'Internal-SelfIP' address: '192.168.68.5' netmask: '255.255.255.0' vlan: 'Internal' allow_service: 'default' module_provisioning: - name: 'asm' level: 'nominal'
3) The playbook
- name: Onboarding BIG-IP hosts: bigip gather_facts: false vars_files: - var-onboard-network_file.yml tasks: - name: Configure NTP server on BIG-IP bigip_device_ntp: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" ntp_servers: "{{ ntp_servers }}" validate_certs: False delegate_to: localhost - name: Configure BIG-IP hostname bigip_hostname: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" validate_certs: False hostname: "{{ hostname }}" delegate_to: localhost - name: Manage SSHD setting on BIG-IP bigip_device_sshd: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" banner: "enabled" banner_text: " {{ banner_text }}" validate_certs: False delegate_to: localhost - name: Manage BIG-IP DNS settings bigip_device_dns: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" name_servers: "{{ dns_servers }}" search: "{{ dns_search_domains }}" forwarders: "{{ bind_servers }}" ip_version: "{{ ip_version }}" validate_certs: False delegate_to: localhost - name: Provision BIG-IP with appropriate modules bigip_provision: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" validate_certs: False module: "{{ item.name }}" level: "{{ item.level }}" with_items: "{{ module_provisioning }}" tags: provision delegate_to: localhost - name: Configure VLANs on the BIG-IP bigip_vlan: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" validate_certs: False name: "{{ item.name }}" tag: "{{ item.tag }}" tagged_interface: "{{ item.interface }}" with_items: "{{ vlan_information }}" delegate_to: localhost - name: Configure SELF-IPs on the BIG-IP bigip_selfip: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" validate_certs: False name: "{{ item.name }}" address: "{{ item.address }}" netmask: "{{ item.netmask }}" vlan: "{{ item.vlan }}" allow_service: "{{item.allow_service}}" with_items: "{{ selfip_information }}" delegate_to: localhost
- B_EarpAltocumulus
Perfect - thanks very much!!!
So after editing /etc/ansible/hosts to include at the bottom:
[bigip] 10.XX.XX.XX [bigip:vars] username=admin password=admin
The second block of text is saved as var-onboard-network_file.yml, and the 3rd block of text is saved in the same folder as the var-onboard-network_file.yml file and is called whatever_you_like.yml
The playbook is then called by running: $ ansible-playbook whatever_you_like.yml
For other beginners, see: http://f5-ansible.readthedocs.io/en/devel/modules/list_of_all_modules.html for additional examples
So if we look at the bigip_selfip ansible command: http://f5-ansible.readthedocs.io/en/devel/modules/bigip_selfip_module.html
For this command there are some settings in the variables file, and some information in the playbook. The playbopok calls the items from the variables file.
bigip_selfip command in the playbook:
- name: Configure SELF-IPs on the BIG-IP bigip_selfip: server: "{{ inventory_hostname }}" user: "{{ username }}" password: "{{ password }}" validate_certs: False name: "{{ item.name }}" name item selected from variable file address: "{{ item.address }}" address item selected from variable file netmask: "{{ item.netmask }}" netmask item selected from variable file vlan: "{{ item.vlan }}" vlan item selected from variable file allow_service: "{{item.allow_service}}" allow_service item selected from variable file with_items: "{{ selfip_information }}" variable file items heading selection = selfip_information delegate_to: localhost
items in the variables file:
selfip_information: - name: 'External-SelfIP' address: '10.128.10.101' netmask: '255.255.255.0' vlan: 'External' allow_service: 'none' - name: 'Internal-SelfIP' address: '10.128.20.101' netmask: '255.255.255.0' vlan: 'Internal' allow_service: 'none' - name: 'HA-SelfIP' address: '1.1.1.1' netmask: '255.255.255.252' vlan: 'HA' allow_service: 'default'
So the ansible command bigip_selfip has multiple switches such as name, address, netmask. The values for these are called from the variables file by the playbook by using {{ item.XXX }} as the value. The values are under selfip_information heading in the var file. So taking a selction from the above config
Playbook: name: "{{ item.name }}" address: "{{ item.address }}" with_items: "{{ selfip_information }}"
Var file items: selfip_information: - name: 'External-SelfIP' equal to {{ item.name }} when called by the playbook address: '10.128.10.101' equal to {{ item.address }} when called by the playbook
And for some other of payal's awesome example playbooks and their associated var files
You also need an updated ansible and f5 and other python modules installed for it to work
-
Ubuntu - Install ansible $ sudo apt-get update $ sudo apt-get install software-properties-common $ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update $ sudo apt-get install ansible
-
Install pip $ sudo apt-get install pip then install the below $ pip install f5-sdk bigsuds netaddr deepdiff
-
- KernelPanicNimbostratus
What are the various software compatibility dependencies for getting ansible f5 to work?
- Payal_SRet. Employee
Recommended BIG-IP version is - 12+ Recommended Ansible version is - 2.4
On the Ansible host, the f5-sdk and bigsuds package will need to be installed - pip install f5-sdk - pip install bigsuds
More information on software dependency on a particular module that is under development, please check the specific module on our github repo: https://github.com/F5Networks/f5-ansible/tree/devel/library