Configuración de la generación de perfiles de GPU en Azure Kubernetes Service (AKS) (versión preliminar)

Las cargas de trabajo basadas en GPU, como los servicios de inferencia de IA, pueden ser intensivas en memoria y difíciles de optimizar sin visibilidad de la actividad de GPU. Es posible que vea errores de memoria insuficiente (OOM), picos de latencia inesperados o aumento de la presión de memoria de GPU, pero las métricas tradicionales de Kubernetes no muestran dónde asigna memoria el código. La generación de perfiles de GPU le ayuda a identificar las funciones responsables del uso de memoria de GPU.

En este artículo se muestra cómo implementar un agente de observabilidad de GPU basado en eBPF, almacenar perfiles en Pyroscope y visualizar asignaciones de memoria de GPU en Grafana.

Important

Las características en versión preliminar de AKS están disponibles en modalidad de autoservicio y previa suscripción. Las versiones preliminares se proporcionan "tal cual" y "como están disponibles", y están excluidas de los Acuerdos de nivel de servicio y la garantía limitada. Las versiones preliminares de AKS cuentan con soporte parcial por parte del servicio al cliente en la medida de lo posible. Por lo tanto, estas características no están diseñadas para su uso en producción. Para más información, consulte los siguientes artículos de soporte:

Important

El software de código abierto se menciona en toda la documentación y ejemplos de AKS. El software que implemente se excluye de los contratos de nivel de servicio de AKS, la garantía limitada y el soporte técnico de Azure. A medida que usa la tecnología de código abierto junto con AKS, consulte las opciones de soporte técnico disponibles en las comunidades y los mantenedores de proyectos respectivos para desarrollar un plan.

Microsoft asume la responsabilidad de crear los paquetes de código abierto que implementamos en AKS. Esa responsabilidad incluye ser plenamente responsable del proceso de compilación, escaneo, firma, validación y corrección rápida, junto con el control de los binarios en las imágenes de contenedor. Para obtener más información, consulte Administración de vulnerabilidades para AKS y Cobertura del soporte técnico de AKS.

Prerequisites

  • Un clúster de AKS con al menos un grupo de nodos habilitado para GPU.
  • CLI de Azure versión 2.72.0 o posterior. Ejecute az --version para comprobar la versión.
  • Extensión de la CLI de k8s-extension Azure. Ejecute az extension add --name k8s-extension para instalarlo.
  • Helm versión 3.x o posterior. Ejecute helm version para comprobar la versión.
  • Azure Monitor, a menos que utilice su propia solución de supervisión.
  • Azure Managed Grafana, a menos que use su propia instancia de Grafana.

Paso 1: Habilitar la generación de perfiles de GPU a través de la extensión Inspektor Gadget

Inspektor Gadget es un marco de observabilidad basado en eBPF de código abierto para Kubernetes. Para el perfilado de la GPU, rastrea las llamadas de asignación de memoria de la Arquitectura Unificada de Dispositivos de Cálculo (CUDA) sin cambios en el código, sidecars ni reinicios de pods.

Habilite la generación de perfiles de GPU en el clúster de AKS:

Note

Este comando supone que ha habilitado Azure Monitor en el clúster de AKS. Si usa su propia configuración de Prometheus, quite --configuration-settings azureMonitor.enabled=true. Para más información, consulte las preguntas más frecuentes sobre la generación de perfiles de 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

Comprueba que los pods de Inspektor Gadget estén en ejecución:

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

Sugerencia

La generación de perfiles de memoria de GPU captura los eventos de asignación de memoria a medida que se producen. Si la carga de trabajo asigna memoria de GPU antes de habilitar la generación de perfiles, el generador de perfiles no captura esos eventos. Para cargas de trabajo como vLLM que asignan previamente memoria de GPU durante el inicio, habilite la generación de perfiles antes de implementar la carga de trabajo o reinicie la carga de trabajo para capturar las rutas de asignación de memoria iniciales.

Paso 2: Habilitación de la visualización de perfiles con Pyroscope

Note

Si ya tienes una pila de Grafana y Pyroscope en tu clúster, omite este paso.

Pyroscope es un proyecto de código abierto que visualiza y almacena perfiles de rendimiento para la optimización y solución de problemas de memoria.

Implemente una única instancia de Pyroscope en el clúster:

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

Comprueba que el pod de Pyroscope esté en ejecución:

kubectl get pods -n gadget pyroscope-0

Note

Para un despliegue de alta disponibilidad, consulte la documentación de microservicios de Pyroscope.

Note

Este comando almacena perfiles en el sistema de archivos local, por lo que los datos de generación de perfiles se pierden si se vuelve a crear el pod. Para conservar los perfiles entre reinicios de pod, consulte las preguntas más frecuentes sobre la generación de perfiles de GPU.

Paso 3: Conectar Pyroscope a Azure Managed Grafana

Note

Si usa su propia instancia de Grafana, consulte las preguntas más frecuentes sobre la generación de perfiles de GPU.

Sugerencia

Para ver los perfiles de carga de trabajo directamente en la interfaz de usuario de Pyroscope, ejecute kubectl port-forward -n gadget pyroscope-0 4040:4040.

Conecte Pyroscope a Azure Managed Grafana a través de Azure Private Link.

Establezca el clúster y las variables de entorno de 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)

Sugerencia

Si no tiene una instancia de Azure Managed Grafana, ejecute az grafana create --name "$GRAFANA_NAME" --resource-group "$RESOURCE_GROUP" --location "$LOCATION" --output none.

Establezca las variables de entorno del punto de conexión privado:

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

Cree el vínculo privado:

Note

La creación del vínculo privado puede tardar unos minutos.

# 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."

Crear el origen de datos Pyroscope en Azure Managed 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."

Compruebe que el origen de datos tiene una dirección URL válida:

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

Paso 4: Conectar Grafana con Azure Monitor Managed Service for Prometheus

Note

Estos pasos se basan en Conexión del servicio administrado de Azure Monitor para Prometheus a Grafana. Asegúrese de que la identidad administrada de Grafana tiene el rol Lector de datos de supervisión en el área de trabajo de Azure Monitor, especialmente si el área de trabajo está en un grupo de recursos o una suscripción diferentes.

Establezca las variables de entorno del área de trabajo de Azure Monitor:

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

Sugerencia

Ejecute az resource list --resource-type Microsoft.Monitor/accounts --resource-group "$AMP_RESOURCE_GROUP" --output table para listar las áreas de trabajo de Azure Monitor en el grupo de recursos. Para buscar la suscripción, omita --resource-group.

Cree el origen de datos de 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\" }
    }
  }"

Compruebe el origen de datos:

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

Paso 5: Configurar paneles en Grafana

Importe el panel de observabilidad de 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)"

Obtenga la dirección URL del panel:

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

echo "${GRAFANA_URL}/d/AdvancedGPUObservability"

Para interpretar los datos de perfilado, consulta Analizar gráficos de llama de perfilado de GPU.

Limpieza de recursos

Elimina la pila de observabilidad de GPU del clúster:

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

Cómo leer gráficos de llamas

Para interpretar los resultados del perfilado e identificar los puntos críticos de memoria de la GPU, consulte Analizar gráficos de llama del perfilado de la GPU.

FAQ

Para obtener integraciones personalizadas de Prometheus y Grafana y almacenamiento piroscopio persistente, consulte las preguntas más frecuentes sobre la generación de perfiles de GPU.

Pasos siguientes