Überwachung von „ vLLM “ auf Kubernetes

Überwachen Sie in Kubernetes -Clustern ausgeführte „ vLLM “-Pods mit „ Instana “, indem Sie einen „ OpenTelemetry “-Collector als von „ Helm “ verwalteten „ StatefulSet “ bereitstellen. Der Collector sammelt „ Prometheus “-Metriken aus „ vLLM “-Pods, ergänzt sie mit „ Kubernetes “-Metadaten und leitet sie an das „ Instana “-Backend weiter.

Vorgehensweise

  1. Einen „ vLLM “-Pod überprüfen:
    kubectl describe pod <vllm-pod-name> -n <namespace>
  2. Beachten Sie die folgenden Werte aus der Ausgabe:
    Zu suchendes Feld Lage im Pod beschreiben Beispielwert
    Namensbereich Namespace: text-generation
    App-Bezeichnung Labels: app= vllm-server
    Bezeichnung der Komponente Labels: component= huggingface-vllm
    Metrik-Port Port: unter „Container“ 8000/TCP
  3. Bevor Sie den Collector bereitstellen, überprüfen Sie, ob vLLM Metriken bereitstellt:
    kubectl exec -n <namespace> <vllm-pod-name> -- \
      curl http://localhost:<metrics-port>/metrics

    Die Ausgabe enthält Metriken im Format „ Prometheus “, wie beispielsweise vllm:*, http_*, und process_*. Falls der Metrics-Endpunkt nicht reagiert, überprüfen Sie, ob „ vLLM “ korrekt gestartet wurde und ob die Portnummer mit der Pod-Beschreibung übereinstimmt.

  4. Den Namen des Clusters abrufen:
    kubectl config current-context

    Der Collector versieht jede Metrik mit Cluster-Metadaten. Erfassen Sie die folgenden Angaben zu Ihrem Cluster.

  5. Die Version von „ Kubernetes “ abrufen:
    kubectl version --short
  6. Rufen Sie die Cluster-UID ab, die sich aus der kube-system Namespace-UID ableitet:
    kubectl get namespace kube-system -o jsonpath='{.metadata.uid}'
  7. Erstellen Sie eine values.yaml Datei anhand der folgenden Vorlage. Ersetzen Sie jeden Platzhalter (gekennzeichnet mit <…>) durch die Werte, die Sie in den vorherigen Schritten ermittelt haben.
    mode: statefulset
    replicaCount: 1
    image:
      repository: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-k8s
    extraEnvs:
      - name: K8S_NODE_NAME
        valueFrom:
          fieldRef:
            fieldPath: spec.nodeName
    presets:
      kubernetesAttributes:
        enabled: true
        extractAllPodLabels: true
        extractAllPodAnnotations: true
      kubeletMetrics:
        enabled: false
      logsCollection:
        enabled: false
      hostMetrics:
        enabled: false
      kubernetesEvents:
        enabled: true
      clusterMetrics:
        enabled: true
    config:
      extensions:
        health_check:
          endpoint: ${env:MY_POD_IP}:13133
    
      receivers:
        k8s_cluster:
          collection_interval: 10s
        kubeletstats:
          collection_interval: 10s
          auth_type: serviceAccount
          endpoint: "https://${env:K8S_NODE_NAME}:10250"
          insecure_skip_verify: true
          metric_groups:
            - pod
            - node
            - container
        prometheus:
          config:
            scrape_configs:
              - job_name: "prometheus-scrape"
                scrape_interval: 10s
                metrics_path: /metrics
                tls_config:
                  insecure_skip_verify: true
                kubernetes_sd_configs:
                  - role: pod
                    namespaces:
                     names:
                      - <vllm-namespace-name>     # your vLLM namespace, e.g. text-generation
                relabel_configs:
                  - source_labels: [__meta_kubernetes_pod_label_component]
                    regex: <component-label-value> # your component label, e.g. huggingface-vllm
                    action: keep
                  - source_labels: [__meta_kubernetes_pod_phase]
                    regex: Running
                    action: keep
                  - source_labels: [__meta_kubernetes_pod_ip]
                    regex: (.+)
                    target_label: __address__
                    replacement: $1:<vllm-metrics-port>  # your metrics port, e.g. 8000
                  - source_labels: [__meta_kubernetes_pod_name]
                    target_label: k8s_pod
                  - source_labels: [__meta_kubernetes_namespace]
                    target_label: k8s_namespace
    
      processors:
        resource/vllm:
          attributes:
            - key: service.name
              value: vllm
              action: upsert
            - key: service.namespace
              from_attribute: k8s.namespace.name
              action: upsert
            - key: service.instance.id
              from_attribute: k8s.pod.uid
              action: insert
            - key: INSTANA_PLUGIN
              value: vllm
              action: upsert
            - key: vllm.entity.type
              value: vllm
              action: upsert
        resource/k8s:
          attributes:
            - key: k8s.cluster.name
              value: <cluster-name>            # e.g. prod-cluster-01
              action: insert
            - key: k8s.cluster.distribution
              value: <cluster-distribution>    # openshift | eks | gke | aks | kubernetes
              action: insert
            - key: k8s.cluster.managedBy
              value: <cluster-managed-by>      # e.g. CNF, EKS, GKE, AKS
              action: insert
            - key: k8s.cluster.shortName
              value: <cluster-short-name>
              action: insert
            - key: k8s.cluster.fullName
              value: <cluster-full-name>
              action: insert
            - key: k8s.cluster.version
              value: <cluster-version>         # e.g. v1.29.0
              action: insert
            - key: k8s.cluster.uid
              value: <cluster-uid>             # kube-system namespace UID
              action: insert
            - key: INSTANA_PLUGIN
              value: k8s
              action: upsert
        memory_limiter:
          check_interval: 1s
          limit_percentage: 50
          spike_limit_percentage: 10
        k8sattributes:
          auth_type: serviceAccount
          passthrough: false
          extract:
            metadata:
              - k8s.namespace.name
              - k8s.pod.name
              - k8s.pod.uid
              - k8s.deployment.name
              - k8s.node.name
            labels:
              - tag_name: k8s.pod.labels.app
                key: app
                from: pod
              - tag_name: k8s.pod.labels.component
                key: component
                from: pod
        resourcedetection/env:
          detectors:
            - env
        filter/cluster:
          metrics:
            metric:
              - 'resource.attributes["k8s.cluster.uid"] == nil'
        filter/vllm:
          metrics:
            include:
              match_type: regexp
              resource_attributes:
                - key: k8s.pod.labels.component
                  value: <component-label-value>  # same value as the Prometheus relabel_configs regex
        batch: {}
    
      exporters:
        otlphttp:
          endpoint: <otlp-endpoint>  # e.g. https://otlp-grpc-<tenant>.instana.io:4318
          tls:
            insecure: false
          headers:
            x-instana-key: <your-instana-agent-key>
        debug:
          verbosity: detailed
    
      service:
        extensions:
          - health_check
        pipelines:
          metrics:
            receivers:
              - prometheus
            processors:
              - k8sattributes
              - filter/vllm
              - resource/k8s
              - resource/vllm
              - batch
            exporters:
              - debug
              - otlphttp
          metrics/k8s:
            receivers:
              - k8s_cluster
              - kubeletstats
            processors:
              - k8sattributes
              - resource/k8s
              - memory_limiter
              - batch
              - filter/cluster
            exporters:
              - debug
              - otlphttp
    
    clusterRole:
      rules:
        - apiGroups: ['']
          resources:
            - pods
            - namespaces
            - nodes
            - nodes/stats
            - nodes/proxy
            - nodes/metrics
            - endpoints
            - services
            - events
            - resourcequotas
            - replicationcontrollers
          verbs: ['get', 'list', 'watch']
  8. Sehen Sie in der Konfigurationsanleitung nach, ob Sie alle erforderlichen Werte haben. Eine vollständige Liste der Platzhalter und Informationen dazu, wie die einzelnen Werte ermittelt werden können, finden Sie unter vLLMKubernetes -Konfigurationsreferenz.
  9. Überprüfen Sie, ob Ihre values.yaml Datei korrekt dargestellt wird:
    helm template my-otel-collector open-telemetry/opentelemetry-collector \
      -f values.yaml \
      --validate

    Beheben Sie alle gemeldeten Syntaxfehler in „ YAML “, bevor Sie fortfahren.

  10. Den Kollektor einbauen:
    helm install my-otel-collector open-telemetry/opentelemetry-collector \
      -f values.yaml \
      -n monitoring \
      --create-namespace
  11. Überprüfen Sie, ob der Collector-Pod läuft:
    kubectl get pods -n monitoring -l app.kubernetes.io/name=opentelemetry-collector
  12. Überprüfen Sie die Protokolle des Collectors, um sicherzustellen, dass der Collector die Metriken von „ vLLM “ erfasst und exportiert:
    kubectl logs -n monitoring -l app.kubernetes.io/name=opentelemetry-collector --tail=100

    Suchen Sie nach Protokolleinträgen, die Folgendes enthalten:Scrape succeededoderMetrics exported successfully. Falls Fehler auftreten, lesen Sie den Abschnitt „Fehlerbehebung bei der Überwachung von vLLM “ unter Kubernetes.

Ergebnisse

Der „ OpenTelemetry “-Collector ist bereitgestellt und erfasst Metriken unter Prometheus aus Ihren „ vLLM “-Pods. Die Kennzahlen werden nun an das Backend von „ Instana “ weitergeleitet.

Nächste Schritte

Sobald der Collector läuft und Daten exportiert, können Sie die Metriken unter „ vLLM “ auf Instana einsehen:

  1. Wechseln Sie in der Benutzeroberfläche von „ Instana “ zu „Infrastruktur“ > „Infrastruktur analysieren “.
  2. Wählen Sie OTel vLLMonitor aus der Liste der Entitätstypen aus.
  3. Klicken Sie auf eine OTel vLLMonitor Instanz, um deren Dashboard zu öffnen.

Das Dashboard zeigt den Token-Durchsatz, laufende und wartende Anfragen sowie weitere Metriken zu „ vLLM “, die aus Ihren Pods erfasst wurden.

Go zum „ Kubernetes “-Pod, um die Ressourcenauslastung anzuzeigen. Die Pod-Übersicht zeigt Kennzahlen zur CPU-Auslastung, zum Arbeitsspeicher und zum Dateisystem an.

Verwenden Sie die Funktion „Upstream/Downstream“ des Pods, um die Upstream-Dienste, die den Pod „ vLLM “ aufrufen, sowie die Anwendungen, zu denen diese gehören, zu überprüfen.