Dynamic Azure Automation with Ansible

Recently I came across a requirement wherein we were supposed to do the end to end automation in Azure virtual machine. The requirement was to:

  1. Install and configure Virtual Machine: Installing and configuring Virtual Machine, Open specific ports and VM template.
  2. Install Mongo DB software and perform post install configurations: Installing Mongo DB and then configure it based on standard best practices. Restore Mongo DB Data ,create users and perform post install configurations.
  3. Install Tomcat and carry out the application specific configurations: Deploy Tomcat and configure manager and admin access. Perform application specific post install configurations.
  4. Install and configure application specific configurations :Deploy application binaries, change application files as per software requirements like URL etc.

Here is the step by step video demo and instructions.

1.Create a CentOS 8.X VM in Azure with Static IP address

First we need to create Azure VM and then install Ansible controller on the newly built VM.

2. Execute pre-installation tasks on the VM.

We need to execute pre-installation steps so we can install ansible :

     dnf update
     
     which python3
   
     alternatives --set python /usr/bin/python3
   
     python
    
     pip3 --version
   
     yum install python3-devel
    
    yum groupinstall 'development tools'
     
    pip3 install --upgrade pip
   
    pip3 --version

3.Installing Ansible on Virtual Machine for Azure Automation

We need to install ansible with PIp and when you use PIP for ansible installation you will not have the ansible.cfg file so you need to create this directory structure /etc/ansible/ and then copy the ansible.cfg from this link. https://github.com/ansible/ansible/blob/devel/examples/ansible.cfg once the cfg file content is copied we need to change the deprecation_warnings = False.

 
       pip3 install ansible[azure]

       ansible-galaxy collection install azure.azcollection
     
       ansible --version
     
       wget https://raw.githubusercontent.com/ansible-collections/azure/dev/requirements-azure.txt
      
       pip3 install -r requirements-azure.txt
      
       pip install msrestazure

       vi /etc/ansible/ansible.cfg
       #Update this value in the cfg file 
       deprecation_warnings = False

4.Create Azure Credentials to login to Azure via Ansible

Ansible uses the Azure service principle to execute the commands on azure. So we need to execute these commands in azure-CLI in (you can use Azure portal) to create the service principle.

Step1: az ad sp create-for-rbac –name ansible

The above comand will provide the app ID put the appid in the following command and execute it 

Step 2: az role assignment create –assignee <appID> –role Contributor

Step3: az account show –query ‘{tenantId:tenantId,subscriptionid:id}’;

Step4: Create Service principal secret as shown below:

Now populate the credential file with subscription, client_id,secret and tenant info retrieved from above sections. First we need to create the azure dirtectory in this path ~/.azure. then we need to create credential file.

       mkdir ~/.azure
       vi ~/.azure/credentials


#Now copy these settings into the credentials file

     [default]
     subscription_id=<your-subscription_id>
     client_id=<security-principal-appid>
     secret=<security-principal-password>
     tenant=<security-principal-tenant>

5.Creating Ansible Automation Playbook

We have used ansible playbooks to create the Azure Virtual Machine with service principle. The entire code can be accessed from the github repo: https://github.com/rajaniesh/dynamic-azure-automation

5.1 Deploy_vm_and_software Playbook.

This is main playbook which creates the azure vm and imports other playbooks provided below.This is main controller playbook.In this playbook we have populated azure vm specific variables and used them while creating the VM. We have used add host task in ansible to dynamically creating the in memory inventory since we do not know the IP address of the VM beforehand.

Once we have the IP address we can use that IP address to login to the VM and deploying the softwares via roles. I have created two roles:

  1. MongoDB deployment role
  2. Tomcat depoloyment role
- name: Create Azure VM
  hosts: localhost
  vars:
    FinalUrl: :8080/
    httpString: http://
    teamsMsg:
    ipaddressToSend:
    teamsMsgToSend:
    resource_group: rg_az_dynamic_automation
    azure_location: eastus
    vnet_name: azure_vnet
    address_prefix: "10.0.0.0/16"
    subnet_prefix: "10.0.1.0/24"
    public_ip_name: vm_public_ip
    nsg_name: az_NSG
    nic_name: az_NIC
    vm_name: azautomationvm
    username: azureuser
    password: Welcome@123456
    vm_offer_name: UbuntuServer
    vm_publisher_name: Canonical
    vm_sku_name: '18.04-LTS'
    size_of_vm: Standard_DS1_v2
  connection: local
  tasks:
  - name: Create resource group
    azure_rm_resourcegroup:
      name: "{{resource_group}}"
      location: "{{azure_location}}"
  - name: Create virtual network
    azure_rm_virtualnetwork:
      resource_group: "{{resource_group}}"
      name: "{{vnet_name}}"
      address_prefixes: "{{address_prefix}}"
  - name: Add subnet
    azure_rm_subnet:
      resource_group: "{{resource_group}}"
      name: default
      address_prefix: "{{subnet_prefix}}"
      virtual_network: "{{vnet_name}}"
  - name: Create public IP address
    azure_rm_publicipaddress:
      resource_group: "{{resource_group}}"
      allocation_method: Static
      name: "{{public_ip_name}}"
    register: output_ip_address
  - name: Dump public IP for VM which will be created
    debug:
      msg: "The public IP is {{ output_ip_address.state.ip_address }}."
  - name: Create Network Security Group that allows SSH
    azure_rm_securitygroup:
      resource_group: "{{resource_group}}"
      name: "{{nsg_name}}"
      rules:
        - name: SSH
          protocol: Tcp
          destination_port_range: 22
          access: Allow
          priority: 1001
          direction: Inbound
        - name: allow-tomcat
          protocol: Tcp
          destination_port_range: 8080
          access: Allow
          priority: 1002
          direction: Inbound
        - name: allow-MongoDB
          protocol: Tcp
          destination_port_range: 27017
          access: Allow
          priority: 1003
          direction: Inbound
  - name: Create virtual network interface card
    azure_rm_networkinterface:
      resource_group: "{{resource_group}}"
      name: "{{nic_name}}"
      virtual_network: "{{vnet_name}}"
      subnet: default
      public_ip_name: "{{public_ip_name}}"
      security_group: "{{nsg_name}}"
  - name: Create VM
    azure_rm_virtualmachine:
      resource_group: "{{resource_group}}"
      name: "{{vm_name}}"
      vm_size: "{{size_of_vm}}"
      admin_username: "{{username}}"
      admin_password: "{{password}}"
      network_interfaces: "{{nic_name}}"
      image:
        offer: "{{vm_offer_name}}"
        publisher: "{{vm_publisher_name}}"
        sku: "{{vm_sku_name}}"
        version: latest

  - name: add host
    add_host:
      name: vmServer
      ansible_ssh_host: "{{output_ip_address.state.ip_address}}"
      groups: vm
      ansible_connection: ssh
      ansible_ssh_pass: Welcome@123456

  - name: set teamsMsg
    set_fact:
      teamsMsg: "{{httpString + output_ip_address.state.ip_address + FinalUrl}}"

  - name: set ipaddressToSend
    set_fact:
      ipaddressToSend: "{{output_ip_address.state.ip_address}}"

  - name: Creating a vmtargetIPAddress.txt
    copy:
      dest: "/home/azureuser/vmtargetIPAddress.txt"
      content: |
        "{{ipaddressToSend}}"

- name: Import install_softwares.yml playbook
  import_playbook: install_softwares.yml

- name: Include WebHook playbook
  import_playbook: teams_webhooks.yml
  vars:
     teamsMsgToSend: "{{teamsMsg}}"

- name: Import Delete IP address
  import_playbook: deleteIPaddress.yml

5.2 DeleteIPaddress Playbook

DeleteIP address playbook is used to delete the ipaddress file. While creating the VM we are storing the IP address of the newly created VM in the text file and later on we are using this IP address to send the messages to the Teams web hook. Once the playbbok is executed we are deleting this file so when next time playbook runs it generates the new ip address instead of using the old ip address.

---
- name: Delete IP address file
  hosts: localhost
  tasks:

  - name: set address variable
    set_fact:
      address: "{{lookup('file', '/home/azureuser/vmtargetIPAddress.txt') }}"

  - name: update address variable
    set_fact:
      address: "{{address | replace('\"','') }}"

  - name: Display the Application URL
    debug:
     msg: " The sketch url is : http://{{address }}:8080"

  - name:  delete IPAddress file
    file:
      path: /home/azureuser/vmtargetIPAddress.txt
      state: absent

5.3 Install_softwares playbook

Install_softwares playbook is used to deploy MongoDB and Tomcat via ansible roles. Ansible provides the prewritten roles in ansible galaxy and you can use preexisting roles from ansible galaxy.

I have created two ansible roles to deploy the softwares:

  1. MongoDB deployment role
  2. Tomcat depoloyment role
---
- name: install Mongo and Tomcat
  hosts:  vm
  become: yes
  become_method: sudo       # Set become method
  remote_user: azureuser         # Update username for remote server

  vars:
    tomcat_ver: 9.0.30                          # Tomcat version to install
    ui_manager_user: manager                    # User who can access the UI manager section only
    ui_manager_pass: Str0ngManagerP@ssw3rd      # UI manager user password
    ui_admin_username: admin                    # User who can access bpth manager and admin UI sections
    ui_admin_pass: Str0ngAdminP@ssw3rd
    # UI admin password
  roles:
    - install_mongodb
    - install_tomcat

You can extend this code by adding your own software deployment logic.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.