Terraform 코드를 사용하여 리눅스 VM 생성 및 apache2 자동 설치 진행 (NSG 정책 추가 포함)
- 리소스 그룹 - azuredev-rg ( 신규 생성 )
- VNET 이름 - azuredev-vnet (신규 생성)
- SUBNET 이름 - azuredev-subnet (신규 생성)
- NSG 이름 - azuredev-nsg (신규 생성) -> SSH, HTTP 정책 생성
- 공인 IP - azuredev1-pip (신규 생성)
- VM 이름 - azuredev1 (신규 생성)
- SSH 접근은 사용자 계정 azuser로 패스워드 인증 사용
디렉토리 구조
각 파일의 내용
- 메인 구성 - 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"
}
# 네트워킹 모듈 호출
module "network" {
source = "./modules/network"
resource_group_name = azurerm_resource_group.rg.name
location = var.location
vnet_name = "azuredev-vnet"
subnet_name = "azuredev-subnet"
}
# 보안 모듈 호출
module "security" {
source = "./modules/security"
resource_group_name = azurerm_resource_group.rg.name
location = var.location
nsg_name = "azuredev-nsg"
}
# VM 모듈 호출
module "vm" {
source = "./modules/vm"
resource_group_name = azurerm_resource_group.rg.name
location = var.location
subnet_id = module.network.subnet_id
nsg_id = module.security.nsg_id
vm_name = "azuredev1"
admin_username = "azuser"
admin_password = var.admin_password
}
- 변수 - variables.tf
variable "location" {
description = "Azure 리전"
default = "koreacentral"
}
variable "admin_password" {
description = "VM 관리자 비밀번호"
type = string
}
- 출력 - outputs.tf
output "vm_public_ip" {
description = "VM의 공용 IP 주소"
value = module.vm.public_ip_address
}
- 네트워킹 모듈 - modules/network/main.tf
# VNET 생성
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/network/variables.tf
variable "resource_group_name" {
description = "리소스 그룹 이름"
type = string
}
variable "location" {
description = "Azure 리전"
type = string
}
variable "vnet_name" {
description = "VNET 이름"
type = string
}
variable "subnet_name" {
description = "서브넷 이름"
type = string
}
- 네트워킹 모듈 출력 - modules/network/outputs.tf
output "subnet_id" {
description = "생성된 서브넷의 ID"
value = azurerm_subnet.subnet.id
}
- 보안 모듈 - modules/security/main.tf
# NSG 생성
resource "azurerm_network_security_group" "nsg" {
name = var.nsg_name
location = var.location
resource_group_name = var.resource_group_name
# SSH 접근을 위한 인바운드 규칙
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 = "*"
}
security_rule {
name = "HTTP"
priority = 1002
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
- 보안 모듈 변수 - modules/security/variables.tf
variable "resource_group_name" {
description = "리소스 그룹 이름"
type = string
}
variable "location" {
description = "Azure 리전"
type = string
}
variable "nsg_name" {
description = "NSG 이름"
type = string
}
- 보안 모듈 출력 - modules/security/outputs.tf
output "nsg_id" {
description = "생성된 NSG의 ID"
value = azurerm_network_security_group.nsg.id
}
- VM 모듈 - modules/vm/main.tf
# 공용 IP 주소 생성
resource "azurerm_public_ip" "public_ip" {
name = "${var.vm_name}-pip"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Dynamic"
sku = "Basic"
}
# 네트워크 인터페이스 생성
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.public_ip.id
}
}
# NIC와 NSG 연결
resource "azurerm_network_interface_security_group_association" "nsg_association" {
network_interface_id = azurerm_network_interface.nic.id
network_security_group_id = var.nsg_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"
}
# Apache2 설치를 위한 사용자 정의 데이터
custom_data = base64encode(<<-EOF
#!/bin/bash
apt-get update
apt-get install -y apache2
systemctl start apache2
systemctl enable apache2
EOF
)
}
- VM 모듈 변수 - modules/vm/variables.tf
variable "resource_group_name" {
description = "리소스 그룹 이름"
type = string
}
variable "location" {
description = "Azure 리전"
type = string
}
variable "subnet_id" {
description = "서브넷 ID"
type = string
}
variable "nsg_id" {
description = "NSG ID"
type = string
}
variable "vm_name" {
description = "가상 머신 이름"
type = string
}
variable "admin_username" {
description = "관리자 사용자 이름"
type = string
}
variable "admin_password" {
description = "관리자 비밀번호"
type = string
sensitive = true
}
- VM 모듈 출력 - modules/vm/outputs.tf
output "public_ip_address" {
description = "VM의 공용 IP 주소"
value = azurerm_public_ip.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 접속 확인
- 접속 및 apache2 패키지 설치 확인
접속 테스트