Deploy on Intel GPUs with DRA

Adapt a DynamoGraphDeployment for Intel GPUs by building an XPU runtime image and allocating devices with Kubernetes Dynamic Resource Allocation.
View as Markdown

This tutorial adapts the aggregated vLLM deployment from Deploy with DGD to run on Intel GPUs. It focuses only on what changes for Intel XPU: cluster device support, the runtime image, and GPU allocation with Kubernetes Dynamic Resource Allocation (DRA).

The result is a two-document manifest:

  1. A ResourceClaimTemplate that requests an Intel GPU from the gpu.intel.com DeviceClass.
  2. A DynamoGraphDeployment (DGD) whose vLLM worker consumes that claim.

This tutorial follows the checked-in vLLM XPU DRA manifests. Dynamo also supports running SGLang on Intel XPU locally, but this tutorial stays with the Kubernetes path represented by the repository’s XPU deployment examples.

Before you begin

Complete the base Deploy with DGD tutorial first, or be familiar with its Frontend, worker, image, Secret, and podTemplate structure. You also need:

  • A Kubernetes 1.34 or later cluster with Intel GPU nodes and the resource.k8s.io/v1 DRA API.
  • The Intel resource drivers for Kubernetes installed with a DeviceClass named gpu.intel.com.
  • The Dynamo Platform installed in the cluster.
  • Docker, access to a container registry, and a local Dynamo checkout.

The Dynamo Platform Helm chart does not install the Intel GPU node driver or the Intel resource driver. Install the Intel device support before deploying the DGD. The Dynamo operator detects the resource.k8s.io/v1 API automatically; you do not need a Dynamo Helm flag to enable DRA.

1

Verify Intel GPU allocation support

Confirm that the cluster serves the DRA v1 API and that the Intel resource driver publishes the expected DeviceClass and device inventory:

$kubectl api-resources --api-group=resource.k8s.io | grep -E 'deviceclasses|resourceclaims|resourceslices'
$kubectl get deviceclass gpu.intel.com
$kubectl get resourceslices

Do not continue until gpu.intel.com exists and at least one ResourceSlice describes the Intel GPU nodes. Installing Dynamo alone does not create either resource.

2

Build the vLLM XPU runtime image

Dynamo does not publish a prebuilt Intel XPU runtime image. From the root of your Dynamo checkout, render the vLLM XPU Dockerfile, build it, and push it to a registry your cluster can pull from:

$export DYNAMO_VERSION="<version>"
$export XPU_IMAGE="registry.example.com/vllm-runtime-xpu:${DYNAMO_VERSION}"
$
$python3 container/render.py \
> --framework=vllm \
> --device=xpu \
> --target=runtime \
> --output-short-filename
$
$docker build --tag "${XPU_IMAGE}" --file container/rendered.Dockerfile .
$docker push "${XPU_IMAGE}"

Use the same Dynamo source revision for the XPU worker image and the Frontend image. Export the Frontend image and deployment namespace for the manifest:

$export NAMESPACE=dynamo-system
$export FRONTEND_IMAGE="nvcr.io/nvidia/ai-dynamo/vllm-runtime:${DYNAMO_VERSION}"

If the registry is private, create its image-pull Secret in ${NAMESPACE}. The operator can discover matching registry credentials in the namespace, as described in Deploy with DGD.

3

Create the model access Secret

This tutorial serves the public Qwen/Qwen3-0.6B model. The example worker still imports a Secret named hf-token-secret, so create it with an empty token. Replace the value for a gated or private model:

$kubectl create secret generic hf-token-secret \
> --namespace "${NAMESPACE}" \
> --from-literal=HF_TOKEN= \
> --dry-run=client -o yaml | kubectl apply -f -
4

Request an Intel GPU with DRA

Start qwen3-xpu.yaml with a ResourceClaimTemplate. The request selects one device from the gpu.intel.com class:

1apiVersion: resource.k8s.io/v1
2kind: ResourceClaimTemplate
3metadata:
4 name: qwen3-xpu-gpu
5spec:
6 spec:
7 devices:
8 requests:
9 - name: gpu
10 exactly:
11 deviceClassName: gpu.intel.com
12 count: 1

The ResourceClaimTemplate is a Kubernetes resource alongside the DGD, not a DGD field. A worker pod that references it receives its own generated ResourceClaim.

5

Attach the claim to the XPU worker

Add the DGD as the second YAML document. The Frontend does not need a GPU and uses the regular Dynamo vLLM runtime image. The worker uses the XPU image and connects the claim at two levels:

  • podTemplate.spec.resourceClaims attaches a claim generated from qwen3-xpu-gpu to the pod.
  • containers[].resources.claims grants the main container access to that claim.

The XPU worker also sets VLLM_TARGET_DEVICE=xpu. The --block-size 64 argument matches the checked-in Intel XPU deployment examples.

1---
2apiVersion: nvidia.com/v1beta1
3kind: DynamoGraphDeployment
4metadata:
5 name: qwen3-xpu
6spec:
7 components:
8 - name: Frontend
9 type: frontend
10 replicas: 1
11 podTemplate:
12 spec:
13 containers:
14 - name: main
15 image: ${FRONTEND_IMAGE}
16 - name: VllmWorker
17 type: worker
18 replicas: 1
19 podTemplate:
20 spec:
21 resourceClaims:
22 - name: gpu
23 resourceClaimTemplateName: qwen3-xpu-gpu
24 containers:
25 - name: main
26 image: ${XPU_IMAGE}
27 command:
28 - python3
29 - -m
30 - dynamo.vllm
31 args:
32 - --model
33 - Qwen/Qwen3-0.6B
34 - --block-size
35 - "64"
36 env:
37 - name: VLLM_TARGET_DEVICE
38 value: xpu
39 envFrom:
40 - secretRef:
41 name: hf-token-secret
42 resources:
43 claims:
44 - name: gpu
45 requests:
46 ephemeral-storage: 2Gi
47 workingDir: /workspace/examples/backends/vllm

Your complete qwen3-xpu.yaml now contains the ResourceClaimTemplate, the --- separator, and the DGD.

6

Apply the manifest

Expand the image variables, validate both resources with the API server, and apply them:

$envsubst < qwen3-xpu.yaml \
> | kubectl apply --namespace "${NAMESPACE}" --dry-run=server -f -
$
$envsubst < qwen3-xpu.yaml \
> | kubectl apply --namespace "${NAMESPACE}" -f -

The namespace passed to kubectl applies to both namespaced resources in the multi-document file.

7

Verify the DRA claim and deployment

Confirm that Kubernetes created and allocated the worker’s claim:

$kubectl get resourceclaimtemplate qwen3-xpu-gpu --namespace "${NAMESPACE}"
$kubectl get resourceclaims --namespace "${NAMESPACE}"
$kubectl get pods --namespace "${NAMESPACE}"

Then wait for the DGD:

$kubectl wait \
> --for=condition=Ready \
> dynamographdeployment/qwen3-xpu \
> --namespace "${NAMESPACE}" \
> --timeout=600s

If the worker remains pending, inspect the pod and claim:

$kubectl describe pod <worker-pod> --namespace "${NAMESPACE}"
$kubectl describe resourceclaim <claim-name> --namespace "${NAMESPACE}"
$kubectl get resourceslices

A missing gpu.intel.com class, no matching devices, or an unallocated claim indicates a cluster DRA/resource-driver problem rather than a DGD reconciliation problem.

8

Send a request

Port-forward the Frontend service:

$kubectl port-forward service/qwen3-xpu-frontend 8000:8000 \
> --namespace "${NAMESPACE}"

In another terminal, send a completion request:

$curl -s http://localhost:8000/v1/chat/completions \
> -H 'Content-Type: application/json' \
> -d '{
> "model": "Qwen/Qwen3-0.6B",
> "messages": [{"role": "user", "content": "Explain dynamic resource allocation."}],
> "max_tokens": 100
> }' | python3 -m json.tool
9

Clean up

Delete both resources from the same manifest:

$envsubst < qwen3-xpu.yaml \
> | kubectl delete --namespace "${NAMESPACE}" -f -

Extend the deployment

Once the aggregated deployment works, you can apply the same Intel-specific changes to other vLLM DGD patterns:

  • Give each GPU worker a DRA claim.
  • Keep VLLM_TARGET_DEVICE=xpu on every vLLM worker.
  • For disaggregated serving, set kv_buffer_device to xpu in the vLLM NIXL connector configuration.

See Disaggregated Serving for the DGD topology and Disaggregated Communication for the network requirements. Validate an aggregated deployment first so device allocation and the XPU runtime are known to work before you add KV transfer.