mcpField
M
ml-azureml-adf-automation

ml-azureml-adf-automation

github.com/josiahsiegel云与 DevOps5950 次安装19 周前更新
代码仓库

关于 ml-azureml-adf-automation

用于在 CI 中自动注册 Azure Machine Learning 代码资源,并将注册版本传入 Azure Data Factory 工作流的技能。强调以 SDK 返回的版本为准,并在运行时验证网络和依赖项。

主要功能

  1. 01在 CI 中注册 Azure ML 代码资源
  2. 02传递 SDK 返回的资源版本
  3. 03通过指针 Blob 传递版本
  4. 04配置 ADF WebActivity 网络
  5. 05验证私有存储访问
  6. 06固定 Azure ML SDK 依赖

适用场景

  1. 01自动化 CI 中的代码资源注册
  2. 02向 ADF 作业传递准确资源版本
  3. 03排查私有存储访问故障
  4. 04在运行时验证 Azure ML 和 ADF 变更

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill ml-azureml-adf-automation

安装后在 Claude Code 中输入/ml-azureml-adf-automation确认已加载。

详细介绍

Azure ML 和 ADF 自动化

概述

当你需要在 CI 中注册代码资产,并通过 Azure Data Factory 编排训练、评分、注册或部署时,请使用此技能。核心不变原则是:运行时系统必须使用实际注册的 Azure ML 资产版本,而不是管道尝试请求的版本。请根据运行时行为验证每条建议,因为 Azure ML、ADF、存储网络和 SDK 依赖项行为可能与静态 API 文档不一致。

核心不变原则

  • CI 负责注册 Azure ML 代码资产,并发布 SDK 实际返回的版本。
  • ADF 通过明确的契约接收代码版本(通常是存储指针 Blob),而不是在运行时发现 AML 代码版本。
  • SDK 结果是事实来源:请求的版本、构建 ID、分支名称或根据提交派生的字符串都不是权威信息。
  • 私有存储不仅需要正确的 RBAC,还需要证明执行环境能够访问数据平面。
  • 必须通过预期的集成运行时测试 ADF WebActivity 的网络连接,而不能只验证 JSON。
  • Azure ML 自动化环境中的依赖项约束必须在 CI 中固定。
  • 运行时证据优先于看似合理的 ARM 路径、文档片段或成功编译的模板。

Azure ML 代码资产注册

如果自动化需要可靠地获取已注册的版本,优先使用 Python SDK 注册 Azure ML 代码资产。只有在确认目标环境中的 az ml 扩展支持所需的代码命令,且返回的信息足以供下游自动化使用之后,才使用 Azure CLI。

from azure.ai.ml import MLClient
from azure.ai.ml.entities._assets._artifacts.code import Code
from azure.identity import AzureCliCredential

ml_client = MLClient(
    AzureCliCredential(),
    subscription_id,
    resource_group,
    workspace_name,
)

result = ml_client._code.create_or_update(
    Code(name=code_name, version=requested_version, path=staged_code_path)
)
actual_version = result.version
print(actual_version)

不要假设 requested_version == result.version。Azure ML 代码资产可以根据内容哈希去重上传;如果暂存目录与先前的资产相同,就会返回已有版本。这种存储行为很有用,但如果 CI 发布的是请求的构建标识符,而不是 SDK 返回的版本,就会造成风险。

CI 输出变量模式

将返回的版本发布为管道输出变量,并将下游步骤连接到该输出。

print(
    "##vso[task.setvariable "
    f"variable=trainingCodeVersion;isOutput=true]{result.version}"
)

优先使用:

$registeredVersion = '$(RegisterTrainingCode.trainingCodeVersion)'

避免使用:

$registeredVersion = '$(Build.BuildId)'

如果即使代码内容重复,操作上仍要求资产版本唯一,请暂存代码目录,并在注册前写入一个小型标记文件,例如 .aml-code-asset-version。此方法仅用于解决去重问题。真正的契约仍然是 SDK 返回的 result.version。

ADF 到 Azure ML 的版本解析

除非经过运行时验证,否则不要让 ADF 通过 Azure ML ARM 代码容器端点发现 AML 代码版本。某些 AML 管理端点在 REST 文档中看似有效,但在执行时可能在 ADF WebActivity 中因不支持的操作而失败。在有证据证明并非如此之前,应将其视为服务行为,而不是主要归因于 RBAC 问题。

使用由 CI 写入的指针 Blob,作为注册与编排之间的运行时契约:

https://<storage-account>.blob.core.windows.net/ml-globals/code-assets/training-code/latest.json

示例负载:

{
  "assetName": "training-code",
  "version": "<actual-sdk-returned-version>",
  "workspaceName": "<workspace-name>",
  "resourceGroup": "<resource-group>",
  "subscriptionId": "<subscription-id>",
  "buildId": "<build-or-run-id>",
  "sourceBranch": "<branch>",
  "sourceVersion": "<source-version>",
  "registeredAtUtc": "<timestamp>"
}

ADF 从此 Blob 中读取 version,并将其作为参数传递给训练、评分、模型注册或部署管道。负载可以包含来源信息字段,但下游作业只能依赖明确纳入契约的字段。

用于指针 Blob 读取的 ADF WebActivity

使用托管标识身份验证从 Azure Storage 读取指针 Blob:

{
  "name": "ReadLatestTrainingCodeVersion",
  "type": "WebActivity",
  "typeProperties": {
    "method": "GET",
    "url": {
      "type": "Expression",
      "value": "@concat('https://', pipeline().globalParameters.StorageAccountName, '.blob.core.windows.net/ml-globals/code-assets/training-code/latest.json')"
    },
    "headers": {
      "x-ms-version": "2023-11-03",
      "Accept": "application/json"
    },
    "authentication": {
      "type": "MSI",
      "resource": "https://storage.azure.com/"
    },
    "connectVia": {
      "referenceName": "<managed-vnet-ir-name>",
      "type": "IntegrationRuntimeReference"
    }
  }
}

关键位置规则:对于 ADF WebActivity,connectVia 必须放在 typeProperties 内。如果将其放在活动根级别,可能会被忽略,导致流量经由公共互联网传出,并在 defaultAction: Deny 的存储帐户上失败。

通常需要以下访问权限:

  • ADF 托管标识:在指针容器或帐户范围内拥有 Storage Blob Data Reader 角色。
  • CI 服务连接标识:拥有 Storage Blob Data Contributor 角色,以写入指针 Blob。
  • CI 服务连接标识:当流水线管理存储防火墙规则时,拥有 Storage Account Contributor 角色。

私有存储和托管 CI Agent

对于具有专用终结点且 defaultAction: Deny 的存储帐户,Microsoft 托管 CI Agent 通常会使用每次运行分配的公共 IP 地址进行流出。如果 Agent 无法访问存储数据平面,仅有正确的 RBAC 权限并不足够。在归咎于 Azure ML SDK、ADF 或 IAM 之前,请先验证 Agent 是否能够访问存储。

安全的 CI 模式:

  1. 获取 Agent 的公共 IP。
  2. 为该 IP 添加临时存储网络规则。
  3. 等待规则传播。
  4. 对存储数据平面访问进行冒烟测试。
  5. 注册代码资源并写入指针 Blob。
  6. 在 always() 清理步骤中移除临时规则。
$agentIp = (Invoke-RestMethod -Uri 'https://api.ipify.org' -TimeoutSec 20).Trim()

az storage account network-rule add `
  --resource-group $rg `
  --account-name $storageAccount `
  --action Allow `
  --ip-address $agentIp `
  --only-show-errors

Start-Sleep -Seconds 30

az storage container list `
  --account-name $storageAccount `
  --auth-mode login `
  --only-show-errors `
  -o none

即使注册失败,也应执行清理。在 Azure DevOps YAML 中,应将网络规则移除操作放在带有 condition: always() 的步骤中。

Python 依赖项固定

某些版本的 azure-ai-ml 会导入 marshmallow 4.x 中不可用的私有 marshmallow 符号。托管 Agent 可能会安装不兼容的传递依赖版本,导致在任何 Azure ML API 调用运行之前就失败。使用受影响的版本时,请同时固定 SDK 和传递依赖。

python -m pip install --upgrade `
  "azure-ai-ml==1.24.0" `
  "azure-identity==1.19.0" `
  "marshmallow>=3.18,<4.0"

如果使用较新的 SDK,请在 CI 中验证依赖行为,不要仅凭本地运行成功就移除版本固定。

ADF 开发工作流

确认哪种 ADF 执行模式会读取未发布的 Git 分支状态,哪种模式会运行已发布的工厂定义。调试运行可能会使用分支状态,而计划运行和生产运行通常会执行最近发布的工厂定义。手动触发的行为取决于工厂的配置和调用方式。请选择能够实际验证所做更改的模式。

运行时验证标准

应接受运行时证据,而非仅凭结构推断合理性。验证以下内容:

  • Azure ML 注册返回了 result.version,且 CI 传递的正是该值。
  • 指针 Blob 中包含 Azure ML 实际注册的版本。
  • ADF 通过指定的集成运行时和托管标识读取 Blob。
  • 使用实际的防火墙配置和 CI Agent 流出路径测试存储。
  • 下游 ADF 参数会传递到运行时使用的 AML 作业定义中。
  • AML 训练或评分作业使用预期的代码资源版本启动。
  • SDK 导入在 CI 使用的同一托管 Agent 映像中成功。

以下验证方式并不足够:文档显示某个终结点存在、解析 JSON、看起来合理的 ARM URL、部署模板成功、日志中打印了请求的版本却未检查 result.version,或只有审查意见而没有运行时证据。

运维检查清单

  • Azure ML 代码资产是否由 CI 负责注册?
  • CI 是否捕获并发布 SDK 返回的 result.version?
  • ADF 是否通过显式参数或指针 Blob 获取准确的代码版本?
  • 指针负载是否将契约字段与可选来源元数据分开?
  • 在需要专用网络时,ADF WebActivities 是否在 typeProperties 中使用 connectVia?
  • MSI Blob 访问是否使用身份验证资源 https://storage.azure.com/?
  • ADF 托管标识是否具有 Storage Blob Data Reader 权限?
  • CI 服务连接标识是否具有 Storage Blob Data Contributor 权限?
  • 如果 CI 更改存储防火墙规则,是否会在清理过程中执行添加、等待、冒烟测试和移除?
  • 是否固定了已知的 Azure ML SDK 依赖约束?
  • 是否针对运行时基础设施路径进行了验证,而不只是编译或审查?

简要规则

  • 注册代码时使用 Azure ML Python SDK,除非已在目标环境中验证 CLI 的行为。
  • 切勿假设请求的版本等于已注册的版本。
  • 将 SDK 的 result.version 视为唯一可信来源。
  • 未经运行时测试,不要从 ADF 中通过 AML ARM /codes/... 进行发现。
  • 使用 Blob 指针作为 ADF 可读取的 ML 资产版本契约。
  • 将 ADF WebActivity 的 connectVia 放在 typeProperties 中。
  • 假定托管 CI Agent 需要临时存储防火墙访问权限才能访问专用存储。
  • 当 AML SDK 导入存在已知约束时,固定传递依赖。
  • ML 基础设施变更必须经过运行时验证。

来源

评论

支持 Markdown