Agenda
- 서로 다른 Azure 구독에 리소스를 배포하는 시나리오
provider
지정으로 서로 다른 구독에 리소스를 배포하기
서로 다른 구독에 리소스를 배포하는 시나리오
Azure 허브 앤 스포크 아키텍처를 도입하면서, 허브 구독에서 공용 리소스를 중앙 집중식으로 관리하고 각 스포크 구독에서는 독립적인 리소스를 운용하는 시나리오가 존재하는 경우 서로 다른 구독에 리소스를 배포하는 Terraform 코드가 필요할 수 있다.
허브 VNET 및 스포크 VNET 피어링 구성
허브 VNET과 각 스포크 VNET 을 피어링하여 네트워크 트래픽의 중앙 집중식 관리를 고려하고 있다면, Terraform 을 사용하여 리소스를 관리하고 배포하는 것은 더 복잡해 진다. 이러한 시나리오를 처리하기 위해서 Terraform 에서는 다중 프로바이더 설정을 사용하여 각 구독에 대한 자격증명과 구성을 따로 관리할 수 있다.
Terraform 폴더 구성
C:.
│ .terraform.lock.hcl
│ main_hub.tf
│ main_spoke.tf
│ provider.tf
│ terraform.tfstate
│ terraform.tfstate.backup
│ variables.tf
│
├─.terraform
│ └─providers
│ └─registry.terraform.io
│ └─hashicorp
│ ├─azurerm
│ │ └─3.102.0
│ │ └─windows_386
│ │ LICENSE.txt
│ │
│ └─null
│ └─3.2.2
│ └─windows_386
│ terraform-provider-null_v3.2.2_x5.exe
│
├─Azure CLI Peering Resync # Optional
│ main_hub_bak.tf
│ main_spoke_bak.tf
│
└─Replace Trigger Peering Resync # Optional
main_hub_bak.tf
main_spoke_bak.tf
다중 프로바이더 설정 ★
각 구독에 대해 별도의 azurerm
프로바이더 인스턴스를 구성한다. 이를 통해 각 구독의 리소스를 관리할 수 있다.
# Common provider.tf
provider "azurerm" {
features {}
subscription_id = "xxxxxxx-xxxxxxx-xxxxxxx-xxxxxxx" # Hub subscription ID
alias = "hub" # Hub subscription Alias
}
provider "azurerm" {
features {}
subscription_id = "xxxxxxx-xxxxxxx-xxxxxxx-xxxxxxx" # Spoke subscription ID
alias = "spoke" # Spoke subscription Alias
}
프로바이더 별칭 사용 방법 ★
VNET 배포 설정
VNET 을 배포할 리소스 그룹을 설정하고, VNET 배포 설정 코드를 추가한다. 리소스 그룹이 생성되는 도중에 VNET 을 생성하려고 하면 리소스 그룹이 존재하지 않다는 에러가 발생하므로, VNET 배포 코드에 리소스 그룹에 대한 의존성 depends_on
을 추가한다.
허브 구독에 있는 VNET과 스포크 구독에 있는 VNET을 구분하기 위해서, 프로바이더의 별칭provider = azurerm.<alias>
를 사용하여 해당 구독의 프로바이더 인스턴스를 지정한다.
# Hub main.tf
resource "azurerm_resource_group" "hub_rg" {
provider = azurerm.hub # Hub subscription provider instance
location = var.location
name = var.resource_group_name
}
# Spoke main.tf
resource "azurerm_resource_group" "spoke_rg" {
provider = azurerm.spoke # Spoke subscription provider instance
location = var.location
name = var.resource_group_name
}
# Hub main.tf
resource "azurerm_virtual_network" "hub_vnet" {
depends_on = [azurerm_resource_group.hub_rg]
provider = azurerm.hub
name = "hubVnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.hub_rg.location
resource_group_name = azurerm_resource_group.hub_rg.name
}
# Spoke main.tf
resource "azurerm_virtual_network" "spoke_vnet" {
depends_on = [azurerm_resource_group.spoke_rg]
provider = azurerm.spoke
name = "spokeVnet"
address_space = ["10.1.0.0/16"]
location = azurerm_resource_group.spoke_rg.location
resource_group_name = azurerm_resource_group.spoke_rg.name
}
VNET 피어링 배포 설정
허브 VNET 과 스포크 VNET 간에 피어링을 설정한다. VNET 과 마찬가지로 피어링 리소스는 각각의 구독의 프로바이더를 사용한다.
Tip. Lifecycle
추가한 이유
VNET 의 주소 공간의 변경이 있을 경우, 허브 와 스포크 VNET 간의 재동기가 필요하다. Lifecycle
로 각 VNET 의 address space 의 변경이 있을 경우, 피어링을 재설정하는 코드를 추가하여 자동으로 재동기하도록 코드를 구성하였다.
ref url : Vnet peering out of sync
# Hub main.tf
resource "azurerm_virtual_network_peering" "hub_to_spoke" {
depends_on = [
azurerm_virtual_network.hub_vnet,
azurerm_virtual_network.spoke_vnet
]
provider = azurerm.hub
name = "hub-to-spoke"
resource_group_name = azurerm_resource_group.hub_rg.name
virtual_network_name = azurerm_virtual_network.hub_vnet.name
remote_virtual_network_id = azurerm_virtual_network.spoke_vnet.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
lifecycle {
replace_triggered_by = [azurerm_virtual_network.hub_vnet.address_space, azurerm_virtual_network.spoke_vnet.address_space]
}
}
# Spoke main.tf
resource "azurerm_virtual_network_peering" "spoke_to_hub" {
depends_on = [
azurerm_virtual_network.spoke_vnet,
azurerm_virtual_network.hub_vnet
]
provider = azurerm.spoke
name = "spoke-to-hub"
resource_group_name = azurerm_resource_group.spoke_rg.name
virtual_network_name = azurerm_virtual_network.spoke_vnet.name
remote_virtual_network_id = azurerm_virtual_network.hub_vnet.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
lifecycle {
replace_triggered_by = [azurerm_virtual_network.hub_vnet.address_space, azurerm_virtual_network.spoke_vnet.address_space]
}
}
코드 배포 테스트
첫번째 배포 (리소스 그룹 + VNET + 피어링 생성)
Terraform 코드 작성이 완료 되었으니, 실제 배포 후 결과를 확인한다.
두번째 배포 (VNET 피어링 Resync 테스트)
각 VNET의 피어링 리소스가 재생성 되는 것을 확인할 수 있다.
Tip. 피어링 재설정의 경우, 스포크 VNET 의 주소 공간을 변경하고 재배포하는 것으로 확인할 수 있다.
# Spoke main.tf
resource "azurerm_virtual_network" "spoke_vnet" {
depends_on = [azurerm_resource_group.spoke_rg]
provider = azurerm.spoke
name = "spokeVnet"
address_space = ["10.1.0.0/16", "10.2.0.0/16"]
location = azurerm_resource_group.spoke_rg.location
resource_group_name = azurerm_resource_group.spoke_rg.name
}
Terraform 로그 확인
# tf apply -auto-approve
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# null_resource.hub_peering_async is tainted, so must be replaced
-/+ resource "null_resource" "hub_peering_async" {
~ id = "1557426316" -> (known after apply)
# (1 unchanged attribute hidden)
}
# null_resource.spoke_peering_async is tainted, so must be replaced
-/+ resource "null_resource" "spoke_peering_async" {
~ id = "576413854" -> (known after apply)
# (1 unchanged attribute hidden)
}