排查 Azure 机器学习扩展问题

在本文中,你将了解如何排查在 AKS 或已启用 Arc 的 Kubernetes 中部署 Azure 机器学习扩展时可能遇到的常见问题。

Azure 机器学习扩展是如何安装的

Azure 机器学习扩展作为 helm 图表发布,由 Helm V3 安装。 Azure 机器学习扩展的所有组件安装在 azureml 命名空间中。 可使用以下命令来检查扩展状态。

# get the extension status
az k8s-extension show --name <extension-name>

# check status of all pods of Azure Machine Learning extension
kubectl get pod -n azureml

# get events of the extension
kubectl get events -n azureml --sort-by='.lastTimestamp'

排查 Azure 机器学习扩展部署错误

错误:无法重用仍被使用的名称

此错误表示你指定的扩展名称已存在。 如果该名称已由 Azure 机器学习扩展使用,需要等待大约一小时,然后重试。 如果该名称已由其他 helm 图表使用,则你需要使用另一个名称。 运行 helm list -Aa 以列出群集中的所有 helm 图表。

错误:先前针对 helm 图表的操作仍在进行中

需要等待大约一小时,让未知操作完成后重试。

错误:无法在命名空间 azureml 中创建新内容,因为该操作正在终止

如果某个卸载操作未完成,而此时触发了另一个安装操作,则会发生此错误。 可以运行 az k8s-extension show 命令来检查扩展的预配状态,并确保在执行其他操作之前已卸载扩展。

错误:下载失败,找不到图表路径

如果指定了错误的扩展版本,则会发生此错误。 需要确保指定的版本存在。 如果你要使用最新版本,则无需指定 --version

错误:无法导入到当前版本: 所有权元数据无效

此错误表示现有群集资源与 Azure 机器学习扩展之间有冲突。 完整的错误消息可能类似于以下文本:

CustomResourceDefinition "jobs.batch.volcano.sh" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "amlarc-extension"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "azureml"

使用以下步骤来缓解此问题。

  • 检查有问题的资源由谁拥有,以及是否可以删除或修改该资源。

  • 如果资源仅由 Azure 机器学习扩展使用并且可删除,则你可以手动添加标签来缓解问题。 以前面的错误消息为例,你可以运行如下所示的命令:

    kubectl label crd jobs.batch.volcano.sh "app.kubernetes.io/managed-by=Helm" 
    kubectl annotate crd jobs.batch.volcano.sh "meta.helm.sh/release-namespace=azureml" "meta.helm.sh/release-name=<extension-name>"
    

    通过为资源设置标签和注释,指明 helm 正在管理由 Azure 机器学习扩展拥有的资源。

  • 如果该资源还由群集中的其他组件使用并且无法修改。 请参阅部署 Azure 机器学习扩展,查看是否存在用于禁用冲突资源的配置设置。

扩展的 HealthCheck

如果安装失败但未出现上述任何错误消息,你可以使用内置的运行状况检查作业来对扩展进行全面检查。 Azure 机器学习扩展包含HealthCheck作业,用于在尝试安装、更新或删除扩展时预先检查群集的就绪状态。 HealthCheck 作业会输出报告,该报告保存在azureml命名空间中名为arcml-healthcheck的配置映射内。 HealthCheck 的错误代码中列出了报告的错误代码和可能的解决方法。

运行以下命令以获取 HealthCheck 报告:

kubectl describe configmap -n azureml arcml-healthcheck

每当你安装、更新或删除扩展时,都会触发运行状况检查。 运行状况检查报告的结构包括 pre-installpre-rollbackpre-upgradepre-delete 这几个部分。

  • 如果扩展安装失败,你应该查看 pre-installpre-delete
  • 如果扩展更新失败,你应该查看 pre-upgradepre-rollback
  • 如果扩展删除失败,你应该查看 pre-delete

当你请求支持时,我们建议运行以下命令并将 healthcheck.logs 文件发送给我们,因为它可以方便我们找出问题。

kubectl logs healthcheck -n azureml

HealthCheck 的错误代码

下表显示了如何对 HealthCheck 报告返回的错误代码进行故障排除。

错误代码 错误消息 说明
E40001 LOAD_BALANCER_NOT_SUPPORT 群集中不支持负载均衡器。 需要在群集中配置负载均衡器,或考虑将inferenceRouterServiceType设置为nodePortclusterIP
E40002 INSUFFICIENT_NODE 已启用 inferenceRouterHA,它要求群集中至少有三个节点。 如果节点少于三个,请禁用 HA。
E40003 INTERNAL_LOAD_BALANCER_NOT_SUPPORT 目前,只有 AKS 支持内部负载均衡器,而我们仅支持 azure 类型。 如果你没有 AKS 群集,请不要设置 internalLoadBalancerProvider
E40007 INVALID_SSL_SETTING SSL 密钥或证书无效。 CNAME 应与证书兼容。
E45002 PROMETHEUS_CONFLICT 安装的 Prometheus Operator 与现有的 Prometheus Operator 冲突。 有关详细信息,请参阅 Prometheus 运算符
E45003 BAD_NETWORK_CONNECTIVITY 需要满足网络要求
E45004 AZUREML_FE_ROLE_CONFLICT 旧版 AKS 中不支持 Azure 机器学习扩展。 若要安装 Azure 机器学习扩展,需要删除旧版 azureml-fe 组件
E45005 AZUREML_FE_DEPLOYMENT_CONFLICT 旧版 AKS 中不支持 Azure 机器学习扩展。 若要安装 Azure 机器学习扩展,需要运行此窗体下面的命令来删除旧 azureml-fe 组件,详细信息请参考此处

用于删除 AKS 群集中的旧 azureml-fe 组件的命令:

kubectl delete sa azureml-fe
kubectl delete clusterrole azureml-fe-role
kubectl delete clusterrolebinding azureml-fe-binding
kubectl delete svc azureml-fe
kubectl delete svc azureml-fe-int-http
kubectl delete deploy azureml-fe
kubectl delete secret azuremlfessl
kubectl delete cm azuremlfeconfig

开源组件集成

Azure 机器学习扩展使用了一些开源组件,包括 Prometheus Operator、Volcano Scheduler 和 DCGM Exporter。 如果 Kubernetes 群集中已安装了上述某些组件,你可以阅读以下部分,以将现有组件与 Azure 机器学习扩展集成。

Prometheus 运算符

Prometheus Operator 是一个开源框架,可帮助在 Kubernetes 中构建指标监视系统。 Azure 机器学习扩展也利用 Prometheus Operator 来帮助监视作业的资源利用率。

如果群集具有由其他服务安装的 Prometheus Operator,可以指定installPromOp=false以在 Azure 机器学习扩展中禁用 Prometheus Operator,从而避免两个 Prometheus Operator 之间发生冲突。 在这种情况下,现有的 Prometheus Operator 管理所有 Prometheus 实例。 为确保 Prometheus 正常工作,在 Azure 机器学习扩展中禁用 Prometheus Operator 时需要注意以下事项。

  1. 检查 azureml 命名空间中的 Prometheus 是否由 Prometheus Operator 管理。 在某些方案中,Prometheus Operator 设置为仅监视某些特定的命名空间。 如果是这样,请确保 azureml 命名空间已列入允许列表。 有关详细信息,请参阅命令标志
  2. 检查 Prometheus Operator 中是否启用了 kubelet-service。 kubelet-service 包含 kubelet 的所有终结点。 有关详细信息,请参阅命令标志。 另外需要确保 kubelet-service 具有标签 k8s-app=kubelet
  3. 为 kubelet-service 创建 ServiceMonitor。 使用替换的变量运行以下命令:
    cat << EOF | kubectl apply -f -
    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: prom-kubelet
      namespace: azureml
      labels:
        release: "<extension-name>"     # Please replace to your Azure Machine Learning extension name
    spec:
      endpoints:
      - port: https-metrics
        scheme: https
        path: /metrics/cadvisor
        honorLabels: true
        tlsConfig:
          caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
          insecureSkipVerify: true
        bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
        relabelings:
        - sourceLabels:
          - __metrics_path__
          targetLabel: metrics_path
      jobLabel: k8s-app
      namespaceSelector:
        matchNames:
        - "<namespace-of-your-kubelet-service>"  # Please change this to the same namespace of your kubelet-service
      selector:
        matchLabels:
          k8s-app: kubelet    # Please make sure your kubelet-service has a label named k8s-app and it's value is kubelet
    
    EOF
    

DCGM Exporter

Dcgm-exporter 是 NVIDIA 建议用于收集 GPU 指标的官方工具。 我们已将其集成到 Azure 机器学习扩展中。 但是,dcgm-exporter 默认未启用,因此不会收集 GPU 指标。 可将 installDcgmExporter 标志指定为 true 来启用它。 由于它是 NVIDIA 的官方工具,因此你可能已将它安装在 GPU 群集中。 如果是这样,可以将installDcgmExporter设置为false,并按照步骤将 dcgm-exporter 集成到 Azure 机器学习扩展中。 需要注意的另一个事项是,dcgm-exporter 允许用户配置要公开的指标。 对于 Azure 机器学习扩展,请确保公开DCGM_FI_DEV_GPU_UTILDCGM_FI_DEV_FB_FREEDCGM_FI_DEV_FB_USED 指标。

  1. 确保已成功安装 Aureml 扩展和 dcgm-exporter。 可以通过 Dcgm-exporter helm 图表Gpu-operator helm 图表安装 dcgm-exporter

  2. 检查是否存在 dcgm-exporter 的服务。 如果不存在或者你不知道如何检查,请运行以下命令创建一个服务。

    cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: dcgm-exporter-service
      namespace: "<namespace-of-your-dcgm-exporter>" # Please change this to the same namespace of your dcgm-exporter
      labels:
        app.kubernetes.io/name: dcgm-exporter
        app.kubernetes.io/instance: "<extension-name>" # Please replace to your Azure Machine Learning extension name
        app.kubernetes.io/component: "dcgm-exporter"
      annotations:
        prometheus.io/scrape: 'true'
    spec:
      type: "ClusterIP"
      ports:
      - name: "metrics"
        port: 9400  # Please replace to the correct port of your dcgm-exporter. It's 9400 by default
        targetPort: 9400  # Please replace to the correct port of your dcgm-exporter. It's 9400 by default
        protocol: TCP
      selector:
        app.kubernetes.io/name: dcgm-exporter  # Those two labels are used to select dcgm-exporter pods. You can change them according to the actual label on the service
        app.kubernetes.io/instance: "<dcgm-exporter-helm-chart-name>" # Please replace to the helm chart name of dcgm-exporter
    EOF
    
  3. 检查上一步骤中的服务是否已正确设置

    kubectl -n <namespace-of-your-dcgm-exporter> port-forward service/dcgm-exporter-service 9400:9400
    # run this command in a separate terminal. You will get a lot of dcgm metrics with this command.
    curl http://127.0.0.1:9400/metrics
    
  4. 设置 ServiceMonitor 以将 dcgm-exporter 服务公开给 Azure 机器学习扩展。 运行以下命令,它会在几分钟后生效。

    cat << EOF | kubectl apply -f -
    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: dcgm-exporter-monitor
      namespace: azureml
      labels:
        app.kubernetes.io/name: dcgm-exporter
        release: "<extension-name>"   # Please replace to your Azure Machine Learning extension name
        app.kubernetes.io/component: "dcgm-exporter"
    spec:
      selector:
        matchLabels:
          app.kubernetes.io/name: dcgm-exporter
          app.kubernetes.io/instance: "<extension-name>"   # Please replace to your Azure Machine Learning extension name
          app.kubernetes.io/component: "dcgm-exporter"
      namespaceSelector:
        matchNames:
        - "<namespace-of-your-dcgm-exporter>"  # Please change this to the same namespace of your dcgm-exporter
      endpoints:
      - port: "metrics"
        path: "/metrics"
    EOF
    

Volcano Scheduler

如果群集中已经安装 volcano 套件,则你可以设置 installVolcano=false,这样,扩展就不会安装 Volcano Scheduler。 需要使用 Volcano Scheduler 和 Volcano Controller 来训练作业提交和安排计划。

Azure 机器学习扩展使用的 Volcano Scheduler 配置是:

volcano-scheduler.conf: |
    actions: "enqueue, allocate, backfill"
    tiers:
    - plugins:
        - name: task-topology
        - name: priority
        - name: gang
        - name: conformance
    - plugins:
        - name: overcommit
        - name: drf
        - name: predicates
        - name: proportion
        - name: nodeorder
        - name: binpack

需要使用此相同的配置设置,并且如果Volcano 版本低于 1.6,需要在 Volcano Admission 中禁用job/validate Webhook,使 Azure 机器学习训练工作负载能够正常执行。

支持群集自动缩放程序的 Volcano Scheduler 集成

正如此主题中所讨论的,gang 插件无法很好地与群集自动缩放程序 (CA) 以及 AKS 中的节点自动缩放程序配合使用。

如果通过设置installVolcano=true使用 Azure 机器学习扩展附带的 Volcano,则默认情况下,该扩展会具有计划程序配置,用于配置gang插件以防止作业死锁。 因此,通过扩展安装的 Volcano 将不支持 AKS 群集中的群集自动缩放器 (CA)。

对于这种情况,如果希望 AKS 群集自动缩放程序能够正常工作,则可以通过更新扩展来配置此volcanoScheduler.schedulerConfigMap参数,并为其指定无 gangVolcano Scheduler 的自定义配置,例如:

volcano-scheduler.conf: |
    actions: "enqueue, allocate, backfill"
    tiers:
    - plugins:
      - name: sla 
        arguments:
        sla-waiting-time: 1m
    - plugins:
      - name: conformance
    - plugins:
        - name: drf
        - name: predicates
        - name: proportion
        - name: nodeorder
        - name: binpack

要在 AKS 群集中使用此配置,需要执行以下步骤:

  1. azureml命名空间中使用上述配置创建 configmap 文件。 此命名空间通常将在你安装 Azure 机器学习扩展时创建。
  2. 在扩展配置中设置 volcanoScheduler.schedulerConfigMap=<configmap name> 以应用此配置映射。 在安装扩展时,需要通过配置 amloperator.skipResourceValidation=true 来跳过资源验证。 例如:
    az k8s-extension update --name <extension-name> --config volcanoScheduler.schedulerConfigMap=<configmap name> amloperator.skipResourceValidation=true --cluster-type managedClusters --cluster-name <your-AKS-cluster-name> --resource-group <your-RG-name>
    

注意

由于删除了 gang 插件,因此 Volcano 计划作业时可能会发生死锁。

  • 为避免这种情况,可以在作业中使用相同的实例类型。

使用 Azure 机器学习扩展提供的默认配置以外的调度程序配置可能不完全受支持。 请谨慎操作。

请注意,如果 Volcano 版本低于 1.6,则需要在 Volcano Admission 中禁用 job/validate Webhook。

入口 Nginx 控制器

默认情况下,Azure 机器学习扩展安装附带入口 nginx 控制器类(作为k8s.io/ingress-nginx)。 如果群集中已有入口 nginx 控制器,需要使用不同的控制器类以避免安装失败。

可以使用两个选项:

  • 将现有的控制器类更改为k8s.io/ingress-nginx以外的其他类。
  • 按照以下示例,使用不同于你的自定义控制器类创建或更新 Azure 机器学习扩展。

例如,要使用自定义控制器类创建扩展:

az ml extension create --config nginxIngress.controller="k8s.io/amlarc-ingress-nginx"

要使用自定义控制器类更新扩展:

az ml extension update --config nginxIngress.controller="k8s.io/amlarc-ingress-nginx"

随 Azure 机器学习扩展一起安装的 nginx 入口控制器因内存不足 (OOM) 错误而发生故障

症状

随 Azure 机器学习扩展一起安装的 nginx 入口控制器因内存不足 (OOM) 错误而发生故障,即使没有工作负载也是这样。 控制器日志不显示诊断问题的任何有用信息。

可能的原因

如果 nginx 入口控制器在具有许多 CPU 的节点上运行,则可能会出现此问题。 默认情况下,nginx 入口控制器会根据 CPU 数生成工作进程,这可能会消耗较多资源,并导致具有较多 CPU 的节点上出现 OOM 错误。 这是 GitHub 上报告的已知问题

解决方案

若要解决此问题,您可以:

  • 通过使用参数 nginxIngress.controllerConfig.worker-processes=8 安装扩展,调整工作进程数。
  • 使用参数 nginxIngress.resources.controller.limits.memory=<new limit> 提高内存上限。

确保根据特定的节点规格和工作负载要求调整这两个参数,以有效地优化工作负载。

后续步骤