Ansible Playbook Optimizing

$ cat ansible.cfg 
hostfile = ./hosts
host_key_checking = False
timeout = 5 
log_path = ./logfile.txt
forks = 50
gathering = smart

pipelining = True

The above file shows the content of ansible.cfg file. I have added the following to make my playbook run faster:


Forks indicate the number of parallel processes spawned to communicate with remote hosts. Default forks is 5 in Ansible.

Gathering indicates the default policy for fact gathering. When “gather_facts” is True within the playbook, facts are gathered for each host. The facts associated with each host will be discovered only once even when the host is referred in multiple plays when we use “smart” within the ansible.cfg file.

Pipelining enabled will reduce the number of SSH operations required to execute a module on a remote host.

Ansible & Python 3

While using Ansible 2.2 and Python 3.x, I ran into the following error:

ERROR! Unexpected Exception: No module named 'urlparse'


1. Downgrade Python to 2.x

2. If there is no root level permission, use virtual env:

virtualenv --python=python2.7

iRule HTTP Referer

This is a simple iRule that performs redirects based on HTTP Referer:

if { ([HTTP::header exists "Referer"]) and 
    ([URI::host [HTTP::header value Referer]] eq"") } {
} else {

Ansible Components


Ansible is a simple IT automation tool. Ansible exists as CLI & GUI. GUI is called the Ansible Tower and Ansible, Inc., which is owned by RedHat, officially supports this.

Controlling Nodes:

The Network infrastructure is managed from these Controlling Nodes. In an Enterprise environment, Controlling Nodes are typically Linux bastion servers.

Managed Nodes:

Managed Nodes are the Network Devices that is being managed by the Controlling Nodes. Managed Nodes are typically of Cisco, Juniper, and Arista make and can be classified as Switches, Routers, Firewalls and Load Balancers based on their function from a Network Engineer’s perspective.


There are many automation tools like Chef, Puppet, and CFEngine but in my opinion, Ansible is suited for Network Automation for the following reasons:

  1. Ansible does not require an agent to be installed in the Managed Node (Network Device).
  2. Ansible requires Python on the Managed Node and most Network Devices support Python.
  3. Ansible relies on YAML as the descriptive language and Jinja2 for templates.

Among the points mentioned above, most Network Vendors do not support the installation of agents and even if they did support the installation, it would be tough to get the relevant permissions within an organization to install the agents in an Enterprise environment that has different Network Teams managing different aspects of the infrastructure.

Fortunately, most network vendors provide native support for Python and Ansible rely on this to execute automation tasks on the “Managed Nodes”.

As a Network Engineer working in an environment with significant scale (1,000s of Network Devices across multiple datacenters), Ansible has been quite useful in obtaining data and deploying configuration. Ansible seems to have widespread support among the Network Engineers seeking automation to manage at scale and there are resources online that can be leveraged to implement Network Automation Solutions.

Ansible Components

Ansible requires the following components in order to automate Network Infrastructure:

  • Controlling Nodes
  • Managed Nodes
  • Ansible Playbook

As noted earlier, Controlling Nodes are usually Linux Bastion Servers that are used to access the switches/routers and other Network Devices. These Network Devices are referred to as the Managed Nodes. Managed Nodes are stored in the hosts file for Ansible automation.

Ansible Playbook:

Ansible Playbooks are expressed in YAML format and serve as the repository for the various tasks that will be executed on the Managed Nodes (hosts). Playbooks are a collection of tasks that will be run on one or more hosts.

Setting up Ansible:

After installing Ansible, I recommend creating a separate directory from which Ansible is executed. For this process, let’s create a directory named “AnsiblePlay”. Within the “AnsiblePlay” directory, I will have the following files:

  • ansible.cfg
  • hosts

and the following directories ./AnsiblePlay/

  • templates
  • hosts_var

Ansible Configuration File:

An Ansible Playbook utilizes the Ansible Configuration File in order to access resources required for the Ansible Playbook. For example, the configuration file stores location information for the hosts file that contains the Managed Nodes (hosts) on which the playbook is executed.

Ansible Configuration File can exist in the following locations and is utilized by the Ansible playbook in the following order.

* ANSIBLE_CONFIG (an environment variable)
* ansible.cfg (in the current directory)
* .ansible.cfg (in the home directory)
* /etc/ansible/ansible.cfg

I would recommend creating your own Ansible configuration file in the Ansible directory. I use the following:

$ cat ansible.cfg

hostfile = ./hosts
timeout = 5

Inventory File or Hosts File:

Inventory File or Hosts File is a text file that contains the Managed Nodes (Hosts) that will be subjected to automation tasks defined in the playbook.

Inventory File can be static or dynamic. For now, the examples use static inventory files.

This is an inventory/host file example:

$ cat hosts



Lists: [ ]

Dictionaries: { }. Dictionary has “Key: Value” pair.

YAML – Anything is a string. Quoting strings is optional most of the times.


FACTS are data about the Managed Nodes. Example: Code Version running on Managed Node.


Ansible playbook contains one or more tasks. A task makes sure that the hosts exist in a specific state. When there are multiple tasks and if any task fails, subsequent tasks will not be executed.


Running a task once or multiple times is the same in terms of the final output. For example, a task that involves creating a user in the Managed Node will create the user only once no matter how many times the task is executed.


F5 Logs

F5 logs are available under /var/log/ directory.

If you are looking for LTM traffic related logs, look under  /var/log/ltm

If you are looking for GTM traffic related logs, look under /var/log/gtm

GTM has been renamed as DNS from 12.x code version.

The logs are rotated every 24 hours. There will be one ltm file that contains the latest logs and multiple ltm.gz files like: ltm.1.gz, ltm.2.gz etc. The ltm.1.gz files can be opened by using the following command: zcat ltm.1.gz

    (tmos)# run util bash
    ~# cd /var/log
    ~# cat ltm

Other such logs are outlined in this article – K16197

Kubernetes Intro

Kubernetes is Greek for Pilot or Helmsman. It is primarily used as an orchestration tool for containers.

Kubernetes Deployment (KD):

Deployment is responsible for creating and updating instances of application.

Kubernetes Master (KM):

KM schedule the application instances that was created by the KD onto individual nodes in the cluster.

Kubernetes Deployment Controller (KDC):

KDC monitors application instances and replaces an instance if the node hosting the instance goes down.

Kubernetes Pod (KP):

KP is a subset of KD. KP consists of one or more application containers and some shared resource for those containers. Shared resource can be shared storage or networking resource like IP address.

Kubernetes Node (KN):

KN is a physical or virtual machine that is managed by KM. Multiple Pods can exist in a Node. KN has the following:

  • kubelet: A process that ensures communication between KM and KN.
  • Container runtime like docker/rkt



Kubernetes Service (KS):

KS is an abstraction layer which defines a logical set of pods and enables external traffic exposure like load balancing. The set of pods can exist in one or more KN.



Labels are key-value pairs that are attached to objects such as pods. They are similar to hash-tags.



Integrated load balancing in KS enables scaling.


Rolling Updates:

Rolling updates allows incremental updates by replacing existing pods with new ones within a KS.

Reference: Kubernetes Basics. Images were taken from the link provided.

Thoughts on F5 Deployment

This is a simplified check list for GTM & LTM deployment based on my experience.

Don’t deploy GTM in HA pair in a single DC:

GTM devices work in a synchronization group across geographic regions. If you deploy GTM-1 in DC-1 and GTM-2 in DC-2, these 2 GTM devices will serve as Active-Active HA Pair for most deployments.

There is no reason to have GTM-1A & GTM-1B in DC-1 and GTM-2A & GTM-2B in DC-2, where the A & B devices are part of an HA pair. Option-B design is just an overkill.


GTM to LTM VS Health Monitors:

Let the LTM monitor its pool members. The GTM will obtain the status of the LTM pool members from the LTM. GTM directly monitoring the LTM pool members or LTM VS is not required in most cases.

Don’t deploy LTM in Active-Active state:

There is a lot of room for flexibility with this statement. I haven’t found the Active-Active pair to be reliable in production environment. Such deployments are rare in the industry and hence, if there are any bugs with Active-Active pair, there is a greater chance that your deployment could be affected by the software bug than the Active-Standby setting which is widely deployed and stable.

Code Upgrade Checklist:

  1. Check license reactivation date before code upgrade.
  2. Check to make sure that the code you are utilizing is not End of Support.
  3. Save the configuration on the box and outside the box whenever upgrading code.
  4. Save the license number on the box in a /var/tmp file and off the box.

Code Version:

You are better off picking one of the Long Term Stable code version releases as provided in this K5903.

Route Domains:

Route domains are F5’s version of VRF. Although they are easy to deploy, they can be a pain to troubleshoot with the “%” addition to IP address.

iRule Vs LTM Policy:

My personal preference is always iRule as it provides greater granular control and flexibility. However, LTM Policy may be better optimized and can provide lower latency for the same function. LTM Policy can be an effective substitute for simple iRules.

Pool & Pool Members:

As a rule of thumb, all the members in a pool should have the same port. For example: POOL_WEB_80. This naming convention tells you that this is a pool of web servers that are listening on port 80 even without looking into the individual pool members. Having multiple members listening on a common port as part of a single pool helps in the long run to scale the configuration without adding significant operational complexity.

Naming Convention:

While creating custom VS, Pool, Monitor etc, I recommend starting with capital letters. For example:


The default configuration elements like tcp, http monitor tends to be lower case in F5. The capital letters helps to distinguish between user-created (custom profiles) and default profiles which are all lower-case.

Custom & Default profiles:

NEVER use default configuration elements. Create custom configuration elements with the default configuration elements as parent profile.Whenever configuration change is required, always change only the custom profiles. This will prevent someone from accidentally changing the default profiles while working on the F5.

F5 TMM Crash

We were using a DNS VS listening on port 53 but configured to handle TCP protocol as shown here:

ltm virtual /Common/VS_DNS {
 destination /Common/
 ip-protocol tcp
 pool /Common/pool_dns
 profiles {
 /Common/tcp { }
 source-address-translation {
 pool /Common/SNAT-
 type snat
 translate-address enabled
 translate-port enabled

An iRule was using RESOLV::lookup against the configured TCP VS. RESOLV::lookup uses UDP requests and since the VS was configured to handle only TCP, the F5 crashed with core file generated.

According to F5 Engineers, bug alias 570575 is associated with this condition where RESOLV::lookup against a TCP Virtual Server causes the F5 to crash generating a core file in /var/core/

The workaround involved using “ip-protocol” as “any” and “profiles” as “fastL4” for a configuration that looks like this:

ltm virtual /Common/VS_DNS {
 destination /Common/
 ip-protocol any
 pool /Common/pool_dns
 profiles {
 /Common/fastL4 { }
 source-address-translation {
 pool /Common/SNAT-
 type snat
 translate-address enabled
 translate-port enabled


Cisco Nexus – Ping Sweep

The following script can be utilized to execute a ping sweep of a /24 network on Cisco Nexus switch. This has been tested and verified on Cisco Nexus 7K running 6.2.8a code version.

Actual script:

for {set i 1} {$i < 255} {incr i} {
cli "ping 192.168.1.$i count 2 time 1 vrf VRF_A"

Script execution on a Cisco Nexus 7000 switch:

N7K_SW1# tclsh
N7K_SW1-tcl# for {set i 1} {$i < 255} {incr i} {  
> cli "ping 192.168.1.$i count 2 time 1 vrf VRF_A"
> }