Ansible
Config

Step 1 - YAML

Under the majority of the role directories you'll notice a ".yml" file. Playbooks are written in a very simple markup language called YAML, which stands for Yet Another Markup Language. YAML is used as it's even easier to read than data structure formats such as XML or JSON.

YAML files optionally begin with --- at the top of the file to signify the start of the file. Following the file start, comes the Ansible modules written in YAML syntax. YAML syntax for Ansible modules are expressed as a list of key/value pairs. Below you can see an example of YAML syntax that contains a list of dictionaries and where the dictionaries contain lists:


- name: CREATE ACI TENANT
  aci_tenant:
    tenant: "My_Tenant"
    descr: "This Tenant is for testing only"
    host: "x.x.x.x"
    username: "admin"
    password: "superpass"
    validate_certs: no

As you can see the first thing, we are doing is to introduce you is to an specific ansible module. In this case the aci_tenant is a ansible module . There are many ansible modules available and more added with each release. Keep the reference to the ACI documentation for Ansible saved. Also the link for modules is available. Just lick on the link and then click on content button.

Step 2 - Ansible Variables

An important key to any programing language is variables and Ansible is no different. If you would have had to create 100 tenants in an ACI fabric, you dont want to have to create 100 different YAML files with the configuration that we showed above. That makes no sense.

Ansible allows the placement of variables in the YAML file via what we know as templates. This template system is called Jinja Templates and is used in many aspects of Python, the core base of Ansible. This is how the syntax would be like for the example above:



- name: CREATE ACI TENANT
  aci_tenant:
    tenant: "{{ tenant_name }}"
    descr: "{{ descr }}"
    host: "{{ inventory_hostname }}"
    username: "{{ user }}"
    password: "{{ pass }}"
    validate_certs: no


Variables can be defined in various locations and Ansible has a precedence system for understanding what and when a variable would be overridden if used in more than one location. The precedence for a variable can be seen below. As an example, a variable in the role defaults directory would be overridden by a variable in the playbook global_vars/all directory and file. Further, both of these are overridden by the local vars directory within the specific role, role vars.

  • role defaults (defined in role/defaults/main.yml)
  • inventory file or script group vars
  • inventory group_vars/all
  • playbook group_vars/all
  • inventory group_vars/*
  • playbook group_vars/*
  • inventory file or script host vars
  • inventory host_vars/*
  • playbook host_vars/*
  • host facts
  • play vars
  • play vars_prompt
  • play vars_files
  • role vars (defined in role/vars/main.yml)
  • block vars (only for tasks in block)
  • task vars (only for the task)
  • role (and include_role) params
  • include params
  • include_vars
  • set_facts / registered vars
  • extra vars (always win precedence)

As an example, each of these network modules have basic requirements for arguments to access the device, albeit, some of these parameters may not apply to the network operating system you work with:

  • host - defines the hostname or IP address of the remote host
  • port - defines the port to connect to
  • username - defines the username to use to authenticate the connection
  • password - defines the password to use to authenticate the connection
  • transport - defines the type of connection transport to build
  • authorize - enables privilege escalation for devices that require it
  • auth_pass - defines the password, if needed, for privilege escalation

Step 3 - Edit variable file

You are now going to create a new file in the group_vars directory under the playbook/aci directory. You will be doing this in the Visual Studio Code (VSC) editor. Right click on the editor left pane where the group_vars directory is and then click on New File to create the all file in group_vars and populate the contents of the file for the ansible_connection, username, password, and protocol to be used in the ACI tasks. group_vars/all is where you place universal variables that apply for all devices.

This new file will be called all


---
ansible_connection: local
user: aciproglab04
pass: cisco.123

Ansible Role Variables

For each role you're now going to create variables to be used per device that are common across all devices specified within the role. The device specific variables can be defined under the host_vars directory for each device - which we will not be doing for this lab. The common variables to be used across all devices in the role will be defined under roles/apic/vars/main.yml.

Note

For this lab you are going to be leveraging a specific user that has write permissions for a specific tenant. For this reason we have created the Tenant for you. The ACI Tenant provides a user space domain for creating network elements and is controlled via RBAC.

You are going to edit a file that was created by Ansible Galaxy when you created your apic role. This file is called main.yml and is located in your directory here: ~/ltrdcn-3225/ansible/playbooks/aci/roles/apic/vars/main.yml. Navigate to this file in the left Explorer pane and double click the file to open it.

Inset the variables for your tenant, VRFs, and application profile after the # vars file for apic comment:



tenant: aciproglab04
vrf1: POD04_vrf_1
vrf2: POD04_vrf_2 
app_profile_name: POD04_APP

Ansible Tasks

The Ansible documentation for each network module provides a synopsis of what function the module performs and a table of parameters or keys. The tabulated parameters inform the user which parameters are required for the module to function as a task, which parameters are optional, and what the defaults are for parameters. There are many network modules that exist to configure Tenants, VRFs, BDs, APs, EPGs, Contracts, etc. Some of the modules that are available and the ones you will use today are the following:

  • aci_vrf
  • aci_bd
  • aci_ap
  • aci_epg

Cisco is commited to Ansible and continues to expand the library with new modules in the pursuit of having 100% correlation between the module and ACI capabilities. In a place where an Ansible module is not available, Cisco has developed a specific module that allows you to send specific ACI configuration objects into the fabric via the REST interface called aci_rest.

Step 4 - Create VRF and Bridge Domains tasks

In the editor find the file main.yml under the roles/apic/tasks directory and open it by double-clicking on it. You will be adding the following Ansible tasks using the beforementioned modules in YAML format after the # tasks file for apic comment. Pay attention to the line numbers as they should match with your editor.


- name: CREATE ACI TENANT VRF1
  aci_vrf: 
    vrf: "{{ vrf1 }}"
    state: present
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false

- name: CREATE ACI TENANT VRF2
  aci_vrf:
    vrf: "{{ vrf2 }}"
    state: present
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false  

- name: CREATE BRIDGE DOMAIN FOR DB
  aci_bd:
    bd: "database"
    description: 'POD04 Database Bridge Domain'
    state: present
    vrf: "{{ vrf1 }}"
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false  

- name: CREATE SUBNET FOR DB BRIDGE DOMAIN
  aci_bd_subnet:
    bd: "database"
    subnet_name: "POD04_subnet1"
    description: 'POD04 Subnet for Database Bridge Domain'
    gateway: "10.100.104.1"
    mask: 24
    scope: private
    state: present
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false

- name: CREATE BRIDGE DOMAIN FOR JAVA APP
  aci_bd:
    bd: "java_app"
    description: 'POD04 JAVA APP Bridge Domain'
    state: present
    vrf: "{{ vrf1 }}"
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false  

- name: CREATE SUBNET FOR JAVA APP BRIDGE DOMAIN 
  aci_bd_subnet:
    bd: "java_app"
    subnet_name: "POD04_bd2_subnet1"
    description: 'POD04 subnet for Java App Bridge Domain'
    gateway: "10.100.204.1"
    mask: 24
    scope: private
    state: present
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false

Step 5 - Create application profile and EPG taks

In the editor, under the same file you will be adding the following modules. You will need to hit the Enter (or Return) key after your line 82.


- name: Create ACI Tenant Application Profile
  aci_ap:
    ap: "POD04_APP"
    description: 'POD04 Application Profile'
    state: present
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false

- name: Create Database EPG
  aci_epg:
    ap: "POD04_APP"
    bd: "database"
    epg: "database"
    description: 'POD04 Database EPG'
    state: present
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false

- name: Create Java APP EPG
  aci_epg:
    ap: "POD04_APP"
    bd: "java_app"
    epg: "java_app"
    description: 'POD04 Java APP EPG'
    state: present
    tenant: "{{ tenant }}" 
    hostname: "{{ inventory_hostname }}" 
    username: "{{ user }}" 
    password: "{{ pass }}" 
    use_ssl: yes
    validate_certs: false

Ansible Host Files

Ansible refers to its host file as an inventory file. The inventory file has a default location in /etc/ansible/hosts, but can also be specified directly within a playbook locally and used with the -i hosts option, where hosts happens to be in the inventory file name. Within the inventory file, you can simply list all the devices/hosts or make use of group names using brackets which classifies devices you are controlling at what times and for what purpose.

Step 6 - Create Ansible Host File

The host file will be created in the location ~/ltrdcn-3225/ansible/playbooks/aci. Please goto this location and create the file hosts.


# hosts file for Ansible playbook
[apic]
10.0.226.41

Main Playbook

As previously mentioned, Ansible calls it's configuration and orchestration framework "playbooks" and is a collections of "play(s)" or tasks for configuration management and deployment to a device or multiple devices. While playbooks can be represented as a single file, Ansible best practices recommend a particular directory structure for playbooks that you built using roles for better organization and reuse. You built all of this over the last three sections. You now need to build the main playbook file, which would look like the below:

The below playbook file you will use for this lab designates the following behaviors, for each role ‘x’:

  • If roles/x/tasks/main.yml exists, tasks listed therein will be added to the play
  • If roles/x/handlers/main.yml exists, handlers listed therein will be added to the play
  • If roles/x/vars/main.yml exists, variables listed therein will be added to the play
  • If roles/x/defaults/main.yml exists, variables listed therein will be added to the play
  • If roles/x/meta/main.yml exists, any role dependencies listed therein will be added to the list of roles (1.3 and later)
  • Any copy, script, template or include tasks (in the role) can reference files in roles/x/{files,templates,tasks}/ (dir depends on task) without having to path them relatively or absolutely

Step 7 - Create main playbook

The host file will be created in the location ~/ltrdcn-3225/ansible/playbooks/aci. Please goto this location and create the file site.yml and add the following content.


---
# main playbook
- hosts: apic
  roles:
    - role: apic

Now we can proceed to execute the ansible playbooks.