1) Why Terraform?
Read article Infrastructure As Code (IaC)
2) What is terraform state?
Terraform state refers to a persistent data store that Terraform uses to keep track of the infrastructure resources it create and manages
3) Where and how this terraform state exists ?
Terraform state (resource information) is stored in a physical file in JSON format and it usually referred as state file (terraform.tfstate) and its by default stored in the same directory where you run
Terraform
4) Is it always mandatory to store it along with Terraform directory?
No, it can be stored remotely. Example, it can be stored in cloud storage like Azure blob storage, AWS S3 or HashiCorp workspace
5) What is the major benefit of storing the state file remotely?
For better collaboration, security and reliability. Example, when multiple team members are working on the same Terraform script there are more changes of concurrent modifications and in this scenario storing state file remotely will resolve this problem by locking and releasing while update by a team member
6) How to install Terraform in my local to start work on it?
You can download it from official HashiCorp portal by following simple steps Install Terraform
7) Can you give some important Terraform ?
terraform init :
Initializes the working directory containing Terraform configuration files.
terraform plan :
Compares the current state with the desired state defined in the configuration files and generates an execution plan.
terraform apply :
Applies the changes required to reach the desired state.
terraform refresh
: Updates the state file with the real-world state of resources.
terraform state :
Commands for advanced state management, such as listing resources (terraform state list), showing details (terraform state show), moving resources (terraform state mv),
and removing resources (terraform state rm)
terraform destroy
: Delete mentioned managed resources through Terraform script
8) Please detail Terraform script file structure by creating a simple Virtual Machine (VM) in Azure ?
Sure, I will try to provide it in a pictorial way for ease understanding
9) Can you provide me the content of each file given in your above example ?
backend.tf
terraform {
backend "azurerm" {
resource_group_name = "terraformTestVM"
storage_account_name = "myterraformstorage"
container_name = "tfstate"
key = "terraform.tfstate"
}
}
variables.tf
variable "location" {
description = "The Azure region to deploy resources"
default = "eastus"
}
variable "resource_group_name" {
description = "The name of the resource group"
default = "TerraForm-RG"
}
variable "vm_name" {
description = "The name of the virtual machine"
default = "terraformTestVM"
}
variable "vm_size" {
description = "The size of the virtual machine"
default = "Standard_B1s"
}
variable "admin_username" {
description = "The admin username for the VM"
default = "adminuser"
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.location
# Specify that the resource group already exists
lifecycle {
ignore_changes = [tags] # This prevents Terraform from attempting to modify tags
}
}
resource "azurerm_virtual_network" "vnet" {
name = "rajaVnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_subnet" "subnet" {
name = "mySubnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}
resource "azurerm_network_interface" "nic" {
name = "myNIC"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_network_security_group" "nsg" {
name = "myNSG"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
security_rule {
name = "Allow_SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_network_interface_security_group_association" "nsg_association" {
network_interface_id = azurerm_network_interface.nic.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "azurerm_public_ip" "public_ip" {
name = "myPublicIP"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
allocation_method = "Dynamic"
}
resource "azurerm_virtual_machine" "vm" {
name = var.vm_name
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
network_interface_ids = [azurerm_network_interface.nic.id]
vm_size = var.vm_size
os_profile {
computer_name = var.vm_name
admin_username = var.admin_username
admin_password = "P@ssw0rd1234!" # Note: For production, use a more secure method for password management.
}
os_profile_linux_config {
disable_password_authentication = false
}
storage_os_disk {
name = "${var.vm_name}_osdisk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
depends_on = [azurerm_network_interface_security_group_association.nsg_association]
tags = {
environment = "Terraform"
}
}
output "public_ip_address" {
value = azurerm_public_ip.public_ip.ip_address
}
location = "eastus"
resource_group_name = "terraformTestVM"
vm_name= "rajatestVM"
vm_size = "Standard_B1s"
admin_username = "adminuser"
Step 2: In command prompt go to terraform script folder and run following commands
terraform apply -var-file="variables.tfvars"
Acquiring state lock. This may take a few moments...
azurerm_resource_group.rg: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM
]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
+ create
Terraform will perform the following actions:
# azurerm_network_interface.nic will be created
+ resource "azurerm_network_interface" "nic" {
+ applied_dns_servers = (known after apply)
+ dns_servers = (known after apply)
+ enable_accelerated_networking = false
# azurerm_network_interface_security_group_association.nsg_association will be created
+ resource "azurerm_network_interface_security_group_association" "nsg_association" {
+ id = (known after apply)
+ network_interface_id = (known after apply)
+ network_security_group_id = (known after apply)
}
# azurerm_network_security_group.nsg will be created
+ resource "azurerm_network_security_group" "nsg" {
+ id = (known after apply)
+ location = "eastus"
+ name = "myNSG"
+ resou
# azurerm_public_ip.public_ip will be created
+ resource "azurerm_public_ip" "public_ip" {
+ allocation_method = "Dynamic"
+ ddos_protection_mode = "VirtualNetworkInherited"
+ fqdn = (known after apply)
+ id = (known after apply)
+ idle_timeou
# azurerm_virtual_machine.vm will be created
+ resource "azurerm_virtual_machine" "vm" {
+ availability_set_id = (known after apply)
+ delete_data_disks_on_termination = false
+ delete_os_disk_on_termination = false
+
Plan: 7 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ public_ip_address = (known after apply)
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes (I confirmed by typing 'yes' here after deliberately reviewed above listing from TF)
azurerm_virtual_network.vnet: Creating...
azurerm_public_ip.public_ip: Creating...
azurerm_network_security_group.nsg: Creating...
........
.........
.........
zurerm_virtual_machine.vm: Creation complete after 19s [id=/subscriptions//91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Compute/virtualMachines/rajatestVM]
Releasing state lock. This may take a few moments...
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
Outputs:
public_ip_address = ""
terraform destroy -var="resource_group_name=terraformTestVM"
Acquiring state lock. This may take a few moments...
azurerm_resource_group.rg: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM]
azurerm_virtual_network.vnet: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/virtualNetworks/rajaVnet]
azurerm_public_ip.public_ip: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/publicIPAddresses/myPublicIP]
azurerm_network_security_group.nsg: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/networkSecurityGroups/myNSG]
azurerm_subnet.subnet: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/virtualNetworks/rajaVnet/subnets/mySubnet]
azurerm_network_interface.nic: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/networkInterfaces/myNIC]
azurerm_network_interface_security_group_association.nsg_association: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/networkInterfaces/myNIC|/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/networkSecurityGroups/myNSG]
azurerm_virtual_machine.vm: Refreshing state... [id=/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Compute/virtualMachines/rajatestVM]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
- destroy
Terraform will perform the following actions:
# azurerm_network_interface.nic will be destroyed
- resource "azurerm_network_interface" "nic" {
- applied_dns_servers = [] -> null
- dns_servers = [] -> null
- enable_accelerated_networking = false -> null
- enable_ip_forwarding = false -> null
- id = "/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Network/networkInterfaces/myNIC" -> null
- internal_domain_name_suffix = "unmumh1g1gyedfjdy5e10qsb2h.bx.internal.cloudapp.net" -> null
- location = "eastus" -> null
- mac_address = "00-0D-3A-1C-A9-E0" -> null
- name = "myNIC" -> null
- private_ip_address = "10.0.1.4" -> null
- private_ip_addresses = [
- "10.0.1.4",
] -> null
- resource_group_name = "terraformTestVM" -> null
- tags = {} -> null
- virtual_machine_id = "/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Compute/virtualMachines/rajatestVM" -> null
# (4 unchanged attributes hidden)
Error: deleting Resource Group "terraformTestVM": the Resource Group still contains Resources.
│
│ Terraform is configured to check for Resources within the Resource Group when deleting the Resource Group - and
│ raise an error if nested Resources still exist to avoid unintentionally deleting these Resources.
│
│ Terraform has detected that the following Resources still exist within the Resource Group:
│
│ * `/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Compute/disks/rajatestVM_osdisk`
│ * `/subscriptions/91ec4999-9cd6-4d56-86d4-dxxx209d7be6/resourceGroups/terraformTestVM/providers/Microsoft.Storage/storageAccounts/myterraformstorage`
│
│ This feature is intended to avoid the unintentional destruction of nested Resources provisioned through some
│ other means (for example, an ARM Template Deployment) - as such you must either remove these Resources, or
│ disable this behaviour using the feature flag `prevent_deletion_if_contains_resources` within the `features`
│ block when configuring the Provider, for example:
│
│ provider "azurerm" {
│ features {
│ resource_group {
│ prevent_deletion_if_contains_resources = false
│ }
│ }
│ }
│
│ When that feature flag is set, Terraform will skip checking for any Resources within the Resource Group and
│ delete this using the Azure API directly (which will clear up any nested resources).
│
│ More information on the `features` block can be found in the documentation:
│ https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/features-block
│
│
│
╵
Releasing state lock. This may take a few moments...