使用托管标识从联机终结点访问 Azure 资源
本文内容
适用范围:Azure CLI ml 扩展 v2(最新版) Python SDK azure-ai-ml v2(最新版)
了解如何使用联机终结点以及系统分配的托管标识或用户分配的托管标识从评分脚本安全访问 Azure 资源。
使用托管终结点和 Kubernetes,Azure 机器学习可以管理预配计算资源和部署机器学习模型的工作。 通常,模型需要访问 Azure 资源,例如 Azure 容器注册表或用于推理的 Blob 存储;可以使用托管标识访问这些资源,而无需在代码中管理凭据。 详细了解托管标识。
本指南假设你没有托管标识、存储帐户或联机终结点。 如果你已有这些组件,请跳到“向托管标识授予访问权限 ”部分。
先决条件
若要使用 Azure 机器学习,必须有一个 Azure 订阅。 如果没有 Azure 订阅,请在开始前创建一个试用版订阅。 立即尝试试用版订阅 。
安装并配置 Azure CLI 和 ML (v2) 扩展。 有关详细信息,请参阅安装、设置和使用 2.0 CLI 。
Azure 资源组,你(或你使用的服务主体)在其中需要具有用户访问管理员 和参与者 访问权限。 如果已按照上述文章配置了 ML 扩展,那么你就有此类资源组。
一个 Azure 机器学习工作区。 如果已按照上述文章配置了 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
若要使用 Azure 机器学习,必须有一个 Azure 订阅。 如果没有 Azure 订阅,请在开始前创建一个试用版订阅。 立即尝试试用版订阅 。
安装并配置 Azure CLI 和 ML (v2) 扩展。 有关详细信息,请参阅安装、设置和使用 2.0 CLI 。
Azure 资源组,你(或你使用的服务主体)在其中需要具有用户访问管理员 和参与者 访问权限。 如果已按照上述文章配置了 ML 扩展,那么你就有此类资源组。
一个 Azure 机器学习工作区。 如果已按照上述文章配置了 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
若要使用 Azure 机器学习,必须有一个 Azure 订阅。 如果没有 Azure 订阅,请在开始前创建一个试用版订阅。 立即尝试试用版订阅 。
安装并配置 Azure 机器学习 Python SDK (v2)。 有关详细信息,请参阅安装和设置 SDK (v2) 。
Azure 资源组,你(或你使用的服务主体)在其中需要具有用户访问管理员 和参与者 访问权限。 如果已按照上述文章配置了 ML 扩展,那么你就有此类资源组。
一个 Azure 机器学习工作区。 如果已按照上述文章配置了 ML 扩展,那么你就有一个工作区。
一个已训练的、可供评分和部署的机器学习模型。 如果你按示例操作,则系统会提供一个模型。
克隆示例存储库,然后更改目录。
git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/sdk/endpoints/online/managed/managed-identities
若要遵循此笔记本,请访问 sdk/endpoints/online/managed/managed-identities 目录中的配套示例笔记本 。
此示例需要其他 Python 包:
Azure 存储管理客户端
Azure 授权管理客户端
使用以下代码安装这些包:
%pip install --pre azure-mgmt-storage
%pip install --pre azure-mgmt-authorization
若要使用 Azure 机器学习,必须有一个 Azure 订阅。 如果没有 Azure 订阅,请在开始前创建一个试用版订阅。 立即尝试试用版订阅 。
通过用户分配的标识进行访问的订阅或 Azure 资源的角色创建权限。
安装并配置 Azure 机器学习 Python SDK (v2)。 有关详细信息,请参阅安装和设置 SDK (v2) 。
Azure 资源组,你(或你使用的服务主体)在其中需要具有用户访问管理员 和参与者 访问权限。 如果已按照上述文章配置了 ML 扩展,那么你就有此类资源组。
一个 Azure 机器学习工作区。 如果已按照上述文章配置了 ML 扩展,那么你就有一个工作区。
一个已训练的、可供评分和部署的机器学习模型。 如果你按示例操作,则系统会提供一个模型。
克隆示例存储库。
git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/sdk/endpoints/online/managed/managed-identities
若要遵循此笔记本,请访问 sdk/endpoints/online/managed/managed-identities 目录中的配套示例笔记本 。
此示例需要其他 Python 包:
Azure MSI 管理客户端
Azure 存储客户端
Azure 授权管理客户端
使用以下代码安装这些包:
%pip install --pre azure-mgmt-msi
%pip install --pre azure-mgmt-storage
%pip install --pre azure-mgmt-authorization
限制
终结点的标识是不可变的。 创建终结点期间,可以将其与系统分配的标识(默认)或用户分配的标识相关联。 创建终结点后,无法更改标识。
为工作区、工作区位置以及要创建的用于部署的终结点配置变量名称。
以下代码将这些值作为终结点中的环境变量导出:
export WORKSPACE="<WORKSPACE_NAME>"
export LOCATION="<WORKSPACE_LOCATION>"
export ENDPOINT_NAME="<ENDPOINT_NAME>"
接下来,指定 Blob 存储帐户、Blob 容器和文件的名称。 这些变量名称在此处定义,并在下一部分所述的 az storage account create
和 az storage container create
命令中引用。
以下代码将这些值作为环境变量导出:
export STORAGE_ACCOUNT_NAME="<BLOB_STORAGE_TO_ACCESS>"
export STORAGE_CONTAINER_NAME="<CONTAINER_TO_ACCESS>"
export FILE_NAME="<FILE_TO_ACCESS>"
导出这些变量后,在本地创建一个文本文件。 部署终结点后,评分脚本将使用在创建终结点时生成的系统分配的托管标识来访问此文本文件。
确定终结点、工作区和工作区位置的名称,然后将该值作为环境变量导出:
export WORKSPACE="<WORKSPACE_NAME>"
export LOCATION="<WORKSPACE_LOCATION>"
export ENDPOINT_NAME="<ENDPOINT_NAME>"
接下来,指定 Blob 存储帐户、Blob 容器和文件的名称。 这些变量名称在此处定义,并在下一部分所述的 az storage account create
和 az storage container create
命令中引用。
export STORAGE_ACCOUNT_NAME="<BLOB_STORAGE_TO_ACCESS>"
export STORAGE_CONTAINER_NAME="<CONTAINER_TO_ACCESS>"
export FILE_NAME="<FILE_TO_ACCESS>"
导出这些变量后,在本地创建一个文本文件。 部署终结点后,评分脚本将使用终结点中所用的用户分配的托管标识访问此文本文件。
确定用户标识名称,并将该值作为环境变量导出:
export UAI_NAME="<USER_ASSIGNED_IDENTITY_NAME>"
为工作区和部署相关的变量分配值:
subscription_id = "<SUBSCRIPTION_ID>"
resource_group = "<RESOURCE_GROUP>"
workspace_name = "<AML_WORKSPACE_NAME>"
endpoint_name = "<ENDPOINT_NAME>"
接下来,指定 Blob 存储帐户、Blob 容器和文件的名称。 这些变量名称在此处定义,并在存储帐户和容器创建代码中由 StorageManagementClient
和 ContainerClient
引用。
storage_account_name = "<STORAGE_ACCOUNT_NAME>"
storage_container_name = "<CONTAINER_TO_ACCESS>"
file_name = "<FILE_TO_ACCESS>"
分配这些变量后,在本地创建一个文本文件。 部署终结点后,评分脚本将使用在创建终结点时生成的系统分配的托管标识来访问此文本文件。
现在,获取工作区的句柄并检索其位置:
from azure.ai.ml import MLClient
from azure.identity import AzureCliCredential
from azure.ai.ml.entities import (
ManagedOnlineDeployment,
ManagedOnlineEndpoint,
Model,
CodeConfiguration,
Environment,
)
credential = AzureCliCredential()
ml_client = MLClient(credential, subscription_id, resource_group, workspace_name)
workspace_location = ml_client.workspaces.get(workspace_name).location
使用此值创建存储帐户。
为工作区和部署相关的变量分配值:
subscription_id = "<SUBSCRIPTION_ID>"
resource_group = "<RESOURCE_GROUP>"
workspace_name = "<AML_WORKSPACE_NAME>"
endpoint_name = "<ENDPOINT_NAME>"
接下来,指定 Blob 存储帐户、Blob 容器和文件的名称。 这些变量名称在此处定义,并在存储帐户和容器创建代码中由 StorageManagementClient
和 ContainerClient
引用。
storage_account_name = "<STORAGE_ACCOUNT_NAME>"
storage_container_name = "<CONTAINER_TO_ACCESS>"
file_name = "<FILE_TO_ACCESS>"
分配这些变量后,在本地创建一个文本文件。 部署终结点后,评分脚本将使用在创建终结点时生成的用户分配的托管标识来访问此文本文件。
确定用户标识名称的名称:
uai_name = "<USER_ASSIGNED_IDENTITY_NAME>"
现在,获取工作区的句柄并检索其位置:
from azure.ai.ml import MLClient
from azure.identity import AzureCliCredential
from azure.ai.ml.entities import (
ManagedOnlineDeployment,
ManagedOnlineEndpoint,
Model,
CodeConfiguration,
Environment,
)
credential = AzureCliCredential()
ml_client = MLClient(credential, subscription_id, resource_group, workspace_name)
workspace_location = ml_client.workspaces.get(workspace_name).location
使用此值创建存储帐户。
定义部署配置
若要使用 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"
若要使用 CLI 部署联机终结点,需要在 YAML 文件中定义配置。 有关 YAML 架构的详细信息,请参阅联机终结点 YAML 参考 文档。
以下示例中的 YAML 文件用于创建联机终结点。
以下 YAML 示例位于 endpoints/online/managed/managed-identities/1-uai-create-endpoint 。 该文件:
定义了用于引用该终结点的名称 my-uai-endpoint
。
指定了用于访问该终结点的授权类型 auth-mode: key
。
指出了要使用的标识类型 type: user_assigned
$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineEndpoint.schema.json
name: my-uai-endpoint
auth_mode: key
identity:
type: user_assigned
user_assigned_identities:
- resource_id: user_identity_ARM_id_place_holder
此 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"
UAI_CLIENT_ID: "uai_client_id_place_holder"
若要使用 Python SDK (v2) 部署联机终结点,可以使用对象定义以下配置。 或者,可以使用 .load
方法加载 YAML 文件。
以下 Python 终结点对象:
为变量 endpoint_name
分配用于引用该终结点的名称。
指定用于访问终结点 auth-mode="key"
的授权类型。
endpoint = ManagedOnlineEndpoint(name=endpoint_name, auth_mode="key")
此部署对象:
通过类指定要创建的部署类型是 ManagedOnlineDeployment
。
指出了该终结点关联了一个名为 blue
的部署。
配置部署的详细信息,例如 name
和 instance_count
定义其他内联对象,并将其与 Model
、CodeConfiguration
和 Environment
的部署相关联。
包括系统分配的托管标识访问存储所需的环境变量。
deployment = ManagedOnlineDeployment(
name="blue",
endpoint_name=endpoint_name,
model=Model(path="../../model-1/model/"),
code_configuration=CodeConfiguration(
code="../../model-1/onlinescoring/", scoring_script="score_managedidentity.py"
),
environment=Environment(
conda_file="../../model-1/environment/conda.yml",
image="mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:20210727.v1",
),
instance_type="Standard_DS2_v2",
instance_count=1,
environment_variables={
"STORAGE_ACCOUNT_NAME": storage_account_name,
"STORAGE_CONTAINER_NAME": storage_container_name,
"FILE_NAME": file_name,
},
)
若要使用 Python SDK (v2) 部署联机终结点,可以使用对象定义以下配置。 或者,可以使用 .load
方法加载 YAML 文件。
对于用户分配的标识,可以在创建用户分配的托管标识后定义终结点配置。
此部署对象:
通过类指定要创建的部署类型是 ManagedOnlineDeployment
。
指出了该终结点关联了一个名为 blue
的部署。
配置部署的详细信息,例如 name
和 instance_count
定义更多内联对象,并将其与 Model
、CodeConfiguration
和 Environment
的部署相关联。
包括用户分配的托管标识访问存储所需的环境变量。
为 UAI_CLIENT_ID
添加一个占位符环境变量,它将在创建配置后且在实际部署此配置前添加。
deployment = ManagedOnlineDeployment(
name="blue",
endpoint_name=endpoint_name,
model=Model(path="../../model-1/model/"),
code_configuration=CodeConfiguration(
code="../../model-1/onlinescoring/", scoring_script="score_managedidentity.py"
),
environment=Environment(
conda_file="../../model-1/environment/conda.yml",
image="mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:20210727.v1",
),
instance_type="Standard_DS2_v2",
instance_count=1,
environment_variables={
"STORAGE_ACCOUNT_NAME": storage_account_name,
"STORAGE_CONTAINER_NAME": storage_container_name,
"FILE_NAME": file_name,
# We will update this after creating an identity
"UAI_CLIENT_ID": "uai_client_id_place_holder",
},
)
创建托管标识
若要访问 Azure 资源,请为联机终结点创建系统分配或用户分配的托管标识。
创建联机终结点 时,会自动生成系统分配的托管标识,因此你无需创建单独的标识。
若要创建用户分配的托管标识,请使用以下命令:
az identity create --name $UAI_NAME
创建联机终结点 时,会自动生成系统分配的托管标识,因此你无需创建单独的标识。
若要创建用户分配的托管标识,请先获取 ManagedServiceIdentityClient
句柄:
from azure.mgmt.msi import ManagedServiceIdentityClient
from azure.mgmt.msi.models import Identity
credential = AzureCliCredential()
msi_client = ManagedServiceIdentityClient(
subscription_id=subscription_id,
credential=credential,
)
然后,创建标识:
msi_client.user_assigned_identities.create_or_update(
resource_group_name=resource_group,
resource_name=uai_name,
parameters=Identity(location=workspace_location),
)
现在,检索标识对象,其中包含你使用的详细信息:
uai_identity = msi_client.user_assigned_identities.get(
resource_group_name=resource_group,
resource_name=uai_name,
)
uai_identity.as_dict()
创建存储帐户和容器
对于此示例,请创建一个 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 storage account create --name $STORAGE_ACCOUNT_NAME --location $LOCATION
还可以使用以下命令检索现有的存储帐户 ID。
storage_id=`az storage account show --name $STORAGE_ACCOUNT_NAME --query "id" -o tsv`
接下来,在该存储帐户中创建 Blob 容器。
az storage container create --account-name $STORAGE_ACCOUNT_NAME --name $STORAGE_CONTAINER_NAME
然后,在容器中上传文件。
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
首先,获取 StorageManagementclient
的句柄:
from azure.mgmt.storage import StorageManagementClient
from azure.storage.blob import ContainerClient
from azure.mgmt.storage.models import Sku, StorageAccountCreateParameters, BlobContainer
credential = AzureCliCredential()
storage_client = StorageManagementClient(
credential=credential, subscription_id=subscription_id
)
然后,创建存储帐户。
storage_account_parameters = StorageAccountCreateParameters(
sku=Sku(name="Standard_LRS"), kind="Storage", location=workspace_location
)
poller = storage_client.storage_accounts.begin_create(
resource_group_name=resource_group,
account_name=storage_account_name,
parameters=storage_account_parameters,
)
poller.wait()
storage_account = poller.result()
接下来,在该存储帐户中创建 Blob 容器:
blob_container = storage_client.blob_containers.create(
resource_group_name=resource_group,
account_name=storage_account_name,
container_name=storage_container_name,
blob_container=BlobContainer(),
)
检索存储帐户密钥,并使用 ContainerClient
创建容器的句柄:
res = storage_client.storage_accounts.list_keys(
resource_group_name=resource_group,
account_name=storage_account_name,
)
key = res.keys[0].value
container_client = ContainerClient(
account_url=storage_account.primary_endpoints.blob,
container_name=storage_container_name,
credential=key,
)
然后,使用 ContainerClient
将 Blob 上传到容器:
file_path = "hello.txt"
with open(file_path, "rb") as f:
container_client.upload_blob(name=file_name, data=f.read())
首先,获取 StorageManagementclient
的句柄:
from azure.mgmt.storage import StorageManagementClient
from azure.storage.blob import ContainerClient
from azure.mgmt.storage.models import Sku, StorageAccountCreateParameters, BlobContainer
credential = AzureCliCredential()
storage_client = StorageManagementClient(
credential=credential, subscription_id=subscription_id
)
然后,创建存储帐户。
storage_account_parameters = StorageAccountCreateParameters(
sku=Sku(name="Standard_LRS"), kind="Storage", location=workspace_location
)
poller = storage_client.storage_accounts.begin_create(
resource_group_name=resource_group,
account_name=storage_account_name,
parameters=storage_account_parameters,
)
poller.wait()
storage_account = poller.result()
接下来,在该存储帐户中创建 Blob 容器:
blob_container = storage_client.blob_containers.create(
resource_group_name=resource_group,
account_name=storage_account_name,
container_name=storage_container_name,
blob_container=BlobContainer(),
)
检索存储帐户密钥,并使用 ContainerClient
创建容器的句柄:
res = storage_client.storage_accounts.list_keys(
resource_group_name=resource_group,
account_name=storage_account_name,
)
key = res.keys[0].value
container_client = ContainerClient(
account_url=storage_account.primary_endpoints.blob,
container_name=storage_container_name,
credential=key,
)
然后,使用 ContainerClient
将 Blob 上传到容器:
file_path = "hello.txt"
with open(file_path, "rb") as f:
container_client.upload_blob(name=file_name, data=f.read())
创建联机终结点
以下代码在不指定部署的情况下创建联机终结点。
警告
终结点的标识是不可变的。 创建终结点期间,可以将其与系统分配的标识(默认)或用户分配的标识相关联。 创建终结点后,无法更改标识。
创建联机终结点时,默认将为该终结点创建系统分配的托管标识。
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
如果遇到任何问题,请参阅排查联机终结点部署和评分问题 。
az ml online-endpoint create --name $ENDPOINT_NAME -f endpoints/online/managed/managed-identities/1-uai-create-endpoint.yml --set identity.user_assigned_identities[0].resource_id=$uai_id
使用以下代码检查终结点的状态。
az ml online-endpoint show --name $ENDPOINT_NAME
如果遇到任何问题,请参阅排查联机终结点部署和评分问题 。
创建联机终结点时,默认将为该终结点创建系统分配的托管标识。
endpoint = ml_client.online_endpoints.begin_create_or_update(endpoint)
使用以下代码通过已部署的终结点对象的详细信息检查终结点的状态:
endpoint = ml_client.online_endpoints.get(endpoint_name)
endpoint.identity.as_dict()
如果遇到任何问题,请参阅排查联机终结点部署和评分问题 。
以下 Python 终结点对象:
为变量 endpoint_name
分配用于引用该终结点的名称。
指定用于访问终结点 auth-mode="key"
的授权类型。
将其标识定义为 ManagedServiceIdentity
,并将托管标识指定为用户分配的托管标识。
定义和部署终结点:
from azure.ai.ml._restclient.v2022_05_01.models import ManagedServiceIdentity
endpoint = ManagedOnlineEndpoint(
name=endpoint_name,
auth_mode="key",
identity=ManagedServiceIdentity(
type="user_assigned",
user_assigned_identities=[{"resource_id": uai_identity.id}],
),
)
ml_client.online_endpoints.begin_create_or_update(endpoint)
使用以下代码通过已部署的终结点对象的详细信息检查终结点的状态:
endpoint = ml_client.online_endpoints.get(endpoint_name)
endpoint.identity.as_dict()
如果遇到任何问题,请参阅排查联机终结点部署和评分问题 。
向托管标识授予访问权限
重要
联机终结点需要对容器注册表拥有 Azure 容器注册表拉取权限和 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
检索用户分配的托管标识客户端 ID。
uai_clientid=`az identity list --query "[?name=='$UAI_NAME'].clientId" -o tsv`
uai_principalid=`az identity list --query "[?name=='$UAI_NAME'].principalId" -o tsv`
检索用户分配的托管标识 ID。
uai_id=`az identity list --query "[?name=='$UAI_NAME'].id" -o tsv`
获取与工作区关联的容器注册表。
container_registry=`az ml workspace show --name $WORKSPACE --query container_registry -o tsv`
检索工作区的默认存储。
storage_account=`az ml workspace show --name $WORKSPACE --query storage_account -o tsv`
向用户分配的托管标识授予存储帐户权限。
az role assignment create --assignee-object-id $uai_principalid --assignee-principal-type ServicePrincipal --role "Storage Blob Data Reader" --scope $storage_id
向用户分配的托管标识授予容器注册表权限。
az role assignment create --assignee-object-id $uai_principalid --assignee-principal-type ServicePrincipal --role "AcrPull" --scope $container_registry
向用户分配的托管标识授予默认工作区存储权限。
az role assignment create --assignee-object-id $uai_principalid --assignee-principal-type ServicePrincipal --role "Storage Blob Data Reader" --scope $storage_account
首先,创建 AuthorizationManagementClient
以列出角色定义:
from azure.mgmt.authorization import AuthorizationManagementClient
from azure.mgmt.authorization.v2018_01_01_preview.models import RoleDefinition
import uuid
role_definition_client = AuthorizationManagementClient(
credential=credential,
subscription_id=subscription_id,
api_version="2018-01-01-preview",
)
现在,执行初始化以创建角色分配:
from azure.mgmt.authorization.v2020_10_01_preview.models import (
RoleAssignment,
RoleAssignmentCreateParameters,
)
role_assignment_client = AuthorizationManagementClient(
credential=credential,
subscription_id=subscription_id,
api_version="2020-10-01-preview",
)
然后,获取系统分配的托管标识的主体 ID:
endpoint = ml_client.online_endpoints.get(endpoint_name)
system_principal_id = endpoint.identity.principal_id
接下来,将存储 Blob 数据读取者 角色分配给终结点。 系统按名称检索角色定义,并将其随终结点的主体 ID 一起传递。 角色在上面创建的存储帐户的范围内应用,并允许终结点读取文件。
role_name = "Storage Blob Data Reader"
scope = storage_account.id
role_defs = role_definition_client.role_definitions.list(scope=scope)
role_def = next((r for r in role_defs if r.role_name == role_name))
role_assignment_client.role_assignments.create(
scope=scope,
role_assignment_name=str(uuid.uuid4()),
parameters=RoleAssignmentCreateParameters(
role_definition_id=role_def.id, principal_id=system_principal_id
),
)
首先,创建 AuthorizationManagementClient
以列出角色定义:
from azure.mgmt.authorization import AuthorizationManagementClient
from azure.mgmt.authorization.v2018_01_01_preview.models import RoleDefinition
import uuid
role_definition_client = AuthorizationManagementClient(
credential=credential,
subscription_id=subscription_id,
api_version="2018-01-01-preview",
)
现在,执行初始化以创建角色分配:
from azure.mgmt.authorization.v2020_10_01_preview.models import (
RoleAssignment,
RoleAssignmentCreateParameters,
)
role_assignment_client = AuthorizationManagementClient(
credential=credential,
subscription_id=subscription_id,
api_version="2020-10-01-preview",
)
然后,获取用户分配的托管标识的主体 ID 和客户端 ID。 若要分配角色,则只需要主体 ID。 但是,在创建部署之前,可使用客户端 ID 填充 UAI_CLIENT_ID
占位符环境变量。
uai_identity = msi_client.user_assigned_identities.get(
resource_group_name=resource_group, resource_name=uai_name
)
uai_principal_id = uai_identity.principal_id
uai_client_id = uai_identity.client_id
接下来,将存储 Blob 数据读取者 角色分配给终结点。 系统按名称检索角色定义,并将其随终结点的主体 ID 一起传递。 角色在上面创建的存储帐户的范围内应用,以允许终结点读取文件。
role_name = "Storage Blob Data Reader"
scope = storage_account.id
role_defs = role_definition_client.role_definitions.list(scope=scope)
role_def = next((r for r in role_defs if r.role_name == role_name))
role_assignment_client.role_assignments.create(
scope=scope,
role_assignment_name=str(uuid.uuid4()),
parameters=RoleAssignmentCreateParameters(
role_definition_id=role_def.id, principal_id=uai_principal_id
),
)
对于接下来的两个权限,需要工作区和容器注册表对象:
workspace = ml_client.workspaces.get(workspace_name)
container_registry = workspace.container_registry
接下来,将 AcrPull 角色分配给用户分配的标识。 此角色允许从 Azure 容器注册表拉取映像。 此范围在与工作区关联的容器注册表的级别应用。
role_name = "AcrPull"
scope = container_registry
role_defs = role_definition_client.role_definitions.list(scope=scope)
role_def = next((r for r in role_defs if r.role_name == role_name))
role_assignment_client.role_assignments.create(
scope=scope,
role_assignment_name=str(uuid.uuid4()),
parameters=RoleAssignmentCreateParameters(
role_definition_id=role_def.id, principal_id=uai_principal_id
),
)
最后,将存储 Blob 数据读取者 角色分配给工作区存储帐户范围内的终结点。 此角色分配允许终结点读取工作区存储帐户和新创建的存储帐户中的 Blob。
该角色的名称和功能与上面分配的第一个角色相同,但它应用于不同的范围,并且具有不同的 ID。
role_name = "Storage Blob Data Reader"
scope = workspace.storage_account
role_defs = role_definition_client.role_definitions.list(scope=scope)
role_def = next((r for r in role_defs if r.role_name == role_name))
role_assignment_client.role_assignments.create(
scope=scope,
role_assignment_name=str(uuid.uuid4()),
parameters=RoleAssignmentCreateParameters(
role_definition_id=role_def.id, principal_id=uai_principal_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.chinacloudapi.cn/",
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.chinacloudapi.cn/{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
az ml online-endpoint create --name $ENDPOINT_NAME -f endpoints/online/managed/managed-identities/1-uai-create-endpoint.yml --set identity.user_assigned_identities[0].resource_id=$uai_id
注意
--name
参数的值可能会替代 YAML 文件中的 name
键。
执行该命令后,可以检查部署状态。
az ml online-endpoint show --name $ENDPOINT_NAME
若要将上述查询具体化为仅返回特定数据,请参阅查询 Azure CLI 命令输出 。
# Check deployment logs to confirm blob storage file contents read operation success.
az ml online-deployment get-logs --endpoint-name $ENDPOINT_NAME --name blue
注意
评分脚本中的 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
首先,创建部署:
deployment = ml_client.online_deployments.begin_create_or_update(deployment)
部署完成后,请检查其状态并确认其标识详细信息:
deployment = ml_client.online_deployments.get(
endpoint_name=endpoint_name, name=deployment.name
)
print(deployment)
注意
评分脚本中的 init 方法使用系统分配的托管标识令牌从你的存储帐户读取文件。
若要检查 init 方法输出,请使用以下代码查看部署日志。
ml_client.online_deployments.get_logs(deployment.name, deployment.endpoint_name, 1000)
确认部署后,将流量设置为 100%:
endpoint.traffic = {str(deployment.name): 100}
ml_client.begin_create_or_update(endpoint)
在部署之前,请更新 UAI_CLIENT_ID
环境变量占位符。
deployment.environment_variables['UAI_CLIENT_ID'] = uai_client_id
现在,创建部署:
deployment = ml_client.online_deployments.begin_create_or_update(deployment)
部署完成后,请检查其状态并确认其标识详细信息:
deployment = ml_client.online_deployments.get(
endpoint_name=endpoint_name, name=deployment.name
)
print(deployment)
注意
评分脚本中的 init 方法使用用户分配的托管标识令牌从你的存储帐户读取文件。
若要检查 init 方法输出,请使用以下代码查看部署日志。
ml_client.online_deployments.get_logs(deployment.name, deployment.endpoint_name, 1000)
确认部署后,将流量设置为 100%:
endpoint.traffic = {str(deployment.name): 100}
ml_client.begin_create_or_update(endpoint)
部署完成后,模型、环境和终结点即已注册到你的 Azure 机器学习工作区。
测试终结点
部署联机终结点后,使用请求测试并确认其操作。 推理的详细信息因模型而异。 在本指南中,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 invoke --name $ENDPOINT_NAME --request-file endpoints/online/model-1/sample-request.json
sample_data = "../../model-1/sample-request.json"
ml_client.online_endpoints.invoke(endpoint_name=endpoint_name, request_file=sample_data)
sample_data = "../../model-1/sample-request.json"
ml_client.online_endpoints.invoke(endpoint_name=endpoint_name, request_file=sample_data)
删除终结点和存储帐户
如果你不打算继续使用部署的联机终结点和存储,请将其删除以降低成本。 删除终结点时,也会删除其所有关联的部署。
az ml online-endpoint delete --name $ENDPOINT_NAME --yes
az storage account delete --name $STORAGE_ACCOUNT_NAME --yes
az ml online-endpoint delete --name $ENDPOINT_NAME --yes
az storage account delete --name $STORAGE_ACCOUNT_NAME --yes
az identity delete --name $UAI_NAME
删除终结点:
ml_client.online_endpoints.begin_delete(endpoint_name)
删除存储帐户:
storage_client.storage_accounts.delete(
resource_group_name=resource_group, account_name=storage_account_name
)
删除终结点:
ml_client.online_endpoints.begin_delete(endpoint_name)
删除存储帐户:
storage_client.storage_accounts.delete(
resource_group_name=resource_group, account_name=storage_account_name
)
删除用户分配的托管标识:
msi_client.user_assigned_identities.delete(
resource_group_name=resource_group, resource_name=uai_name
)
相关内容