共用方式為


使用 Terraform 建立 Azure AI Foundry 中樞

在本文中,您會使用 Terraform 來建立 Azure AI Foundry 中樞、專案和 AI 服務連線。 中樞是資料科學家和開發人員在機器學習專案上共同作業的中心位置。 能夠提供共用、共同作業的空間,以建置、訓練及部署機器學習模型。 中樞已與 Azure Machine Learning 和其他 Azure 服務整合,使其成為機器學習工作的完整解決方案。 中樞也可讓您管理和監視 AI 部署,確保它們如預期般執行。

Terraform 可讓您定義、預覽和部署雲端基礎結構。 使用 Terraform 時,您可以使用 HCL 語法來建立設定檔。 HCL 語法可讓您指定雲端提供者 (例如 Azure) 和構成雲端基礎結構的元素。 建立設定檔之後,您可以建立執行計畫,讓您先預覽基礎結構變更,之後再部署。 驗證變更之後,您可以套用執行計畫來部署基礎結構。

  • 建立資源群組
  • 設定儲存體帳戶
  • 建立金鑰保存庫
  • 設定 AI 服務
  • 建置 Azure AI Foundry 中樞
  • 開發 Azure AI Foundry 專案
  • 建立 AI 服務連線

必要條件

實作 Terraform 程式碼

  1. 建立目錄,然後在目錄中測試並執行範例 Terraform 程式碼,且設為目前的目錄。

  2. 建立名為 providers.tf 的檔案,並插入下列程式碼。

    terraform {
      required_version = ">= 1.0"
    
      required_providers { 
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>3.0"
        }
        azapi = {
          source  = "azure/azapi"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    
    provider "azurerm" {
      features {
        key_vault {
          recover_soft_deleted_key_vaults    = false
          purge_soft_delete_on_destroy       = false
          purge_soft_deleted_keys_on_destroy = false
        }
        resource_group {
          prevent_deletion_if_contains_resources = false
        }
      }
    }
    
    provider "azapi" {
    }
    
  3. 建立名為 main.tf 的檔案,並插入下列程式碼。

    resource "random_pet" "rg_name" { 
      prefix = var.resource_group_name_prefix
    }
    
    // RESOURCE GROUP
    resource "azurerm_resource_group" "rg" {
      location = var.resource_group_location
      name     = random_pet.rg_name.id
    }
    
    data "azurerm_client_config" "current" {
    }
    
    // STORAGE ACCOUNT
    resource "azurerm_storage_account" "default" {
      name                            = "${var.prefix}storage${random_string.suffix.result}"
      location                        = azurerm_resource_group.rg.location
      resource_group_name             = azurerm_resource_group.rg.name
      account_tier                    = "Standard"
      account_replication_type        = "GRS"
      allow_nested_items_to_be_public = false
    }
    
    // KEY VAULT
    resource "azurerm_key_vault" "default" {
      name                     = "${var.prefix}keyvault${random_string.suffix.result}"
      location                 = azurerm_resource_group.rg.location
      resource_group_name      = azurerm_resource_group.rg.name
      tenant_id                = data.azurerm_client_config.current.tenant_id
      sku_name                 = "standard"
      purge_protection_enabled = false
    }
    
    // AzAPI AIServices
    resource "azapi_resource" "AIServicesResource"{
      type = "Microsoft.CognitiveServices/accounts@2023-10-01-preview"
      name = "AIServicesResource${random_string.suffix.result}"
      location = azurerm_resource_group.rg.location
      parent_id = azurerm_resource_group.rg.id
    
      identity {
        type = "SystemAssigned"
      }
    
      body = jsonencode({
        name = "AIServicesResource${random_string.suffix.result}"
        properties = {
          //restore = true
          customSubDomainName = "${random_string.suffix.result}domain"
            apiProperties = {
                statisticsEnabled = false
            }
        }
        kind = "AIServices"
        sku = {
            name = var.sku
        }
        })
    
      response_export_values = ["*"]
    }
    
    // Azure AI Hub
    resource "azapi_resource" "hub" {
      type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview"
      name = "${random_pet.rg_name.id}-aih"
      location = azurerm_resource_group.rg.location
      parent_id = azurerm_resource_group.rg.id
    
      identity {
        type = "SystemAssigned"
      }
    
      body = jsonencode({
        properties = {
          description = "This is my Azure AI hub"
          friendlyName = "My Hub"
          storageAccount = azurerm_storage_account.default.id
          keyVault = azurerm_key_vault.default.id
    
          /* Optional: To enable these field, the corresponding dependent resources need to be uncommented.
          applicationInsight = azurerm_application_insights.default.id
          containerRegistry = azurerm_container_registry.default.id
          */
    
          /*Optional: To enable Customer Managed Keys, the corresponding 
          encryption = {
            status = var.encryption_status
            keyVaultProperties = {
                keyVaultArmId = azurerm_key_vault.default.id
                keyIdentifier = var.cmk_keyvault_key_uri
            }
          }
          */
          
        }
        kind = "hub"
      })
    }
    
    // Azure AI Project
    resource "azapi_resource" "project" {
      type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview"
      name = "my-ai-project${random_string.suffix.result}"
      location = azurerm_resource_group.rg.location
      parent_id = azurerm_resource_group.rg.id
    
      identity {
        type = "SystemAssigned"
      }
    
      body = jsonencode({
        properties = {
          description = "This is my Azure AI PROJECT"
          friendlyName = "My Project"
          hubResourceId = azapi_resource.hub.id
        }
        kind = "project"
      })
    }
    
    // AzAPI AI Services Connection
    resource "azapi_resource" "AIServicesConnection" {
      type = "Microsoft.MachineLearningServices/workspaces/connections@2024-04-01-preview"
      name = "Default_AIServices${random_string.suffix.result}"
      parent_id = azapi_resource.hub.id
    
      body = jsonencode({
          properties = {
            category = "AIServices",
            target = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint,
            authType = "AAD",
            isSharedToAll = true,
            metadata = {
              ApiType = "Azure",
              ResourceId = azapi_resource.AIServicesResource.id
            }
          }
        })
      response_export_values = ["*"]
    }
    
    /* The following resources are OPTIONAL.
    // APPLICATION INSIGHTS
    resource "azurerm_application_insights" "default" {
      name                = "${var.prefix}appinsights${random_string.suffix.result}"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      application_type    = "web"
    }
    
    // CONTAINER REGISTRY
    resource "azurerm_container_registry" "default" {
      name                     = "${var.prefix}contreg${random_string.suffix.result}"
      resource_group_name      = azurerm_resource_group.rg.name
      location                 = azurerm_resource_group.rg.location
      sku                      = "premium"
      admin_enabled            = true
    }
    */
    
  4. 建立名為 variables.tf 的檔案,並插入下列程式碼。

    variable "resource_group_location" {
      type        = string
      default     = "eastus"
      description = "Location of the resource group."
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      default     = "rg"
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
    }
    
    variable "prefix" {
        type = string
        description="This variable is used to name the hub, project, and dependent resources."
        default = "ai"
    }
    
    variable "sku" {
        type        = string
        description = "The sku name of the Azure Analysis Services server to create. Choose from: B1, B2, D1, S0, S1, S2, S3, S4, S8, S9. Some skus are region specific. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region"
        default     = "S0"
    }
    
    resource "random_string" "suffix" {  
      length           = 4  
      special          = false  
      upper            = false  
    } 
    
    /*Optional: For Customer Managed Keys, uncomment this part AND the corresponding section in main.tf
    variable "cmk_keyvault_key_uri" {
        description = "Key vault uri to access the encryption key."
    }
    
    variable "encryption_status" {
        description = "Indicates whether or not the encryption is enabled for the workspace."
        default = "Enabled"
    }
    */
    
  5. 建立名為 outputs.tf 的檔案,並插入下列程式碼。

    output "resource_group_name" {
      value = azurerm_resource_group.rg.id
    }
    
    output "workspace_name" {
        value = azapi_resource.project.id
    }
    
    output "endpoint" {
      value = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint
    }
    

初始化 Terraform

執行 terraform init 來初始化 Terraform 部署。 此命令會下載管理 Azure 資源所需的 Azure 提供者。

terraform init -upgrade

重點︰

  • -upgrade 參數會將必要的提供者外掛程式升級至符合設定版本條件約束的最新版本。

建立 Terraform 執行計畫

執行 terraform plan 以建立執行計畫。

terraform plan -out main.tfplan

重點︰

  • terraform plan 命令會建立執行計畫,但不會執行。 相反地,其會決定要在您指定的設定檔中建立設定所需的動作。 此模式可讓您在對實際資源進行任何變更之前,先確認執行方案是否符合您的預期。
  • 選用的 -out 參數可讓您指定計畫的輸出檔。 使用 -out 參數可確保您所檢閱的方案就是所套用的方案。

套用 Terraform 執行計畫

執行 terraform apply 將執行計畫套用至您的雲端基礎結構。

terraform apply main.tfplan

重點︰

  • 範例 terraform apply 命令假設您之前已執行過 terraform plan -out main.tfplan
  • 如果您為 -out 參數指定了不同的檔案名稱,請在呼叫 terraform apply 時使用該檔案名稱。
  • 若您未使用 -out 參數,請呼叫 terraform apply,不需要使用參數。

驗證結果

  1. 取得 Azure 資源群組名稱。

    resource_group_name=$(terraform output -raw resource_group_name)
    
  2. 取得工作區名稱。

    workspace_name=$(terraform output -raw workspace_name)
    
  3. 執行 az ml workspace show 以顯示新工作區的相關資訊。

    az ml workspace show --resource-group $resource_group_name \
                         --name $workspace_name
    

清除資源

當您不再需要透過 Terraform 建立的資源時,請執行下列步驟:

  1. 執行 terraform plan 並指定 destroy 旗標。

    terraform plan -destroy -out main.destroy.tfplan
    

    重點︰

    • terraform plan 命令會建立執行計畫,但不會執行。 相反地,其會決定要在您指定的設定檔中建立設定所需的動作。 此模式可讓您在對實際資源進行任何變更之前,先確認執行方案是否符合您的預期。
    • 選用的 -out 參數可讓您指定計畫的輸出檔。 使用 -out 參數可確保您所檢閱的方案就是所套用的方案。
  2. 執行 terraform apply 以套用執行方案。

    terraform apply main.destroy.tfplan
    

對 Azure 上的 Terraform 進行疑難排解

針對在 Azure 上使用 Terraform 時的常見問題進行疑難排解。

下一步