Terraform을 사용하여 Azure 가상 머신 확장 집합 만들기
Terraform은 클라우드 인프라의 정의, 미리 보기 및 배포를 사용합니다. Terraform을 사용하는 경우 HCL 구문를 사용하여 구성 파일을 만듭니다. HCL 구문을 사용하면 클라우드 공급자(예: Azure) 그리고 클라우드 인프라를 구성하는 요소를 지정할 수 있습니다. 구성 파일을 만든 후 배포되기 전에 인프라 변경을 미리 볼 수 있는 실행 계획를 만듭니다. 변경 내용을 확인 한 후에는 실행 계획을 적용하여 인프라를 배포합니다.
Azure 가상 머신 확장 집합을 사용하면 동일한 VM을 구성할 수 있습니다. VM 인스턴스 수는 수요 또는 일정에 따라 조정할 수 있습니다. 자세한 내용은 Azure Portal에서 가상 머신 확장 집합의 자동 크기 조정을 참조하세요.
이 문서에서는 다음 방법을 설명합니다.
- Terraform 배포 설정
- Terraform 배포용 변수 및 출력 사용
- 네트워크 인프라 만들기 및 배포
- 가상 머신 확장 집합 만들기 및 배포 및 네트워크에 연결
- SSH를 통해 VM에 연결하는 jumpbox 만들기 및 배포
1. 환경 구성
- Azure 구독: Azure 구독이 아직 없는 경우 시작하기 전에 체험 계정을 만듭니다.
Terraform 구성: 아직 구성하지 않은 경우 다음 옵션 중 하나를 사용하여 Terraform을 구성합니다.
- SSH 키 쌍 만들기: 자세한 내용은 Azure에서 Linux VM에 대해 SSH 공개 및 프라이빗 키 쌍을 만들고 사용하는 방법을 참조하세요.
2. Terraform 코드 구현
샘플 Terraform 코드를 테스트할 디렉터리를 만들고, 이를 현재 디렉터리로 만듭니다.
main.tf
라는 파일을 만들고 다음 코드를 삽입합니다.terraform { required_version = ">=0.12" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>3.0" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } } resource "random_password" "password" { count = var.admin_password == null ? 1 : 0 length = 20 } locals { admin_password = try(random_password.password[0].result, var.admin_password) } resource "azurerm_resource_group" "vmss" { name = var.resource_group_name location = var.location tags = var.tags } resource "random_string" "fqdn" { length = 6 special = false upper = false numeric = false } resource "azurerm_virtual_network" "vmss" { name = "vmss-vnet" address_space = ["10.0.0.0/16"] location = var.location resource_group_name = azurerm_resource_group.vmss.name tags = var.tags } resource "azurerm_subnet" "vmss" { name = "vmss-subnet" resource_group_name = azurerm_resource_group.vmss.name virtual_network_name = azurerm_virtual_network.vmss.name address_prefixes = ["10.0.2.0/24"] } resource "azurerm_public_ip" "vmss" { name = "vmss-public-ip" location = var.location resource_group_name = azurerm_resource_group.vmss.name allocation_method = "Static" domain_name_label = random_string.fqdn.result tags = var.tags } resource "azurerm_lb" "vmss" { name = "vmss-lb" location = var.location resource_group_name = azurerm_resource_group.vmss.name frontend_ip_configuration { name = "PublicIPAddress" public_ip_address_id = azurerm_public_ip.vmss.id } tags = var.tags } resource "azurerm_lb_backend_address_pool" "bpepool" { loadbalancer_id = azurerm_lb.vmss.id name = "BackEndAddressPool" } resource "azurerm_lb_probe" "vmss" { loadbalancer_id = azurerm_lb.vmss.id name = "ssh-running-probe" port = var.application_port } resource "azurerm_lb_rule" "lbnatrule" { loadbalancer_id = azurerm_lb.vmss.id name = "http" protocol = "Tcp" frontend_port = var.application_port backend_port = var.application_port backend_address_pool_ids = [azurerm_lb_backend_address_pool.bpepool.id] frontend_ip_configuration_name = "PublicIPAddress" probe_id = azurerm_lb_probe.vmss.id } resource "azurerm_virtual_machine_scale_set" "vmss" { name = "vmscaleset" location = var.location resource_group_name = azurerm_resource_group.vmss.name upgrade_policy_mode = "Manual" sku { name = "Standard_DS1_v2" tier = "Standard" capacity = 2 } storage_profile_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "16.04-LTS" version = "latest" } storage_profile_os_disk { name = "" caching = "ReadWrite" create_option = "FromImage" managed_disk_type = "Standard_LRS" } storage_profile_data_disk { lun = 0 caching = "ReadWrite" create_option = "Empty" disk_size_gb = 10 } os_profile { computer_name_prefix = "vmlab" admin_username = var.admin_user admin_password = local.admin_password custom_data = file("web.conf") } os_profile_linux_config { disable_password_authentication = false } network_profile { name = "terraformnetworkprofile" primary = true ip_configuration { name = "IPConfiguration" subnet_id = azurerm_subnet.vmss.id load_balancer_backend_address_pool_ids = [azurerm_lb_backend_address_pool.bpepool.id] primary = true } } tags = var.tags } resource "azurerm_public_ip" "jumpbox" { name = "jumpbox-public-ip" location = var.location resource_group_name = azurerm_resource_group.vmss.name allocation_method = "Static" domain_name_label = "${random_string.fqdn.result}-ssh" tags = var.tags } resource "azurerm_network_interface" "jumpbox" { name = "jumpbox-nic" location = var.location resource_group_name = azurerm_resource_group.vmss.name ip_configuration { name = "IPConfiguration" subnet_id = azurerm_subnet.vmss.id private_ip_address_allocation = "Dynamic" public_ip_address_id = azurerm_public_ip.jumpbox.id } tags = var.tags } resource "azurerm_virtual_machine" "jumpbox" { name = "jumpbox" location = var.location resource_group_name = azurerm_resource_group.vmss.name network_interface_ids = [azurerm_network_interface.jumpbox.id] vm_size = "Standard_DS1_v2" storage_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "16.04-LTS" version = "latest" } storage_os_disk { name = "jumpbox-osdisk" caching = "ReadWrite" create_option = "FromImage" managed_disk_type = "Standard_LRS" } os_profile { computer_name = "jumpbox" admin_username = var.admin_user admin_password = local.admin_password } os_profile_linux_config { disable_password_authentication = false } tags = var.tags }
variables.tf
라는 파일을 만들어 프로젝트 변수를 포함하고 다음 코드를 삽입합니다.variable "resource_group_name" { description = "Name of the resource group in which the resources will be created" default = "myResourceGroup" } variable "location" { default = "eastus" description = "Location where resources will be created" } variable "tags" { description = "Map of the tags to use for the resources that are deployed" type = map(string) default = { environment = "codelab" } } variable "application_port" { description = "Port that you want to expose to the external load balancer" default = 80 } variable "admin_user" { description = "User name to use as the admin account on the VMs that will be part of the VM scale set" default = "azureuser" } variable "admin_password" { description = "Default password for admin account" default = null sensitive = true }
output.tf
라는 파일을 만들어 Terraform이 표시하는 값을 지정하고 다음 코드를 삽입합니다.output "vmss_public_ip_fqdn" { value = azurerm_public_ip.vmss.fqdn } output "jumpbox_public_ip_fqdn" { value = azurerm_public_ip.jumpbox.fqdn } output "jumpbox_public_ip" { value = azurerm_public_ip.jumpbox.ip_address }
web.conf
라는 파일을 만들고 다음 코드를 삽입합니다.#cloud-config packages: - nginx
3. Terraform 초기화
terraform init를 실행하여 Terraform 배포를 초기화합니다. 이 명령은 Azure 리소스를 관리하는 데 필요한 Azure 공급자를 다운로드합니다.
terraform init -upgrade
주요 정보:
-upgrade
매개 변수는 필요한 공급자 플러그 인을 구성의 버전 제약 조건을 준수하는 최신 버전으로 업그레이드합니다.
4. Terraform 실행 계획 만들기
terraform plan을 실행하여 실행 계획을 만듭니다.
terraform plan -out main.tfplan
주요 정보:
terraform plan
명령은 실행 계획을 만들지만 실행하지는 않습니다. 대신 구성 파일에 지정된 구성을 만드는 데 필요한 작업을 결정합니다. 이 패턴을 사용하면 실제 리소스를 변경하기 전에 실행 계획이 예상과 일치하는지 확인할 수 있습니다.- 선택 사항인
-out
매개 변수를 사용하여 계획의 출력 파일을 지정할 수 있습니다.-out
매개 변수를 사용하면 검토한 계획이 정확하게 적용됩니다.
5. Terraform 실행 계획 적용
terraform apply를 실행하여 실행 계획을 클라우드 인프라에 적용합니다.
terraform apply main.tfplan
주요 정보:
- 예시
terraform apply
명령은 이전에terraform plan -out main.tfplan
를 실행했다고 가정합니다. -out
매개 변수에 다른 파일 이름을 지정한 경우terraform apply
에 대한 호출에서 동일한 파일 이름을 사용합니다.-out
매개 변수를 사용하지 않은 경우 매개 변수 없이terraform apply
를 호출합니다.
6. 결과 확인
명령의
terraform apply
출력에서 다음 값이 표시됩니다.- 가상 머신 FQDN
- Jumpbox FQDN
- Jumpbox IP 주소
가상 머신 URL로 이동하여 nginx 시작이라는 텍스트가 있는 기본 페이지를 확인합니다.
SSH를 사용하여 변수 파일에 정의된 사용자 이름과
terraform apply
를 실행할 때 지정한 암호를 사용하여 jumpbox VM에 연결합니다. 예:ssh azureuser@<ip_address>
7. 리소스 정리
Terraform을 통해 리소스를 만들 필요가 더 이상 없으면 다음 단계를 수행합니다.
terraform 플랜을 실행하고
destroy
플래그를 지정합니다.terraform plan -destroy -out main.destroy.tfplan
주요 정보:
terraform plan
명령은 실행 계획을 만들지만 실행하지는 않습니다. 대신 구성 파일에 지정된 구성을 만드는 데 필요한 작업을 결정합니다. 이 패턴을 사용하면 실제 리소스를 변경하기 전에 실행 계획이 예상과 일치하는지 확인할 수 있습니다.- 선택 사항인
-out
매개 변수를 사용하여 계획의 출력 파일을 지정할 수 있습니다.-out
매개 변수를 사용하면 검토한 계획이 정확하게 적용됩니다.
terraform apply를 실행하여 실행 계획을 적용합니다.
terraform apply main.destroy.tfplan
Azure의 Terraform 문제 해결
Azure에서 Terraform을 사용할 때 일반적인 문제 해결