在我的 Azure 基础结构中,我有一项策略阻止我在没有网络安全组的情况下创建子网。因为我想创建一个灵活的 postgres 服务器,所以我需要创建一个委托(delegate)子网。为了创建委托(delegate)子网,我需要将子网与 vnet 创建分开,即我需要在与 vnet 不同的资源中创建子网。理论上,我应该这样做:
resource "azurerm_virtual_network" "vnet_hub" {
name = "HubVnet"
location = var.location
resource_group_name = var.resource_group_name
address_space = ["10.0.0.0/21"]
}
resource "azurerm_subnet" "db" {
name = "db-subnet"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.vnet_hub.name
address_prefixes = ["10.0.3.0/24"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.DBforPostgreSQL/flexibleServers"
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
}
}
}
resource "azurerm_network_security_group" "db" {
name = "db-nsg"
location = var.location
resource_group_name = var.resource_group_name
security_rule {
name = "test123"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_subnet_network_security_group_association" "db" {
subnet_id = azurerm_subnet.db.id
network_security_group_id = azurerm_network_security_group.db.id
}
但是,这是不可能的,因为委派子网首先在没有网络安全组的情况下创建,然后才与 NSG 关联。 Azure 提示说,由于我们实现的 Azure 策略,没有 NSG 就无法创建子网。我们不想废除该政策。
所以到目前为止我能想到的唯一解决方案如下:
resource "azurerm_virtual_network" "vnet_hub" {
name = "HubVnet"
location = var.location
resource_group_name = var.resource_group_name
address_space = ["10.0.0.0/21"]
}
resource "azurerm_network_security_group" "db" {
name = "db-nsg"
location = var.location
resource_group_name = var.resource_group_name
security_rule {
name = "test123"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "null_resource" "database_subnet" {
depends_on = [azurerm_virtual_network.vnet_hub]
provisioner "local-exec" {
command = format("%s/%s", path.module, "add_database_subnet.sh")
interpreter = ["sh"]
environment = {
RESOURCE_GROUP_NAME = var.resource_group_name
SUBNET_NAME = "db-subnet"
VNET_NAME = azurerm_virtual_network.vnet_hub.name
ADDRESS_PREFIX = "10.0.3.0/24"
NETWORK_SECURITY_GROUP_ID = azurerm_network_security_group.db.id
}
}
}
其中 add_database_subnet.sh
包含
#! /bin/sh
az network vnet subnet create \
--name "${SUBNET_NAME}" \
--vnet-name "${VNET_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--address-prefixes "${ADDRESS_PREFIX}" \
--network-security-group "${NETWORK_SECURITY_GROUP_ID}" \
--service-endpoints "Microsoft.Storage" \
--delegations "Microsoft.DBforPostgreSQL/flexibleServers"
虽然当我运行一次terraformdeploy
时它可以工作,但当我运行它两次时它就不起作用了。当我第二次运行 terraform deploy
时,db-subnet
被删除,使我的数据库不再有子网。
例如,为了更新我的基础设施,我希望能够运行多个terraform部署
。我应该如何进行?我能做些什么来实现它?有没有不用shell脚本的方法?
最佳答案
我尝试在我的环境中重现相同的结果,结果如下
首先,我创建了虚拟网络和网络安全组资源,然后创建委托(delegate)的子网资源并将其与<使用 Terraform 的strong>VNet 和 NSG 资源。
您可以使用 Terraform lifecycle
元参数来防止删除子网资源。您可以将 azurerm_subnet
资源 block 中的 prevent_destroy
属性设置为 true
以防止其被删除。
lifecycle {
prevent_destroy = true
}
prevent_destroy
设置为 true,terraform 不会删除子网资源,即使它认为不再需要该资源。这应该可以解决您在多次运行 Terraform 时遇到的问题。
Terraform 代码:
provider "azurerm" {
features {}
}
#Resource Group Creation
resource "azurerm_resource_group" "sqlrg" {
name = "test-resources"
location = "eastus"
}
#Virtual Network creation
resource "azurerm_virtual_network" "sqlvnet" {
name = "example-security-group"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.sqlrg.location
resource_group_name = azurerm_resource_group.sqlrg.name
}
#NSG Creation
resource "azurerm_network_security_group" "sqlnsg" {
name = "example-security-group"
location = azurerm_resource_group.sqlrg.location
resource_group_name = azurerm_resource_group.sqlrg.name
# Subnet Creation
resource "azurerm_subnet" "sqlsubnet" {
name = "example-security-group"
resource_group_name = azurerm_resource_group.sqlrg.name
virtual_network_name = azurerm_virtual_network.sqlvnet.name
address_prefixes = ["10.0.5.0/24"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.DBforPostgreSQL/flexibleServers"
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
}
}
lifecycle {
prevent_destroy = true
}
}
}
resource "azurerm_subnet_network_security_group_association" "sqlnic" {
subnet_id = azurerm_subnet.sqlsubnet.id
network_security_group_id = azurerm_network_security_group.sqlnsg.id
}
地形应用:
当我尝试添加和更新子网时,它不会删除现有子网。
更新子网 IP 前缀
在同一 Vnet 中添加另一个子网
当我在门户中检查相同内容时,它已更新,而不会破坏现有资源,如下所示。
关于azure - 如何使用 terraform 使 azure 子网安装可重入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75754978/