Technical Thursday – Azure resources with Ansible

In March I started a serie about Ansible. Now I would like to show you the first real code and solution how you can create Azure resources with Ansible. I know this is only the second part of the serie therefore I will show a simple and easy-to-understand example which can work in a live environment as well. Let’s start…

I hope you read the latest article and now you have a basic knowledge about Ansible.

Scenario

Our example for Today is a solution which creates the followings:

  • Resource Group
  • Virtual Network
  • FrontEnd subnet for Virtual Network
  • Network Security Group for FrontEnd subnet
  • Some Network Cards which connect to FrontEnd subnet

Simple but covers some real life requests. 🙂

Prepapare our Ansible computer

Before we start the real scripting we have to install some packages to our system. We will use the Ansible 2.5.x for our example.

Install packages for ansible

# update PIP on your computer
sudo pip install --upgrade pip

# Install/Update azure
sudo pip install azure --upgrade

# Install/Update msrestazure
sudo pip install msrestazure --upgrade 

# Install/update packaging
sudo pip install packaging --upgrade

# Install/Update cryptography
sudo pip install cryptography --upgrade

# Install/Update azure module for Ansible
sudo pip install ansible[azure] --upgrade

 

Access on Azure for Ansible

Here we create a Service Principal in Azurre and the credential file for Azure access.

Create Service Principal

  1. Login to Azure  (and set the default subscription)
    az cloud update
    
    az cloud set -n AzureCloud
     
    # Login with your account
    az login -u <your username>
     
    # Set the required subsctiption
    az account set --subscription <subscriptionID>
  2. Create the service principal for automation
    az ad sp create-for-rbac --name Automation_ResourceManager --query '{"client_id": appId, "secret": password, "tenant": tenant}'
  • Please write down and store in a secret place the “secret” because you cannot receive again from system anymore.
  • Required permission for this SP on subscription: Contributor
  • You have to be owner or co-administrator privileges on Azure to be able to create Service Principal
Make credential file

When you execute a playbook with Ansible it requires the Azure login data. For this we have to create a file.

# Create directory
mkdir ~/.azure

# Create the azure file for credential
vim ~/.azure/credentials

[default]
subscription_id=53455...
client_id=7f37...
secret=ft56...
tenant=987d...

 

Ansible solution

Ansible files

Regarding Ansible there are 2 very important group of files.

.
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   └── vms.yml
│   └── hosts
└── playbooks
    ├── azure_network.yml
    └── azure_vnet.yml
  1. Inventory files: Contain all parameters for our solution or Azure environment. (more information)
    1. hosts: this is the main file which contains the basic parameters and the basic groups. This is an INI-like file.
    2. all.yml: Contains the global variables for plays
    3. other yaml files which match with the group names in hosts file. These contains the group related information.
  2. Playbooks: Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want to enforce. (more information)

 

Create Inventory files

Create these files into inventory directory.

hosts

As you read above this is a INI-like file and this is the file where we will define the groups we would like to deploy in Azure.

  1. [vnet]: In our example we will deploy Virtual Network related resources (VNET, Subnet, NSG) therefore we have to put here a [vnet] group. Because all the information will be used later we can manage the Virtual Network parameters as global variables. (so we will define them later) Here we just put a vnet value which is a suffix for our Virtual Network name.
  2. [vms]: As I mentioned above we will deploy some NICs so this group name could be [nics] but in the near future I will show you a whole VM deployment so this group name is fine for us. In this group we define the name of VMs (which will be part of the NICs’ names) and the NICs related FrontEnd IPv4 addresses.

Here is our hosts file:

[vnet]
vnet

[vms]
cust-01 vm_fe_ip="79.0.0.11"
cust-02 vm_fe_ip="79.0.0.12"
cust-03 vm_fe_ip="79.0.0.13"
cust-04 vm_fe_ip="79.0.0.14"
group_vars/vms.yml

This file is a [vms] group specific file where we could define things for [vms] group related activities. In our example this is an empty file.

---

 

group_vars/all.yml

This is the file which contains the global variables for plays and playbooks. Therefore we will define here all global variables and the [vnet] group related parameters.

---
env_id: "the1bit"
location: "westeurope"
resource_group: "custom"
vnet_address_prefix: "79.0.0.0/23"
vnet_fe_subnet_address_prefix: "79.0.0.0/24"

 

Of course you can create some other files and variables…

 

Create Playbooks

And now we will create the playbooks for the different steps. For this scenario only file would be enough. Nevertheless on this way it will be easy to understand.

The parameters from inventory files will be used like in MVC app. I mean when you would like to use the location variable from all.yml you can do that on this way: "{{location}}"

Then if you would like to use a variable from hosts file from the first column (where there is no variable name) such as “cust-03” from [vms] group you can do this on this way: "{{inventory_hostname}}".

 

Create these files into playbooks directory.

azure_vnet.yml

This file contains the following creation steps:

  • Resource Group
  • Virtual Network
  • FrontEnd subnet for Virtual Network
  • Network Security Group for FrontEnd subnet
- name: Create VirtualNetwork
  hosts: vnet
  connection: local
  vars:
   rgName: "{{env_id}}-rg-{{resource_group}}"
   vnet_name: "{{env_id}}-{{inventory_hostname}}"
  tasks:
  - name: Create resource Group - {{env_id}}-rg-{{resource_group}}
    shell: az group create -n "{{rgName}}" --location "{{location}}"
  - name: Create virtual network - {{vnet_name}}
    azure_rm_virtualnetwork:
      resource_group: "{{rgName}}"
      name: "{{vnet_name}}"
      address_prefixes: "{{vnet_address_prefix}}"
  - name: Add FE subnet {{vnet_name}}-subnet-fe
    azure_rm_subnet:
      resource_group: "{{rgName}}"
      name: "{{vnet_name}}-subnet-fe"
      address_prefix: "{{vnet_fe_subnet_address_prefix}}"
      virtual_network: "{{vnet_name}}"
  - name: Create Network Security Group - FE - {{vnet_name}}-nsg-fe
    azure_rm_securitygroup:
      resource_group: "{{rgName}}"
      name: "{{vnet_name}}-nsg-fe"

Here we have some exciting sections:

  • hosts: name of group from hosts file
  • connection: where we would like to execute this play. We will do it on this machine, so we use local
  • vars: here you can create custom variables or create variables from concatenated variables
  • tasks: tasks in this play (we have 4 tasks in this play)
    • Create resource Group
    • Create virtual network
    • Add FE subnet
    • Create Network Security Group

 

azure_network.yml

This file contains the following creation steps:

  • Some Network Cards which connect to FrontEnd subnet (parallel)
- name: Create Network
  hosts: vms
  connection: local
  vars:
    rgName: "{{env_id}}-rg-{{resource_group}}"
    vnet_name: "{{env_id}}-vnet"
  tasks:
  - name: Create virtual network interface card - FE
    azure_rm_networkinterface:
      resource_group: "{{rgName}}"
      name: "{{env_id}}-{{inventory_hostname}}-nic-fe"
      virtual_network: "{{vnet_name}}"
      subnet: "{{vnet_name}}-subnet-fe"
      security_group: "{{vnet_name}}-nsg-fe"
      ip_configurations:
        - name: ipconfig1
          private_ip_allocation_method: Static
          private_ip_address: "{{vm_fe_ip}}"
          primary: true

Here we have some exciting sections:

  • hosts: name of group from hosts file
  • connection: where we would like to execute this play. We will do it on this machine, so we use local
  • vars: here you can create custom variables or create variables from concatenated variables
  • tasks: tasks in this play (we have 1 task in this play, but this task will be executed multiple times according to the number of lines in [vms] group in hosts file)
    • Create virtual network interface card for FrontEnd subnet

 

We are ready for execution.

 

Execute playbooks

Just only one step left: execute playbooks.

Please be sure you are out of inventory and playbooks directory. Then you have to execute the following commands

1. Create VNET related resources

ansible-playbook -i inventory/ playbooks/azure_vnet.yml

Where:

  • after -i you have to put the root directory of inventory files
  • then you put the path of vnet playbook

Result:

2. Create NETWORK related resources

ansible-playbook -i inventory/ playbooks/azure_network.yml

Where:

  • after -i you have to put the root directory of inventory files
  • then you put the path of network playbook

Result:

Final result in Azure:


As you can see with some simple configuration you can make some quite cool things. Nevertheless this is merely a fundamental for your future with Ansible.

You can find this and another exciting solutions for Ansible on my azansible Git repository.

Leave a comment