배포 계획
구조: Hub-Spoke 네트워크 모델
- Hub: 공통 인프라 구성 (VPN Gateway, Firewall 등)
- Spoke: 업무별 구분된 네트워크 (Web, WAS, DB 등 리소스 배치)
보안 구성
- NSG (Network Security Group): 각 Spoke VNet 및 서브넷에 할당
- VPN Gateway: Hub VNet에 배치
- Firewall: Hub VNet에 배치 및 UDR과 연동
리소스 그룹 구조
- RG-NETWORK – 가상 네트워크 및 서브넷 등 네트워크 리소스
- RG-SECURITY – NSG, Firewall, VPN 등 보안 리소스
- RG-COMPUTE – 가상 머신 등 컴퓨트 리소스
- RG-STORAGE – Storage Account 등 저장소 리소스
Tag 구성
- Key : Value 예시
- ResourceName : vm-web-prd-01 등
- ServiceType : WEB, WAS, DB 등
- Environment : PRD, QA, DEV
- DeploymentDate : 2025-05-07 등
1. Firewall 모듈
- modules/firewall/main.tf
variable "firewalls" {
description = "Firewall 구성 정보 map"
type = map(any)
default = {}
}
variable "location" {
description = "리소스 위치"
type = string
}
variable "resource_groups" {
description = "리소스 그룹 이름 map (예: { security = \"rg-security\" })"
type = map(string)
}
variable "subnet_ids" {
description = "Subnet ID map (예: { firewall = \"subnet-id\" })"
type = map(string)
}
resource "azurerm_public_ip" "firewall_pip" {
for_each = var.firewalls
name = each.value.pip_name
location = var.location
resource_group_name = var.resource_groups.security
allocation_method = "Static"
sku = "Standard"
tags = merge({
DeploymentDate = "2025-05-07"
}, each.value.tags)
}
resource "azurerm_firewall" "hub_fw" {
for_each = var.firewalls
name = each.value.fw_name
location = var.location
resource_group_name = var.resource_groups.security
ip_configuration {
name = each.value.ip_config_name
subnet_id = var.subnet_ids[each.key]
public_ip_address_id = azurerm_public_ip.firewall_pip[each.key].id
}
sku_name = "AZFW_VNet"
sku_tier = "Standard"
tags = merge({
DeploymentDate = "2025-05-07"
}, each.value.tags)
}
- main.tf
module "firewall" {
source = "./modules/firewall"
location = var.location
resource_groups = {
security = module.resource_groups.resource_group_names["security"]
}
subnet_ids = {
fw01 = module.subnet.subnet_ids["firewall"]
}
firewalls = {
fw01 = {
pip_name = "hub-fw-pip"
fw_name = "hub-fw"
ip_config_name = "hub-fw-ipcfg"
tags = {
DeploymentDate = "2025-05-07"
}
}
}
}
terraform validate를 통해 설정 유효성 검사
terraform plan을 통해 리소스 생성 계획 확인
terraform apply -auto-approve (yes 자동 입력 )
2. UDR 모듈
- UDR : User Defined Route, 사용자 지정 경로
- Firewall을 통하는 inbound traffic은 DNAT으로 처리되나, VM outbound는 Firewall을 통해서 외부로 나갈 수 있도록 URD 설정을 해주어야함
- (Spoke) PRD web VM이 Hub의 Azure Firewall을 통해 인터넷이나 외부 네트워크로 나가도록 유도하는 UDR(User Defined Route) 설정
** UDR과 VM이 동일한 RG에 존재하지 않아도 됨. UDR은 Subnet에 연결되므로, VM의 NIC가 해당 Subnet에 속해 있다면 라우팅 정책이 잘 적용됨.
- modules/udr/main.tf
variable "route_tables" {
description = "Map of route tables"
type = map(object({
name = string
location = string
resource_group_name = string
tags = map(string)
}))
default = {}
}
variable "routes" {
description = "Map of routes, keyed by route name"
type = map(object({
route_table_name = string
resource_group_name = string
address_prefix = string
next_hop_type = string
next_hop_in_ip_address = string
}))
default = {}
}
variable "associations" {
description = "Map of subnet associations"
type = map(object({
subnet_id = string
route_table_id = string
}))
default = {}
}
# Route Table 생성
resource "azurerm_route_table" "this" {
for_each = var.route_tables
name = each.value.name
location = each.value.location
resource_group_name = each.value.resource_group_name
tags = each.value.tags
}
# Route 생성
resource "azurerm_route" "this" {
for_each = var.routes
name = each.key
resource_group_name = each.value.resource_group_name
route_table_name = each.value.route_table_name
address_prefix = each.value.address_prefix
next_hop_type = each.value.next_hop_type
next_hop_in_ip_address = each.value.next_hop_in_ip_address
}
# Subnet-Route Table 연결
resource "azurerm_subnet_route_table_association" "this" {
for_each = var.associations
subnet_id = each.value.subnet_id
route_table_id = each.value.route_table_id
}
# parent 모듈 associations 참조용
output "route_table_ids" {
value = { for k, v in azurerm_route_table.this : k => v.id }
}
- main.tf
module "udr" {
source = "./modules/udr"
route_tables = {
prd-web = {
name = "prd-web-subnet-rt"
location = var.location
resource_group_name = module.resource_groups.resource_group_names["network"]
tags = {
ResourceName = "prd-web-subnet-rt"
Environment = "PRD"
DeploymentDate = "2025-05-07"
}
}
}
routes = {
default-to-fw = {
route_table_name = "prd-web-subnet-rt"
resource_group_name = module.resource_groups.resource_group_names["network"]
address_prefix = "0.0.0.0/0"
next_hop_type = "VirtualAppliance"
next_hop_in_ip_address = module.firewall.private_ip_address["fw01"] # firewall output에서 참조
}
}
associations = {
prd-web = {
subnet_id = module.subnet.subnet_ids["prd_web"]
route_table_id = module.udr.route_table_ids["prd-web"]
}
}
}
- - modules/firewall/main.tf
** routes (경로) 생성시 기입할 next hop 참조값으로서, 서로다른 모듈에 있기 때문에 firewall에 output 값 추가
# udr (vm->fw)에서 next hop 참조용
output "private_ip_address" {
value = {
for key, fw in azurerm_firewall.hub_fw :
key => fw.ip_configuration[0].private_ip_address
}
}
terraform validate를 통해 설정 유효성 검사
terraform plan을 통해 리소스 생성 계획 확인
terraform apply -auto-approve (yes 자동 입력 )
'Cloud > AZURE' 카테고리의 다른 글
Azure Policy 정리 (1) | 2025.06.10 |
---|---|
Terraform on Azure [모듈화] - (5) VPN 모듈 (0) | 2025.05.22 |
Terraform on Azure [모듈화] - (4) VM & NSG 모듈 (1) | 2025.05.22 |
Terraform on Azure [모듈화] - (3) network 모듈 (1) | 2025.05.22 |
Terraform on Azure [모듈화] - (2) VS Code 기본 설정 (0) | 2025.05.20 |