Настройка профилирования GPU на Azure Kubernetes Service (AKS) (предварительная версия)

Нагрузки, использующие GPU, такие как сервисы инференса ИИ, могут требовать большого объёма памяти, и их сложно оптимизировать без возможности отслеживать активность GPU. Вы можете столкнуться с ошибками нехватки памяти (OOM), неожиданными скачками задержки или ростом нагрузки на память GPU, но традиционные метрики Kubernetes не показывают, где код выделяет память. Профилирование GPU помогает определить функции, ответственные за использование памяти GPU.

В этой статье показано, как развернуть агент наблюдаемости GPU на основе eBPF, сохранить профили в Пироскопе и визуализировать выделение памяти GPU в Grafana.

Important

Предварительные версии функций AKS доступны на условиях самообслуживания и по выбору пользователя. Предварительные версии предоставляются "как есть" и "при наличии". На них не распространяются соглашения об уровне обслуживания и ограниченная гарантия. Предварительные версии AKS сопровождаются частичной поддержкой клиентов на основе принципа лучших усилий. Как таковые, эти функции не предназначены для использования в производстве. Для получения дополнительной информации ознакомьтесь со следующими статьями поддержки:

Important

Программное обеспечение с открытым кодом упоминается во всей документации и примерах AKS. Программное обеспечение, которое вы развертываете, не покрывается соглашениями об уровне обслуживания AKS, ограниченной гарантией и поддержкой Azure. При использовании технологии с открытым исходным кодом вместе с AKS ознакомьтесь с вариантами поддержки, доступными от соответствующих сообществ и обслуживающих проектов для разработки плана.

Корпорация Майкрософт несет ответственность за создание пакетов с открытым кодом, которые мы развертываем в AKS. Эта ответственность включает полное управление процессами сборки, сканирования, подписывания, проверки и исправления ошибок, а также контроль над двоичными файлами в образах контейнеров. Для получения дополнительной информации см. Управление уязвимостями в AKS и Покрытие поддержки AKS.

Необходимые условия

  • Кластер AKS с по крайней мере одним пулом узлов с поддержкой GPU.
  • Azure CLI версии 2.72.0 или более поздней. Выполните команду az --version, чтобы узнать номер версии.
  • Расширение k8s-extension Azure CLI. Выполните az extension add --name k8s-extension, чтобы установить его.
  • Helm версии 3.x или более поздней. Выполните команду helm version, чтобы узнать номер версии.
  • Azure Monitor, если вы не используете собственную систему мониторинга.
  • Управление Azure для Grafana, если только вы не используете собственный экземпляр Grafana.

Шаг 1. Включение профилирования GPU с помощью расширения Inspektor Gadget

Inspektor Gadget — это платформа наблюдения на основе eBPF с открытым кодом для Kubernetes. Для профилирования GPU выполняется трассировка вызовов выделения памяти единой архитектуры устройств (CUDA) без изменений кода, боковой кареты или перезапуск pod.

Включите профилирование GPU в кластере AKS:

Note

Эта команда предполагает, что вы включили Azure Monitor в кластере AKS. Если вы используете собственную установку Prometheus, удалите --configuration-settings azureMonitor.enabled=true. Дополнительные сведения см. в часто задаваемых вопросы о профилировании GPU.

az k8s-extension create \
  --extension-type microsoft.inspektorgadget \
  --subscription <your-subscription-id> \
  --resource-group <your-resource-group> \
  --cluster-name <your-cluster-name> \
  --cluster-type managedClusters \
  --release-train preview \
  --name inspektor-gadget \
  --configuration-settings gpuObservability.enabled=true \
  --configuration-settings azureMonitor.enabled=true

Убедитесь, что поды Inspektor Gadget запущены:

kubectl get pods -n gadget -l k8s-app=gadget

Tip

Профилирование памяти GPU записывает события выделения памяти по мере их возникновения. Если рабочая нагрузка выделяет память GPU перед включением профилирования, профилировщик не записывает эти события. Для рабочих нагрузок, таких как vLLM, которые предварительно выделяют память GPU во время запуска, включите профилирование перед развертыванием рабочей нагрузки или перезапустите рабочую нагрузку для записи начальных путей выделения памяти.

Шаг 2. Включение визуализации профиля с помощью Пироскопа

Note

Если в кластере есть существующий стек Grafana и Pyroscope, пропустите этот шаг.

Пироскоп — это проект с открытым исходным кодом, который визуализирует и сохраняет профили производительности для оптимизации памяти и устранения неполадок.

Разверните один экземпляр Пироскопа в кластере:

helm install pyroscope -n gadget \
  oci://ghcr.io/grafana/helm-charts/pyroscope \
  --version 1.15.0 \
  --set pyroscope.image.repository=grafana/pyroscope \
  --set-string pyroscope.image.tag=1.15.0 \
  --set pyroscope.replicaCount=1 \
  --set pyroscope.structuredConfig.self_profiling.disable_push=true \
  --set pyroscope.structuredConfig.storage.backend=filesystem \
  --set pyroscope.service.type=LoadBalancer \
  --set pyroscope.service.port=4040 \
  --set-string pyroscope.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true \
  --set-string pyroscope.service.annotations."service\.beta\.kubernetes\.io/azure-pls-create"=true \
  --set-string pyroscope.service.annotations."service\.beta\.kubernetes\.io/azure-pls-name"=pyroscope-pls \
  --set-string pyroscope.service.annotations."service\.beta\.kubernetes\.io/azure-pls-proxy-protocol"=false \
  --set-string pyroscope.service.annotations."service\.beta\.kubernetes\.io/azure-pls-visibility"='*' \
  --set alloy.enabled=false \
  --set minio.enabled=false

Убедитесь, что модуль Pod Pyroscope запущен:

kubectl get pods -n gadget pyroscope-0

Note

Сведения о высокодоступном развертывании см. в документации по микрослужбам Пироскопа.

Note

Эта команда сохраняет профили в локальной файловой системе, поэтому данные профилирования теряются, если модуль pod повторно создан. Сведения о сохранении профилей в перезапуске pod см. в разделе часто задаваемые вопросы о профилировании GPU.

Шаг 3. Подключение Пироскопа к Управление Azure для Grafana

Note

Если вы используете собственный экземпляр Grafana, ознакомьтесь с часто задаваемыми вопросами о профилировании GPU.

Tip

Чтобы просмотреть профили рабочей нагрузки непосредственно в пользовательском интерфейсе Пироскопа, выполните команду kubectl port-forward -n gadget pyroscope-0 4040:4040.

Подключите Пироскоп к Управление Azure для Grafana через Приватный канал Azure.

Задайте переменные среды кластера и Grafana:

export RESOURCE_GROUP="<your-resource-group>"
export AKS_CLUSTER="<your-aks-cluster-name>"
export LOCATION="<your-aks-cluster-location>"
export GRAFANA_NAME="<your-azure-managed-grafana-name>"
export AKS_NODE_RG=$(az aks show \
  --resource-group "$RESOURCE_GROUP" \
  --name "$AKS_CLUSTER" \
  --query 'nodeResourceGroup' \
  --output tsv)

Tip

Если у вас нет экземпляра Управление Azure для Grafana, выполните командуaz grafana create --name "$GRAFANA_NAME" --resource-group "$RESOURCE_GROUP" --location "$LOCATION" --output none.

Задайте переменные среды для приватной конечной точки:

export PYROSCOPE_PLS="pyroscope-pls"
export PYROSCOPE_MPE="pyroscope-mpe"
export PYROSCOPE_PORT="4040"

Создайте приватную ссылку:

Note

Создание приватного подключения может занять несколько минут.

# Check the Azure Managed Grafana extension version.
ver=$(az extension show --name amg --query version --output tsv)
[[ "${ver%%.*}" -ge 3 ]] && MPE="managed-private-endpoint" || MPE="mpe"

# Wait until the Pyroscope private link service is available.
until az network private-link-service show \
  --name "$PYROSCOPE_PLS" \
  --resource-group "$AKS_NODE_RG" \
  --output none 2>/dev/null; do
  sleep 10
done

PYRO_PLS_ID=$(az network private-link-service show \
  --name "$PYROSCOPE_PLS" \
  --resource-group "$AKS_NODE_RG" \
  --query 'id' \
  --output tsv)

az grafana $MPE create \
  --workspace-name "$GRAFANA_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --name "$PYROSCOPE_MPE" \
  --private-link-resource-id "$PYRO_PLS_ID" \
  --location "$LOCATION" \
  --output none

sleep 30

PYRO_CONN=$(az network private-link-service show \
  --name "$PYROSCOPE_PLS" \
  --resource-group "$AKS_NODE_RG" \
  --query "privateEndpointConnections[?privateLinkServiceConnectionState.status=='Pending' && starts_with(name, 'grafana-${GRAFANA_NAME}')].name | [0]" \
  --output tsv)

az network private-link-service connection update \
  --name "$PYRO_CONN" \
  --service-name "$PYROSCOPE_PLS" \
  --resource-group "$AKS_NODE_RG" \
  --connection-status Approved \
  --output none

az grafana $MPE refresh \
  --workspace-name "$GRAFANA_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --output none

echo "Successfully created private link."

Создайте источник данных Пироскопа в Управление Azure для Grafana:

ver=$(az extension show --name amg --query version --output tsv)
[[ "${ver%%.*}" -ge 3 ]] && MPE="managed-private-endpoint" || MPE="mpe"

PYRO_IP=$(az grafana $MPE show \
  --workspace-name "$GRAFANA_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --name "$PYROSCOPE_MPE" \
  --query 'privateLinkServicePrivateIP' \
  --output tsv)

export PYROSCOPE_URL="http://${PYRO_IP}:${PYROSCOPE_PORT}"

az grafana data-source create \
  --name "$GRAFANA_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --definition "{
    \"name\": \"local-pyroscope\",
    \"uid\": \"local-pyroscope\",
    \"type\": \"grafana-pyroscope-datasource\",
    \"access\": \"proxy\",
    \"url\": \"${PYROSCOPE_URL}\",
    \"jsonData\": { \"keepCookies\": [\"pyroscope_git_session\"] }
  }" \
  --output none

echo "Successfully created the local-pyroscope data source."

Убедитесь, что источник данных имеет допустимый URL-адрес:

az grafana data-source show \
  --name "$GRAFANA_NAME" \
  --data-source local-pyroscope

Шаг 4: Подключите Grafana к управляемой службе Azure Monitor для Prometheus

Note

Эти шаги основаны на Подключении управляемой службы Azure Monitor для Prometheus к Grafana. Убедитесь, что управляемое удостоверение Grafana имеет роль Monitoring Data Reader для рабочей области Azure Monitor, особенно если рабочая область находится в другой группе ресурсов или подписке.

Задайте переменные среды рабочей области Azure Monitor:

export AMP_NAME="<your-azure-monitor-workspace-name>"
export AMP_RESOURCE_GROUP="<your-azure-monitor-workspace-resource-group>"

Tip

Запустите az resource list --resource-type Microsoft.Monitor/accounts --resource-group "$AMP_RESOURCE_GROUP" --output table, чтобы вывести список рабочих областей Azure Monitor в группе ресурсов. Чтобы найти подписку, опустите --resource-group.

Создайте источник данных Prometheus:

AMP_ENDPOINT=$(az resource show \
  --resource-type Microsoft.Monitor/accounts \
  --name "$AMP_NAME" \
  --resource-group "$AMP_RESOURCE_GROUP" \
  --query properties.metrics.prometheusQueryEndpoint \
  --output tsv)

az grafana data-source create \
  --name "$GRAFANA_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --definition "{
    \"name\": \"$AMP_NAME\",
    \"type\": \"prometheus\",
    \"access\": \"proxy\",
    \"url\": \"$AMP_ENDPOINT\",
    \"jsonData\": {
      \"httpMethod\": \"POST\",
      \"azureCredentials\": { \"authType\": \"msi\" }
    }
  }"

Проверьте источник данных:

az grafana data-source show \
  --name "$GRAFANA_NAME" \
  --data-source "$AMP_NAME"

Шаг 5. Настройка панелей мониторинга в Grafana

Импорт панели мониторинга наблюдаемости GPU:

az grafana dashboard create \
  --name "$GRAFANA_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --definition "$(curl -sSL https://raw.githubusercontent.com/inspektor-gadget/grafana-dashboards/refs/heads/main/dashboards/gpu-observability/AdvancedGPUObservability.json)"

Получите URL-адрес панели мониторинга:

GRAFANA_URL=$(az grafana show \
  --name "$GRAFANA_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --query properties.endpoint \
  --output tsv)

echo "${GRAFANA_URL}/d/AdvancedGPUObservability"

Сведения о интерпретации данных профилирования см. в статье Анализ графов профилирования GPU.

Очистите ресурсы

Удалите стек наблюдаемости GPU в кластере:

helm uninstall pyroscope -n gadget
az k8s-extension delete \
  --name inspektor-gadget \
  --cluster-name <your-cluster-name> \
  --resource-group <your-resource-group> \
  --cluster-type managedClusters \
  --yes
kubectl delete namespace gadget

Чтение графиков пламени

Сведения о интерпретации результатов профилирования и выявлении горячих точек памяти GPU см. в статье "Анализ графиков пламени профилирования GPU".

FAQ

О пользовательских интеграциях Prometheus и Grafana, а также о постоянном хранилище Pyroscope см. в разделе Часто задаваемые вопросы о профилировании GPU.

Дальнейшие действия