如何使用Terraform和Azure强制删除/释放网络服务组(Network Service Group)?

huangapple go评论74阅读模式
英文:

How to force delete/release of Network Service Group using Terraform with Azure?

问题

以下是您提供的代码的翻译部分:

│ 错误:删除 Azure 中的 Network Security Group "multisqlite-bacalhau-eastus-ssh-nsg" (资源组 "multisqlite-bacalhau-eastus-rg") 时出错:network.SecurityGroupsClient#Delete: 发送请求时失败:StatusCode=400 -- 原始错误:Code="NetworkSecurityGroupOldReferencesNotCleanedUp" Message="无法删除网络安全组 multisqlite-bacalhau-eastus-ssh-nsg,因为以下 NIC 的旧引用尚未释放:(\n/subscriptions/72ac7288-fb92-4ad6-83bc-5cfd361f47ef/resourceGroups/multisqlite-bacalhau-eastus-rg/providers/Microsoft.Network/networkSecurityGroups/multisqlite-bacalhau-eastus-ssh-nsg:/subscriptions/72ac7288-fb92-4ad6-83bc-5cfd361f47ef/resourceGroups/multisqlite-bacalhau-eastus-rg/providers/Microsoft.Network/networkInterfaces/multisqlite-bacalhau-eastus-nic) 和子网:(\n/subscriptions/72ac7288-fb92-4ad6-83bc-5cfd361f47ef/resourceGroups/multisqlite-bacalhau-eastus-rg/providers/Microsoft.Network/networkSecurityGroups/multisqlite-bacalhau-eastus-ssh-nsg:) 仍未释放。" 详细信息=[]
不明显为什么会出现这个错误 - 我看到它说 "未释放",但当我转到 Web UI 时,它允许我正确删除它(并且 terraform 完成)。这里是否有什么我可以做的?以下是完整的 Terraform。

terraform {
  required_version = ">=1.0"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>3.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~>3.0"
    }
  }
}
provider "azurerm" {
  tenant_id       = var.tenantId
  subscription_id = var.subscriptionId
  client_id       = var.clientId
  client_secret   = var.clientSecret
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
}

data "cloudinit_config" "user_data" {
  for_each = var.locations

  # Azure VMs 显然要求它以 b64 编码
  gzip          = true
  base64_encode = true

  part {
    filename     = "cloud-config.yaml"
    content_type = "text/cloud-config"

    content = templatefile("cloud-init/init-vm.yml", {
      app_name : var.app_tag,
      bacalhau_service : filebase64("${path.root}/node_files/bacalhau.service"),
      ipfs_service : base64encode(file("${path.module}/node_files/ipfs.service")),
      start_bacalhau : filebase64("${path.root}/node_files/start-bacalhau.sh"),
      sensor_data_generator_py : filebase64("${path.root}/node_files/sensor_data_generator.py"),
      requirements_txt : filebase64("${path.root}/node_files/requirements.txt"),

      # 需要执行以下操作以删除公钥中的空格和换行符
      ssh_key : compact(split("\n", file(var.public_key)))[0],
      tailscale_key : var.tailscale_key,
      node_name : "${var.app_tag}-${each.key}-vm",
      username : var.username,
      region : each.value.region,
      zone : each.value.region,
      project_id : "${var.app_tag}",
    })
  }
}

resource "azurerm_resource_group" "rg" {
  for_each = var.locations
  name     = "${var.app_tag}-${each.key}-rg"
  location = each.key
}

resource "azurerm_virtual_network" "vnet" {
  for_each            = var.locations
  name                = "${var.app_tag}-${each.key}-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg[each.key].location
  resource_group_name = azurerm_resource_group.rg[each.key].name
}

resource "azurerm_subnet" "internal" {
  for_each             = var.locations
  name                 = "${var.app_tag}-${each.key}-internal-vnet"
  resource_group_name  = azurerm_resource_group.rg[each.key].name
  virtual_network_name = azurerm_virtual_network.vnet[each.key].name
  address_prefixes     = ["10.0.2.0/24"]
}

resource "azurerm_public_ip" "public_ip_allocator" {
  for_each            = var.locations
  name                = "${var.app_tag}-${each.key}-public-ip"
  resource_group_name = azurerm_resource_group.rg[each.key].name
  location            = azurerm_resource_group.rg[each.key].location
  allocation_method   = "Dynamic"
}

data "azurerm_public_ip" "public_ip" {
  for_each            = var.locations
  name                = azurerm_public_ip.public_ip_allocator[each.key].name
  resource_group_name = azurerm_linux_virtual_machine.instance[each.key].resource_group_name
}

resource "azurerm_network_interface" "nic" {
  for_each            = var.locations
  name                = "${var.app_tag}-${each.key}-nic"
  location            = azurerm_resource_group.rg[each.key].location
  resource_group_name = azurerm_resource_group.rg[each.key].name

  ip_configuration {
    name                          = "${var.app_tag}-${each.key}-ipConfiguration"
    subnet_id                     = azurerm_subnet.internal[each.key].id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.public_ip_allocator[each.key].id
  }
}

resource "azurerm_network_security_group" "nsg" {
  for_each            = var.locations
  name                = "${var.app_tag}-${each.key}-ssh-nsg"
  location            = azurerm_resource_group.rg[each.key].location
  resource_group_name = azurerm_resource_group.rg[each.key].name

  security_rule {
    name                       = "allow_ssh_sg"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

resource "azurerm_network_interface_security_group_associ

<details>
<summary>英文:</summary>

I&#39;m getting this error when I delete from Azure regularly.

```bash
│ Error: deleting Network Security Group &quot;multisqlite-bacalhau-eastus-ssh-nsg&quot; (Resource Group &quot;multisqlite-bacalhau-eastus-rg&quot;): network.SecurityGroupsClient#Delete: Failure sending request: StatusCode=400 -- Original Error: Code=&quot;NetworkSecurityGroupOldReferencesNotCleanedUp&quot; Message=&quot;Network security group multisqlite-bacalhau-eastus-ssh-nsg cannot be deleted because old references for the following Nics: (\n/subscriptions/72ac7288-fb92-4ad6-83bc-5cfd361f47ef/resourceGroups/multisqlite-bacalhau-eastus-rg/providers/Microsoft.Network/networkSecurityGroups/multisqlite-bacalhau-eastus-ssh-nsg:/subscriptions/72ac7288-fb92-4ad6-83bc-5cfd361f47ef/resourceGroups/multisqlite-bacalhau-eastus-rg/providers/Microsoft.Network/networkInterfaces/multisqlite-bacalhau-eastus-nic) and Subnet: (\n/subscriptions/72ac7288-fb92-4ad6-83bc-5cfd361f47ef/resourceGroups/multisqlite-bacalhau-eastus-rg/providers/Microsoft.Network/networkSecurityGroups/multisqlite-bacalhau-eastus-ssh-nsg:) have not been released yet.&quot; Details=[]

It's not obvious why - I see that it says "hasn't been released", but when I go to the Web UI, it lets me delete it correctly (and the terraform completes). Is there something I can do here? Here's the entire Terraform.

terraform {
required_version = &quot;&gt;=1.0&quot;
required_providers {
azurerm = {
source  = &quot;hashicorp/azurerm&quot;
version = &quot;~&gt;3.0&quot;
}
random = {
source  = &quot;hashicorp/random&quot;
version = &quot;~&gt;3.0&quot;
}
}
}
provider &quot;azurerm&quot; {
tenant_id       = var.tenantId
subscription_id = var.subscriptionId
client_id       = var.clientId
client_secret   = var.clientSecret
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
}
data &quot;cloudinit_config&quot; &quot;user_data&quot; {
for_each = var.locations
# Azure VMs apparently require it to be b64 encoded
gzip          = true
base64_encode = true
part {
filename     = &quot;cloud-config.yaml&quot;
content_type = &quot;text/cloud-config&quot;
content = templatefile(&quot;cloud-init/init-vm.yml&quot;, {
app_name : var.app_tag,
bacalhau_service : filebase64(&quot;${path.root}/node_files/bacalhau.service&quot;),
ipfs_service : base64encode(file(&quot;${path.module}/node_files/ipfs.service&quot;)),
start_bacalhau : filebase64(&quot;${path.root}/node_files/start-bacalhau.sh&quot;),
sensor_data_generator_py : filebase64(&quot;${path.root}/node_files/sensor_data_generator.py&quot;),
requirements_txt : filebase64(&quot;${path.root}/node_files/requirements.txt&quot;),
# Need to do the below to remove spaces and newlines from public key
ssh_key : compact(split(&quot;\n&quot;, file(var.public_key)))[0],
tailscale_key : var.tailscale_key,
node_name : &quot;${var.app_tag}-${each.key}-vm&quot;,
username : var.username,
region : each.value.region,
zone : each.value.region,
project_id : &quot;${var.app_tag}&quot;,
})
}
}
resource &quot;azurerm_resource_group&quot; &quot;rg&quot; {
for_each = var.locations
name     = &quot;${var.app_tag}-${each.key}-rg&quot;
location = each.key
}
resource &quot;azurerm_virtual_network&quot; &quot;vnet&quot; {
for_each            = var.locations
name                = &quot;${var.app_tag}-${each.key}-vnet&quot;
address_space       = [&quot;10.0.0.0/16&quot;]
location            = azurerm_resource_group.rg[each.key].location
resource_group_name = azurerm_resource_group.rg[each.key].name
}
resource &quot;azurerm_subnet&quot; &quot;internal&quot; {
for_each             = var.locations
name                 = &quot;${var.app_tag}-${each.key}-internal-vnet&quot;
resource_group_name  = azurerm_resource_group.rg[each.key].name
virtual_network_name = azurerm_virtual_network.vnet[each.key].name
address_prefixes     = [&quot;10.0.2.0/24&quot;]
}
resource &quot;azurerm_public_ip&quot; &quot;public_ip_allocator&quot; {
for_each            = var.locations
name                = &quot;${var.app_tag}-${each.key}-public-ip&quot;
resource_group_name = azurerm_resource_group.rg[each.key].name
location            = azurerm_resource_group.rg[each.key].location
allocation_method   = &quot;Dynamic&quot;
}
data &quot;azurerm_public_ip&quot; &quot;public_ip&quot; {
for_each            = var.locations
name                = azurerm_public_ip.public_ip_allocator[each.key].name
resource_group_name = azurerm_linux_virtual_machine.instance[each.key].resource_group_name
}
resource &quot;azurerm_network_interface&quot; &quot;nic&quot; {
for_each            = var.locations
name                = &quot;${var.app_tag}-${each.key}-nic&quot;
location            = azurerm_resource_group.rg[each.key].location
resource_group_name = azurerm_resource_group.rg[each.key].name
ip_configuration {
name                          = &quot;${var.app_tag}-${each.key}-ipConfiguration&quot;
subnet_id                     = azurerm_subnet.internal[each.key].id
private_ip_address_allocation = &quot;Dynamic&quot;
public_ip_address_id          = azurerm_public_ip.public_ip_allocator[each.key].id
}
}
resource &quot;azurerm_network_security_group&quot; &quot;nsg&quot; {
for_each            = var.locations
name                = &quot;${var.app_tag}-${each.key}-ssh-nsg&quot;
location            = azurerm_resource_group.rg[each.key].location
resource_group_name = azurerm_resource_group.rg[each.key].name
security_rule {
name                       = &quot;allow_ssh_sg&quot;
priority                   = 100
direction                  = &quot;Inbound&quot;
access                     = &quot;Allow&quot;
protocol                   = &quot;Tcp&quot;
source_port_range          = &quot;*&quot;
destination_port_range     = &quot;22&quot;
source_address_prefix      = &quot;*&quot;
destination_address_prefix = &quot;*&quot;
}
}
resource &quot;azurerm_network_interface_security_group_association&quot; &quot;association&quot; {
for_each                  = var.locations
network_interface_id      = azurerm_network_interface.nic[each.key].id
network_security_group_id = azurerm_network_security_group.nsg[each.key].id
}
# Create a random password
resource &quot;random_password&quot; &quot;password&quot; {
length           = 16
special          = true
override_special = &quot;_%@&quot;
}
resource &quot;azurerm_linux_virtual_machine&quot; &quot;instance&quot; {
for_each              = var.locations
name                  = &quot;${var.app_tag}-${each.key}-vm&quot;
location              = azurerm_resource_group.rg[each.key].location
resource_group_name   = azurerm_resource_group.rg[each.key].name
network_interface_ids = [azurerm_network_interface.nic[each.key].id]
size                  = &quot;Standard_D2s_v3&quot;
computer_name         = &quot;${var.app_tag}-${each.key}-vm&quot;
admin_username        = var.username
custom_data = data.cloudinit_config.user_data[each.key].rendered
admin_ssh_key {
username   = var.username
public_key = file(var.public_key)
}
os_disk {
caching              = &quot;ReadWrite&quot;
storage_account_type = &quot;Standard_LRS&quot;
}
source_image_reference {
publisher = &quot;canonical&quot;
offer     = &quot;0001-com-ubuntu-server-jammy&quot;
sku       = &quot;22_04-lts-gen2&quot;
version   = &quot;latest&quot;
}
}
locals {
# Get just one of the bootstrap IP from data.azurerm_public_ip.public_ip where it is in the bootstrap region
bootstrap_ip = data.azurerm_public_ip.public_ip[var.bootstrap_region].ip_address
# Get all the regions except the bootstrap region and put them in a set
non_bootstrap_regions = toset([for region in keys(var.locations) : region if region != var.bootstrap_region])
}
resource &quot;null_resource&quot; &quot;copy-bacalhau-bootstrap-to-local&quot; {
depends_on = [azurerm_linux_virtual_machine.instance]
connection {
host        = local.bootstrap_ip
port        = 22
user        = var.username
private_key = file(var.private_key)
}
provisioner &quot;remote-exec&quot; {
inline = [
&quot;echo &#39;SSHD is now alive.&#39;&quot;,
&quot;timeout 300 bash -c &#39;until [[ -s /run/bacalhau.run ]]; do sleep 1; done&#39; &amp;&amp; echo &#39;Bacalhau is now alive.&#39;&quot;,
]
}
provisioner &quot;local-exec&quot; {
command = &quot;ssh -o StrictHostKeyChecking=no ${var.username}@${local.bootstrap_ip} &#39;sudo cat /run/bacalhau.run&#39; &gt; ${var.bacalhau_run_file}&quot;
}
}
resource &quot;null_resource&quot; &quot;copy-to-node-if-worker&quot; {
// Only run this on worker nodes, not the bootstrap node
for_each = local.non_bootstrap_regions
depends_on = [null_resource.copy-bacalhau-bootstrap-to-local]
connection {
host        = data.azurerm_public_ip.public_ip[each.value].ip_address
port        = 22
user        = var.username
private_key = file(var.private_key)
}
provisioner &quot;file&quot; {
destination = &quot;/home/${var.username}/bacalhau-bootstrap&quot;
content     = file(var.bacalhau_run_file)
}
provisioner &quot;remote-exec&quot; {
inline = [
&quot;sudo mv /home/${var.username}/bacalhau-bootstrap /etc/bacalhau-bootstrap&quot;,
&quot;sudo systemctl daemon-reload&quot;,
&quot;sudo systemctl restart bacalhau.service&quot;,
]
}
}

答案1

得分: 1

我已经创建了与之关联的 NSG 和 NIC。

代码:

资源 "azurerm_virtual_network" "example" {
名称 = "kexamplenetwork"
地址空间 = ["10.0.0.0/16"]
位置 = data.azurerm_resource_group.example.location
资源组名称 = data.azurerm_resource_group.example.name
}
资源 "azurerm_subnet" "example" {
名称 = "internal"
资源组名称 = data.azurerm_resource_group.example.name
虚拟网络名称 = azurerm_virtual_network.example.name
地址前缀 = ["10.0.2.0/24"]
}
资源 "azurerm_network_security_group" "example" {
名称 = "kexample-nsg"
位置 = data.azurerm_resource_group.example.location
资源组名称 = data.azurerm_resource_group.example.name
安全规则 {
名称 = "test123"
优先级 = 100
方向 = "Inbound"
访问 = "Allow"
协议 = "Tcp"
源端口范围 = "*"
目标端口范围 = "*"
源地址前缀 = "*"
目标地址前缀 = "*"
}
}
资源 "azurerm_network_interface" "example" {
名称 = "kexample-nic"
位置 = data.azurerm_resource_group.example.location
资源组名称 = data.azurerm_resource_group.example.name
IP配置 {
名称 = "testconfiguration1"
子网ID = azurerm_subnet.example.id
私有IP地址分配 = "Dynamic"
}
}
资源 "azurerm_network_interface_security_group_association" "example" {
网络接口ID = azurerm_network_interface.example.id
网络安全组ID = azurerm_network_security_group.example.id
}

我使用以下命令删除了 NSG 并成功删除了它。

terraform destroy -target=’resourcetype.name’

terraform destroy -target=&#39;azurerm_network_security_group.example&#39;

但请注意,它首先删除了与 NSG 关联的网络接口关联,然后再删除 NSG。

因此,请确保首先取消关联 NICS 和子网到 NSG,或取消关联 NIC 关联,因为它们依赖于 NSG 引用。

在 PowerShell 中检查所有与 NSG 关联或附加的子网:

az network nsg show -n "kexample-nsg" -g “rg” --query 'subnets[].id' -o tsv
az network nsg show -n "kexample-nsg" -g “rg”

然后可以使用所有这些 ID 更改 NSG:

az network vnet subnet update --ids [] (resource IDs space-delimited) --network-security-group "kexample-nsg"


az network vnet subnet update -g networks --name subnetName --remove networkSecurityGroup --vnet-name vnetName --subscription subscription

或可以取消关联 NIC:

Get-AzureRmNetworkInterface -ResourceGroupName “rg” -Name "examplenic" 
$nic.NetworkSecurityGroup = $null
Set-AzureRmNetworkInterface -NetworkInterface $nic

你也可以查看这个 bad request - Azure - Cannot delete Network Security Group - Stack Overflow

英文:

I have created NSG and NICs associated to it.

code:

resource &quot;azurerm_virtual_network&quot; &quot;example&quot; {
name                = &quot;kexamplenetwork&quot;
address_space       = [&quot;10.0.0.0/16&quot;]
location            = data.azurerm_resource_group.example.location
resource_group_name = data.azurerm_resource_group.example.name
}
resource &quot;azurerm_subnet&quot; &quot;example&quot; {
name                 = &quot;internal&quot;
resource_group_name = data.azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes     = [&quot;10.0.2.0/24&quot;]
}
resource &quot;azurerm_network_security_group&quot; &quot;example&quot; {
name                = &quot;kexample-nsg&quot;
location            = data.azurerm_resource_group.example.location
resource_group_name = data.azurerm_resource_group.example.name
security_rule {
name                       = &quot;test123&quot;
priority                   = 100
direction                  = &quot;Inbound&quot;
access                     = &quot;Allow&quot;
protocol                   = &quot;Tcp&quot;
source_port_range          = &quot;*&quot;
destination_port_range     = &quot;*&quot;
source_address_prefix      = &quot;*&quot;
destination_address_prefix = &quot;*&quot;
}
}
resource &quot;azurerm_network_interface&quot; &quot;example&quot; {
name                = &quot;kexample-nic&quot;
location            = data.azurerm_resource_group.example.location
resource_group_name = data.azurerm_resource_group.example.name
ip_configuration {
name                          = &quot;testconfiguration1&quot;
subnet_id                     = azurerm_subnet.example.id
private_ip_address_allocation = &quot;Dynamic&quot;
}
}
resource &quot;azurerm_network_interface_security_group_association&quot; &quot;example&quot; {
network_interface_id      = azurerm_network_interface.example.id
network_security_group_id = azurerm_network_security_group.example.id
}

I deleted the nsg using below command and it got deleted.

terraform destroy -target=’resourcetype.name’

terraform destroy -target=&#39;azurerm_network_security_group.example&#39;

如何使用Terraform和Azure强制删除/释放网络服务组(Network Service Group)?

But note that it deleted Network interface association with NSG first and then deleted NSG .

So make sure to first dissociate NICS and subnet to the nsg or dissociate NIC association , as they are depended on the nsg references.

In powershell check all the subnets associated or attached to the nsg :

az network nsg show -n &quot;kexample-nsg&quot; -g “rg” --query &#39;subnets[].id&#39; -o tsv
az network nsg show -n &quot;kexample-nsg&quot; -g “rg”

如何使用Terraform和Azure强制删除/释放网络服务组(Network Service Group)?

Then all those ids can be used to change nsg

az network vnet subnet update --ids [] (resource IDs space-delimited) --network-security-group &quot;kexample-nsg&quot;

or
az network vnet subnet update -g networks --name subnetName --remove networkSecurityGroup --vnet-name vnetName --subscription subscription

or the NIC can be dissociated:

Get-AzureRmNetworkInterface -ResourceGroupName “rg” -Name &quot;examplenic&quot; 
$nic.NetworkSecurityGroup = $null
Set-AzureRmNetworkInterface -NetworkInterface $nic

You can also check this out bad request - Azure - Cannot delete Network Security Group - Stack Overflow

huangapple
  • 本文由 发表于 2023年6月16日 09:23:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486426.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定