Azure

子網沒有在 azure 上使用 terraform 創建,如何解決?

  • January 15, 2022

我正在嘗試在 azure 上創建兩台帶有 terraform 的 centos 8 機器。

我的模板 github連結

當我嘗試申請時,我遇到了與政策相關的錯誤。你能建議如何解決這個問題嗎?

>     │ Error: creating Subnet: (Name "subnetforAutomation" / Virtual Network Name "vnetforAutomation" / Resource Group "automation_mart"):
> network.SubnetsClient#CreateOrUpdate: Failure sending request:
> StatusCode=0 -- Original Error: Code="RequestDisallowedByPolicy"
> Message="Resource 'subnetforAutomation' was disallowed by policy.
> Policy identifiers:
> '[{\"policyAssignment\":{\"name\":\"Deny-Subnet-Without-Nsg\",\"id\":\"/providers/Microsoft.Management/managementGroups/QSFT-landingzones/providers/Microsoft.Authorization/policyAssignments/Deny-Subnet-Without-Nsg\"},\"policyDefinition\":{\"name\":\"Subnets
> should have a Network Security Group
> \",\"id\":\"/providers/Microsoft.Management/managementGroups/QSFT/providers/Microsoft.Authorization/policyDefinitions/Deny-Subnet-Without-Nsg\"}}]'."
> Target="subnetforAutomation"
> AdditionalInfo=[{"info":{"evaluationDetails":{"evaluatedExpressions":[{"expression":"type","expressionKind":"Field","expressionValue":"Microsoft.Network/virtualNetworks/subnets","operator":"Equals","path":"type","result":"True","targetValue":"Microsoft.Network/virtualNetworks/subnets"},{"expression":"Microsoft.Network/virtualNetworks/subnets/networkSecurityGroup.id","expressionKind":"Field","operator":"Exists","path":"properties.networkSecurityGroup.id","result":"True","targetValue":"false"}]},"policyAssignmentDisplayName":"Deny-Subnet-Without-Nsg","policyAssignmentId":"/providers/Microsoft.Management/managementGroups/QSFT-landingzones/providers/Microsoft.Authorization/policyAssignments/Deny-Subnet-Without-Nsg","policyAssignmentName":"Deny-Subnet-Without-Nsg","policyAssignmentScope":"/providers/Microsoft.Management/managementGroups/QSFT-landingzones","policyDefinitionDisplayName":"Subnets
> should have a Network Security Group
> ","policyDefinitionEffect":"Deny","policyDefinitionId":"/providers/Microsoft.Management/managementGroups/QSFT/providers/Microsoft.Authorization/policyDefinitions/Deny-Subnet-Without-Nsg","policyDefinitionName":"Deny-Subnet-Without-Nsg"},"type":"PolicyViolation"}]
> 
>     │
>     │   with azurerm_subnet.subnet,
>     │   on main.tf line 24, in resource "azurerm_subnet" "subnet":
>     │   24: resource "azurerm_subnet" "subnet" {
>     │

我嘗試保持內聯,即 vnet 內的子網。在計劃階段本身從 VM 實例資源塊中引用子網時,問題就出現了。

Error: Unsupported attribute
│
│   on network.tf line 26, in resource "azurerm_network_interface" "example":
│   26:     subnet_id                     =  azurerm_virtual_network.vnet.subnet.id #azurerm_subnet.subnet.id
│
│ Can't access attributes on a set of objects. Did you mean to access an attribute across all elements of the set?
╵

//main.tf

## <https://www.terraform.io/docs/providers/azurerm/r/windows_virtual_machine.html>
resource "azurerm_windows_virtual_machine" "example" {
 name                = var.machine_details.name
 computer_name       = var.machine_details.name
 resource_group_name = azurerm_resource_group.rg.name
 location            = azurerm_resource_group.rg.location
 size                = var.machine_details.size
 admin_username      = var.machine_details.username
 admin_password      = var.machine_details.password
 network_interface_ids = [
   azurerm_network_interface.example.id,
 ]

 os_disk {
   caching              = "ReadWrite"
   storage_account_type = "Standard_LRS"
 }

 source_image_reference {
   publisher = "MicrosoftWindowsServer"
   offer     = "WindowsServer"
   sku       = "2019-Datacenter"
   version   = "latest"
 }
}

//network.tf

## <https://www.terraform.io/docs/providers/azurerm/r/virtual_network.html>
resource "azurerm_virtual_network" "vnet" {
 name                = "vNet"
 address_space       = ["10.0.0.0/16"]
 location            = azurerm_resource_group.rg.location
 resource_group_name = azurerm_resource_group.rg.name

subnet{
name = "internal"
address_prefix     = "10.0.2.0/24"
security_group = azurerm_network_security_group.example.id
}

}


## <https://www.terraform.io/docs/providers/azurerm/r/network_interface.html>
resource "azurerm_network_interface" "example" {
 name                = "example-nic"
 location            = azurerm_resource_group.rg.location
 resource_group_name = azurerm_resource_group.rg.name

 ip_configuration {
   name                          = "internal"
   subnet_id                     =  azurerm_virtual_network.vnet.subnet.id #azurerm_subnet.subnet.id
   private_ip_address_allocation = "Dynamic"
   public_ip_address_id          = azurerm_public_ip.myvm1publicip.id
 }
}

resource "azurerm_public_ip" "myvm1publicip" {
 name                = var.public_ip.name
 location            = azurerm_resource_group.rg.location
 resource_group_name = azurerm_resource_group.rg.name
 allocation_method   = var.public_ip.allocation_method
 sku                 = var.public_ip.sku
}

resource "azurerm_network_security_group" "example" {
 name                = var.nsg
 location            = azurerm_resource_group.rg.location
 resource_group_name = azurerm_resource_group.rg.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 = "*"
 }
}

//provider.tf

## <https://www.terraform.io/docs/providers/azurerm/index.html>
provider "azurerm" {
 features {}
}

//rg.tf

## <https://www.terraform.io/docs/providers/azurerm/r/resource_group.html>
resource "azurerm_resource_group" "rg" {
 name     = "TerraformTesting2"
 location = var.location
}

//variables.tf

variable "location" {
 type        = string
 description = "Azure Region where all these resources will be provisioned"
 default     = "eastus2"
}

variable "public_ip" {


 default = {
     name              = "pip1"
     allocation_method = "Dynamic"
     sku               = "Basic"
   }
 
 
}

variable "nsg" {
 type        = string
 description = "Azure NSG"
 default     = "example-nsg"
}

variable "machine_details" {
 
 default = {
     name             = "example-vm2"
     size = "Standard_E2s_v3" #"Standard_F2"
     username               = "adminnasme"
     password = "MyPaword!@3"
   }
 
}

子網創建失敗,因為它不符合您的管理員應用的策略。這表明子網必須先應用 NSG,然後才能創建它。不幸的是,Terraform 創建資源的方式是先創建子網,然後將 NSG 與其關聯。這是兩個 API 呼叫,第一個呼叫失敗,因為它沒有關聯的 NSG。策略不知道第二個呼叫即將到來以將 NSG 與子網相關聯。

這是 Terraform 在 ARM API 之上建構方式的缺點。除了讓您的管理員放寬此政策外,沒有很好的解決方案。

編輯:

因此,看看這個與您所看到的非常相似的問題,您似乎可以通過在virtual_network資源中定義子網而不是作為單獨的子網資源來解決這個問題。使用它,您可以定義 NSG 關聯內聯,這可以在一個單一的 cale 中完成:

resource "azurerm_virtual_network" "example" {
 name                = "virtualNetwork1"
 location            = azurerm_resource_group.example.location
 resource_group_name = azurerm_resource_group.example.name
 address_space       = ["10.0.0.0/16"]
 dns_servers         = ["10.0.0.4", "10.0.0.5"]

 ddos_protection_plan {
   id     = azurerm_network_ddos_protection_plan.example.id
   enable = true
 }


 subnet {
   name           = "subnet3"
   address_prefix = "10.0.3.0/24"
   security_group = azurerm_network_security_group.example.id
 }

 tags = {
   environment = "Production"
 }
}

引用自:https://serverfault.com/questions/1085382