[Avg. reading time: 23 minutes]
Terraform
Features of Terraform
Infrastructure as Code: Terraform allows you to write, plan, and create infrastructure using configuration files. This makes infrastructure management automated, consistent, and easy to collaborate on.
Multi-Cloud Support: Terraform supports many cloud providers and on-premises environments, allowing you to manage resources across different platforms seamlessly.
State Management: Terraform keeps track of the current state of your infrastructure in a state file. This enables you to manage changes, plan updates, and maintain consistency in your infrastructure.
Resource Graph: Terraform builds a resource dependency graph that helps in efficiently creating or modifying resources in parallel, speeding up the provisioning process and ensuring dependencies are handled correctly.
Immutable Infrastructure: Terraform promotes the practice of immutable infrastructure, meaning that resources are replaced rather than updated directly. This ensures consistency and reduces configuration drift.
Execution Plan: Terraform provides an execution plan (terraform plan) that previews changes before they are applied, allowing you to understand and validate the impact of changes before implementing them.
Modules: Terraform supports reusability through modules, which are self-contained, reusable pieces of configuration that help you maintain best practices and reduce redundancy in your infrastructure code.
Community and Ecosystem: Terraform has a large open-source community and many providers and modules available through the Terraform Registry, which makes it easier to get started and integrate with various services.
Use Cases
- Multi-Cloud Provisioning
- Infrastructure Scaling
- Disaster Recovery
- Environment Management
- Compliance & Standardization
- CI/CD Pipelines
- Speed and Simplicity
- Team Collaboration
- Error Reduction
- Enhanced Security
Install Terraform CLI
<a href="https://developer.hashicorp.com/terraform/downloads"" title="" target="_blank">Terraform Download
Terraform Structure for Azure
Provider Block: Specifies Azure as the cloud provider and authentication method.
provider "azurerm" {
features {}
subscription_id = "your-subscription-id"
tenant_id = "your-tenant-id"
}
Resource Block: Defines Azure resources like VMs, Storage Accounts, or Virtual Networks.
resource "azurerm_virtual_machine" "example" {
name = "example-vm"
location = "East US"
resource_group_name = azurerm_resource_group.example.name
vm_size = "Standard_DS1_v2"
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
Data Block: Retrieves information about existing Azure resources.
data "azurerm_resource_group" "example" {
name = "existing-resource-group"
}
data "azurerm_virtual_network" "existing" {
name = "existing-vnet"
resource_group_name = data.azurerm_resource_group.example.name
}
Variable Block: Defines input variables for flexible configuration.
variable "location" {
description = "The Azure Region to deploy resources"
type = string
default = "East US"
}
variable "environment" {
description = "Environment name"
type = string
default = "dev"
}
Output Block: Returns values after applying the configuration.
output "vm_ip_address" {
value = azurerm_public_ip.example.ip_address
}
output "storage_account_primary_key" {
value = azurerm_storage_account.example.primary_access_key
sensitive = true
}
Module Block: Reusable components for Azure infrastructure.
module "vnet" {
source = "./modules/vnet"
resource_group_name = azurerm_resource_group.example.name
location = var.location
address_space = ["10.0.0.0/16"]
}
Locals Block: Local variables for repeated values.
locals {
common_tags = {
Environment = var.environment
Project = "MyProject"
Owner = "DevOps Team"
}
resource_prefix = "${var.environment}-${var.location}"
}
az login
Get the Subscription ID
Create a new folder
Copy the .tf into it
storage.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=4.4.0"
}
}
}
provider "azurerm" {
features{
}
subscription_id = "your subscription id"
}
# Create a resource group
resource "azurerm_resource_group" "example" {
name = "demo-resourcegroup-via-tf"
location = "East US"
tags = {
environment = "dev"
}
}
# Create a storage account
resource "azurerm_storage_account" "example" {
name = "chandr34demo"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
tags = {
environment = "dev"
}
}
terraform init
terraform validate
terraform plan
terraform apply
terraform destroy
Repeat the above steps to create Resource Group, Blob, ADLS, Containers
Remember to install Azure CLI.
az login
# Configure the Azure provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "= 4.4.0"
}
}
}
# Configure the Microsoft Azure Provider using CLI authentication
provider "azurerm" {
features {}
subscription_id = "your subscription id"
}
# Create a resource group
resource "azurerm_resource_group" "example" {
name = "gc-example-resources"
location = "East US"
tags = {
environment = "dev"
}
}
# Create a storage account with ADLS Gen2 enabled
resource "azurerm_storage_account" "adls" {
name = "chandr34adlsgen2"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
account_kind = "StorageV2" # Required for ADLS Gen2
is_hns_enabled = true # This enables hierarchical namespace for ADLS Gen2
tags = {
environment = "dev"
type = "data-lake"
}
}
# Create a storage account for Blob storage
resource "azurerm_storage_account" "blob" {
name = "chandr34blobstorage"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
account_kind = "StorageV2"
is_hns_enabled = false # Disabled for regular blob storage
# Enable blob-specific features
blob_properties {
versioning_enabled = true
last_access_time_enabled = true
container_delete_retention_policy {
days = 7
}
}
tags = {
environment = "dev"
type = "blob"
}
}
# Create a container in the blob storage account
resource "azurerm_storage_container" "blob_container" {
name = "myblobs"
storage_account_name = azurerm_storage_account.blob.name
container_access_type = "private"
}
# Create a filesystem in the ADLS Gen2 storage account
resource "azurerm_storage_data_lake_gen2_filesystem" "example" {
name = "myfilesystem"
storage_account_id = azurerm_storage_account.adls.id
}
Create a Linux VM with SSH Keys
Create a new folder and continue
vm_ssh.tf
# Provider configuration
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "= 4.4.0"
}
tls = {
source = "hashicorp/tls"
version = "~> 4.0"
}
local = {
source = "hashicorp/local"
version = "~> 2.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = "your subscription id"
}
# Generate SSH key
resource "tls_private_key" "ssh" {
algorithm = "RSA"
rsa_bits = 4096
}
# Save private key locally
resource "local_file" "private_key" {
content = tls_private_key.ssh.private_key_pem
filename = "vm_ssh_key.pem"
file_permission = "0600"
}
# Resource Group
resource "azurerm_resource_group" "rg" {
name = "ubuntu-vm-rg"
location = "eastus"
}
# Virtual Network
resource "azurerm_virtual_network" "vnet" {
name = "ubuntu-vm-vnet"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
address_space = ["10.0.0.0/16"]
}
# Subnet
resource "azurerm_subnet" "subnet" {
name = "ubuntu-vm-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}
# Public IP
resource "azurerm_public_ip" "pip" {
name = "ubuntu-vm-pip"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
allocation_method = "Static"
sku = "Standard"
}
# Network Security Group
resource "azurerm_network_security_group" "nsg" {
name = "ubuntu-vm-nsg"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
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 = "*"
}
}
# Network Interface
resource "azurerm_network_interface" "nic" {
name = "ubuntu-vm-nic"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.pip.id
}
}
# Connect the NSG to the subnet
resource "azurerm_subnet_network_security_group_association" "nsg_association" {
subnet_id = azurerm_subnet.subnet.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
# Virtual Machine
resource "azurerm_linux_virtual_machine" "vm" {
name = "ubuntu-vm"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_D2s_v3"
admin_username = "azureuser"
network_interface_ids = [
azurerm_network_interface.nic.id
]
admin_ssh_key {
username = "azureuser"
public_key = tls_private_key.ssh.public_key_openssh
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
}
# Outputs
output "public_ip_address" {
value = azurerm_public_ip.pip.ip_address
}
output "ssh_command" {
value = "ssh -i vm_ssh_key.pem azureuser@${azurerm_public_ip.pip.ip_address}"
}
output "tls_private_key" {
value = tls_private_key.ssh.private_key_pem
sensitive = true
}
ssh aazureuser@ip
Create a Linux VM with UserName and PWD
Create a new folder and continue
vm_pwd.tf
# Provider configuration
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "= 4.4.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = "your subscription id"
}
# Resource Group
resource "azurerm_resource_group" "rg" {
name = "ubuntu-vm-rg"
location = "eastus"
}
# Virtual Network
resource "azurerm_virtual_network" "vnet" {
name = "ubuntu-vm-vnet"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
address_space = ["10.0.0.0/16"]
}
# Subnet
resource "azurerm_subnet" "subnet" {
name = "ubuntu-vm-subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}
# Public IP
resource "azurerm_public_ip" "pip" {
name = "ubuntu-vm-pip"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
allocation_method = "Static"
sku = "Standard"
}
# Network Security Group
resource "azurerm_network_security_group" "nsg" {
name = "ubuntu-vm-nsg"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
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 = "*"
}
}
# Network Interface
resource "azurerm_network_interface" "nic" {
name = "ubuntu-vm-nic"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.pip.id
}
}
# Connect the NSG to the subnet
resource "azurerm_subnet_network_security_group_association" "nsg_association" {
subnet_id = azurerm_subnet.subnet.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
# Virtual Machine
resource "azurerm_linux_virtual_machine" "vm" {
name = "ubuntu-vm"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_D2s_v3"
admin_username = "azureuser"
admin_password = "H3ll0W0rld$"
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.nic.id
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
}
# Output the public IP
output "public_ip_address" {
value = azurerm_public_ip.pip.ip_address
}
````<span id='footer-class'>Ver 5.5.3</span>
<footer id="last-change">Last change: 2025-10-15</footer>````