Azure and Terraform

From Deployment to Decommission

Hello Muser!

In our last session, we ventured into the world of Terraform with a focus on Azure. We navigated through the initial setup and scripting phases. Now, it's time to bring our configuration to life and also learn how to dismantle it safely.

Here’s a diagram of what we’ll be done with after completing this work:

----------

Applying the Terraform Configuration

The moment of truth in any Terraform journey is the application of your configuration. This process involves a few critical steps:

1. Execute terraform apply: This command is your gateway to transforming your script into actual cloud resources. It's crucial to review the plan Terraform generates carefully before confirming.

2. Review the Plan: Terraform will present a summary of what it intends to do. This step is your last line of defense against potential misconfigurations. Take careful note of Plan line: Plan: 11 to add, 0 to change, 0 to destroy. This can be used to do quick verification of what you expect to happen!

3. Monitor the Apply Process: Keep an eye on the output. Terraform provides real-time feedback, informing you of each step it takes.

... # output is truncated

  # local_file.public_key will be created
  + resource "local_file" "public_key" {
      + content              = (known after apply)
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./public_key.pub"
      + id                   = (known after apply)
    }

  # tls_private_key.myprivatekey will be created
  + resource "tls_private_key" "myprivatekey" {
      + algorithm                     = "RSA"
      + ecdsa_curve                   = "P224"
      + id                            = (known after apply)
      + private_key_openssh           = (sensitive value)
      + private_key_pem               = (sensitive value)
      + private_key_pem_pkcs8         = (sensitive value)
      + public_key_fingerprint_md5    = (known after apply)
      + public_key_fingerprint_sha256 = (known after apply)
      + public_key_openssh            = (known after apply)
      + public_key_pem                = (known after apply)
      + rsa_bits                      = 4096
    }

Plan: 11 to add, 0 to change, 0 to destroy.

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

4. After confirming, you should see an output like this

tls_private_key.myprivatekey: Creating...
tls_private_key.myprivatekey: Creation complete after 4s [id=b78413933336a1c846a933881ae7ee36b429dc68]
local_file.private_key: Creating...
local_file.public_key: Creating...
local_file.private_key: Creation complete after 0s [id=be853b928de4f115415910cb7e3ba29169d31fc8]
local_file.public_key: Creation complete after 0s [id=ab9ac7adebf9af8546e9f8357de96ca40d8b64e0]
azurerm_resource_group.my_rg: Creating...
azurerm_resource_group.my_rg: Creation complete after 1s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup]
azurerm_network_security_group.my_nsg: Creating...
azurerm_public_ip.my_public_ip: Creating..
azurerm_virtual_network.my_vnet: Creating...
azurerm_public_ip.my_public_ip: Creation complete after 3s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/publicIPAddresses/MyPublicIP]
azurerm_network_security_group.my_nsg: Creation complete after 3s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkSecurityGroups/MyNSG]
azurerm_virtual_network.my_vnet: Creation complete after 5s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVNet]
azurerm_subnet.my_subnet: Creating...
azurerm_subnet.my_subnet: Creation complete after 4s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVNet/subnets/MySubnet]
azurerm_network_interface.my_nic: Creating...
azurerm_network_interface.my_nic: Still creating... [10s elapsed]
azurerm_network_interface.my_nic: Creation complete after 12s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkInterfaces/MyNIC]
azurerm_network_interface_security_group_association.myprivatekey: Creating...
azurerm_virtual_machine.my_vm: Creating...
azurerm_network_interface_security_group_association.myprivatekey: Creation complete after 2s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkInterfaces/MyNIC|/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkSecurityGroups/MyNSG]
azurerm_virtual_machine.my_vm: Still creating... [10s elapsed]
azurerm_virtual_machine.my_vm: Still creating... [20s elapsed]
azurerm_virtual_machine.my_vm: Still creating... [30s elapsed]
azurerm_virtual_machine.my_vm: Still creating... [40s elapsed]
azurerm_virtual_machine.my_vm: Creation complete after 50s [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/MyVM]

Apply complete! Resources: 11 added, 0 changed, 0 destroyed.
----------

Behind the Scenes: Terraform Apply

Understanding what happens under the hood during the apply process is essential for any DevOps professional:

  • Resource Dependency Graph: Terraform constructs a graph to understand the dependencies between resources. This graph dictates the order of resource creation and modification.

  • State Management: The state file is a snapshot of your resources at any given time. Terraform uses this to map real-world resources to your configuration.

  • API Interactions: Terraform communicates with Azure's APIs to create, update, or delete resources based on your script.

  • Error Handling: If Terraform encounters an error, it will attempt to provide a clear explanation and halt the process to prevent partial resource deployment.

----------

Pros and Cons of Using Terraform as IaC

Advantages:

  • Platform Agnostic: Terraform's ability to work with multiple cloud providers is a significant advantage.

  • State Management: The robust state tracking helps in managing complex infrastructures.

  • Community and Ecosystem: A strong community and a wealth of plugins and modules make Terraform highly versatile.

Disadvantages:

  • Learning Curve: The initial complexity can be daunting for beginners.

  • State File Sensitivity: Managing the state file, especially in team environments, requires careful handling to avoid conflicts.

----------

Destroying the Infrastructure

The ability to tear down your infrastructure as easily as you set it up is a powerful feature of Terraform:

1. Understanding terraform destroy: This command removes the resources managed by your Terraform configuration, which is essential for managing temporary or experimental environments.

2. Executing the Destroy Command: Running terraform destroy will prompt Terraform to plan the removal of all resources it manages under the current configuration.

3. Post-Destruction State: After destruction, it's crucial to verify that all resources have been properly removed in Azure. The state file will be updated to reflect these changes.

 # tls_private_key.myprivatekey will be destroyed
  - resource "tls_private_key" "myprivatekey" {
      - algorithm                     = "RSA" -> null
      - ecdsa_curve                   = "P224" -> null
      - id                            = "b78413933336a1c846a933881ae7ee36b429dc68" -> null
      - private_key_openssh           = (sensitive value) -> null
      - private_key_pem               = (sensitive value) -> null
      - private_key_pem_pkcs8         = (sensitive value) -> null
      - public_key_fingerprint_md5    = "98:02:fd:29:89:61:51:3a:d6:39:ea:4d:4b:81:80:b7" -> null
      - public_key_fingerprint_sha256 = "SHA256:7z+Wxs2qQ7qKRHDFcU2pZMYT2IYoR/axNJPR+3qObYA" -> null
      - public_key_openssh            = <<-EOT
            ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCpOMPcL6vUgzVrvKKGoHwR0ACYX60LxsOVzZKDeBboyY/bZizQgqQsj3tXukkpl6yjQWc9v6xDNJjpn+AHlc94B/iiqPFSkYJF96GkQtH1CGjR/xSAnzx3B3uZqeA3pdKkDeLKsEaQpaeRbUloB3hPXs14Eb3b10JlTOdVBWqELVzE3X64NFUnn6WHMXIKH3ExFeordFF6REItJCmgICu05gOOYFICLtaXSRxj7U9rapHqKh/wRpFXpuBM/rY1V2VvyrCE/aebgUZjdIELEOjqfflHSe9XNs1WxBHj8WLGa2LehaOwN9lm9o2K47SIRJiCfz3p2ebOEZcAauThYwzYBrwXfy4iYto6r/PmnN9b7GDDFjpEMP9ccZnDoyWwHhlb1OrRafblMfG1jOrsJ065yyaOjdT2YRfH+J/J8LYY6R+n9HDEPm5l+v73gKqZgBT6kr5wJ219n05EZYuDrKirgd7HJ1LDAChz/3tBqtVU/QJc3m4R4xyZdFH4DPBO0eT06QPsIDNf7kjnD6OwVoWf5sqt9YAs75YCblej8JQDSE7aTBliRVsdfOGevqIu3x7GB5NJVaBEXwKNU7Tj3iAIOL7kBUC0ryGVrGkALGpO714fFIXTSSgCAcE+lUXHObDPZ603sQzWS/F4GAlbfU74bbH5fAe45xlxryehuCMTaw==
        EOT -> null
      - public_key_pem                = <<-EOT
            -----BEGIN PUBLIC KEY-----        MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqTjD3C+r1IM1a7yihqB8EdAAmF+tC8bDlc2Sg3gW6MmP22Ys0IKkLI97V7pJKZeso0FnPb+sQzSY6Z/gB5XPeAf4oqjxUpGCRfehpELR9Qho0f8UgJ88dwd7mangN6XSpA3iyrBGkKWnkW1JaAd4T17NeBG929dCZUznVQVqhC1cxN1+uDRVJ5+lhzFyCh9xMRXqK3RRekRCLSQpoCArtOYDjmBSAi7Wl0kcY+1Pa2qR6iof8EaRV6bgTP62NVdlb8qwhP2nm4FGY3SBCxDo6n35R0nvVzbNVsQR4/Fixmti3oWjsDfZZvaNiuO0iESYgn896dnmzhGXAGrk4WMM2Aa8F38uImLaOq/z5pzfW+xgwxY6RDD/XHGZw6MlsB4ZW9Tq0Wn25THxtYzq7CdOucsmjo3U9mEXx/ifyfC2GOkfp/RwxD5uZfr+94CqmYAU+pK+cCdtfZ9ORGWLg6yoq4HexydSwwAoc/97QarVVP0CXN5uEeMcmXRR+AzwTtHk9OkD7CAzX+5I5w+jsFaFn+bKrfWALO+WAm5Xo/CUA0hO2kwZYkVbHXzhnr6iLt8exgeTSVWgRF8CjVO0494gCDi+5AVAtK8hlaxpACxqTu9eHxSF00koAgHBPpVFxzmwz2etN7EM1kvxeBgJW31O+G2x+XwHuOcZca8nobgjE2sCAwEAAQ==
            -----END PUBLIC KEY-----
        EOT -> null
      - rsa_bits                      = 4096 -> null
    }

Plan: 0 to add, 0 to change, 11 to destroy.

Do you really want to destroy all resources?

  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

4. After confirming you should see the reverse of the apply output:

local_file.public_key: Destroying... [id=ab9ac7adebf9af8546e9f8357de96ca40d8b64e0
local_file.private_key: Destroying... [id=be853b928de4f115415910cb7e3ba29169d31fc8]
local_file.private_key: Destruction complete after 0s
local_file.public_key: Destruction complete after 0s
azurerm_network_interface_security_group_association.myprivatekey: Destroying... [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkInterfaces/MyNIC|/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkSecurityGroups/MyNSG]
azurerm_virtual_machine.my_vm: Destroying... [id=/subscriptions/a610997c-3ac3-426a-a387-d670c6fad64f/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/MyVM]
azurerm_virtual_machine.my_vm: Still destroying... [id=/subscriptions/a610997c-3ac3-426a-a387-...Microsoft.Compute/virtualMachines/MyVM, 10s elapsed]
azurerm_virtual_machine.my_vm: Still destroying... [id=/subscriptions/a610997c-3ac3-426a-a387-...Microsoft.Compute/virtualMachines/MyVM, 20s elapsed]
azurerm_virtual_machine.my_vm: Still destroying... [id=/subscriptions/a610997c-3ac3-426a-a387-...Microsoft.Compute/virtualMachines/MyVM, 30s elapsed]
azurerm_virtual_machine.my_vm: Still destroying... [id=/subscriptions/a610997c-3ac3-426a-a387-...Microsoft.Compute/virtualMachines/MyVM, 40s elapsed]
azurerm_virtual_machine.my_vm: Destruction complete after 41s
tls_private_key.myprivatekey: Destroying... [id=b78413933336a1c846a933881ae7ee36b429dc68]
tls_private_key.myprivatekey: Destruction complete after 0s
----------

From setting up your Azure account, scripting in Terraform, applying the configuration, and finally destroying it, we've covered a substantial journey. These steps form the core of Infrastructure as Code practices. Remember, practice is key to mastering Terraform. In our next issue, we'll explore how to modularize this code for reuse and organization!

Subscribe now and share with your colleagues who might find this useful!

Have any questions or experiences to share about Terraform? Leave a comment below. Also, your comments help me understand what you're curious about, and what topics you'd like to see covered next! I'd love to hear from you!

Keep learning and keep growing,

Darrell

Reply

or to participate.