Power Automation & Management of Infrastructure Using Ansible and Terraform

Overview of Ansible

Ansible is an automation tool widely used by many of the tech companies to automate apps and IT infrastructure. The whole story goes like Application Deployment + Configuration Management + Continuous Delivery. There are lot other tools used for the same purpose, some of the example are Chef, Puppet and Salt-Stack. How ansible differs from all of them is with the term being “Agent-less”. It means for a working ansible model you just have to be up and running with a fine working SSH connection between host and your ansible base machine. This is how it is being able to enable Infrastructure As Code.

$ ansible --version
[testmachines]
192.168.12.1 ansible_connection=ssh ansible_user=myuser
myVM ansible_port=5555

[prodservers]
VMone
VMtwo
ansible -i hosts all -m ping
---
- name: Telnet {{ hostname }}
ignore_errors: yes
expect:
timeout: 10
command: telnet 127.0.0.1 10896
responses:
"Escape character is": "\n"
"login:": "root"
"password: ": "admin123"
"# ":
- conf
- hostname {{ hostname }}
- exit
- save all
---
- hosts:
become: true
tasks:
- name: restart server
shell: sleep 2 && shutdown -r now
async: 1
poll: 0
ignore_errors: true
- name: waiting for the server to come back
local_action: wait_for host=testcentos state=started delay=3 timeout=300
---
- hosts:
become: true
tasks:
- name: Creating the User
user: name=testuser password=testuser123 groups=ansible shell=/bin/bash
- name: Removing the User
user: name=testuser state=absent remove=yes force=yes
$ ansible-playbook <name-of-playbook>.yml -i <host-file-path>
- name: Create Azure VM
hosts: localhost
connection: local
tasks:
- name: Create resource group
azure_rm_resourcegroup:
name: myResourceGroup
location: eastus
- name: Create virtual network
azure_rm_virtualnetwork:
resource_group: myResourceGroup
name: myVnet
address_prefixes: "10.0.0.0/16"
- name: Add subnet
azure_rm_subnet:
resource_group: myResourceGroup
name: mySubnet
address_prefix: "10.0.1.0/24"
virtual_network: myVnet
- name: Create public IP address
azure_rm_publicipaddress:
resource_group: myResourceGroup
allocation_method: Static
name: myPublicIP
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: myResourceGroup
name: myNetworkSecurityGroup
rules:
- name: SSH
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 1001
direction: Inbound
- name: Create virtual network interface card
azure_rm_networkinterface:
resource_group: myResourceGroup
name: myNIC
virtual_network: myVnet
subnet: mySubnet
public_ip_name: myPublicIP
security_group: myNetworkSecurityGroup
- name: Create VM
azure_rm_virtualmachine:
resource_group: myResourceGroup
name: myVM
vm_size: Standard_DS1_v2
admin_username: azureuser
ssh_password_enabled: false
ssh_public_keys:
- path: /home/azureuser/.ssh/authorized_keys
key_data: <your-key-data>
network_interfaces: myNIC
image:
offer: CentOS
publisher: OpenLogic
sku: '7.5'
version: latest

Overview of Terraform

Terraform is a famous open-source tool which uses the concept of Infrastructure As Code for the automation and provisioning of many cloud, Infrastructure or such services. It was developed by HashiCorp, it follows a Freemium business model. It delivers consistent workflows to provision, secure, connect, and run any infrastructure for any application.

# Create a new instance of the latest Ubuntu 20.04 on an
# t2.micro node with an AWS Tag naming it "HelloWorld"terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}# Configure the AWS Provider
provider "aws" {
region = "us-east-1"
}# Setting up the EC2 instace named as testingweb
resource "aws_instance" "testingweb" {
ami = "ami-0dba2cb6798deb6d8"
instance_type = "t2.micro"tags = {
Name = "HelloWorld"
}
}
  • provider “aws”, this is to set the service provider, you are using. So here we are setting up EC2, so we have write aws here.
  • resource “aws_instance” “testingweb” resource is to tell what service of AWS we are using, here we are using EC2 which is an AWS Instance so aws_instance would be hardcoded and testingweb is the name we have assign to it.
# Configure the Microsoft Azure Providerterraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>2.0"
}
}
}
# Configure the Microsoft Azure Providerprovider "azurerm" {
features {}
}
# refer to a resource group
data "azurerm_resource_group" "myterraformgroup" {
name = "testing-resource-group"
}
# Create virtual network
resource "azurerm_virtual_network" "myterraformnetwork" {
name = "myVnet"
address_space = ["10.0.0.0/16"]
location = "eastus"
resource_group_name = data.azurerm_resource_group.myterraformgroup.name
}
# Create subnet
resource "azurerm_subnet" "myterraformsubnet" {
name = "mySubnet"
resource_group_name = data.azurerm_resource_group.myterraformgroup.name
virtual_network_name = azurerm_virtual_network.myterraformnetwork.name
address_prefixes = ["10.0.1.0/24"]
}
# Create public IPs
resource "azurerm_public_ip" "myterraformpublicip" {
name = "myPublicIP"
location = "eastus"
resource_group_name = data.azurerm_resource_group.myterraformgroup.name
allocation_method = "Dynamic"
}
# Create network interface
resource "azurerm_network_interface" "myterraformnic" {
name = "myNIC"
location = "eastus"
resource_group_name = data.azurerm_resource_group.myterraformgroup.name
ip_configuration {
name = "myNicConfiguration"
subnet_id = azurerm_subnet.myterraformsubnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.myterraformpublicip.id
}
}
# Create Network Security Group and rule
resource "azurerm_network_security_group" "myterraformnsg" {
name = "myNetworkSecurityGroup"
location = "eastus"
resource_group_name = data.azurerm_resource_group.myterraformgroup.name
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
tags = {
environment = "Terraform Demo"
}
}
resource "azurerm_network_interface_security_group_association" "example" {
network_interface_id = azurerm_network_interface.myterraformnic.id
network_security_group_id = azurerm_network_security_group.myterraformnsg.id
}
# Create virtual machine
resource "azurerm_linux_virtual_machine" "myterraformvm" {
name = "myVM"
location = "eastus"
resource_group_name = data.azurerm_resource_group.myterraformgroup.name
network_interface_ids = [azurerm_network_interface.myterraformnic.id]
size = "Standard_B1s"
os_disk {
name = "myOsDisk"
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
disk_size_gb = "30"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
computer_name = "myvm"
admin_username = "azureuser"
disable_password_authentication = true
admin_ssh_key {
username = "azureuser"
public_key = file("")
}
tags = {
environment = "Terraform Demo"
}
}

Power of Unification of Ansible and Terraform

After seeing the power of both the tools, one can easily think of merging the usage of both of them in order to take automation to the next step. Just think of using Ansible with Terraform, It is a powerful combo that I use for provisioning cloud infrastructure and for setting up cloud instances.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Syed Saad Ahmed

Syed Saad Ahmed

Python, DevOps, Cryptography, Infra-Structure Automation. https://syedsaadahmed.com/