azure - 如何使用 terraform 使 azure 子网安装可重入?

标签 azure terraform

在我的 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
    }

地形应用:

enter image description here

当我尝试添加和更新子网时,它不会删除现有子网。

更新子网 IP 前缀

enter image description here

在同一 Vnet 中添加另一个子网

enter image description here

当我在门户中检查相同内容时,它已更新,而不会破坏现有资源,如下所示。

enter image description here

关于azure - 如何使用 terraform 使 azure 子网安装可重入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75754978/

相关文章:

azure - 上传 zip 文件时 Windows Azure 中出现错误 : "ZipException was unhandled" "EOF in header"

amazon-web-services - 将 OpenAPI 规范中描述的 REST API 转换为 Terraform 模板中描述的 AWS API Gateway REST API

amazon-web-services - 启动配置中的用户数据与 Ansible

terraform - gitignore .tfvars 但不是 .auto.tfvars

terraform - 对空资源本地执行使用时间戳

azure - Azure 数据工厂的发布流程是否支持导出 ARM 模板?

asp.net - Windows Azure 访问 POST 数据

azure - Windows Azure : Mismatch of the security binding between the client and the server

azure - 负载中的属性文件夹具有与架构不匹配的值

kubernetes - 在 EKS 上使用 Istio Operator 和 Terraform 安装 Istio