🐶
Terraform

Deploy Ubuntu 20.04 Linux VM on Azure with Terraform

By Ondřej Dolanský on 12/22/2024

Learn how to easily create and configure an Azure Linux VM running Ubuntu 20.04 using infrastructure as code with Terraform.

Deploy Ubuntu 20.04 Linux VM on Azure with Terraform

Table of Contents

Introduction

This guide provides a step-by-step approach to deploying a Linux virtual machine (VM) on Microsoft Azure using Terraform. We will cover the essential configurations required to set up the VM, including creating a resource group, defining network resources, and establishing secure access to the instance. By following these instructions, you'll be able to leverage Terraform's infrastructure-as-code capabilities to efficiently provision and manage your Azure VM.

Step-by-Step Guide

  1. Install Terraform: Download and install Terraform from the official website (https://developer.hashicorp.com/terraform/downloads).

  2. Authenticate to Azure: Use the Azure CLI or other methods to authenticate your Terraform scripts to your Azure subscription.

  3. Define Azure Provider: In your Terraform configuration file (e.g., main.tf), specify the Azure provider and your desired Azure region.

    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 3.0" 
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
  4. Create a Resource Group: Define a resource group to organize your Azure resources.

    resource "azurerm_resource_group" "example" {
      name     = "my-resource-group"
      location = "West Europe" 
    }
  5. Define Network Resources: Create a virtual network and subnet for your VM.

    resource "azurerm_virtual_network" "example" {
      name                = "my-network"
      resource_group_name = azurerm_resource_group.example.name
      location            = azurerm_resource_group.example.location
      address_space       = ["10.0.0.0/16"]
    }
    
    resource "azurerm_subnet" "example" {
      name                 = "my-subnet"
      resource_group_name  = azurerm_resource_group.example.name
      virtual_network_name = azurerm_virtual_network.example.name
      address_prefixes     = ["10.0.1.0/24"]
    }
  6. Create a Public IP: If you need to access the VM from the internet, create a public IP address.

    resource "azurerm_public_ip" "example" {
      name                = "my-public-ip"
      resource_group_name = azurerm_resource_group.example.name
      location            = azurerm_resource_group.example.location
      allocation_method   = "Dynamic"
    }
  7. Define Network Interface: Create a network interface and attach it to the subnet and public IP.

    resource "azurerm_network_interface" "example" {
      name                = "my-nic"
      resource_group_name = azurerm_resource_group.example.name
      location            = azurerm_resource_group.example.location
      ip_configuration {
        name                          = "internal"
        subnet_id                     = azurerm_subnet.example.id
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.example.id
      }
    }
  8. Create the Linux VM: Define the azurerm_linux_virtual_machine resource, specifying the Ubuntu 20.04 image, size, authentication details, and network settings.

    resource "azurerm_linux_virtual_machine" "example" {
      name                            = "my-vm"
      resource_group_name             = azurerm_resource_group.example.name
      location                        = azurerm_resource_group.example.location
      size                            = "Standard_B2s" 
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
      network_interface_ids = [azurerm_network_interface.example.id]
    
      source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "20.04-LTS"
        version   = "latest"
      }
    
      ssh_keys {
        path     = "~/.ssh/id_rsa.pub" 
        key_data = file("~/.ssh/id_rsa.pub")
      }
    }
  9. Apply Terraform Configuration: Run terraform init to initialize your Terraform project, then terraform apply to create the resources.

  10. Access Your VM: Once the VM is created, you can SSH into it using the public IP address and the SSH key pair you specified.

Code Example

This Terraform code sets up basic infrastructure on Azure. It provisions a resource group, a virtual network with a subnet, a public IP address, and a network interface. Then, it creates a Linux virtual machine running Ubuntu 20.04 LTS, attaches it to the network, and configures SSH access using a provided public key.

# Configure the Azure Provider
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

provider "azurerm" {
  features {}
}

# Create a Resource Group
resource "azurerm_resource_group" "example" {
  name     = "my-resource-group"
  location = "West Europe"
}

# Create a Virtual Network
resource "azurerm_virtual_network" "example" {
  name                = "my-network"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  address_space       = ["10.0.0.0/16"]
}

# Create a Subnet
resource "azurerm_subnet" "example" {
  name                 = "my-subnet"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.1.0/24"]
}

# Create a Public IP Address
resource "azurerm_public_ip" "example" {
  name                = "my-public-ip"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  allocation_method   = "Dynamic"
}

# Create a Network Interface
resource "azurerm_network_interface" "example" {
  name                = "my-nic"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.example.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.example.id
  }
}

# Create a Linux Virtual Machine
resource "azurerm_linux_virtual_machine" "example" {
  name                            = "my-vm"
  resource_group_name             = azurerm_resource_group.example.name
  location                        = azurerm_resource_group.example.location
  size                            = "Standard_B2s"
  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }
  network_interface_ids = [azurerm_network_interface.example.id]

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "20.04-LTS"
    version   = "latest"
  }

  # Replace with your actual SSH key path
  ssh_keys {
    path     = "~/.ssh/id_rsa.pub"
    key_data = file("~/.ssh/id_rsa.pub")
  }
}

Before running the code:

  1. Install Terraform: Download and install Terraform from https://developer.hashicorp.com/terraform/downloads.
  2. Authenticate to Azure: Make sure you are authenticated to Azure using the Azure CLI or have configured authentication in your environment.
  3. SSH Key: Ensure you have an SSH key pair generated and replace the placeholder ~/.ssh/id_rsa.pub with the path to your public key file.

Steps to deploy:

  1. Save the code above as main.tf.
  2. Open a terminal and navigate to the directory where you saved the file.
  3. Run terraform init to initialize the Terraform project.
  4. Run terraform apply and confirm the deployment by typing yes.

Terraform will create the resources in your Azure subscription. Once the deployment is complete, you can SSH into your Linux VM using the public IP address assigned to it and the private key associated with the public key you provided.

Additional Notes

General:

  • Resource Naming: Use descriptive and consistent naming conventions for all resources (e.g., prefixing with project or environment).
  • Location: Choose an Azure region closest to your users for optimal latency.
  • Terraform State: Store your Terraform state remotely (e.g., Azure Storage Account) for collaboration and disaster recovery.

Security:

  • SSH Keys: Use a strong SSH key pair and store your private key securely. Consider using SSH key management solutions.
  • Network Security Group (NSG): Implement an NSG to restrict inbound and outbound traffic to your VM. Only open necessary ports.
  • Azure Bastion: For enhanced security, consider using Azure Bastion to connect to your VM over a browser-based SSH/RDP session.

Cost Optimization:

  • VM Size: Choose a VM size that meets your performance requirements while minimizing costs. Consider using Azure Spot VMs for cost-effective development and testing environments.
  • Auto-Shutdown: Configure auto-shutdown for your VM during non-peak hours to reduce costs.

Customization:

  • Data Disks: Attach additional data disks to your VM for storing applications, data, and logs separately from the OS disk.
  • Cloud-Init: Use cloud-init to automate initial configurations, install software packages, and run scripts on your VM during provisioning.
  • Terraform Modules: Leverage Terraform modules to create reusable and modular infrastructure components.

Troubleshooting:

  • Terraform Logs: Review Terraform logs (terraform apply -verbose) for detailed information on resource creation and any errors encountered.
  • Azure Portal: Use the Azure portal to monitor resource provisioning, view logs, and troubleshoot issues.

Best Practices:

  • Version Control: Store your Terraform code in a version control system (e.g., Git) for tracking changes and collaboration.
  • Automated Testing: Implement automated testing using tools like Terratest to validate your infrastructure code.
  • Continuous Integration/Continuous Deployment (CI/CD): Integrate Terraform with your CI/CD pipeline for automated infrastructure provisioning and deployments.

Summary

This guide provides a concise overview of deploying a Linux VM on Azure using Terraform.

Steps:

  1. Preparation:

    • Install Terraform.
    • Authenticate to your Azure subscription using the Azure CLI or other methods.
  2. Terraform Configuration:

    • Define the Azure provider and target region in your main.tf file.
    • Create a resource group to organize your Azure resources.
    • Define network resources:
      • Create a virtual network.
      • Create a subnet within the virtual network.
    • Create a public IP address for external access to the VM.
    • Define a network interface and associate it with the subnet and public IP.
    • Create the Linux VM:
      • Specify the desired Ubuntu 20.04 image, VM size, and storage settings.
      • Configure network settings by referencing the network interface.
      • Provide SSH key details for authentication.
  3. Deployment:

    • Initialize your Terraform project with terraform init.
    • Deploy the resources to Azure using terraform apply.
  4. Access:

    • Once deployed, SSH into your Linux VM using its public IP address and the configured SSH key pair.

This summary outlines the essential steps for deploying a Linux VM on Azure with Terraform. For detailed code snippets and explanations, refer to the original article.

Conclusion

By following the steps outlined in this guide, you can effectively utilize Terraform to deploy and manage a Linux VM on Azure. This approach not only simplifies the provisioning process but also promotes infrastructure as code, enhancing consistency, repeatability, and scalability in your cloud deployments. Remember to consider the additional notes and best practices mentioned to optimize your VM configuration for security, cost-effectiveness, and customization based on your specific requirements.

References

Were You Able to Follow the Instructions?

😍Love it!
😊Yes
😐Meh-gical
😞No
🤮Clickbait