Chapter 10. Distributed Inference with llm-d observability
You can use Observability to analyze your llm-d deployments, improving overall model management and monitoring on the platform.
Use Prometheus to collect metrics from Distributed Inference with llm-d deployments and build custom observability dashboards to monitor token throughput, cache use, routing decisions, and inference performance. On OpenShift, the controller automatically creates PodMonitor and ServiceMonitor resources to scrape metrics from vLLM engines and the inference scheduler. On other Kubernetes platforms, configure Prometheus scrape targets manually to collect metrics from the vLLM and inference scheduler endpoints.
Distributed Inference with llm-d Observability is a Developer Preview feature only. Developer Preview features are not supported by Red Hat in any way and are not functionally complete or production-ready. Do not use Developer Preview features for production or business-critical workloads. Developer Preview features provide early access to upcoming product features in advance of their possible inclusion in a Red Hat product offering, enabling customers to test functionality and provide feedback during the development process. These features might not have any documentation, are subject to change or removal at any time, and testing is limited. Red Hat might provide ways to submit feedback on Developer Preview features without an associated SLA.
10.1. Metrics for llm-d inference deployments Copy linkLink copied to clipboard!
Distributed Inference with llm-d deployments expose Prometheus metrics that you can use to monitor inference performance, track resource usage, and detect operational issues. On OpenShift, the controller automatically creates PodMonitor and ServiceMonitor resources to collect these metrics when you deploy an LLMInferenceService. On other Kubernetes platforms, you must configure Prometheus scrape targets manually to collect metrics from the vLLM engine and inference scheduler endpoints. You can build custom dashboards for SLO compliance and capacity planning.
llm-d components expose three distinct categories of Prometheus metrics:
- vLLM engine metrics
-
The vLLM model servers expose metrics on port
8000at the/metricsendpoint. These metrics cover token throughput, request latency distributions, KV cache utilization, request queue depth, and model loading status. vLLM metrics provide the foundation for understanding individual model server performance and resource consumption. - EPP and inference scheduler metrics
-
The Endpoint Picker (EPP) exposes metrics at the
/metricsendpoint on themetricsservice port. These metrics cover request routing decisions, endpoint scoring, scheduling latency, plugin processing times, and prefix cache indexing performance. EPP metrics help you understand how requests are distributed across model server replicas and how efficiently the scheduler routes traffic. - Inference objective metrics
- The inference scheduler also exposes higher-level metrics that track end-to-end inference performance against service level objectives. These metrics include request error rates, time to first token (TTFT), time per output token (TPOT), SLO violation counts, and request duration distributions. Inference objective metrics provide the basis for SLO-based alerting and compliance monitoring.
These three metric categories work together to provide a complete picture of your llm-d deployment health. Use vLLM metrics to monitor individual model server capacity, EPP metrics to evaluate routing efficiency, and inference objective metrics to track overall service quality.
10.2. Verify metrics collection for llm-d deployments Copy linkLink copied to clipboard!
On OpenShift, the controller automatically creates PodMonitor and ServiceMonitor resources to scrape metrics from vLLM engines and the inference scheduler when you deploy an LLMInferenceService. On other Kubernetes platforms, the controller does not create these resources. You must configure Prometheus scrape targets manually to collect metrics.
The following scrape targets expose llm-d metrics:
- vLLM engine metrics
-
Exposed on port
8000at the/metricsendpoint on each model server pod. - EPP and inference scheduler metrics
-
Exposed at the
/metricsendpoint on themetricsservice port of the scheduler service.
Prerequisites
- You have a deployed Distributed Inference with llm-d inference deployment on Red Hat OpenShift AI 3.5.
- You have cluster administrator access.
You have a Prometheus-based monitoring stack configured in your cluster.
On OpenShift, enable user workload monitoring. The Prometheus Operator is included automatically. See Configuring user workload monitoring.
On other Kubernetes platforms, you must have the Prometheus Operator installed if you want to use
PodMonitorandServiceMonitorresources, or a standalone Prometheus deployment configured with static or service-discovery-based scrape targets.
Procedure
On OpenShift:
Verify that the
PodMonitorresource for vLLM engine metrics exists in your deployment namespace:$ kubectl get podmonitors -n <NAMESPACE> -l app.kubernetes.io/component=llm-monitoringReplace
<NAMESPACE>with the namespace where your llm-d deployment runs.The output shows a
PodMonitorresource with a name that begins withkserve-llm-isvc-vllm-engine. This resource scrapes vLLM metrics from port8000on all model server pods.Verify that the
ServiceMonitorresource for inference scheduler metrics exists in your deployment namespace:$ kubectl get servicemonitors -n <NAMESPACE> -l app.kubernetes.io/component=llm-monitoringThe output shows a
ServiceMonitorresource with a name that begins withkserve-llm-isvc-scheduler. This resource scrapes EPP and inference scheduler metrics from themetricsport on the scheduler service.
On other Kubernetes platforms without the Prometheus Operator:
Configure your Prometheus instance to scrape the following targets in your deployment namespace:
Expand Table 10.1. llm-d scrape targets Component Port Path Pod selector vLLM engine
8000/metricsPods with the label
app: <POOL_NAME>, where<POOL_NAME>is the name of yourInferencePoolresource.EPP and inference scheduler
9090/metricsThe EPP service, selected by the label
app: <EPP_NAME>, where<EPP_NAME>is the name of your EPP deployment.
On all platforms:
Verify that Prometheus is scraping vLLM metrics by running the following PromQL query against your Prometheus instance:
vllm:num_requests_running{namespace="<NAMESPACE>"}Replace
<NAMESPACE>with your deployment namespace.On OpenShift, run this query from the web console by navigating to Observe > Metrics.
On other Kubernetes platforms, run this query by using your Prometheus web UI or API.
If the query returns results, Prometheus is successfully scraping vLLM metrics.
Verify that Prometheus is scraping EPP and inference scheduler metrics by running the following PromQL query:
llm_d_inference_scheduler_disagg_decision_total{namespace="<NAMESPACE>"}Replace
<NAMESPACE>with your deployment namespace.If the query returns results, Prometheus is successfully scraping inference scheduler metrics.
Metrics might take up to 60 seconds to appear after the LLMInferenceService is deployed. If metrics do not appear, verify that your monitoring stack is configured to scrape metrics from the deployment namespace. On OpenShift, verify that user workload monitoring is enabled and that PodMonitor and ServiceMonitor resources are present. On other platforms, verify that the Prometheus scrape configuration targets the correct namespace, ports, and label selectors.
10.3. PromQL queries for llm-d monitoring Copy linkLink copied to clipboard!
You can use the following PromQL queries to monitor your Distributed Inference with llm-d deployments. The queries are organized into two groups: immediate failure and saturation indicators that drive operational alerts, and diagnostic drill-down queries that support deeper investigation.
Failure and saturation indicators
Use the following queries for dashboards and alerts that track service health and capacity limits.
| Operational concern | PromQL query |
|---|---|
| Overall error rate |
|
| Per-model error rate |
|
| Error rate by error code |
|
| Request rate by model |
|
| Overall latency P99 |
|
| Overall latency P90 |
|
| Model-specific TTFT P99 |
|
| Model-specific TPOT P99 |
|
| EPP end-to-end latency P99 |
|
| Plugin processing latency P99 |
|
| Scheduler health |
|
| Request preemptions per vLLM instance |
|
Diagnostic drill-down queries
Use the following queries for deeper investigation when failure and saturation indicators signal issues.
| Operational concern | PromQL query |
|---|---|
| KV cache utilization by pod |
|
| Request queue length by pod |
|
| Model throughput in tokens per second |
|
| Generation token rate by pod |
|
| Active requests per pod |
|
| Operational concern | PromQL query |
|---|---|
| Request distribution per instance |
|
| Token distribution across pods |
|
| Routing decision latency P99 |
|
| Operational concern | PromQL query |
|---|---|
| Prefix cache hit rate |
|
| Per-instance prefix cache hit rate |
|
| KV cache utilization percentage |
|
| EPP prefix indexer size |
|
| EPP prefix indexer hit ratio P90 |
|
| Operational concern | PromQL query |
|---|---|
| Prefill worker utilization |
|
| Decode worker KV cache utilization |
|
| Prefill queue length |
|
| Disaggregation decision rate by type |
|
| Disaggregation decision ratio |
|
10.4. Import Grafana dashboards for llm-d Copy linkLink copied to clipboard!
You can import community Grafana dashboards to get a baseline monitoring view of your Distributed Inference with llm-d deployments. The dashboards provide pre-built visualizations for vLLM performance, failure and saturation indicators, diagnostic drill-downs, KV cache performance, and prefill/decode disaggregation metrics.
Prerequisites
- You have a Grafana instance deployed and connected to a Prometheus data source that collects llm-d metrics. Grafana is not included with OpenShift. You must deploy Grafana separately, for example, by using the Grafana community Operator.
- Metrics collection is enabled for your Distributed Inference with llm-d deployment.
Procedure
Download the community Grafana dashboard JSON files from the llm-d project.
The following dashboards are available:
- llm-d vLLM Overview
- General vLLM metrics overview for monitoring llm-d inference servers. Download from llm-d-vllm-overview.json.
- llm-d Failure and Saturation Indicators
- Key failure and saturation indicators for identifying system issues and capacity constraints. Download from llm-d-failure-saturation-dashboard.json.
- llm-d Diagnostic Drill-Down
- Detailed diagnostic metrics for investigating performance issues. Download from llm-d-diagnostic-drilldown-dashboard.json.
- llm-d Performance Dashboard
- Performance metrics including KV cache utilization. Download from llm-d-performance-kv-cache.json.
- P/D Coordinator Metrics
- Prefill/decode disaggregation performance metrics, including vLLM end-to-end latency, prefill duration, decode duration, and phase breakdown. Download from llm-d-pd-coordinator-metrics.json.
- In the Grafana web interface, navigate to Dashboards > New > Import.
- Upload a dashboard JSON file or paste the JSON content into the import dialog.
- Select the Prometheus data source that collects metrics from your llm-d deployment.
- Click Import to create the dashboard.
- Repeat the import process for each dashboard JSON file.
Verification
- Navigate to a newly imported dashboard and verify that the panels display data from your llm-d deployment. If a "No data" message is shown, verify that the Prometheus data source is correctly configured and that metrics collection is enabled for the llm-d namespace.
In disconnected environments, download the dashboard JSON files from a connected network and transfer them to a workstation with access to the Grafana instance. The dashboards do not reference external data sources, so they function in disconnected environments after Prometheus and Grafana are available.
10.5. vLLM metrics for llm-d Copy linkLink copied to clipboard!
The vLLM model servers in Distributed Inference with llm-d deployments expose Prometheus metrics on port 8000 at the /metrics endpoint. You can use these metrics to monitor token throughput, request latency, KV cache usage, and request queue depth for individual model server replicas.
Token throughput metrics
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| counter |
| The total number of prompt tokens processed by the model server. |
|
| counter |
| The total number of generation tokens produced by the model server. |
|
| histogram |
| The end-to-end request latency distribution in seconds, measured from request receipt to response completion. |
Latency metrics
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| histogram |
| The time to first token (TTFT) distribution in seconds. This measures the latency from request submission to the first generated token. |
|
| histogram |
| The inter-token latency distribution in seconds. This measures the time between consecutive output tokens. |
KV cache metrics
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| gauge |
|
The GPU KV cache utilization as a percentage between |
|
| counter |
| The total number of request preemptions caused by KV cache pressure. Preemptions occur when the cache is full and running requests must be evicted to make room for new requests. |
Request queue metrics
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| gauge |
| The current number of requests being actively processed by the model server. |
|
| gauge |
| The current number of requests waiting in the queue for processing. |
|
| counter |
| The total number of successfully completed inference requests, broken down by completion reason. |
Prefix cache metrics
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| counter |
| The total number of prefix cache hits. A cache hit occurs when a request prompt matches cached key-value data, avoiding redundant computation. |
|
| counter |
|
The total number of prefix cache queries. Use this metric with |
10.6. EPP and inference scheduler metrics for llm-d Copy linkLink copied to clipboard!
The Endpoint Picker (EPP) and inference scheduler in Distributed Inference with llm-d deployments expose Prometheus metrics at the /metrics endpoint on the metrics service port. You can use these metrics to monitor request routing decisions, scheduling latency, inference objective compliance, and prefix cache indexing performance.
Inference objective metrics
The inference objective metrics track end-to-end inference performance and SLO compliance. These metrics use the inference_objective_ prefix.
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| counter |
| The total number of inference requests processed by the scheduler. |
|
| counter |
| The total number of inference request errors, broken down by error code. |
|
| histogram |
| The end-to-end inference request duration distribution in seconds. |
|
| histogram |
| The time to first token (TTFT) distribution in seconds. |
|
| histogram |
| The time per output token (TPOT) distribution in seconds. |
|
| histogram |
| The predicted TTFT distribution in seconds, used by the scheduler for routing decisions. |
|
| histogram |
| The predicted TPOT distribution in seconds, used by the scheduler for routing decisions. |
|
| counter |
|
The total number of SLO violations, broken down by violation type: |
|
| gauge |
| The current number of active inference requests. |
|
| histogram |
| The input token count distribution per request. |
|
| histogram |
| The output token count distribution per request. |
Scheduling and routing metrics
The scheduling and routing metrics track the internal performance of the Endpoint Picker. These metrics use the inference_extension_ prefix.
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| histogram | None | The end-to-end scheduling duration in seconds, measured from request receipt to endpoint selection. |
|
| counter |
|
The total number of scheduling attempts, broken down by status: |
|
| histogram |
| The plugin processing duration in seconds, broken down by extension point, plugin type, and plugin name. Use this metric to identify slow plugins that impact scheduling latency. |
|
| counter |
| The total number of model rewrite decisions made by the scheduler. |
Prefix cache indexer metrics
The prefix cache indexer metrics track KV cache prefix matching performance in the scheduler. These metrics use the inference_extension_ prefix.
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| gauge | None | The current size of the prefix cache index maintained by the scheduler. |
|
| histogram | None | The prefix cache hit ratio distribution. A higher hit ratio indicates that requests frequently match cached prefixes, reducing redundant computation. |
|
| histogram | None | The prefix cache hit size distribution in bytes. Larger hit sizes indicate more effective prefix reuse. |
Inference pool metrics
The inference pool metrics track aggregate statistics across all endpoints in a pool. These metrics use the inference_pool_ prefix.
| Metric name | Type | Labels | Description |
|---|---|---|---|
|
| gauge |
| The average KV cache utilization across all endpoints in the inference pool. |
|
| gauge |
| The average request queue size across all endpoints in the inference pool. |
|
| gauge |
| The average number of running requests across all endpoints in the inference pool. |
|
| gauge |
| The number of ready pods in the inference pool. |
|
| gauge |
| The request queue size for a specific pod in the inference pool. |
10.7. Monitor batch inference workloads Copy linkLink copied to clipboard!
You can monitor batch inference workloads by collecting Prometheus metrics from the batch gateway components and configuring alerts for batch processing failures. The batch gateway API server, processor, and garbage collector expose metrics that you can use to track job throughput, queue depth, processing latency, and error rates.
Prerequisites
- The batch inference subsystem is deployed and configured. For more information, see Configure batch inference for Distributed Inference with llm-d.
You have a Prometheus-based monitoring stack configured in your cluster.
On OpenShift, enable user workload monitoring. See Configuring user workload monitoring.
- You have cluster administrator access.
Procedure
Verify that the
ServiceMonitorresource for the batch gateway API server exists:$ oc get servicemonitors -n <batch_gateway_namespace> -l app.kubernetes.io/component=apiserverReplace
<batch_gateway_namespace>with the namespace where the batch gateway is deployed.The
ServiceMonitorscrapes API server metrics from port 8081. The Batch Gateway Operator creates this resource automatically during deployment. If theServiceMonitordoes not exist, verify that the Batch Gateway Operator deployment completed successfully.Verify that the
PodMonitorresource for the batch processor exists:$ oc get podmonitors -n <batch_gateway_namespace> -l app.kubernetes.io/component=processorThe
PodMonitorscrapes processor metrics from port 9090. The Batch Gateway Operator creates this resource automatically during deployment. If thePodMonitordoes not exist, verify that the Batch Gateway Operator deployment completed successfully.Verify that the
PodMonitorresource for the garbage collector exists:$ oc get podmonitors -n <batch_gateway_namespace> -l app.kubernetes.io/component=gcThe
PodMonitorscrapes garbage collector metrics from port 9091. The Batch Gateway Operator creates this resource automatically during deployment. If thePodMonitordoes not exist, verify that the Batch Gateway Operator deployment completed successfully.NoteFor PromQL queries and metric names, see the batch gateway metrics implementation in the repository. The metric definitions are in the
apiserver/metrics/,processor/metrics/, andgc/metrics/subdirectories.Optional: Import pre-built Grafana dashboards for batch gateway components.
The batch gateway includes
ConfigMapresources containing Grafana dashboard JSON definitions. Import these dashboards into your Grafana instance to visualize batch processing metrics.$ oc get configmaps -n <batch_gateway_namespace> -l grafana_dashboard=1
Verification
-
Verify that the
ServiceMonitorandPodMonitorresources exist and that Prometheus is configured to scrape them.
Additional resources
10.8. Configure distributed tracing for Distributed Inference with llm-d deployments Copy linkLink copied to clipboard!
Configure distributed tracing for LLM distributed inference (Distributed Inference with llm-d) deployments using the Red Hat build of Tempo. Distributed tracing provides end-to-end visibility into inference requests, enabling performance debugging, latency analysis, and system health monitoring across the inference scheduler, routing sidecar, and vLLM model server.
10.8.1. Distributed tracing architecture for Distributed Inference with llm-d Copy linkLink copied to clipboard!
Distributed tracing for Distributed Inference with llm-d records request flows across the gateway, inference scheduler, routing sidecar, and vLLM model server to help you identify latency and troubleshoot inference workloads.
10.8.1.1. Four-component tracing pipeline Copy linkLink copied to clipboard!
The distributed tracing pipeline consists of four components:
- vLLM model server instrumentation
- The vLLM model server emits trace data using the OpenTelemetry SDK.
- Inference scheduler instrumentation
- The inference scheduler emits trace data using the OpenTelemetry SDK. The scheduler creates spans for request routing decisions and forwards requests with trace context headers to enable parent-child span relationships across components.
- Routing sidecar instrumentation
- The routing sidecar emits traces for disaggregated inference operations, including prefill-decode coordination and KV cache transfers between pods. The sidecar propagates trace context to ensure end-to-end visibility across distributed inference stages.
- Tempo storage with Jaeger UI
- Tempo receives traces directly from the inference components, stores trace data with configurable retention policies, and exposes the Jaeger Query Frontend for searching, visualizing, and analyzing traces.
All instrumented components export traces directly to Tempo over gRPC using OTLP. == Data flow
Traces flow through the system in the following sequence:
- A client sends an inference request to the Gateway endpoint over HTTPS.
- The inference scheduler receives the request, creates a child span, selects a vLLM replica, and forwards the request with trace context headers.
- In disaggregated prefill and decode deployments, the routing sidecar coordinates request handling and KV cache transfer between the prefill and decode pods. Its spans record these operations for each inference request.
- The vLLM model server receives the request, creates child spans for tokenization and model inference operations, and returns the response.
- All components export their spans directly to Tempo over gRPC (port 4317) using OTLP.
- Tempo ingests the spans and stores them in the configured backend. You can use in-memory storage for development and testing or supported object storage for persistent production storage.
- Users access the Jaeger UI to search for traces by service name, time range, or trace ID.
10.8.1.2. Span hierarchy Copy linkLink copied to clipboard!
A typical inference request generates the following span structure:
Root Span:
├── Child Span: inference-server-decode
│ └── Child Span: llm_request
Each span includes timing data, service name, and trace context. This hierarchy enables latency analysis at each stage of the inference pipeline.
10.8.1.3. Why distributed tracing matters for LLM inference Copy linkLink copied to clipboard!
Distributed tracing addresses key observability challenges in LLM inference deployments:
- Latency diagnosis
- Identifies which component contributes most to request latency across the gateway, scheduler, and vLLM model server.
- Bottleneck identification
- Reveals slow operations within vLLM (tokenization, model forward pass, tensor operations).
- Request flow visualization
- Shows the complete path of inference requests through distributed components.
- Error correlation
- Links errors across services by trace ID, simplifying troubleshooting.
- Performance tuning
- Provides data for optimizing scheduling decisions, model loading, and GPU utilization.
10.8.2. Install distributed tracing prerequisite Operators Copy linkLink copied to clipboard!
Install the Red Hat build of Tempo Operator required for distributed tracing support in Distributed Inference with llm-d deployments. The Tempo Operator manages the lifecycle of trace storage and query components.
Prerequisites
- You have an Openshift Container Platform 4.19.9+ cluster.
-
You have
cluster-adminaccess. - You have installed the OpenShift CLI (`oc`).
- You have configured access to your cluster.
Procedure
Install the Red Hat build of Tempo Operator:
On OpenShift 4.20 and later, install from the software catalog
- On OpenShift 4.19, install from the OperatorHub.
- Search for Red Hat build of Tempo.
- Select the Operator from the redhat-operators catalog.
- Click Install.
- On the Install Operator page, accept the default settings and click Install.
Verify the Tempo Operator installation:
$ oc get csv -n openshift-operators | grep tempo
Verification
-
The Tempo Operator CSV shows
Succeededstatus. The Tempo Operator pod is running in the
openshift-operatorsnamespace:$ oc get pods -n openshift-operators | grep tempo
Additional resources
10.8.3. Deploy a Tempo instance for trace storage Copy linkLink copied to clipboard!
You can store and inspect distributed traces from Distributed Inference with llm-d deployments by configuring a TempoMonolithic instance with a Jaeger user interface.
Prerequisites
- You have installed the Red Hat build of Tempo Operator.
-
You have
cluster-adminaccess. - You have installed the OpenShift CLI (`oc`).
Procedure
Create a namespace for the Tempo deployment:
$ oc new-project tempo-systemSave the following YAML to a file named
tempo-monolithic.yaml. Create aTempoMonolithiccustom resource:apiVersion: tempo.grafana.com/v1alpha1 kind: TempoMonolithic metadata: name: tempo-llmd namespace: tempo-system spec: storage: traces: backend: memory jaegerui: enabled: true route: enabled: true ingestion: otlp: grpc: enabled: true http: enabled: truewhere:
storage.traces.backend-
Specifies the trace storage backend. The value
memoryprovides temporary, in-memory storage for development and testing. jaegerui.enabled- Enables the Jaeger Query Frontend for trace visualization.
jaegerui.route.enabled-
Creates a
Routefor external access to the Jaeger user interface. ingestion.otlp.grpc.enabled- Enables ingestion of telemetry data by using OTLP over gRPC.
ingestion.otlp.http.enabledEnables ingestion of telemetry data by using OTLP over HTTP.
NoteThe
memorybackend does not persist traces after the Tempo pod restarts. For production environments, configure a supported persistent storage backend.
Apply the
TempoMonolithiccustom resource:$ oc apply -f tempo-monolithic.yamlWait for the Tempo instance to be ready:
$ oc get tempomonolithic tempo-llmd -n tempo-system -wWait until the
READYstatus showsTrue.Retrieve the Jaeger user interface route URL:
$ oc get route -n tempo-systemExample output
NAME HOST/PORT tempo-llmd-jaegerui tempo-llmd-jaegerui-tempo-system.apps.example.com
Verification
Verify that the
TempoMonolithiccustom resource showsREADY=True:$ oc get tempomonolithic tempo-llmd -n tempo-systemThe output shows
READYstatus asTrue.Verify that Tempo pods are running in the
tempo-systemnamespace:$ oc get pods -n tempo-systemAll pods show
Runningstatus.Verify that the Jaeger user interface route is accessible:
$ oc get route tempo-llmd-jaegerui -n tempo-system -o jsonpath='{.spec.host}'The output shows the route hostname.
10.8.4. Enable distributed tracing for LLMInferenceService Copy linkLink copied to clipboard!
Enable distributed tracing for an LLMInferenceService by using the declarative spec.tracing API. Distributed tracing provides end-to-end visibility into inference request flows from the Gateway through the scheduler to the vLLM model server.
Prerequisites
- You have deployed a Tempo instance for trace storage. For more information, see Deploy a Tempo instance for trace storage.
-
You have an
LLMInferenceServiceresource deployed. - You have installed the OpenShift CLI (`oc`).
- You have cluster administrator access.
Procedure
Save the following YAML to a file named
llminferenceservice-tracing.yaml. Create anLLMInferenceServicecustom resource with distributed tracing enabled:apiVersion: serving.kserve.io/v1alpha2 kind: LLMInferenceService metadata: name: traced-llm-inference namespace: llm-inference spec: tracing: exporterEndpoint: "http://tempo-tracing:4317" sampler: "parentbased_traceidratio" samplerArg: "0.05" exporter: "otlp" model: uri: hf://Qwen/Qwen2.5-7B-Instruct name: Qwen/Qwen2.5-7B-Instruct replicas: 1 router: scheduler: {} route: {} gateway: {} template: containers: - name: main image: registry.redhat.io/rhaii-early-access/vllm-cuda-rhel9:3.5.0-ea.1-1780065492 imagePullPolicy: Always resources: limits: cpu: "4" memory: 32Gi nvidia.com/gpu: "1" requests: cpu: "2" memory: 16Gi nvidia.com/gpu: "1"where:
spec.tracing.exporterEndpoint-
Specifies the Tempo endpoint for trace export. Use the cluster-internal service DNS name
tempo-tracing:4317. spec.tracing.sampler-
Specifies the sampling strategy. Use
parentbased_traceidratiofor probabilistic sampling. spec.tracing.samplerArg-
Specifies the sampling rate as a ratio between 0 and 1. A value of
0.05captures 5% of traces. For production deployments, use 1% to 5% to reduce trace volume and storage costs. spec.tracing.exporter-
Specifies the trace export protocol. Use
otlpfor OTLP over gRPC.
Apply the LLMInferenceService custom resource:
$ oc apply -f llminferenceservice-tracing.yamlWait for the
LLMInferenceServiceresource to be ready:$ oc get llmisvc traced-llm-inference -n llm-inference -wWait until
READY=True.Verify that the tracing configuration is applied:
$ oc get llmisvc traced-llm-inference -n llm-inference -o jsonpath='{.spec.tracing}'
Verification
Verify that the
LLMInferenceServiceresource showsREADY=True:$ oc get llmisvc traced-llm-inference -n llm-inferenceVerify that the scheduler and vLLM pods are running:
$ oc get pods -n llm-inferenceAll pods show
Runningstatus.
The configuration uses parentbased_traceidratio sampling with a 5% sampling rate (samplerArg: "0.05"). This balances observability with trace volume and storage costs. For higher-traffic production deployments, consider reducing the sampling rate to 1-2%. For more information, see Configure distributed tracing sampling rates.
Next steps
10.8.5. Distributed tracing sampling strategies Copy linkLink copied to clipboard!
OpenTelemetry sampling strategies control what percentage of traces are captured and stored. Choosing the right sampling approach balances observability coverage with performance overhead and storage costs.
Understanding sampling strategies helps you configure appropriate trace capture rates for development and production environments.
10.8.5.1. Why sample traces Copy linkLink copied to clipboard!
Sampling reduces the volume of trace data without completely disabling observability:
- Performance impact
- Capturing every trace adds CPU overhead for span creation, serialization, and network export. Sampling reduces this overhead proportionally.
- Storage costs
- Storing all traces in high-traffic environments requires significant object storage capacity. Sampling reduces storage requirements and costs.
- Network overhead
- Exporting traces to the OpenTelemetry Collector consumes network bandwidth. Sampling reduces outbound traffic from inference pods.
- Query performance
- Searching through millions of traces degrades Jaeger UI responsiveness. Sampling keeps trace volume within manageable limits.
10.8.5.2. Sampling strategies Copy linkLink copied to clipboard!
OpenTelemetry supports multiple sampling strategies, each suited to different use cases.
10.8.5.2.1. Always-on sampling Copy linkLink copied to clipboard!
Always-on sampling captures 100% of traces.
- Use case
- Development, debugging, and low-traffic environments where complete observability is required.
- Performance impact
- High storage and network overhead. All inference requests generate trace data. For low request volumes, the performance overhead might be acceptable.
- Configuration
tracing: sampler: parentbased_always_on
10.8.5.2.2. Probabilistic sampling Copy linkLink copied to clipboard!
Probabilistic sampling captures a configurable percentage of traces based on trace ID hash.
- Use case
- Production environments with moderate traffic where statistical sampling provides sufficient coverage.
- Sampling rate
-
Configured as a decimal between 0.0 and 1.0. For example,
0.1means 10% of traces are sampled. - Consistent sampling
- The same trace ID always produces the same sampling decision, ensuring complete traces (not partial).
- Configuration
tracing: sampler: "parentbased_traceidratio" samplerArg: "0.1"
10.8.5.2.3. Parent-based sampling Copy linkLink copied to clipboard!
Parent-based samplers make sampling decisions based on whether the parent span was sampled:
parentbased_always_on- If the parent span was sampled, this span is sampled. If there is no parent span, the trace is always sampled.
parentbased_always_off- If the parent span was sampled, this span is sampled. If there is no parent span, the trace is not sampled.
parentbased_traceidratio- If the parent span was sampled, this span is sampled. If there is no parent span, probabilistic sampling is used based on trace ID.
This ensures trace completeness across distributed components.
10.8.5.3. Coordinating sampling across components Copy linkLink copied to clipboard!
Both the inference scheduler and vLLM should use the same sampling strategy and rate to ensure trace completeness:
spec:
tracing:
sampler: "parentbased_traceidratio"
samplerArg: "0.05"
Mismatched sampling rates can result in incomplete traces where some spans are missing.
Additional resources
10.8.6. Configure distributed tracing sampling rates Copy linkLink copied to clipboard!
Configure OpenTelemetry trace sampling rates to balance observability needs with performance overhead and storage costs. Probabilistic sampling reduces trace volume in production deployments while maintaining statistical coverage.
Prerequisites
- You understand distributed tracing sampling strategies. For more information, see Distributed tracing sampling strategies.
-
You have deployed an
LLMInferenceServiceresource with distributed tracing enabled. - You have installed the OpenShift CLI (`oc`).
- You have cluster administrator access.
Configure the scheduler and vLLM components with the same sampling settings. Different settings can produce incomplete traces with missing spans.
Procedure
Choose a sampling strategy for your environment:
-
Development and testing: Use
parentbased_always_onto sample all traces. -
Production: Use
parentbased_traceidratiowith an initial sampling rate of 1% to 5%.
-
Development and testing: Use
Save the following YAML to a file named
llminferenceservice-tracing.yaml. Update theLLMInferenceServiceresource to use probabilistic sampling. The following example configures a 5% sampling rate:apiVersion: serving.kserve.io/v1alpha2 kind: LLMInferenceService metadata: name: traced-llm-inference namespace: llm-inference spec: tracing: exporterEndpoint: "http://tempo-tracing:4317" sampler: "parentbased_traceidratio" samplerArg: "0.05" exporter: "otlp"Apply the configuration:
$ oc apply -f llminferenceservice-tracing.yamlMonitor trace volume and adjust the sampling rate as needed:
Check Tempo storage usage:
$ oc exec -n tempo-system <tempo_pod> -- df -hwhere:
__<tempo_pod>__- Specifies the name of the Tempo pod.
- In the Jaeger UI, review the number and distribution of sampled traces.
-
Adjust the
samplerArgvalue based on observed trace volume.
Verification
Confirm that the sampling configuration is present in the
LLMInferenceServiceresource:$ oc get llminferenceservice traced-llm-inference -n llm-inference -o yaml-
Verify that the
spec.tracing.samplerfield is set toparentbased_traceidratioand that thespec.tracing.samplerArgfield is set to"0.05". - Generate inference requests and confirm that traces appear in the tracing interface at approximately the configured sampling rate.
Each sampled trace adds approximately 1-2 KB of data and minimal CPU overhead for trace context propagation. Monitor vLLM and scheduler CPU and memory usage when enabling tracing.
Additional resources
10.8.7. Verify distributed tracing deployment Copy linkLink copied to clipboard!
Verify that distributed tracing is working correctly by generating test inference traffic and viewing traces in Jaeger UI. Successful verification confirms that traces flow end-to-end from the inference components to Tempo storage.
Prerequisites
- You have deployed distributed tracing infrastructure
-
The
LLMInferenceServicewith tracing enabled showsREADY=True - Jaeger UI is accessible
Procedure
Send a test inference request to generate trace data:
$ SERVICE_URL=$(oc get llmisvc traced-llm-inference -n llm-inference \ -o jsonpath='{.status.url}') $ curl -X POST "${SERVICE_URL}/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen/Qwen2.5-7B-Instruct", "messages": [{"role": "user", "content": "What is Kubernetes?"}], "max_tokens": 100 }'NoteIf you configured trace sampling, send multiple requests to ensure at least one trace is captured. The number of requests needed is
1 / sample_rate. For example, with a 5% sample rate, send at least 20 requests to see a trace in Jaeger UI.Access the Jaeger UI by using port forwarding:
$ oc port-forward -n tempo-system svc/tempo-llmd-query-frontend 16686:16686-
Open a web browser to
http://localhost:16686. Search for traces:
-
In the Service dropdown, select
inference-server-decodeorgateway-api-inference-extension. - Set the Lookback time to Last 15 minutes.
- Click Find Traces.
-
In the Service dropdown, select
Examine a trace to verify end-to-end spans:
- Click a trace from the search results.
Verify the trace has the following spans:
- Scheduler span showing request routing
- vLLM span showing model inference
- Check that all spans share the same Trace ID.
- Verify span attributes include service names.
Verify trace context propagation:
- Expand each span in the trace view.
- Verify parent-child relationships between spans.
- Confirm span timing data is accurate.
10.8.8. Troubleshoot common distributed tracing issues Copy linkLink copied to clipboard!
Diagnose and resolve common issues with distributed tracing for Distributed Inference with llm-d deployments. This reference covers the most frequently encountered problems and their solutions.
10.8.8.1. No traces appearing in Jaeger UI Copy linkLink copied to clipboard!
Symptoms:
- Inference requests succeed but no traces appear in Jaeger UI
- Jaeger UI shows no services or traces
Diagnosis:
Check Tempo logs for receiver errors:
$ oc logs -n tempo-system -l app.kubernetes.io/name=tempo-monolithic | grep -i errorVerify the
spec.tracingconfiguration:$ oc get llmisvc traced-llm-inference -n llm-inference -o yaml | grep -A 4 tracing:Check network connectivity from vLLM to Tempo:
$ oc exec -n llm-inference <vllm-pod> -- \ curl -v http://tempo-tracing:4317
Resolution:
-
If the
spec.tracingconfiguration is missing, update the LLMInferenceService custom resource with the correct tracing parameters. - If network connectivity fails, check NetworkPolicy resources and ensure Tempo is running.
10.8.9. Distributed tracing sampling parameters Copy linkLink copied to clipboard!
OpenTelemetry sampling parameters control which traces an LLMInferenceService resource records and exports, enabling you to manage trace volume across Distributed Inference with llm-d components.
10.8.9.1. sampler field Copy linkLink copied to clipboard!
| Sampler value | Description | Use case |
|---|---|---|
|
| Samples 100% of traces. | Development, debugging, low-traffic environments. |
|
| Does not sample any traces. | Temporarily stop trace collection without removing the tracing configuration. |
|
| Samples based on trace ID hash (probabilistic). | Production environments requiring consistent sampling. |
|
| Always samples if parent span is sampled, otherwise always samples. | Ensures complete traces when distributed tracing spans services. |
|
| Always samples if parent span is sampled, otherwise uses traceidratio. | Production environments with consistent sampling across services. |
Use parentbased_traceidratio for production Distributed Inference with llm-d deployments to ensure consistent sampling decisions across scheduler and vLLM components.
10.8.9.2. samplerArg field Copy linkLink copied to clipboard!
For traceidratio and parentbased_traceidratio samplers:
| Value | Sampling rate | Description |
|---|---|---|
|
| 100% | Samples all traces. |
|
| 50% | Samples approximately 1 in 2 traces. |
|
| 10% | Samples approximately 1 in 10 traces. |
|
| 1% | Samples approximately 1 in 100 traces. |
|
| 0.1% | Samples approximately 1 in 1,000 traces. |
|
| 0% | Does not sample any traces. |
Format: Decimal value between 0.0 and 1.0 (inclusive).
10.8.9.3. Configuration example Copy linkLink copied to clipboard!
The following example configures a 5% parent-based sampling rate in the spec.tracing section of an LLMInferenceService custom resource:
spec:
tracing:
sampler: "parentbased_traceidratio"
samplerArg: "0.05"
Additional resources