빠른 시작: Terraform을 사용하여 Linux VM 만들기

적용 대상: ✔️ Linux VM

다음 Terraform 및 Terraform 공급자 버전으로 테스트된 문서:

이 문서에서는 Terraform을 사용하여 전체 Linux 환경 및 지원 리소스를 만드는 방법을 보여 줍니다. 이러한 리소스에는 가상 네트워크, 서브넷, 공용 IP 주소 등이 포함됩니다.

Terraform은 클라우드 인프라의 정의, 미리 보기 및 배포를 사용합니다. Terraform을 사용하는 경우 HCL 구문를 사용하여 구성 파일을 만듭니다. HCL 구문을 사용하면 클라우드 공급자(예: Azure) 그리고 클라우드 인프라를 구성하는 요소를 지정할 수 있습니다. 구성 파일을 만든 후 배포되기 전에 인프라 변경을 미리 볼 수 있는 실행 계획를 만듭니다. 변경 내용을 확인 한 후에는 실행 계획을 적용하여 인프라를 배포합니다.

이 문서에서는 다음 방법을 설명합니다.

  • 가상 네트워크 만들기
  • 서브넷 만들기
  • 공용 IP 주소 만들기
  • 네트워크 보안 그룹 및 SSH 인바운드 규칙 만들기
  • 가상 네트워크 인터페이스 카드 만들기
  • 네트워크 보안 그룹을 네트워크 인터페이스에 연결
  • 부팅 진단을 위한 스토리지 계정 만들기
  • SSH 키 만들기
  • 가상 머신 만들기
  • SSH를 사용하여 가상 머신에 연결

사전 요구 사항

  • Azure 구독: Azure 구독이 아직 없는 경우 시작하기 전에 체험 계정을 만듭니다.

Terraform 코드 구현

  1. 샘플 Terraform 코드를 테스트할 디렉터리를 만들고, 이를 현재 디렉터리로 만듭니다.

  2. providers.tf라는 파일을 만들고 다음 코드를 삽입합니다.

    terraform {
      required_version = ">=0.12"
    
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>2.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
        tls = {
          source = "hashicorp/tls"
          version = "~>4.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
  3. main.tf라는 파일을 만들고 다음 코드를 삽입합니다.

    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "azurerm_resource_group" "rg" {
      location = var.resource_group_location
      name     = random_pet.rg_name.id
    }
    
    # Create virtual network
    resource "azurerm_virtual_network" "my_terraform_network" {
      name                = "myVnet"
      address_space       = ["10.0.0.0/16"]
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    # Create subnet
    resource "azurerm_subnet" "my_terraform_subnet" {
      name                 = "mySubnet"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.my_terraform_network.name
      address_prefixes     = ["10.0.1.0/24"]
    }
    
    # Create public IPs
    resource "azurerm_public_ip" "my_terraform_public_ip" {
      name                = "myPublicIP"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      allocation_method   = "Dynamic"
    }
    
    # Create Network Security Group and rule
    resource "azurerm_network_security_group" "my_terraform_nsg" {
      name                = "myNetworkSecurityGroup"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.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 = "*"
      }
    }
    
    # Create network interface
    resource "azurerm_network_interface" "my_terraform_nic" {
      name                = "myNIC"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    
      ip_configuration {
        name                          = "my_nic_configuration"
        subnet_id                     = azurerm_subnet.my_terraform_subnet.id
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.my_terraform_public_ip.id
      }
    }
    
    # Connect the security group to the network interface
    resource "azurerm_network_interface_security_group_association" "example" {
      network_interface_id      = azurerm_network_interface.my_terraform_nic.id
      network_security_group_id = azurerm_network_security_group.my_terraform_nsg.id
    }
    
    # Generate random text for a unique storage account name
    resource "random_id" "random_id" {
      keepers = {
        # Generate a new ID only when a new resource group is defined
        resource_group = azurerm_resource_group.rg.name
      }
    
      byte_length = 8
    }
    
    # Create storage account for boot diagnostics
    resource "azurerm_storage_account" "my_storage_account" {
      name                     = "diag${random_id.random_id.hex}"
      location                 = azurerm_resource_group.rg.location
      resource_group_name      = azurerm_resource_group.rg.name
      account_tier             = "Standard"
      account_replication_type = "LRS"
    }
    
    # Create (and display) an SSH key
    resource "tls_private_key" "example_ssh" {
      algorithm = "RSA"
      rsa_bits  = 4096
    }
    
    # Create virtual machine
    resource "azurerm_linux_virtual_machine" "my_terraform_vm" {
      name                  = "myVM"
      location              = azurerm_resource_group.rg.location
      resource_group_name   = azurerm_resource_group.rg.name
      network_interface_ids = [azurerm_network_interface.my_terraform_nic.id]
      size                  = "Standard_DS1_v2"
    
      os_disk {
        name                 = "myOsDisk"
        caching              = "ReadWrite"
        storage_account_type = "Premium_LRS"
      }
    
      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 = tls_private_key.example_ssh.public_key_openssh
      }
    
      boot_diagnostics {
        storage_account_uri = azurerm_storage_account.my_storage_account.primary_blob_endpoint
      }
    }
    
  4. variables.tf라는 파일을 만들고 다음 코드를 삽입합니다.

    variable "resource_group_location" {
      default     = "eastus"
      description = "Location of the resource group."
    }
    
    variable "resource_group_name_prefix" {
      default     = "rg"
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
    }
    
  5. outputs.tf라는 파일을 만들고 다음 코드를 삽입합니다.

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
    output "public_ip_address" {
      value = azurerm_linux_virtual_machine.my_terraform_vm.public_ip_address
    }
    
    output "tls_private_key" {
      value     = tls_private_key.example_ssh.private_key_pem
      sensitive = true
    }
    

Terraform 초기화

terraform init를 실행하여 Terraform 배포를 초기화합니다. 이 명령은 Azure 리소스 그룹을 관리하는 데 필요한 Azure 모듈을 다운로드합니다.

terraform init

Terraform 실행 계획 만들기

terraform plan을 실행하여 실행 계획을 만듭니다.

terraform plan -out main.tfplan

주요 정보:

  • terraform plan 명령은 실행 계획을 만들지만 실행하지는 않습니다. 대신 구성 파일에 지정된 구성을 만드는 데 필요한 작업을 결정합니다. 이 패턴을 사용하면 실제 리소스를 변경하기 전에 실행 계획이 예상과 일치하는지 확인할 수 있습니다.
  • 선택 사항인 -out 매개 변수를 사용하여 계획의 출력 파일을 지정할 수 있습니다. -out 매개 변수를 사용하면 검토한 계획이 정확하게 적용됩니다.
  • 실행 계획 및 보안을 유지하는 방법에 대한 자세한 내용은 보안 경고 섹션을 참조하세요.

Terraform 실행 계획 적용

terraform apply를 실행하여 실행 계획을 클라우드 인프라에 적용합니다.

terraform apply main.tfplan

주요 정보:

  • 위의 terraform apply 명령은 이전에 terraform plan -out main.tfplan을 실행한 것으로 가정합니다.
  • -out 매개 변수에 다른 파일 이름을 지정한 경우 terraform apply에 대한 호출에서 동일한 파일 이름을 사용합니다.
  • -out 매개 변수를 사용하지 않은 경우 매개 변수 없이 terraform apply를 호출합니다.

결과 확인

SSH를 사용하여 가상 머신에 연결하려면 다음 단계를 수행합니다.

  1. terraform 출력을 실행하여 SSH 프라이빗 키를 가져와서 파일에 저장합니다.

    terraform output -raw tls_private_key > id_rsa
    
  2. terraform 출력을 실행하여 가상 머신 공용 IP 주소를 가져옵니다.

    terraform output public_ip_address
    
  3. SSH를 사용하여 가상 머신에 연결합니다.

    ssh -i id_rsa azureuser@<public_ip_address>
    

    주요 정보:

    • 사용자 환경의 권한에 따라 id_rsa 키 파일을 사용하여 가상 머신에 ssh를 시도하면 오류가 발생할 수 있습니다. 프라이빗 키 파일이 보호되지 않아 사용할 수 없다는 오류가 발생하는 경우 파일 소유자에 대한 읽기 및 쓰기 액세스를 제한하는 chmod 600 id_rsa 명령을 실행해 보세요.

리소스 정리

Terraform을 통해 리소스를 만들 필요가 더 이상 없으면 다음 단계를 수행합니다.

  1. terraform 플랜을 실행하고 destroy 플래그를 지정합니다.

    terraform plan -destroy -out main.destroy.tfplan
    

    주요 정보:

    • terraform plan 명령은 실행 계획을 만들지만 실행하지는 않습니다. 대신 구성 파일에 지정된 구성을 만드는 데 필요한 작업을 결정합니다. 이 패턴을 사용하면 실제 리소스를 변경하기 전에 실행 계획이 예상과 일치하는지 확인할 수 있습니다.
    • 선택 사항인 -out 매개 변수를 사용하여 계획의 출력 파일을 지정할 수 있습니다. -out 매개 변수를 사용하면 검토한 계획이 정확하게 적용됩니다.
    • 실행 계획 및 보안을 유지하는 방법에 대한 자세한 내용은 보안 경고 섹션을 참조하세요.
  2. terraform apply를 실행하여 실행 계획을 적용합니다.

    terraform apply main.destroy.tfplan
    

Azure의 Terraform 문제 해결

Azure에서 Terraform을 사용할 때 일반적인 문제 해결

다음 단계

이 빠른 시작에서는 Terraform을 사용하여 간단한 가상 머신을 배포했습니다. Azure 가상 머신에 대한 자세한 내용을 알아보려면 Linux VM의 자습서를 계속 진행합니다.