排查联机终结点的部署和评分问题

适用范围:Azure CLI ml 扩展 v2(最新版)Python SDK azure-ai-ml v2(最新版)

了解如何解决 Azure 机器学习联机终结点的常见部署和评分问题。

本文档采用一种可方便你着手进行故障排除的结构:

  1. 在云中部署之前,请使用本地部署在本地测试和调试模型。
  2. 使用容器日志帮助调试问题。
  3. 了解可能会出现的常见部署错误及其解决方法。

HTTP 状态代码部分解释了在使用 REST 请求为终结点评分时,调用和预测错误如何映射到 HTTP 状态代码。

先决条件

本地部署

本地部署会将模型部署到本地 Docker 环境。 本地部署可用于在部署到云之前进行测试和调试。

提示

你还可以使用 Azure 机器学习推理 HTTP 服务器 Python 包在本地调试评分脚本。 使用推理服务器进行调试有助于在部署到本地终结点之前调试评分脚本,以便在不受部署容器配置影响的情况下进行调试。

本地部署支持创建、更新和删除本地终结点。 它还允许从终结点调用和获取日志。

若要使用本地部署,请将 --local 添加到相应的 CLI 命令:

az ml online-deployment create --endpoint-name <endpoint-name> -n <deployment-name> -f <spec_file.yaml> --local

在本地部署过程中,将执行以下步骤:

  • Docker 生成新的容器映像,或者从本地 Docker 缓存拉取现有映像。 如果某个现有映像与规范文件的环境部分相匹配,将使用该映像。
  • Docker 启动装载了本地项目(如模型和代码文件)的新容器。

有关详细信息,请参阅在本地部署机器学习模型并为其评分

提示

使用 Visual Studio Code 在本地测试和调试终结点。 有关详细信息,请参阅在 Visual Studio Code 中以本地方式调试联机终结点

Conda 安装

通常,MLflow 部署问题源于 conda.yaml 文件中指定的用户环境的安装问题。

若要调试 conda 安装问题,请尝试以下步骤:

  1. 检查 conda 安装的日志。 如果容器崩溃或启动时间过长,则可能是 conda 环境更新无法正确解析。

  2. 使用命令 conda env create -n userenv -f <CONDA_ENV_FILENAME> 在本地安装 mlflow conda 文件。

  3. 如果本地存在错误,请尝试解析 conda 环境并创建一个功能性环境,然后再重新部署。

  4. 如果即使在本地解析,容器也会崩溃,则用于部署的 SKU 大小可能太小。

    1. Conda 包安装在运行时进行,因此如果 SKU 太小而无法容纳 conda.yaml 环境文件中详述的所有包,则容器可能会崩溃。
    2. Standard_F4s_v2 VM 是一个很好的启动 SKU 大小,但可能需要更大的 SKU,具体取决于 conda 文件中指定的依赖项。
    3. 对于 Kubernetes 联机终结点,Kubernetes 群集必须至少有 4 个 vCPU 核心和 8 GB 内存。

获取容器日志

无法直接访问部署了模型的 VM。 但是,可以从该 VM 上运行的某些容器获取日志。 获取的信息量取决于部署的预配状态。 如果指定的容器已启动且正在运行,则你会看到其控制台输出,否则会收到一条请你稍后重试的消息。

可以从两种类型的容器中获取日志:

  • 推理服务器:日志包括控制台日志(来自推理服务器),其中包含评分脚本(score.py 代码)的打印/日志记录函数的输出。
  • 存储初始化表达式:日志包含有关代码和模型数据是否已成功下载到容器的信息。 该容器会在推理服务器容器开始运行之前运行。

若要查看容器的日志输出,请使用以下 CLI 命令:

az ml online-deployment get-logs -e <endpoint-name> -n <deployment-name> -l 100

az ml online-deployment get-logs --endpoint-name <endpoint-name> --name <deployment-name> --lines 100

如果尚未通过 az configure 设置 --resource-group--workspace-name 参数,请将这些参数添加到这些命令。

若要查看有关如何设置这些参数的信息,且你当前已设置了值,则请运行:

az ml online-deployment get-logs -h

默认情况下,日志是从推理服务器拉取的。

注意

如果使用 Python 日志记录,请确保为要发布到日志中的消息使用正确的日志记录级别顺序。 例如 INFO。

还可以通过传递 –-container storage-initializer 从存储初始化表达式容器获取日志。

添加 --help 和/或 --debug 命令以查看更多信息。

对于 Kubernetes 联机终结点,管理员可以直接访问部署模型的群集,因此可以更灵活地在 Kubernetes 中查看日志。 例如:

kubectl -n <compute-namespace> logs <container-name>

请求跟踪

受支持的跟踪标头有两个:

  • x-request-id 保留用于服务器跟踪。 我们重写此标头以确保它是有效的 GUID。

    注意

    为失败的请求创建支持票证时,请附加失败的请求 ID 以加快调查。

  • x-ms-client-request-id 可用于客户端跟踪方案。 此标头经过清理,仅接受字母数字字符、连字符和下划线,并被截断为最多 40 个字符。

常见部署错误

以下列表列出了作为部署操作状态的一部分报告的常见部署错误:

如果要创建或更新 Kubernetes 联机部署,你会看到特定于 Kubernetes 部署的常见错误

错误:ImageBuildFailure

生成环境(docker 映像)时返回此错误。 可以检查生成日志,了解有关失败的更多详细信息。 生成日志位于 Azure 机器学习工作区的默认存储中。 确切位置可能作为错误的一部分返回。 例如 "the build log under the storage account '[storage-account-name]' in the container '[container-name]' at the path '[path-to-the-log]'"

以下列表包含常见的映像生成失败方案:

如果有 ImageBuild 超时,则还建议查看默认探测设置

容器注册表授权失败

如果错误消息提及了 "container registry authorization failure",这意味着你无法使用当前凭据访问容器注册表。 工作区资源的键不同步可能会造成的此错误,自动同步需要一些时间。 但是,你可以手动调用键同步,这可能会解决授权失败的问题。

如果设置不正确,虚拟网络后的容器注册表也可能会遇到此错误。 你必须验证是否已正确设置虚拟网络。

未在具有 VNet 的专用工作区中设置映像生成计算

如果错误消息提到 "failed to communicate with the workspace's container registry",而你使用的是虚拟网络,并且工作区的 Azure 容器注册表是专用的,且配置了专用终结点,则需要启用 Azure 容器注册表以允许在虚拟网络中生成映像。

泛型映像生成失败

如前所述,可以检查生成日志,了解有关失败的更多详细信息。 如果在生成日志中没有发现明显的错误,并且最后一行是 Installing pip dependencies: ...working...,则错误可能是由依赖项引起的。 在 conda 文件中固定版本依赖项可解决此问题。

我们还建议在本地部署以在本地测试和调试模型,然后再部署到云中。

错误:OutOfQuota

以下列表列出了在使用 Azure 服务时可能用完配额的常见资源:

此外,以下列表列出了可能用完 Kubernetes 联机终结点专用配额的常见资源:

CPU 配额

在部署模型之前,需有足够的计算配额。 此配额定义每个订阅、每个工作区、每个 SKU 和每个区域可用的虚拟核心数。 每次部署都会扣减可用配额,删除部署后,会根据 SKU 的类型重新增加配额。

一种可能的缓解措施是检查能否删除未使用的部署。 或者,可以提交配额提高请求

群集配额

如果没有足够的 Azure 机器学习计算群集配额,则会出现此问题。 此配额定义每个订阅一次可用于在 Azure 云中部署 CPU 或 GPU 节点的群集总数。

一种可能的缓解措施是检查能否删除未使用的部署。 或者,可以提交配额提高请求。 请确保选择 Machine Learning Service: Cluster Quota 作为此配额提高请求的配额类型。

磁盘配额

如果模型的大小大于可用磁盘空间,并且无法下载模型,则会出现此问题。 试用具有更多磁盘空间的 SKU 或减小映像和模型大小。

内存配额

当模型的内存占用大于可用内存时,就会发生此问题。 试用具有更多内存的 SKU

角色分配配额

创建托管联机终结点时,托管标识需要角色分配才能访问工作区资源。 如果已达到角色分配限制,请尝试删除此订阅中的一些未使用的角色分配。 可以导航到“访问控制”菜单以检查 Azure 门户中的所有角色分配。

终结点配额

尝试删除此订阅中某些未使用的终结点。 如果所有终结点都在积极使用中,可以尝试请求调高终结点限制。 若要详细了解终结点限制,请参阅 Azure 机器学习联机终结点和批处理终结点的终结点配额

Kubernetes 配额

当由于节点对此部署不可调度而无法提供所请求的 CPU 或内存时,就会出现此问题。 例如,节点可能已被封锁或不可用。

错误消息通常会指示群集中的资源不足,例如 OutOfQuota: Kubernetes unschedulable. Details:0/1 nodes are available: 1 Too many pods...,这意味着群集中的 Pod 太多,资源不足,无法根据请求部署新模型。

您可以尝试以下缓解措施来解决此问题:

  • 对于维护 Kubernetes 群集的 IT 运营人员,可以尝试添加更多节点,或者清除群集中一些未使用的 Pod 来释放一些资源。
  • 对于部署模型的机器学习工程师,可尝试减少部署的资源请求:
    • 如果通过资源部分在部署配置中直接定义资源请求,则可以尝试减少资源请求。
    • 如果使用 instance type 定义模型部署的资源,则可以联系 IT 运营人员来调整实例类型资源配置。有关详细信息,请参阅如何管理 Kubernetes 实例类型

区域范围的 VM 容量

由于区域中缺少 Azure 机器学习容量,服务无法预配指定的 VM 大小。 请稍后重试,或尝试部署到其他区域。

其他配额

为了运行在部署过程中提供的 score.py,Azure 将创建一个包含 score.py 所需全部资源的容器,并在该容器上运行评分脚本。

如果容器无法启动,则意味着无法进行评分。 可能是容器请求的资源数量超过了 instance_type 可以支持的数量。 如果是这样,请考虑更新联机部署的 instance_type

若要获取确切的错误原因,请运行:

az ml online-deployment get-logs -e <endpoint-name> -n <deployment-name> -l 100

错误:BadArgument

以下列表列出了使用托管联机终结点或 Kubernetes 联机终结点时可能会遇到此错误的原因:

以下列表列出了仅当使用 Kubernetes 联机终结点时可能会遇到此错误的原因:

订阅不存在

输入的 Azure 订阅必须存在。 如果找不到引用的 Azure 订阅,则会发生此错误。 此错误可能是由于订阅 ID 中的拼写错误造成的。 请仔细检查是否已正确键入订阅 ID,以及它当前是否处于活动状态。

有关 Azure 订阅的详细信息,可参阅先决条件部分

授权错误

预配计算资源(创建部署时)后,Azure 会尝试从工作区 Azure 容器注册表 (ACR) 拉取用户容器映像。 它尝试从工作区存储帐户将用户模型和代码项目装载到用户容器中。

为了执行这些操作,Azure 使用托管标识来访问存储帐户和容器注册表。

  • 如果使用系统分配的标识创建了关联的终结点,则系统会自动授予 Azure 基于角色的访问控制 (RBAC) 权限,此时不需要任何进一步的权限。

  • 如果使用用户分配的标识创建了关联的终结点,则用户的托管标识必须对工作区的存储帐户具有存储 Blob 数据读取者权限,并且对工作区的 Azure 容器注册表 (ACR) 具有 AcrPull 权限。 确保用户分配的标识具有正确的权限。

有关详细信息,请参阅容器注册表授权错误

无效的模板函数规范

错误地指定了模板函数时,会发生此错误。 请修复策略或移除策略分配以取消阻止。 错误消息可能包括策略分配名称和策略定义,以帮助调试此错误,以及 Azure 策略定义结构文章,其中讨论了避免模板故障的提示。

无法下载用户容器映像

可能找不到用户容器。 请检查容器日志以获取更多详细信息。

请确保该容器映像在工作区 ACR 中可用。

例如,如果映像为 testacr.azurecr.io/azureml/azureml_92a029f831ce58d2ed011c3c42d35acb:latest,请使用 az acr repository show-tags -n testacr --repository azureml/azureml_92a029f831ce58d2ed011c3c42d35acb --orderby time_desc --output table 检查存储库。

无法下载用户模型

找不到用户的模型。 请检查容器日志以获取更多详细信息。

确保将模型注册到部署所在的工作区。 在工作区中显示模型的详细信息:

az ml model show --name <model-name> --version <version>

警告

必须指定版本或标签才能获取模型信息。

还可以检查 Blob 是否存在于工作区存储帐户中。

  • 例如,如果 Blob 为 https://foobar.blob.core.chinacloudapi.cn/210212154504-1517266419/WebUpload/210212154504-1517266419/GaussianNB.pkl,则可使用以下命令检查它是否存在:

    az storage blob exists --account-name foobar --container-name 210212154504-1517266419 --name WebUpload/210212154504-1517266419/GaussianNB.pkl --subscription <sub-name>`
    
  • 如果 Blob 存在,可以使用此命令从存储初始化表达式中获取日志:

    az ml online-deployment get-logs --endpoint-name <endpoint-name> --name <deployment-name> –-container storage-initializer`
    

不支持使用专用网络的 MLFlow 模型格式

当你尝试将无代码部署方法与适用于托管在线端点的传统网络隔离方法结合使用来部署 MLflow 模型时,就会发生此错误。 如果你使用传统网络隔离方法,则此专用网络功能不能与 MLFlow 模型格式结合使用。 如果你需要使用无代码部署方法来部署 MLflow 模型,请尝试使用工作区托管 VNet

资源请求数大于限制

资源的请求数必须小于或等于限制。 如果你未设置限制,我们会在你将计算附加到 Azure 机器学习工作区时设置默认值。 可以通过 Azure 门户或 az ml compute show 命令来检查限制。

azureml-fe not ready

将传入的推理请求路由到已部署服务的前端组件 (azureml-fe) 可根据需要自动缩放。 它是在 k8s-extension 安装期间安装的。

该组件在集群上应能正常运行,至少有一个正常运行的副本。 如果在你触发 kubernetes 联机终结点和部署创建/更新请求时它不可用,你会收到此错误消息。

请检查 Pod 状态和日志以解决此问题,也可尝试更新群集上安装的 k8s-extension。

错误:ResourceNotReady

为了运行在部署过程中提供的 score.py,Azure 将创建一个包含 score.py 所需全部资源的容器,并在该容器上运行评分脚本。 在这种场景下发生的错误表现为此容器在运行时崩溃,这意味着无法评分。 出现以下情况时会发生此错误:

  • score.py 中有错误。 使用 get-logs 来诊断常见问题:
    • score.py 尝试导入的包未包含在 conda 环境中。
    • 语法错误。
    • init() 方法失败。
  • 如果 get-logs 未生成任何日志,通常意味着容器启动失败。 若要调试此问题,请改为尝试进行本地部署
  • 未正确设置就绪状态或运行情况探测。
  • 容器初始化耗时过长,导致就绪情况或运行情况探测因超过失败阈值而失败。 在这种情况下,请调整探测设置以允许更长的时间初始化容器。 或者,在支持的 VM SKU 中尝试更大的 VM SKU,从而加速初始化。
  • 容器的环境设置有错误,例如缺少依赖项。
  • 收到 TypeError: register() takes 3 positional arguments but 4 were given 错误时,请检查 flask v2 和 azureml-inference-server-http 之间的依赖项。 有关详细信息,请参阅推理 HTTP 服务器的常见问题解答

错误:ResourceNotFound

以下列表列出了仅当使用托管联机终结点或 Kubernetes 联机终结点时可能会遇到此错误的原因:

资源管理器找不到所需资源

当 Azure 资源管理器找不到所需资源时,将发生此错误。 例如,如果引用了存储帐户,但在指定的路径上找不到该帐户,则可能会收到此错误。 请务必仔细检查可能已通过精确路径或其名称拼写提供的资源。

有关详细信息,请参阅解决“找不到资源”错误

容器注册表授权错误

当为部署提供属于专用或无法访问的容器注册表的映像时,会发生此错误。 目前,我们的 API 无法接受专用注册表凭据。

若要缓解此错误,请确保容器注册表不是专用的或执行以下步骤:

  1. 将专用注册表的 acrPull 角色授予联机终结点的系统标识。
  2. 在环境定义中,指定专用映像的地址以及不修改(生成)映像的说明。

如果缓解成功,则映像不需要生成,最终映像地址为给定的映像地址。 部署时,联机终结点的系统标识将从专用注册表中拉取映像。

有关详细的诊断信息,请参阅如何使用工作区诊断 API

错误:OperationCanceled

以下列表列出了使用托管联机终结点或 Kubernetes 联机终结点时可能会遇到此错误的原因:

操作已被另一个具有更高优先级的操作取消

Azure 操作具有一定的优先级,并按从最高到最低的顺序执行。 当操作被具有较高优先级的另一个操作替代时,会发生此错误。

重试该操作可能可以在不取消的情况下执行操作。

操作在等待锁定确认时被取消

Azure 操作在提交后有短暂的等待期,在此期间它们会检索锁来确保不会遇到争用条件。 如果提交的操作与另一个操作相同,则会发生此错误。 另一个操作当前正在等待确认它已收到锁才能继续进行。 这可能表明你在初始请求后过快提交了相似的请求。

在等待几秒钟至一分钟后重试操作,这样它可能在不取消的情况下执行操作。

错误:SecretsInjectionError

在联机部署创建过程中,机密检索和注入使用与联机终结点关联的标识从工作区连接和/或密钥保管库中检索机密。 出现以下情况时会发生此错误:

  • 终结点标识没有从工作区连接和/或密钥保管库读取机密的 Azure RBAC 权限,即使部署定义将机密指定为引用(映射到环境变量)也是如此。 请记住,角色分配可能需要一段时间才能使更改生效。
  • 机密引用的格式无效,或者工作区连接和/或密钥保管库中不存在指定的机密。

有关详细信息,请参阅联机终结点中的机密注入(预览版)使用机密注入从联机部署访问机密(预览版)

错误:InternalServerError

尽管我们会尽最大努力提供稳定可靠的服务,但有时事情不会按计划进行。 如果收到此错误,表示我们这一端出现了问题,我们需要予以修复。 请提交客户支持票证并随附所有相关信息,我们会解决问题。

特定于 Kubernetes 部署的常见错误

有关标识和身份验证的错误:

有关 crashloopbackoff 的错误:

有关评分脚本的错误:

其他:

ERROR: ACRSecretError

以下列表列出了在创建/更新 Kubernetes 联机部署时可能遇到此错误的原因:

  • 角色分配尚未完成。 在这种情况下,请等待几秒钟,然后重试。
  • Azure ARC(适用于 Azure Arc Kubernetes 群集)或 Azure 机器学习扩展(适用于 AKS)未正确安装或配置。 请尝试检查 Azure ARC 或 Azure 机器学习扩展配置和状态。
  • Kubernetes 群集的网络配置不正确,请检查代理、网络策略或证书。
    • 如果使用专用 AKS 群集,则需要在 AKS vnet 中为 ACR、存储帐户、工作区设置专用终结点。
  • 确保 Azure 机器学习扩展版本高于 v1.1.25。

错误:TokenRefreshFailed

此错误是因为扩展无法从 Azure 获取主体凭据,因为 Kubernetes 群集标识未正确设置。 重新安装 Azure 机器学习扩展,然后重试。

错误:GetAADTokenFailed

此错误是因为 Kubernetes 群集请求 Azure AD 令牌失败或超时,请检查网络可访问性,然后重试。

  • 可以按照配置所需的网络流量来检查出站代理,以确保群集可以连接到工作区。
  • 可以在群集的联机终结点 CRD 中找到工作区终结点 URL。

如果工作区是已禁用公用网络访问的专用工作区,则 Kubernetes 群集应仅通过专用链接与该专用工作区通信。

  • 可以检查工作区访问是否允许公共访问,无论 AKS 群集本身是公共的还是专用的,它都无法访问专用工作区。
  • 有关详细信息,请参阅保护 Azure Kubernetes 服务推理环境

错误:ACRAuthenticationChallengeFailed

此错误是因为 Kubernetes 群集无法访问工作区的 ACR 服务来执行身份验证质询。 请检查网络(尤其是 ACR 公用网络访问),然后重试。

可以按照 GetAADTokenFailed 中的故障排除步骤检查网络。

错误:ACRTokenExchangeFailed

此错误是因为 Kubernetes 群集交换 ACR 令牌失败,因为 Azure AD 令牌尚未授权。 由于角色分配需要一些时间,因此可以等待片刻,然后重试。

此故障也可能是由于当时对 ACR 服务的请求过多,这应该是暂时性错误,因此可以稍后重试。

错误:KubernetesUnaccessible

可能在 Kubernetes 模型部署期间收到以下错误:

{"code":"BadRequest","statusCode":400,"message":"The request is invalid.","details":[{"code":"KubernetesUnaccessible","message":"Kubernetes error: AuthenticationException. Reason: InvalidCertificate"}],...}

若要缓解此错误,可以:

ERROR: ImagePullLoopBackOff

创建/更新 Kubernetes 联机部署时可能会遇到此错误的原因是,无法从容器注册表下载映像,从而导致映像拉取失败。

在这种情况下,可以检查群集网络策略和工作区容器注册表,查看群集是否可以从容器注册表中拉取映像。

错误:DeploymentCrashLoopBackOff

创建/更新 Kubernetes 联机部署时遇到此错误可能的原因是用户容器在初始化时故障。 此错误有两个可能的原因:

  • 用户脚本 score.py 出现语法错误或导入错误,然后在初始化时引发异常。
  • 或者部署 Pod 需要的内存超过其上限。

若要缓解此错误,首先可以在部署日志中检查用户脚本中是否存在任何异常。 如果错误仍然存在,请尝试扩展资源/实例类型内存限制。

ERROR: KubernetesCrashLoopBackOff

以下列表列出了在创建/更新 Kubernetes 联机终结点/部署时可能遇到此错误的原因:

  • 一个或多个 Pod 停滞在 CrashLoopBackoff 状态,你可以检查部署日志是否存在,并查看日志中是否存在错误信息。
  • score.py 中存在错误且初始化分数代码时容器故障,可按照 ERROR: ResourceNotReady 部分的说明操作。
  • 评分过程需要更多的内存,但部署配置限制不足,可以尝试使用更大的内存限制更新部署。

ERROR: NamespaceNotFound

创建/更新 Kubernetes 联机终结点时可能会遇到此错误的原因是,Kubernetes 计算使用的命名空间在群集中不可用。

可以在工作区门户中检查 Kubernetes 计算,并检查 Kubernetes 群集中的命名空间。 如果命名空间不可用,可以拆离旧计算并重新附加以创建新计算,从而指定一个群集中已存在的命名空间。

错误:UserScriptInitFailed

创建/更新 Kubernetes 联机部署时遇到此错误可能的原因是你上传的 score.py 文件中的 init 函数引发了异常。

可以检查部署日志以详细查看异常消息并修复异常。

错误:UserScriptImportError

创建/更新 Kubernetes 联机部署时遇到此错误可能的原因是你上传的 score.py 文件导入了不可用的包。

可以检查部署日志以详细查看异常消息并修复异常。

错误:UserScriptFunctionNotFound

创建/更新 Kubernetes 联机部署时遇到此错误可能的原因是你上传的 score.py 文件没有名为 init()run() 的函数。 可以检查代码并添加函数。

ERROR: EndpointNotFound

创建/更新 Kubernetes 联机部署时可能会遇到此错误的原因是,系统在群集中找不到部署的终结点资源。 应在现有终结点中创建部署,或首先在群集中创建此终结点。

ERROR: EndpointAlreadyExists

创建 Kubernetes 联机终结点时可能会遇到此错误的原因是,正在创建的终结点已存在于群集中。

终结点名称在每个工作区和每个群集中应是唯一的,因此在这种情况下,应使用其他名称创建终结点。

ERROR: ScoringFeUnhealthy

创建/更新 Kubernetes 联机终结点/部署时可能会遇到此错误的原因是,未找到作为群集中运行的系统服务的 Azureml-fe 或其运行状况不佳。

若要解决此问题,可以在群集中重新安装或更新 Azure 机器学习扩展。

ERROR: ValidateScoringFailed

创建/更新 Kubernetes 联机部署时可能会遇到此错误的原因是,处理模型部署时评分请求 URL 验证失败。

在这种情况下,可以先检查终结点 URL,然后尝试重新部署。

ERROR: InvalidDeploymentSpec

创建/更新 Kubernetes 联机部署时可能会遇到此错误的原因是部署规范无效。

在这种情况下,可以检查错误消息。

  • 请确保 instance count 有效。
  • 如果你已启用自动缩放,请确保 minimum instance countmaximum instance count 均有效。

ERROR: PodUnschedulable

以下列表列出了在创建/更新 Kubernetes 联机终结点/部署时可能遇到此错误的原因:

  • 由于群集中的资源不足,无法将 Pod 计划到节点。
  • 无节点匹配节点相关性/选择器。

若要缓解此错误,可以按照以下步骤操作:

  • 检查所使用的 instance typenode selector 定义,以及群集节点的 node label 配置。
  • 检查 instance type 以及 AKS 群集的节点 SKU 大小或 Arc-Kubernetes 群集的节点资源。
    • 如果群集资源不足,可以降低实例类型资源需求,或使用所需的资源较少的其他实例类型。
  • 如果群集没有可满足部署要求的资源,请删除一些部署以释放资源。

错误:PodOutOfMemory

创建/更新联机部署时遇到此错误可能的原因是,为部署提供内存限制不足。 可以将内存限制设置为更大的值,或使用更大的实例类型来缓解此错误。

ERROR: InferencingClientCallFailed

创建/更新 Kubernetes 联机终结点/部署时可能会遇到此错误的原因是,Kubernetes 群集的 k8s 扩展不可连接。

在这种情况下,可以拆离计算,然后再重新附加。

注意

若要通过重新附加来排查错误,请保证重新附加时使用与以前拆离的计算完全相同的配置(例如相同的计算名称和命名空间),否则可能会遇到其他错误。

如果它仍然无法正常工作,请让可以访问群集的管理员使用 kubectl get po -n azureml 来检查中继服务器 Pod 是否正在运行。

自动缩放问题

如果在自动缩放时遇到问题,请参阅排查 Azure 自动缩放问题

Kubernetes 联机终结点有一个 Azure 机器学习推理路由器,它是一个前端组件,用于处理 Kubernetes 群集上所有模型部署的自动缩放。有关详细信息,请参阅 Kubernetes 推理路由的自动缩放

常见模型使用错误

以下列表列出了终结点 invoke 操作状态导致的常见模型消耗错误。

带宽限制问题

托管联机终结点对于每个终结点都有带宽限制。 有关限制配置,可查看联机终结点的限制。 如果带宽使用量超出限制,则请求会延迟。 监视带宽延迟的步骤:

  • 使用“网络字节数”指标来了解当前带宽使用情况。 有关详细信息,请参阅监视托管联机终结点
  • 如果强制实施带宽限制,则返回两个响应尾部:
    • ms-azureml-bandwidth-request-delay-ms:请求流传输所用的延迟时间(以毫秒为单位)。
    • ms-azureml-bandwidth-response-delay-ms:响应流传输所用的延迟时间(以毫秒为单位)。

HTTP 状态代码

使用 REST 请求访问联机终结点时,返回的状态代码将遵守 HTTP 状态代码标准。 下面详述了终结点调用和预测错误如何映射到 HTTP 状态代码。

托管联机终结点的常见错误代码

下表包含通过 REST 请求使用托管联机终结点时的常见错误代码:

状态代码 原因短语 返回此代码的可能原因
200 确定 已在延迟范围内成功执行了模型。
401 未授权 你无权执行请求的操作(如评分),或者令牌已过期。
404 未找到 终结点没有任何权重为正的有效部署。
408 请求超时 模型执行所用的时间超过了在模型部署配置的 request_settings 下的 request_timeout_ms 中提供的超时。
424 模型错误 如果模型容器返回非 200 响应,则 Azure 将返回 424。 在终结点的 Azure Monitor 指标资源管理器中的 Requests Per Minute 指标下查看 Model Status Code 维度。 或者查看响应头 ms-azureml-model-error-statuscodems-azureml-model-error-reason 了解详细信息。 如果 424 伴随着运行情况或就绪情况探测失败,请考虑调整探测设置,以留出更长的时间来探测容器的运行情况或就绪情况。
429 挂起的请求太多 模型当前收到的请求数超过了它可以处理的数量。 Azure 机器学习实现了一个系统,该系统允许在任何给定时刻并行处理最多 2 * max_concurrent_requests_per_instance * instance_count requests 个请求,以保证平稳运行。 超过此最大值的其他请求将被拒绝。 可以在 request_settings 和 scale_settings 部分下查看模型部署配置,以验证和调整这些设置。 此外,如 RequestSettings 的 YAML 定义中所述,请务必确保正确传递环境变量 WORKER_COUNT

如果使用自动缩放并收到此错误,则意味着模型获取请求的速度比系统纵向扩展的速度更快。 在这种情况下,请考虑使用指数退避重新发送请求,以便为系统提供调整所需的时间。 你还可以使用代码计算实例计数,以便增加实例数。 这些步骤与设置自动缩放相结合,有助于确保模型已准备好处理涌入的请求。
429 速率受限 每秒请求数已达到托管联机终结点的限制
500 内部服务器错误 Azure 机器学习预配的基础结构发生故障。

Kubernetes 联机终结点的常见错误代码

下表包含通过 REST 请求使用 Kubernetes 联机终结点时的常见错误代码:

状态代码 原因短语 返回此代码的可能原因
409 冲突错误 如有操作正在进行,则同一联机终结点上的任何新操作都会响应 409 冲突错误。 例如,如果创建或更新联机终结点操作正在进行,那么触发新的删除操作会引发错误。
502 在 score.py 文件的 run() 方法中引发了异常或崩溃 score.py 中存在错误时(例如导入的包在 conda 环境中不存在)或在 init() 方法中存在语法错误或失败时。 可以按照此处说明调试文件。
503 收到大量每秒接收数峰值 自动缩放程序旨在处理负载中的逐步更改。 如果每秒收到大量请求,客户端可能会收到 HTTP 状态代码 503。 即使自动缩放器反应迅速,但 AKS 仍需要大量时间来创建其他容器。 可以按照此处说明阻止 503 状态代码。
504 请求已超时 504 状态代码指示请求已超时。默认超时值设置为 5 秒。 可通过修改 score.py,删除不必要的调用来增加超时值或尝试加快终结点速度。 如果这些操作无法更正问题,可以在此处调试 score.py 文件。 代码可能处于无响应状态或无限循环。
500 内部服务器错误 Azure 机器学习预配的基础结构发生故障。

如何阻止 503 状态代码

Kubernetes 联机部署支持自动缩放,它允许添加副本以支持额外的负载,有关详细信息,请参阅 Azure 机器学习推理路由器。 纵向扩展/缩减决策取决于当前容器副本的利用率。

有两种方法可以帮助防止 503 状态代码:

提示

这两种方法可以单独使用,也可以结合使用。

  • 更改自动缩放创建新副本的利用率。 可以通过将 autoscale_target_utilization 设置为较低的值来调整利用率目标。

    重要

    该更改不会导致更快创建副本。 而会以较低的利用率阈值创建副本。 可以在利用率达到 30% 时,通过将值改为 30% 来创建副本,而不是等待该服务的利用率达到 70% 时再创建。

    如果 Kubernetes 联机终结点已在使用当前最大副本数量,而你仍会看到 503 状态代码,请增加 autoscale_max_replicas 值以增加副本的最大数量。

  • 更改副本最小数量。 增加最小副本可提供一个更大的池来处理传入峰值。

    要增加实例数量,可以按照这些代码计算所需的副本。

    from math import ceil
    # target requests per second
    target_rps = 20
    # time to process the request (in seconds, choose appropriate percentile)
    request_process_time = 10
    # Maximum concurrent requests per instance
    max_concurrent_requests_per_instance = 1
    # The target CPU usage of the model container. 70% in this example
    target_utilization = .7
    
    concurrent_requests = target_rps * request_process_time / target_utilization
    
    # Number of instance count
    instance_count = ceil(concurrent_requests / max_concurrent_requests_per_instance)
    

    注意

    如果收到的峰值请求数大于新的最小副本数可以处理的数量,则可能会再次收到 503 代码。 例如,终结点流量增加时,可能需要增加最小副本数量。

如何计算实例数

若要增大实例数,可以使用以下代码计算所需的副本:

from math import ceil
# target requests per second
target_rps = 20
# time to process the request (in seconds, choose appropriate percentile)
request_process_time = 10
# Maximum concurrent requests per instance
max_concurrent_requests_per_instance = 1
# The target CPU usage of the model container. 70% in this example
target_utilization = .7

concurrent_requests = target_rps * request_process_time / target_utilization

# Number of instance count
instance_count = ceil(concurrent_requests / max_concurrent_requests_per_instance)

被 CORS 策略阻止

联机终结点 (v2) 目前不支持本机跨域资源共享 (CORS)。 如果 Web 应用程序尝试调用终结点时未正确处理 CORS 预检请求,你会看到以下错误消息:

Access to fetch at 'https://{your-endpoint-name}.{your-region}.inference.studio.ml.azure.cn/score' from origin http://{your-url} has been blocked by CORS policy: Response to preflight request doesn't pass access control check. No 'Access-control-allow-origin' header is present on the request resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with the CORS disabled.

建议使用 Azure Functions、Azure 应用程序网关或任何服务作为临时层来处理 CORS 预检请求。

常见网络隔离问题

联机终结点创建失败,并显示 V1LegacyMode == true 消息

可以针对 v1_legacy_mode 对 Azure 机器学习工作区进行配置,这将禁用 v2 API。 托管联机终结点是 v2 API 平台的一项功能,如果为工作区启用 v1_legacy_mode,该功能将无法正常使用。

重要

在禁用 v1_legacy_mode 之前,请咨询网络安全团队。 网络安全团队可能出于某种原因启用了它。

有关如何禁用 v1_legacy_mode 的信息,请参阅使用 v2 配置网络隔离

使用基于密钥的身份验证创建联机终结点失败

使用以下命令列出工作区的 Azure 密钥保管库的网络规则。 请将 <keyvault-name> 替换为你的密钥保管库名称:

az keyvault network-rule list -n <keyvault-name>

此命令的响应类似于以下 JSON 文档:

{
    "bypass": "AzureServices",
    "defaultAction": "Deny",
    "ipRules": [],
    "virtualNetworkRules": []
}

如果 bypass 的值不是 AzureServices,请使用配置密钥保管库网络设置中的指导将其设置为 AzureServices

联机部署失败并出现映像下载错误

注意

对托管联机终结点使用旧版网络隔离方法时,此问题适用,其中 Azure 机器学习会为终结点下的每个部署创建一个托管虚拟网络。

  1. 检查部署的 egress-public-network-access 标志是否已禁用。 如果此标志已启用,并且容器注册表的可见性为“专用”,则预期会发生这种失败。

  2. 使用以下命令检查专用终结点连接的状态。 请将 <registry-name> 替换为你的工作区的 Azure 容器注册表名称:

    az acr private-endpoint-connection list -r <registry-name> --query "[?privateLinkServiceConnectionState.description=='Egress for Microsoft.MachineLearningServices/workspaces/onlineEndpoints'].{Name:name, status:privateLinkServiceConnectionState.status}"
    

    在响应文档中,验证 status 字段是否设置为 Approved。 如果不是 approved,请使用以下命令进行批准。 请将 <private-endpoint-name> 替换为上一命令返回的名称:

    az network private-endpoint-connection approve -n <private-endpoint-name>
    

无法解析评分终结点

  1. 验证发出评分请求的客户端是否为可以访问 Azure 机器学习工作区的虚拟网络。

  2. 对终结点主机名使用 nslookup 命令来检索 IP 地址信息:

    nslookup endpointname.westcentralus.inference.ml.azure.com
    

    响应包含一个地址。 此地址应在虚拟网络提供的范围内

    注意

    对于 Kubernetes 联机终结点,终结点主机名应当是已在 Kubernetes 群集中指定的 CName(域名)。 如果它是一个 HTTP 终结点,则 IP 地址将包含在终结点 URI 中,可以直接在 Studio UI 中获取该 URI。 有关获取终结点 IP 地址的更多方法,请参阅安全 Kubernetes 联机终结点

  3. 如果 nslookup 命令未解析主机名:

    对于托管联机终结点,

    1. 请检查虚拟网络的专用 DNS 区域中是否存在 A 记录。

      若要检查记录,请使用以下命令:

      az network private-dns record-set list -z privatelink.api.azureml.ms -o tsv --query [].name
      

      结果应包含类似于 *.<GUID>.inference.<region> 的条目。

    2. 如果未返回推理值,请删除工作区的专用终结点,然后重新创建。 有关详细信息,请参阅如何配置专用终结点

    3. 如果使用自定义 DNS 设置具有专用终结点的工作区(参见如何通过自定义 DNS 服务器使用工作区),请使用以下命令来验证解析是否能够正确地通过自定义 DNS 进行。

      dig endpointname.westcentralus.inference.ml.azure.com
      

    对于 Kubernetes 联机终结点,

    1. 请检查 Kubernetes 群集中的 DNS 配置。

    2. 此外,可以使用以下命令检查 azureml-fe 是否按预期工作:

      kubectl exec -it deploy/azureml-fe -- /bin/bash
      (Run in azureml-fe pod)
      
      curl -vi -k https://localhost:<port>/api/v1/endpoint/<endpoint-name>/swagger.json
      "Swagger not found"
      

      对于 HTTP,请使用

      curl https://localhost:<port>/api/v1/endpoint/<endpoint-name>/swagger.json
      "Swagger not found"
      

    如果 curl HTTP 失败(例如超时)但 HTTP 正常工作,请检查证书是否有效。

    如果无法解析为 A 记录,请验证解析是否可以从 Azure DNS (168.63.129.16) 进行。

    dig @168.63.129.16 endpointname.westcentralus.inference.ml.azure.com
    

    如果成功,则可以排查自定义 DNS 上的专用链接的条件转发器问题。

无法为联机部署评分

  1. 使用以下命令查看部署是否成功:

    az ml online-deployment show -e <endpointname> -n <deploymentname> --query '{name:name,state:provisioning_state}' 
    

    如果部署成功完成,则 state 的值将是 Succeeded

  2. 如果部署成功,请使用以下命令检查流量是否已分配到部署。 将 <endpointname> 替换为终结点的名称:

    az ml online-endpoint show -n <endpointname>  --query traffic
    

    提示

    如果在请求中使用 azureml-model-deployment 标头将此部署定为目标,则不需要执行此步骤。

    此命令的响应应会列出分配到部署的流量百分比。

  3. 如果正确设置了流量分配(或部署标头),请使用以下命令获取终结点的日志。 请将 <endpointname> 替换为终结点名称,将 <deploymentname> 替换为部署:

    az ml online-deployment get-logs  -e <endpointname> -n <deploymentname> 
    

    浏览日志,确定在向部署提交请求时运行的评分代码是否有问题。

对推理服务器进行故障排除

在本节中,我们提供了 Azure 机器学习推理 HTTP 服务器的基本故障排除技巧。

基本步骤

故障排除的基本步骤包括:

  1. 收集 Python 环境的版本信息。
  2. 确保环境文件中指定的 azureml-inference-server-http python 包版本与启动日志中显示的 AzureML 推理 HTTP 服务器版本相匹配。 有时,pip 的依赖项解析程序会导致安装不必要的包版本。
  3. 如果在环境中指定 Flask(和/或其依赖项),请将其移除。 依赖项包括 FlaskJinja2itsdangerousWerkzeugMarkupSafeclick。 Flask 作为依赖项列在服务器包中,最好让服务器安装它。 这样,当服务器支持新版 Flask 时,你将自动获取新版本。

服务器版本

服务器包 azureml-inference-server-http 会发布到 PyPI。 可以在 PyPI 页面上查找我们的更改日志和所有先前版本。 如果使用的是早期版本,请更新到最新版本。

  • 0.4.x:训练映像 ≤ 20220601azureml-defaults>=1.34,<=1.43 中捆绑的版本。 0.4.13 是最新稳定版本。 如果使用版本 0.4.11 之前的服务器,则可能会看到 Flask 依赖项问题,例如无法从 jinja2 导入名称 Markup。 如果可能,建议升级到 0.4.130.8.x(最新版本)。
  • 0.6.x:预装在推理映像 ≤ 20220516 的版本。 最新稳定版本为 0.6.1
  • 0.7.x:第一个支持 Flask 2 的版本。 最新稳定版本为 0.7.7
  • 0.8.x:日志格式发生更改,Python 3.6 支持删除。

包依赖项

与服务器 azureml-inference-server-http 最相关的包是以下包:

  • flask
  • opencensus-ext-azure
  • inference-schema

如果在 Python 环境中指定 azureml-defaults,则会依赖 azureml-inference-server-http 包,并且将自动安装。

提示

如果使用 Python SDK v1,并且未在 Python 环境中显式指定 azureml-defaults,则 SDK 可能会为你添加包。 但是,它会将其锁定到 SDK 所在的版本。 例如,如果 SDK 版本为 1.38.0,则会将 azureml-defaults==1.38.0 添加到环境的 pip 要求中。

常见问题

1. 我在服务器启动过程中遇到如下错误:


TypeError: register() takes 3 positional arguments but 4 were given

  File "/var/azureml-server/aml_blueprint.py", line 251, in register

    super(AMLBlueprint, self).register(app, options, first_registration)

TypeError: register() takes 3 positional arguments but 4 were given

你已在 python 环境中安装 Flask 2,但运行的 azureml-inference-server-http 版本不支持 Flask 2。 在 azureml-inference-server-http>=0.7.0 中添加了对 Flask 2 的支持,该支持也在 azureml-defaults>=1.44 中。

  • 如果不在 AzureML Docker 映像中使用此包,请使用最新版 azureml-inference-server-httpazureml-defaults

  • 如果在 AzureML Docker 映像中使用此包,请确保使用在 2022 年 7 月或之后构建的映像。该映像版本在容器日志中提供。 应该能够找到如下所示的日志:

    2022-08-22T17:05:02,147738763+00:00 | gunicorn/run | AzureML Container Runtime Information
    2022-08-22T17:05:02,161963207+00:00 | gunicorn/run | ###############################################
    2022-08-22T17:05:02,168970479+00:00 | gunicorn/run | 
    2022-08-22T17:05:02,174364834+00:00 | gunicorn/run | 
    2022-08-22T17:05:02,187280665+00:00 | gunicorn/run | AzureML image information: openmpi4.1.0-ubuntu20.04, Materializaton Build:20220708.v2
    2022-08-22T17:05:02,188930082+00:00 | gunicorn/run | 
    2022-08-22T17:05:02,190557998+00:00 | gunicorn/run | 
    

    映像的生成日期显示在“具体化生成”之后,在上面的示例中为 20220708 或 2022 年 7 月 8 日。 此映像与 Flask 2 兼容。 如果在容器日志中未看到这样的横幅,则表明映像已过期,应进行更新。 如果使用 CUDA 映像且找不到较新的映像,请检查映像在 AzureML-Containers 中是否已弃用。 如果是,则应该能够找到替换项。

  • 如果将服务器与联机终结点结合使用,则还可以在 Azure 机器学习工作室中的联机终结点页的“部署日志”下找到日志。 如果你使用 SDK v1 进行部署,并且未在部署配置中显式指定映像,则它会默认使用与本地 SDK 工具集匹配的 openmpi4.1.0-ubuntu20.04 版本,该版本可能不是映像的最新版本。 例如,SDK 1.43 将默认使用不兼容的 openmpi4.1.0-ubuntu20.04:20220616。 请确保使用最新 SDK 进行部署。

  • 如果出于某种原因而无法更新映像,可以通过固定 azureml-defaults==1.43azureml-inference-server-http~=0.4.13(将通过 Flask 1.0.x 来安装较旧版本的服务器)来暂时避免此问题。

2. 启动期间在模块 opencensusjinja2MarkupSafeclick 上遇到 ImportErrorModuleNotFoundError,如以下消息所示:

ImportError: cannot import name 'Markup' from 'jinja2'

旧版 (<= 0.4.10) 服务器未将 Flask 的依赖项固定到兼容版本。 此问题已在最新版服务器中解决。

后续步骤