Learning DevOps
上QQ阅读APP看书,第一时间看更新

Using a dynamic inventory for Azure infrastructure

When configuring an infrastructure that is composed of several VMs, along with ephemeral environments that are built on demand, the observation often made is that maintaining a static inventory, as we saw in the Creating an inventory for targeting Ansible hosts section, can quickly become complicated and its maintenance takes a lot of time.

To overcome this problem, Ansible allows inventories to be obtained dynamically by calling a script (for example, in Python) that is either provided by cloud providers or a script that we can develop and that aims to return the contents of the inventory.

In this section, we will see the different steps to use Ansible to configure VMs in Azure using a dynamic inventory:

  1. The first step is to configure Ansible to be able to access Azure resources. For this, we will create an Azure Service Principal in Azure AD, exactly in the same way as we did for Terraform (see the Configuring Terraform for Azure section in Chapter 2, Provisioning Cloud Infrastructure with Terraform)Then, export the information of four service principal IDs to the following environment variables:
export AZURE_SUBSCRIPTION_ID=<subscription_id>
export AZURE_CLIENT_ID=<client ID>
export AZURE_SECRET=<client Secret>
export AZURE_TENANT=<tenant ID>
For more information on Azure environment variables for Ansible, refer to the Azure documentation here:  https://docs.microsoft.com/fr-fr/azure/virtual-machines/linux/ansible-install-configure#create-azure-credentials.
  1. Then, to be able to generate an inventory with groups and to filter VMs, it is necessary to add Tags to the VMs. Tags can be added using Terraform, an az cli command line, or an Azure PowerShell script.

Here are some examples of scripts with az cli:

az resource tag --tags role=webserver -n VM01 -g demoAnsible --resource-type "Microsoft.Compute/virtualMachines"

The preceding script adds a role tag of the webserver value to the VM, VM01. Then, we do the same operation with the VM02 VM (just change the value of the -n parameter to VM02 in the preceding script). 

The following screenshot shows the VM tag in the Azure portal:

And then, we add the tag on our VM that contains the database with this script:

az resource tag --tags role=database -n VM04 -g demoAnsible --resource-type "Microsoft.Compute/virtualMachines"

This script adds a role tag to VM04, which has the value database.

  1. To use a dynamic inventory in Azure, we need to do the following:

The following screenshot shows the content of the azure_rm.ini file in which the value of the group_by_tag property has been changed to yes:

A complete list of all dynamic inventory scripts for all cloud providers provided by Ansible can be found here:  https://github.com/ansible/ansible/tree/devel/contrib/inventory.
  1. As regards the inventory, we could very well stop there, but the problem is that we have to reconstitute an inventory that contains the same group of hosts as our original static inventory. To ensure that our dynamic inventory can be used by our playbook, we need to install nginx on all hosts in the webserver group and install MySQL on all hosts in the database group.

To have a dynamic inventory that contains our web server and database groups, we will, in our inventories folder, create a file called demo that will have the following content:

;init azure group to remove warning
[webserver:children]
role_webserver

[database:children]
role_database

[all:vars]
ansible_user=demobook11
ansible_password=xxxxxxx #if login to vm need password

The [webserver:children] code indicates that we are creating a webserver group that will be composed (as children) of other groups, and here it is the role_webserver group. This group is returned by the dynamic inventory script that returns all VMs that have the role tag with the webserver value.

This is how the dynamic inventory creates its groups with the tagname_value notation. It is exactly the same for the [database:children] group, which is composed of the role_database group; it will contain all of the VMs that have the role tag with the database value.

Finally, in the last part, we define the user name, which is the same for all VMs.

To summarize, here is the final content of our devopsansible working folder:

The complete source code of the inventories folder is available here:  https://github.com/PacktPublishing/Learning_DevOps/tree/master/CHAP03/devopsansible/inventories.
  1. After having set up all of the artifacts for our Ansible dynamic inventory in Azure, it is good to test its proper functioning, which includes the following:
    • That there are no execution errors.
    • The connection and authentication to our Azure environment are done correctly.
    • Its execution returns the Azure VMs from our infrastructure.
As mentioned in the  Technical requirements section, before running the following commands, we need to have the Azure Python SDK installed on the machine. Read the following link for more information:  https://azure.github.io/azure-sdk-for-python/.

To perform this test, the following command is executed:

ansible-inventory -i inventories/azure_rm.py --list

This command allows us to display as output the return of the inventory script in list format. The Python script returns the complete list of all VMs and their Azure properties in JSON format. Here is a small sample screen from this execution:

We can also display this inventory in graph mode by running the same command, but with the --graph option, as follows:

With the --graph option, we have a better visualization of the VMs according to their tags.

With the test being conclusive, we can proceed to the final step, which is the execution of Ansible with a dynamic inventory.

  1. Once we have tested our dynamic inventory in Azure, we just have to run Ansible on it, using the tags applied on the VMs. For this, we execute the first Ansible command with the --check option, which allows us to check that the playbook execution is based on the right VM groups:
ansible-playbook -i inventories/ playbook.yml --check --vault-password-file ~/.vault_pass.txt

As we see in this command, we used the inventories folder as an argument. The Ansible command will use all of its content (the Python script and its configuration as well as the inventory file) to obtain the list of hosts.

The following screenshot shows the execution of the check command:

This check shows us that the playbook will be executed on the right groups of VMs.

Let's now run our playbook with the same command, minus the --check option:

ansible-playbook -i inventories/ playbook.yml --vault-password-file ~/.vault_pass.txt

This screenshot shows the execution of the Ansible playbook with the dynamic inventory:

From now on, each time a VM of our Azure infrastructure has a role=webserver or role=database tag, it will be automatically taken into account by the dynamic inventory, and therefore, no code modification will be necessary.

In terms of another method to use a dynamic inventory on Azure, you can also consult the Azure documentation on the use of a dynamic inventory at https://docs.microsoft.com/fr-fr/azure/ansible/ansible-manage-azure-dynamic-inventories.

The use of a dynamic inventory, therefore, allows full advantage to be taken of the scalability of the cloud with an automatic VM configuration and without code change.

In this section, we have seen how to use a dynamic inventory for Azure with the implementation of its configuration and the necessary script recovery and finally, we have executed Ansible with this dynamic inventory.