Guida introduttiva: Creare una topologia di rete mesh con Azure Rete virtuale Manager usando Terraform

Introduzione ad Azure Rete virtuale Manager usando Terraform per effettuare il provisioning della connettività per tutte le reti virtuali.

In questa guida introduttiva si distribuiscono tre reti virtuali e si usa Azure Rete virtuale Manager per creare una topologia di rete mesh. Verificare quindi che la configurazione della connettività sia stata applicata. È possibile scegliere tra una distribuzione con un ambito sottoscrizione o un ambito del gruppo di gestione. Altre informazioni sugli ambiti di gestione di rete.

Terraform consente di definire, visualizzare in anteprima e distribuire l'infrastruttura cloud. Con Terraform è possibile creare file di configurazione usando la sintassi HCL. La sintassi HCL consente di specificare il provider di servizi cloud, ad esempio Azure, e gli elementi che costituiscono l'infrastruttura cloud. Dopo aver creato i file di configurazione, è necessario creare un piano di esecuzione che consenta di visualizzare in anteprima le modifiche apportate all'infrastruttura prima che vengano distribuite. Dopo aver verificato le modifiche, è possibile applicare il piano di esecuzione per distribuire l'infrastruttura.

In questo articolo vengono illustrate le operazioni seguenti:

Prerequisiti

Implementare il codice Terraform

Questo esempio di codice implementerà Azure Rete virtuale Manager nell'ambito della sottoscrizione.

  1. Creare una directory in cui testare ed eseguire il codice Terraform di esempio e impostarla come directory corrente.

  2. Creare un file denominato providers.tf e inserire il codice seguente:

    terraform {
      required_version = ">=1.0"
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = ">= 3.56.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    provider "azurerm" {
      features {}
    }
    
  3. Creare un file denominato main.tf e inserire il codice seguente:

    
    # Create the Resource Group
    
    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "azurerm_resource_group" "rg" {
      location = var.resource_group_location
      name     = random_pet.rg_name.id
    }
    
    # Create three virtual networks
    resource "random_string" "prefix" {
      length = 4
      special = false
      upper = false
    }
    
    resource "random_pet" "virtual_network_name" {
      prefix = "vnet-${random_string.prefix.result}"
    }
    resource "azurerm_virtual_network" "vnet" {
      count = 3
    
      name                = "${random_pet.virtual_network_name.id}-0${count.index}"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      address_space       = ["10.${count.index}.0.0/16"]
    }
    
    # Add a subnet to each virtual network
    
    resource "azurerm_subnet" "subnet_vnet" {
      count = 3
    
      name                 = "default"
      virtual_network_name = azurerm_virtual_network.vnet[count.index].name
      resource_group_name  = azurerm_resource_group.rg.name
      address_prefixes     = ["10.${count.index}.0.0/24"]
    }
    
    # Create a Virtual Network Manager instance
    
    data "azurerm_subscription" "current" {
    }
    
    resource "azurerm_network_manager" "network_manager_instance" {
      name                = "network-manager"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      scope_accesses      = ["Connectivity"]
      description         = "example network manager"
      scope {
        subscription_ids = [data.azurerm_subscription.current.id]
      }
    }
    
    # Create a network group
    
    resource "azurerm_network_manager_network_group" "network_group" {
      name               = "network-group"
      network_manager_id = azurerm_network_manager.network_manager_instance.id
    }
    
    # Add three virtual networks to a network group as dynamic members with Azure Policy
    
    resource "random_pet" "network_group_policy_name" {
      prefix = "network-group-policy"
    }
    
    resource "azurerm_policy_definition" "network_group_policy" {
      name         = "${random_pet.network_group_policy_name.id}"
      policy_type  = "Custom"
      mode         = "Microsoft.Network.Data"
      display_name = "Policy Definition for Network Group"
    
      metadata = <<METADATA
        {
          "category": "Azure Virtual Network Manager"
        }
      METADATA
    
      policy_rule = <<POLICY_RULE
        {
          "if": {
            "allOf": [
              {
                  "field": "type",
                  "equals": "Microsoft.Network/virtualNetworks"
              },
              {
                "allOf": [
                  {
                  "field": "Name",
                  "contains": "${random_pet.virtual_network_name.id}"
                  }
                ]
              }
            ]
          },
          "then": {
            "effect": "addToNetworkGroup",
            "details": {
              "networkGroupId": "${azurerm_network_manager_network_group.network_group.id}"
            }
          }
        }
      POLICY_RULE
    }
    
    resource "azurerm_subscription_policy_assignment" "azure_policy_assignment" {
      name                 = "${random_pet.network_group_policy_name.id}-policy-assignment"
      policy_definition_id = azurerm_policy_definition.network_group_policy.id
      subscription_id      = data.azurerm_subscription.current.id
    }
    
    # Create a connectivity configuration
    
    resource "azurerm_network_manager_connectivity_configuration" "connectivity_config" {
      name                  = "connectivity-config"
      network_manager_id    = azurerm_network_manager.network_manager_instance.id
      connectivity_topology = "Mesh"
      applies_to_group {
        group_connectivity = "None"
        network_group_id   = azurerm_network_manager_network_group.network_group.id
      }
    }
    
    
    # Commit deployment
    
    resource "azurerm_network_manager_deployment" "commit_deployment" {
      network_manager_id = azurerm_network_manager.network_manager_instance.id
      location           = azurerm_resource_group.rg.location
      scope_access       = "Connectivity"
      configuration_ids  = [azurerm_network_manager_connectivity_configuration.connectivity_config.id]
    }
    
  4. Creare un file denominato variables.tf e inserire il codice seguente:

    variable "resource_group_location" {
      type        = string
      default     = "eastus"
      description = "Location of the resource group."
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
      default     = "rg"
    }
    
  5. Creare un file denominato outputs.tf e inserire il codice seguente:

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
    output "virtual_network_names" {
      value = azurerm_virtual_network.vnet[*].name
    }
    

Implementare il codice Terraform

Questo esempio di codice implementerà Azure Rete virtuale Manager nell'ambito del gruppo di gestione.

  1. Creare una directory in cui testare ed eseguire il codice Terraform di esempio e impostarla come directory corrente.

  2. Creare un file denominato providers.tf e inserire il codice seguente:

    terraform {
      required_version = ">=1.0"
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 3.56.0, < 4.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    provider "azurerm" {
      features {}
    }
    
  3. Creare un file denominato main.tf e inserire il codice seguente:

    # Create the Resource Group
    
    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "azurerm_resource_group" "rg" {
      location = var.resource_group_location
      name     = random_pet.rg_name.id
    }
    
    # Create three virtual networks
    resource "random_string" "prefix" {
      length  = 4
      special = false
      upper   = false
    }
    
    resource "random_pet" "virtual_network_name" {
      prefix = "vnet-${random_string.prefix.result}"
    }
    resource "azurerm_virtual_network" "vnet" {
      count = 3
    
      name                = "${random_pet.virtual_network_name.id}-0${count.index}"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      address_space       = ["10.${count.index}.0.0/16"]
    }
    
    # Add a subnet to each virtual network
    
    resource "azurerm_subnet" "subnet_vnet" {
      count = 3
    
      name                 = "default"
      virtual_network_name = azurerm_virtual_network.vnet[count.index].name
      resource_group_name  = azurerm_resource_group.rg.name
      address_prefixes     = ["10.${count.index}.0.0/24"]
    }
    
    data "azurerm_subscription" "current" {
    }
    
    # Create a Management Group
    
    resource "random_pet" "management_group_name" {
      prefix = "AVNM-management-group"
    }
    
    resource "azurerm_management_group" "mg" {
      display_name = random_pet.management_group_name.id
    
      subscription_ids = [
        data.azurerm_subscription.current.subscription_id,
      ]
    }
    
    data "azurerm_client_config" "this" {}
    
    resource "azurerm_role_assignment" "management_group_owner" {
      principal_id         = coalesce(var.msi_id, data.azurerm_client_config.this.object_id)
      scope                = azurerm_management_group.mg.id
      role_definition_name = "Contributor"
    }
    
    # register Microsoft.Network to the Management Group
    
    resource "null_resource" "register_rp_to_mg" {
      provisioner "local-exec" {
        command = "az provider register --namespace Microsoft.Network -m ${azurerm_management_group.mg.name}"
      }
      depends_on = [azurerm_role_assignment.management_group_owner]
    }
    
    resource "time_sleep" "wait_5_seconds" {
      create_duration = "5s"
      depends_on      = [null_resource.register_rp_to_mg]
    }
    
    # Create a Virtual Network Manager instance
    
    resource "azurerm_network_manager" "network_manager_instance" {
      name                = "network-manager"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      scope_accesses      = ["Connectivity"]
      description         = "example network manager"
      scope {
        management_group_ids = [azurerm_management_group.mg.id]
      }
      depends_on = [time_sleep.wait_5_seconds]
    }
    
    # Create a network group
    
    resource "azurerm_network_manager_network_group" "network_group" {
      name               = "network-group"
      network_manager_id = azurerm_network_manager.network_manager_instance.id
    }
    
    # Add three virtual networks to a network group as dynamic members with Azure Policy
    
    resource "random_pet" "network_group_policy_name" {
      prefix = "network-group-policy"
    }
    
    resource "azurerm_policy_definition" "network_group_policy" {
      name         = random_pet.network_group_policy_name.id
      policy_type  = "Custom"
      mode         = "Microsoft.Network.Data"
      display_name = "Policy Definition for Network Group"
    
      metadata = <<METADATA
        {
          "category": "Azure Virtual Network Manager"
        }
      METADATA
    
      policy_rule = <<POLICY_RULE
        {
          "if": {
            "allOf": [
              {
                  "field": "type",
                  "equals": "Microsoft.Network/virtualNetworks"
              },
              {
                "allOf": [
                  {
                  "field": "Name",
                  "contains": "${random_pet.virtual_network_name.id}"
                  }
                ]
              }
            ]
          },
          "then": {
            "effect": "addToNetworkGroup",
            "details": {
              "networkGroupId": "${azurerm_network_manager_network_group.network_group.id}"
            }
          }
        }
      POLICY_RULE
    }
    
    resource "azurerm_subscription_policy_assignment" "azure_policy_assignment" {
      name                 = "${random_pet.network_group_policy_name.id}-policy-assignment"
      policy_definition_id = azurerm_policy_definition.network_group_policy.id
      subscription_id      = data.azurerm_subscription.current.id
    }
    
    # Create a connectivity configuration
    
    resource "azurerm_network_manager_connectivity_configuration" "connectivity_config" {
      name                  = "connectivity-config"
      network_manager_id    = azurerm_network_manager.network_manager_instance.id
      connectivity_topology = "Mesh"
      applies_to_group {
        group_connectivity = "None"
        network_group_id   = azurerm_network_manager_network_group.network_group.id
      }
    }
    
    
    # Commit deployment
    
    resource "azurerm_network_manager_deployment" "commit_deployment" {
      network_manager_id = azurerm_network_manager.network_manager_instance.id
      location           = azurerm_resource_group.rg.location
      scope_access       = "Connectivity"
      configuration_ids  = [azurerm_network_manager_connectivity_configuration.connectivity_config.id]
    }
    
  4. Creare un file denominato variables.tf e inserire il codice seguente:

    variable "resource_group_location" {
      type        = string
      default     = "eastus"
      description = "Location of the resource group."
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
      default     = "rg"
    }
    
    variable "msi_id" {
      type    = string
      description = "(Optional) Manage identity id that be used as authentication method. Defaults to `null`."
      default = null
    }
    
  5. Creare un file denominato outputs.tf e inserire il codice seguente:

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
    output "virtual_network_names" {
      value = azurerm_virtual_network.vnet[*].name
    }
    

Inizializzare Terraform

Per inizializzare la distribuzione di Terraform, eseguire terraform init. Questo comando scarica il provider di Azure necessario per gestire le risorse di Azure.

terraform init -upgrade

Punti principali:

  • Il parametro -upgrade aggiorna i plug-in del provider necessari alla versione più recente conforme ai vincoli di versione della configurazione.

Creare un piano di esecuzione Terraform

Eseguire terraform plan per creare un piano di esecuzione.

terraform plan -out main.tfplan

Punti principali:

  • Il comando terraform plan consente di creare un piano di esecuzione, ma non di eseguirlo. Determina invece le azioni necessarie per creare la configurazione specificata nei file di configurazione. Questo modello consente di verificare se il piano di esecuzione corrisponde alle aspettative prima di apportare modifiche alle risorse effettive.
  • Il parametro -out facoltativo consente di specificare un file di output per il piano. L'uso del parametro -out garantisce che il piano esaminato sia esattamente quello che viene applicato.

Applicare un piano di esecuzione Terraform

Eseguire terraform apply per applicare il piano di esecuzione all'infrastruttura cloud.

terraform apply main.tfplan

Punti principali:

  • Il comando terraform apply di esempio presuppone che in precedenza sia stato eseguito terraform plan -out main.tfplan.
  • Se è stato specificato un nome file diverso per il parametro -out, usare lo stesso nome file nella chiamata a terraform apply.
  • Se non è stato usato il parametro -out, chiamare terraform apply senza parametri.

Verificare i risultati

  1. Ottenere il nome del gruppo di risorse di Azure.

    resource_group_name=$(terraform output -raw resource_group_name)
    
  2. Ottenere i nomi delle reti virtuali.

    terraform output virtual_network_names
    
  3. Per ogni nome di rete virtuale stampato nel passaggio precedente, eseguire az network manager list-effective-connectivity-config per stampare le configurazioni valide (applicate). Sostituire il <virtual_network_name> segnaposto con il nome della rete virtuale.

    az network manager list-effective-connectivity-config \
      --resource-group $resource_group_name \
      --vnet-name <virtual_network_name>
    

Pulire le risorse

Quando le risorse create tramite Terraform non sono più necessarie, eseguire i passaggi seguenti:

  1. Eseguire terraform plan e specificare il flag destroy.

    terraform plan -destroy -out main.destroy.tfplan
    

    Punti principali:

    • Il comando terraform plan consente di creare un piano di esecuzione, ma non di eseguirlo. Determina invece le azioni necessarie per creare la configurazione specificata nei file di configurazione. Questo modello consente di verificare se il piano di esecuzione corrisponde alle aspettative prima di apportare modifiche alle risorse effettive.
    • Il parametro -out facoltativo consente di specificare un file di output per il piano. L'uso del parametro -out garantisce che il piano esaminato sia esattamente quello che viene applicato.
  2. Eseguire terraform apply per applicare il piano di esecuzione.

    terraform apply main.destroy.tfplan
    

Risolvere i problemi di Terraform in Azure

Risolvere i problemi comuni relativi all'uso di Terraform in Azure

Passaggi successivi