다음을 통해 공유


빠른 시작: Terraform을 사용하여 Azure에서 프라이빗 DNS 영역 구성

이 빠른 시작에서는 Terraform을 사용하여 Azure에서 프라이빗 DNS 영역, 네트워크 인터페이스, Windows 가상 머신, 프라이빗 DNS A 레코드, 네트워크 보안 그룹 및 네트워크 보안 규칙을 만듭니다.

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

  • 고유한 이름으로 Azure 리소스 그룹을 만듭니다.
  • 지정된 이름과 주소를 사용하여 가상 네트워크를 설정합니다.
  • 만든 가상 네트워크 내에서 서브넷을 설정합니다.
  • 프라이빗 DNS 영역 만들기.
  • 가상 머신에 대한 임의의 암호를 생성합니다.
  • 두 개의 네트워크 인터페이스를 만듭니다.
  • 두 개의 Windows 가상 머신을 만들고 네트워크 인터페이스를 연결합니다.
  • 프라이빗 DNS A 레코드를 만듭니다.
  • ICMP 트래픽을 허용하는 네트워크 보안 그룹 및 네트워크 보안 규칙을 만듭니다.
  • 가상 머신의 이름 및 관리자 자격 증명을 출력합니다.

필수 조건

Terraform 코드 구현

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

  2. 이름이 지정된 main.tf파일을 만들고 다음 코드를 삽입합니다.

    # Resource Group
    resource "random_pet" "rg_name" {
      separator = "-"
    }
    
    resource "azurerm_resource_group" "rg" {
      location = var.resource_group_location
      name     = "${var.resource_group_name_prefix}-${random_pet.rg_name.id}"
    }
    
    # Random String for unique naming
    resource "random_string" "name" {
      length  = 8
      special = false
      upper   = false
      lower   = true
      numeric = false
    }
    
    # Virtual Network
    resource "azurerm_virtual_network" "vnet" {
      name                = "vnet-${random_string.name.result}"
      address_space       = var.address_space
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    # Subnet
    resource "azurerm_subnet" "subnet" {
      name                 = "subnet-${random_string.name.result}"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.vnet.name
      address_prefixes     = var.address_prefixes
    }
    
    # Private DNS Zone
    resource "azurerm_private_dns_zone" "dns_zone" {
      name                = var.private_dns_zone_name
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    # Private DNS Zone Virtual Network Link
    resource "azurerm_private_dns_zone_virtual_network_link" "dsn_vnet_link" {
      name                  = "dns-vnet-link-${random_string.name.result}"
      resource_group_name   = azurerm_resource_group.rg.name
      private_dns_zone_name = azurerm_private_dns_zone.dns_zone.name
      virtual_network_id    = azurerm_virtual_network.vnet.id
    }
    
    # Random Passwords for VMs
    resource "random_password" "vm1_admin_password" {
      length  = 16
      special = true
    }
    
    resource "random_password" "vm2_admin_password" {
      length  = 16
      special = true
    }
    
    # Network Interfaces
    resource "azurerm_network_interface" "nic1" {
      name                = "nic1-${random_string.name.result}"
      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_interface" "nic2" {
      name                = "nic2-${random_string.name.result}"
      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"
      }
    }
    
    # Windows Virtual Machines
    resource "azurerm_windows_virtual_machine" "vm1" {
      name                = "vm1-${random_string.name.result}"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      size                = "Standard_F2"
      admin_username      = var.admin_username
      admin_password      = random_password.vm1_admin_password.result
      network_interface_ids = [
        azurerm_network_interface.nic1.id,
      ]
    
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
    
      source_image_reference {
        publisher = "MicrosoftWindowsServer"
        offer     = "WindowsServer"
        sku       = "2019-Datacenter"
        version   = "latest"
      }
    
      # Make idempotent
      vm_agent_platform_updates_enabled = true
    }
    
    resource "azurerm_windows_virtual_machine" "vm2" {
      name                = "vm2-${random_string.name.result}"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      size                = "Standard_F2"
      admin_username      = var.admin_username
      admin_password      = random_password.vm1_admin_password.result
      network_interface_ids = [
        azurerm_network_interface.nic2.id,
      ]
    
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
    
      source_image_reference {
        publisher = "MicrosoftWindowsServer"
        offer     = "WindowsServer"
        sku       = "2019-Datacenter"
        version   = "latest"
      }
    
      # Make idempotent
      vm_agent_platform_updates_enabled = true
    }
    
    # Private DNS A Record
    resource "azurerm_private_dns_a_record" "pdar" {
      name                = "test"
      zone_name           = azurerm_private_dns_zone.dns_zone.name
      resource_group_name = azurerm_resource_group.rg.name
      ttl                 = 300
      records             = [azurerm_windows_virtual_machine.vm1.private_ip_address]
    }
    
    # Network Security Group
    resource "azurerm_network_security_group" "nsg" {
      name                = "nsg-${random_string.name.result}"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    # Network Security Rule
    resource "azurerm_network_security_rule" "nsr_icmp" {
      name                        = "Allow-ICMP"
      priority                    = 100
      direction                   = "Inbound"
      access                      = "Allow"
      protocol                    = "Icmp"
      source_port_range           = "*"
      destination_port_range      = "*"
      source_address_prefix       = "*"
      destination_address_prefix  = "*"
      resource_group_name         = azurerm_resource_group.rg.name
      network_security_group_name = azurerm_network_security_group.nsg.name
    }
    
  3. 이름이 지정된 outputs.tf파일을 만들고 다음 코드를 삽입합니다.

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
    output "windows_virtual_machine_1_name" {
      value = azurerm_windows_virtual_machine.vm1.name
    }
    
    output "windows_virtual_machine_2_name" {
      value = azurerm_windows_virtual_machine.vm2.name
    }
    
    output "windows_virtual_machine_1_password" {
      value     = azurerm_windows_virtual_machine.vm1.admin_password
      sensitive = true
    }
    
    output "windows_virtual_machine_2_password" {
      value     = azurerm_windows_virtual_machine.vm2.admin_password
      sensitive = true
    }
    
    output "windows_virtual_machine_1_admin_username" {
      value     = azurerm_windows_virtual_machine.vm1.admin_username
      sensitive = true
    }
    
    output "windows_virtual_machine_2_admin_username" {
      value     = azurerm_windows_virtual_machine.vm2.admin_username
      sensitive = true
    }
    
  4. 이름이 지정된 providers.tf파일을 만들고 다음 코드를 삽입합니다.

    terraform {
      required_version = ">=1.0"
    
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>3.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
  5. 이름이 지정된 variables.tf파일을 만들고 다음 코드를 삽입합니다.

    variable "resource_group_location" {
      type        = string
      default     = "eastus"
      description = "Location of the resource group."
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      default     = "rg"
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
    }
    
    variable "address_space" {
      type = list(string)
      default = ["10.0.0.0/16"]
      description = "The address space that is used the virtual network."
    }
    
    variable "address_prefixes" {
      type = list(string)
      default = ["10.0.2.0/24"]
      description = "The address prefixes to use for the subnet"
    }
    
    variable "private_dns_zone_name" {
      type = string
      default = "private.contoso.com"
      description = "The name of the Private DNS Zone. Must be a valid domain name. Changing this value forces a new resource to be created."
    }
    
    variable "admin_username" {
      type = string
      default = "adminuser"
      description = "The username for the Windows virtual machines."
    }
    

Terraform 초기화

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

terraform init -upgrade

핵심 사항:

  • -upgrade 매개 변수는 필요한 공급자 플러그 인을 구성의 버전 제약 조건을 준수하는 최신 버전으로 업그레이드합니다.

Terraform 실행 계획 만들기

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

terraform plan -out main.tfplan

핵심 사항:

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

Terraform 실행 계획 적용

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

terraform apply main.tfplan

핵심 사항:

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

결과 확인

  1. 실행 az network private-dns zone list 하여 모든 DNS 영역을 보고 찾습니다.

    az network private-dns zone list --output table
    
  2. DNS 영역과 연결된 리소스 그룹을 보려면 실행 az network private-dns zone show 합니다.

    az network private-dns zone show --name $dnsZoneName --resource-group $resourceGroupName
    

리소스 정리

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

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

    terraform plan -destroy -out main.destroy.tfplan
    

    핵심 사항:

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

    terraform apply main.destroy.tfplan
    

Azure의 Terraform 문제 해결

Azure에서 Terraform을 사용할 때 발생하는 일반적인 문제를 해결합니다.

다음 단계