使用受控識別從線上端點存取 Azure 資源

適用於:Azure CLI ml 延伸模組 v2 (目前)Python SDK azure-ai-ml v2 (目前)

了解如何使用線上端點以及系統指派的受控識別或使用者指派的受控識別,從評分指令碼存取 Azure 資源。

受控端點和 Kubernetes 端點皆可讓 Azure Machine Learning 處理佈建計算資源和部署機器學習模型的負擔。 您的模型通常需要存取 Azure 資源,例如 Azure Container Registry 或 Blob 記憶體以進行推斷;透過受控識別,您可以存取這些資源,而不需要管理程式碼中的認證。 深入了解受控識別

本指南假設您沒有受控識別、記憶體帳戶或在線端點。 如果您已經有這些元件,請跳到 授與受控識別 的存取權一節。

必要條件

  • 如要使用 Azure Machine Learning,您必須擁有 Azure 訂閱。 如尚未擁有 Azure 訂用帳戶,請在開始之前先建立免費帳戶。 立即試用免費或付費版本的 Azure Machine Learning

  • 安裝和設定 Azure CLI 和 ML (v2) 延伸模組。 如需詳細資訊,請參閱安裝、設定和使用 2.0 CLI

  • Azure 資源群組,其中您(或使用的服務主體)必須具有使用者存取 管理員 istrator參與者存取權。 如果您根據上述文章設定 ML 擴充功能,您有這樣的資源群組。

  • Azure Machine Learning 工作區。 如果您已根據上述文章設定 ML 擴充功能,則已有工作區。

  • 已定型的機器學習模型,可供評分和部署。 如果您遵循範例,則會提供模型。

  • 如果您尚未設定 Azure CLI 的預設值,請儲存您的預設設定。 若要避免多次傳遞訂用帳戶、工作區和資源群組的值,請執行下列程式碼:

    az account set --subscription <subscription ID>
    az configure --defaults gitworkspace=<Azure Machine Learning workspace name> group=<resource group>
    
  • 若要遵循範例,請複製範例存放庫,然後將目錄變更為 cli

    git clone https://github.com/Azure/azureml-examples --depth 1
    cd azureml-examples/cli
    

限制

  • 端點的身分識別是不可變的。 在端點建立期間,您可以將其關聯至系統指派的身分識別 (預設) 或使用者指派的身分識別。 建立端點之後,您無法變更身分識別。
  • 如果您的ARC和 Blob 記憶體設定為私人,也就是虛擬網路後方,則不論您的工作區是公用還是私人,從 Kubernetes 端點的存取都應該是透過私人連結。 如需私人連結設定的詳細資訊,請參閱 如何保護工作區 vnet

設定變數以進行部署

設定工作區的變數名稱、工作區位置,以及您想要建立以與部署搭配使用的端點。

下列程式碼會將這些值匯出為您端點中的環境變數:

export WORKSPACE="<WORKSPACE_NAME>"
export LOCATION="<WORKSPACE_LOCATION>"
export ENDPOINT_NAME="<ENDPOINT_NAME>"

接下來,指定您要為 Blob 儲存體帳戶、Blob 容器和檔案命名的內容。 在這裡定義這些變數名稱,並在下一節中參考 az storage account createaz storage container create 命令。

下列程式碼會將這些值匯出為環境變數:

export STORAGE_ACCOUNT_NAME="<BLOB_STORAGE_TO_ACCESS>"
export STORAGE_CONTAINER_NAME="<CONTAINER_TO_ACCESS>"
export FILE_NAME="<FILE_TO_ACCESS>"

匯出這些變數之後,請在本機建立文字檔。 部署端點時,評分腳本會使用建立端點時所產生的系統指派受控識別來存取此文本檔。

定義部署設定

若要使用 CLI 部署線上端點,您需要在 YAML 檔案中定義設定。 如需有關 YAML 結構描述的詳細資訊,請參閱線上端點 YAML 參考文件。

下列範例中的 YAML 檔案是用來建立線上端點。

下列 YAML 範例位於 endpoints/online/managed/managed-identities/1-sai-create-endpoint。 檔案,

  • 定義您想要用來參考端點的名稱,my-sai-endpoint
  • 指定用來存取端點的授權類型,auth-mode: key
$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineEndpoint.schema.json
name: my-sai-endpoint
auth_mode: key

此 YAML 範例2-sai-deployment.yml

  • 指定您想要建立的端點類型是 online 端點。
  • 指出端點具有名為 blue 的相關聯部署。
  • 設定部署的詳細資料,例如要部署的模型,以及要使用的環境和評分指令碼。
$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
name: blue
model:
  path: ../../model-1/model/
code_configuration:
  code: ../../model-1/onlinescoring/
  scoring_script: score_managedidentity.py
environment:
  conda_file: ../../model-1/environment/conda-managedidentity.yaml
  image: mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest
instance_type: Standard_DS3_v2
instance_count: 1
environment_variables:
  STORAGE_ACCOUNT_NAME: "storage_place_holder"
  STORAGE_CONTAINER_NAME: "container_place_holder"
  FILE_NAME: "file_place_holder"

建立受控識別

若要存取 Azure 資源,請為您的線上端點建立系統指派或使用者指派的受控識別。

當您建立線上端點時,系統會為您自動產生系統指派的受控識別,因此不需要另外建立一個受控識別。

建立儲存體帳戶和容器

針對這個範例,請建立 Blob 儲存體帳戶和 Blob 容器,然後將先前建立的文字檔上傳至 Blob 容器。 您會提供此記憶體帳戶和 Blob 容器的線上端點和受控識別存取權。

首先,請建立儲存體帳戶。

az storage account create --name $STORAGE_ACCOUNT_NAME --location $LOCATION

接下來,在儲存體帳戶中建立 Blob 容器。

az storage container create --account-name $STORAGE_ACCOUNT_NAME --name $STORAGE_CONTAINER_NAME

然後,將您的文字檔上傳至 Blob 容器。

az storage blob upload --account-name $STORAGE_ACCOUNT_NAME --container-name $STORAGE_CONTAINER_NAME --name $FILE_NAME --file endpoints/online/managed/managed-identities/hello.txt

建立線上端點

下列程式碼會在不指定部署的情況下建立線上端點。

警告

端點的身分識別是不可變的。 在端點建立期間,您可以將其關聯至系統指派的身分識別 (預設) 或使用者指派的身分識別。 您無法在建立端點之後變更身分識別。

當您建立線上端點時,預設會為端點建立系統指派的受控識別。

az ml online-endpoint create --name $ENDPOINT_NAME -f endpoints/online/managed/managed-identities/1-sai-create-endpoint.yml

使用下列項目來檢查端點的狀態。

az ml online-endpoint show --name $ENDPOINT_NAME

如果您遇到任何問題,請參閱針對線上端點部署和評分進行疑難排解

授與受控識別的存取權限

重要

線上端點需要 Azure Container Registry 的提取權限、AcrPull 權限、容器登錄,以及工作區預設資料存放區的儲存體 Blob 資料讀取器權限。

您可以允許線上端點權限透過其系統指派的受控識別來存取您的儲存體,或授與使用者指派的受控識別權限,以存取上一節所建立的儲存體帳戶。

擷取針對您的端點所建立的系統指派受控識別。

system_identity=`az ml online-endpoint show --name $ENDPOINT_NAME --query "identity.principal_id" -o tsv`

您可以從這裡提供系統指派的受控識別權限,以存取您的儲存體。

az role assignment create --assignee-object-id $system_identity --assignee-principal-type ServicePrincipal --role "Storage Blob Data Reader" --scope $storage_id

用來存取 Azure 資源的評分指令碼

請參閱下列指令碼,以了解如何使用您的身分識別權杖來存取 Azure 資源,在此案例中是在先前章節建立的儲存體帳戶。

import os
import logging
import json
import numpy
import joblib
import requests
from azure.identity import ManagedIdentityCredential
from azure.storage.blob import BlobClient


def access_blob_storage_sdk():
    credential = ManagedIdentityCredential(client_id=os.getenv("UAI_CLIENT_ID"))
    storage_account = os.getenv("STORAGE_ACCOUNT_NAME")
    storage_container = os.getenv("STORAGE_CONTAINER_NAME")
    file_name = os.getenv("FILE_NAME")

    blob_client = BlobClient(
        account_url=f"https://{storage_account}.blob.core.windows.net/",
        container_name=storage_container,
        blob_name=file_name,
        credential=credential,
    )
    blob_contents = blob_client.download_blob().content_as_text()
    logging.info(f"Blob contains: {blob_contents}")


def get_token_rest():
    """
    Retrieve an access token via REST.
    """

    access_token = None
    msi_endpoint = os.environ.get("MSI_ENDPOINT", None)
    msi_secret = os.environ.get("MSI_SECRET", None)

    # If UAI_CLIENT_ID is provided then assume that endpoint was created with user assigned identity,
    # # otherwise system assigned identity deployment.
    client_id = os.environ.get("UAI_CLIENT_ID", None)
    if client_id is not None:
        token_url = (
            msi_endpoint + f"?clientid={client_id}&resource=https://storage.azure.com/"
        )
    else:
        token_url = msi_endpoint + f"?resource=https://storage.azure.com/"

    logging.info("Trying to get identity token...")
    headers = {"secret": msi_secret, "Metadata": "true"}
    resp = requests.get(token_url, headers=headers)
    resp.raise_for_status()
    access_token = resp.json()["access_token"]
    logging.info("Retrieved token successfully.")
    return access_token


def access_blob_storage_rest():
    """
    Access a blob via REST.
    """

    logging.info("Trying to access blob storage...")
    storage_account = os.environ.get("STORAGE_ACCOUNT_NAME")
    storage_container = os.environ.get("STORAGE_CONTAINER_NAME")
    file_name = os.environ.get("FILE_NAME")
    logging.info(
        f"storage_account: {storage_account}, container: {storage_container}, filename: {file_name}"
    )
    token = get_token_rest()

    blob_url = f"https://{storage_account}.blob.core.windows.net/{storage_container}/{file_name}?api-version=2019-04-01"
    auth_headers = {
        "Authorization": f"Bearer {token}",
        "x-ms-blob-type": "BlockBlob",
        "x-ms-version": "2019-02-02",
    }
    resp = requests.get(blob_url, headers=auth_headers)
    resp.raise_for_status()
    logging.info(f"Blob contains: {resp.text}")


def init():
    global model
    # AZUREML_MODEL_DIR is an environment variable created during deployment.
    # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)
    # For multiple models, it points to the folder containing all deployed models (./azureml-models)
    # Please provide your model's folder name if there is one
    model_path = os.path.join(
        os.getenv("AZUREML_MODEL_DIR"), "model/sklearn_regression_model.pkl"
    )
    # deserialize the model file back into a sklearn model
    model = joblib.load(model_path)
    logging.info("Model loaded")

    # Access Azure resource (Blob storage) using system assigned identity token
    access_blob_storage_rest()
    access_blob_storage_sdk()

    logging.info("Init complete")


# note you can pass in multiple rows for scoring
def run(raw_data):
    logging.info("Request received")
    data = json.loads(raw_data)["data"]
    data = numpy.array(data)
    result = model.predict(data)
    logging.info("Request processed")
    return result.tolist()

使用您的組態建立部署

建立與線上端點相關聯的部署。 深入了解如何部署到線上端點

警告

這項部署可能需要大約 8-14 分鐘的時間,視基礎環境/映像是否為第一次建立而定。 使用相同環境的後續部署將會更快。

az ml online-deployment create --endpoint-name $ENDPOINT_NAME --all-traffic --name blue --file endpoints/online/managed/managed-identities/2-sai-deployment.yml --set environment_variables.STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT_NAME environment_variables.STORAGE_CONTAINER_NAME=$STORAGE_CONTAINER_NAME environment_variables.FILE_NAME=$FILE_NAME

注意

引數 --name 的值可能會覆寫 YAML 檔案內的 name 索引鍵。

檢查部署狀態。

az ml online-deployment show --endpoint-name $ENDPOINT_NAME --name blue

若要將上述查詢修改為只傳回特定資料,請參閱查詢 Azure CLI 命令輸出

注意

評分指令碼中的 init 方法會使用系統指派的受控識別權杖,從您的儲存體帳戶讀取檔案。

若要檢查 init 方法輸出,請使用下列程式碼來查看部署記錄。

# Check deployment logs to confirm blob storage file contents read operation success.
az ml online-deployment get-logs --endpoint-name $ENDPOINT_NAME --name blue

當您的部署完成時,會在您的 Azure Machine Learning 工作區中註冊模型、環境和端點。

測試端點

部署線上端點後,請透過要求測試並確認其作業。 推斷的詳細資料會因模型而異。 在本指南中,JSON 查詢參數看起來如下所示:

{"data": [
    [1,2,3,4,5,6,7,8,9,10], 
    [10,9,8,7,6,5,4,3,2,1]
]}

若要呼叫您的端點,請執行:

az ml online-endpoint invoke --name $ENDPOINT_NAME --request-file endpoints/online/model-1/sample-request.json

刪除端點和儲存體帳戶

如果您不打算繼續使用已部署的線上端點和儲存體,請將其刪除以降低成本。 當您刪除端點時,也會一併刪除其所有相關聯的部署。

az ml online-endpoint delete --name $ENDPOINT_NAME --yes
az storage account delete --name $STORAGE_ACCOUNT_NAME --yes