[Azure] Terraform - 다수의 VM 생성 및 LB 연동

2024. 10. 29. 11:17·클라우드(Azure, AWS, Alibaba)

Terraform 코드를 사용하여 다수의 리눅스 VM 생성 및 LB 연동

  • 리소스 그룹 - azuredev-rg (생성되어 있는 그룹 사용)
  • VNET 이름 - azuredev-vnet (신규 생성)
  • SUBNET 이름 - azuredev-subnet (신규 생성)
  • 공인 IP - azuredev1-pip  (신규 생성)
  • VM 이름 - azuredev1  (신규 생성)
  • SSH 접근은 사용자 계정 azuser로 패스워드 인증 사용
  • LB 이름 -  azuredev-lb (신규 생성)
  • LB 공인 IP - azuredev-lb-pip (신규 생성)

추가적으로 SSH 및 80 포트 접속을 위한 NSG 구성 및 포트 설정이 필요(NSG 이름 - azuredev-nsg) -> 수동 구성


 

디렉토리 구조

 

 

각 파일의 내용

  • 메인 구성 - main.tf
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "4.4.0"
    }
  }
}

variable "subscription_id" {}
variable "client_id" {}
variable "client_secret" {}
variable "tenant_id" {}


provider "azurerm" {
  # Configuration options
  features {}

  subscription_id = var.subscription_id
  client_id       = var.client_id
  client_secret   = var.client_secret
  tenant_id       = var.tenant_id

}

# 리소스 그룹 신규 구성 시
# resource "azurerm_resource_group" "rg" {
#   location = var.location
#   name     = "azuredev-rg"
# }

# 기존 리소스 그룹 사용 시
data "azurerm_resource_group" "rg" {
   name     = "azuredev-rg"
 }

module "networking" {
  source              = "./modules/networking"
  resource_group_name = data.azurerm_resource_group.rg.name
  location            = data.azurerm_resource_group.rg.location
  vnet_name           = "azuredev-vnet"
  subnet_name         = "azuredev-subnet"
}

module "loadbalancer" {
  source              = "./modules/loadbalancer"
  resource_group_name = data.azurerm_resource_group.rg.name
  location            = data.azurerm_resource_group.rg.location
  lb_name             = "azuredev-lb"
  subnet_id           = module.networking.subnet_id
}

module "vm" {
  count               = 3
  source              = "./modules/vm"
  resource_group_name = data.azurerm_resource_group.rg.name
  location            = data.azurerm_resource_group.rg.location
  subnet_id           = module.networking.subnet_id
  vm_name             = "azuredev-${count.index + 1}"
  admin_username      = "azuser"
  admin_password      = var.admin_password
  lb_backend_pool_id  = module.loadbalancer.backend_pool_id
}

 

  • 변수 - variables.tf
variable "admin_password" {
  description = "Password for the admin user"
  type        = string
}

 

  • 출력 - outputs.tf
output "vm_public_ips" {
  value = module.vm[*].public_ip_address
}

output "lb_public_ip" {
  value = module.loadbalancer.public_ip_address
}

 

  • 네트워킹 모듈 - modules/networking/main.tf
resource "azurerm_virtual_network" "vnet" {
  name                = var.vnet_name
  address_space       = ["10.0.0.0/16"]
  location            = var.location
  resource_group_name = var.resource_group_name
}

resource "azurerm_subnet" "subnet" {
  name                 = var.subnet_name
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.101.0/24"]
}

 

  • 네트워킹 모듈 변수 - modules/networking/variables.tf
variable "resource_group_name" {
  description = "Name of the resource group"
  type        = string
}

variable "location" {
  description = "Azure region"
  type        = string
}

variable "vnet_name" {
  description = "Name of the virtual network"
  type        = string
}

variable "subnet_name" {
  description = "Name of the subnet"
  type        = string
}

 

  • 네트워킹 모듈 출력 - modules/networking/outputs.tf
output "subnet_id" {
  value = azurerm_subnet.subnet.id
}

 

  • 로드밸런스 모듈 - modules/loadbalancer/main.tf
resource "azurerm_public_ip" "lb_public_ip" {
  name                = "${var.lb_name}-pip"
  location            = var.location
  resource_group_name = var.resource_group_name
  allocation_method   = "Static"
  sku                 = "Standard"
}

resource "azurerm_lb" "lb" {
  name                = var.lb_name
  location            = var.location
  resource_group_name = var.resource_group_name
  sku                 = "Standard"

  frontend_ip_configuration {
    name                 = "PublicIPAddress"
    public_ip_address_id = azurerm_public_ip.lb_public_ip.id
  }
}

resource "azurerm_lb_backend_address_pool" "backend_pool" {
  loadbalancer_id = azurerm_lb.lb.id
  name            = "BackEndAddressPool"
}

resource "azurerm_lb_probe" "probe" {
  loadbalancer_id = azurerm_lb.lb.id
  name            = "http-probe"
  port            = 80
}

resource "azurerm_lb_rule" "rule" {
  loadbalancer_id                = azurerm_lb.lb.id
  name                           = "http"
  protocol                       = "Tcp"
  frontend_port                  = 80
  backend_port                   = 80
  frontend_ip_configuration_name = "PublicIPAddress"
  backend_address_pool_ids       = [azurerm_lb_backend_address_pool.backend_pool.id]
  probe_id                       = azurerm_lb_probe.probe.id
}

 

  • 로드밸런스 모듈 변수 - modules/loadbalancer/variables.tf
variable "resource_group_name" {
  description = "Name of the resource group"
  type        = string
}

variable "location" {
  description = "Azure region"
  type        = string
}

variable "lb_name" {
  description = "Name of the load balancer"
  type        = string
}

variable "subnet_id" {
  description = "ID of the subnet"
  type        = string
}

 

  • 로드밸런스 모듈 출력 - modules/loadbalancer/outputs.tf
output "backend_pool_id" {
  value = azurerm_lb_backend_address_pool.backend_pool.id
}

output "public_ip_address" {
  value = azurerm_public_ip.lb_public_ip.ip_address
}

 

  • VM 모듈 - modules/vm/main.tf
resource "azurerm_public_ip" "vm_public_ip" {
  name                = "${var.vm_name}-pip"
  location            = var.location
  resource_group_name = var.resource_group_name
  allocation_method   = "Static"
  sku                 = "Standard"
}

resource "azurerm_network_interface" "nic" {
  name                = "${var.vm_name}-nic"
  location            = var.location
  resource_group_name = var.resource_group_name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = var.subnet_id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.vm_public_ip.id
  }
}

resource "azurerm_linux_virtual_machine" "vm" {
  name                = var.vm_name
  resource_group_name = var.resource_group_name
  location            = var.location
  size                = "Standard_B1s"
  admin_username      = var.admin_username
  admin_password      = var.admin_password
  disable_password_authentication = false
  network_interface_ids = [
    azurerm_network_interface.nic.id,
  ]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "ubuntu-24_04-lts"
    sku       = "server"
    version   = "latest"
  }
}

resource "azurerm_network_interface_backend_address_pool_association" "example" {
  network_interface_id    = azurerm_network_interface.nic.id
  ip_configuration_name   = "internal"
  backend_address_pool_id = var.lb_backend_pool_id
}

 

  • VM 모듈 변수 - modules/vm/variables.tf
variable "resource_group_name" {
  description = "Name of the resource group"
  type        = string
}

variable "location" {
  description = "Azure region"
  type        = string
}

variable "subnet_id" {
  description = "ID of the subnet"
  type        = string
}

variable "vm_name" {
  description = "Name of the virtual machine"
  type        = string
}

variable "admin_username" {
  description = "Admin username"
  type        = string
}

variable "admin_password" {
  description = "Admin password"
  type        = string
}

variable "lb_backend_pool_id" {
  description = "ID of the load balancer backend pool"
  type        = string
}

 

  • VM 모듈 출력 - modules/vm/outputs.tf
output "public_ip_address" {
  value = azurerm_public_ip.vm_public_ip.ip_address
}

 

 

 

VM 리소스 생성

1. 초기화

terraform init

 

2. 계획 확인

  • plan 실행 시 azuser 계정이 사용할 패스워드(Password123!)를 함께 등록
terraform plan -var="admin_password=Password123!"

 

 

3. 리소스 생성 

  • apply 실행 시 azuser 계정이 사용할 패스워드 (Password123!)를 함께 등록
terraform apply -var="admin_password=Password123!"

 

 

 

VM 리소스 확인

 

 

 

VM 접속 확인

 

 

 

접속 테스트

1. apache2 설치

2. 외부 접근을 위한 NSG 설정

  • 100번 - SSH 접근을 위한 포트 오픈 
  • 110번 - 웹 페이지 접근을 위한 포트 오픈 (LB 공인 IP)
  • 120번 - 개별 VM HTTP 포트 오픈 (VM 사설 IP)
    • "외부 -> LB -> VM" 통신의 경우 LB IP 뿐만 아니라 VM IP도 오픈이 필요함

3. LB 접속 테스트

 

 


"외부 -> LB -> VM" 통신의 경우 LB IP 뿐만 아니라 VM IP도 오픈이 필요한 이유

  • 참고: https://adityagarg94.medium.com/azure-loadbalancer-fundamentals-how-to-use-nsgs-with-azure-classic-loadbalancer-2-3-1ea57eec2bd9
 

Azure Loadbalancer Fundamentals, How to use NSGs with Azure Classic Loadbalancer?(2/3)

This blog is a continuation of my first article here:

adityagarg94.medium.com

 

 

 

 

저작자표시 비영리 변경금지 (새창열림)
'클라우드(Azure, AWS, Alibaba)' 카테고리의 다른 글
  • [Azure] Terraform - VM 생성 및 apache2 자동 설치(NSG 정책 추가 포함)
  • [Azure] Terraform - AGW 구성 후 기존 VM 및 NSG 정책 추가
  • [Azure] Terraform - VM 생성
  • [Azure] 별도의 인증 파일을 사용하여 서비스 주체와 Terraform 연동
기억보다는 기록을...
기억보다는 기록을...
내가 보려고 정리하는 글..
  • 기억보다는 기록을...
    메모장
    기억보다는 기록을...
    • 분류 전체보기
      • 클라우드(Azure, AWS, Alibaba)
      • 모니터링(Zabbix,Grafana)
      • 가상화(VMWare, Hyper-V)
      • Docker
      • Ansible
      • Linux
      • Windows
      • 이것저것
      • SQL
      • -------------------------
      • 재테크
  • 전체
    오늘
    어제
  • hELLO· Designed By정상우.v4.10.2
기억보다는 기록을...
[Azure] Terraform - 다수의 VM 생성 및 LB 연동
상단으로

티스토리툴바