Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • Guided learning
      Receive custom learning paths powered by our AI assistant.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

Trace Kubernetes resources for llm-d model serving

LLM inference on Kubernetes: What actually gets created when you deploy a model on Red Hat AI

August 5, 2026
Alexa Griffith
Related topics:
Artificial intelligenceAI inferenceKubernetes
Related products:
Red Hat AI InferenceRed Hat AI

    Red Hat AI Inference on Amazon EKS: Exploring the Kubernetes resources covered platform installation. After setup, deploying an inference service on Red Hat AI involves submitting a YAML file and letting the controller manage the underlying infrastructure.

    In this post, we deploy a model twice—first as a basic inference workload without routing, and then with the llm-d router block enabled. We trace the core Kubernetes resources created in both configurations to demonstrate how the platform sets up model serving and lays the foundation for intelligent routing.

    Deploying an inference service

    The gateway and controller pods are platform components that handle inference requests, and they are already running from the platform setup in part 1:

    kubectl get deployment -n redhat-ods-applications
    NAME                         READY
    inference-gateway-istio      1/1
    llmisvc-controller-manager   1/1

    Gateway

    The gateway handles external traffic through a load balancer. This example runs on Amazon Elastic Kubernetes Service (EKS) and uses an Amazon Web Services (AWS) Elastic Load Balancer, though any Gateway API-compatible gateway will work.

    Controller

    The controller reconciles our inference resources. We will configure and create our inference resources from an LLMInferenceService YAML. LLMInferenceService is the KServe custom resource that defines an inference service. The KServe controller reconciles this configuration into all the resources needed to serve the model consistently and at scale.

    Note

    KServe has two model-serving custom resources. InferenceService is the original, built for predictive (traditional machine learning) models and basic large language model (LLM) use cases, while LLMInferenceService is purpose-built for LLMs, adding capabilities and fields for intelligent (llm-d) routing, disaggregated prefill/decode, and Gateway API integration. This post uses LLMInferenceService throughout.

    First, we deploy a simple LLMInferenceService, with no router block (the llm-d component) defined.

    apiVersion: serving.kserve.io/v1alpha2
    kind: LLMInferenceService
    metadata:
      name: test
      namespace: llm-test
    spec:
      model:
        uri: hf://Qwen/Qwen2.5-0.5B-Instruct
        name: Qwen/Qwen2.5-0.5B-Instruct
      replicas: 2
      template:
        containers:
        - name: main
          resources:
            limits:
              nvidia.com/gpu: "1"
        imagePullSecrets:
        - name: rhai-pull-secret

    We have defined the following fields:

    • Model: Qwen 2.5 (0.5B), pulled from Hugging Face. The model.name field is used by clients in OpenAI API requests ({"model": "Qwen/Qwen2.5-0.5B-Instruct"}).
    • Replicas: Deploy two identical vLLM pods, each with one GPU.
    • Containers: Container name is a required value, and the name main is the convention for a single-container pod.
    • Resources: Each pod requests 1 GPU from Kubernetes.

    Apply the YAML in our test namespace:

    kubectl apply -f test-deploy.yaml
    llminferenceservice.serving.kserve.io/test created

    With the kubectl tree tool, we can view all the resources created after running kubectl apply, as shown in Figure 1:

    kubectl tree llminferenceservice test -n llm-test
    LLMInferenceService/test
    ├─Deployment/test-kserve
    │ └─ReplicaSet/test-kserve-rs
    │   ├─Pod/test-kserve-1
    │   └─Pod/test-kserve-2
    ├─Secret/test-kserve-self-signed-certs
    └─Service/test-kserve-workload-svc
      └─EndpointSlice/test-kserve-workload-svc-eps
    Tree structure branching from LLMInferenceService into Serving the model (Deployment, ReplicaSet, two pods, workload Service, EndpointSlice) and Identity and security (TLS Secret).
    Figure 1: The resources KServe creates for an LLMInferenceService with no router block, grouped into Serving the model (Deployment, ReplicaSet, two vLLM pods, workload Service and EndpointSlice) and Identity and security (the self-signed TLS Secret).

    Note on names

    To keep things readable, the resource names in this post are simplified. Pods managed by a ReplicaSet actually carry a template hash and a random suffix (for example, test-kserve-7bbcc796fb-gnhbx).

    Let's walk through each of these components.

    Serving the model

    Each LLMInferenceService consists of a Deployment with ReplicaSets and Pods, and a Service with an EndpointSlice configuration.

    In Kubernetes, a Deployment manages a ReplicaSet, and the ReplicaSet manages the state of the pods (Figure 2).

    Flowchart showing a Deployment declaring desired state, pointing to a ReplicaSet keeping replicas running, pointing to two vLLM pods.
    Figure 2: A Deployment manages a ReplicaSet, and the ReplicaSet keeps the desired number of vLLM pods running.

    KServe creates a deployment resource (Deployment/test-kserve) that manages two (replicas: 2) of our model-serving pods through a single ReplicaSet (test-kserve-rs). A ReplicaSet is the Kubernetes controller that keeps the model available by managing the number of running pods.

    kubectl get pod -n llm-test -l kserve.io/component=workload
    NAME            READY   STATUS    RESTARTS
    test-kserve-1   1/1     Running   0
    test-kserve-2   1/1     Running   0

    Each pod:

    • Runs the vLLM inference engine (registry.redhat.io/rhaii/vllm-cuda-rhel9).
    • Is allocated 1 GPU (nvidia.com/gpu: "1").
    • Serves an OpenAI-compatible API on port 8000, so any OpenAI client or tool is compatible.
    • Exposes vLLM's Prometheus metrics on the same port (queue depth, KV cache usage, token throughput, latency, and more), which the scheduler will scrape once we add llm-d.
    • Is automatically tagged by KServe with kserve.io/component=workload.

    Service

    The inference workload’s Service function is to provide the model pods with a single stable ClusterIP address. Pods can restart and scale up or down without affecting the overall Service, though each restart assigns a new IP address to the pod. To address this possibility, the workload Service exposes a single internal address that doesn’t change (ClusterIP). An EndpointSlice stays in sync with the IPs of the ready pods and forwards incoming requests to an available pod IP.

    kubectl get svc test-kserve-workload-svc -n llm-test
    NAME                       TYPE        CLUSTER-IP      PORT(S)
    test-kserve-workload-svc   ClusterIP   172.20.19.153   8000/TCP
    kubectl get endpoints test-kserve-workload-svc -n llm-test
    
    NAME                       ENDPOINTS
    test-kserve-workload-svc   10.11.1.129:8000,10.11.1.223:8000

    Note on serving inference at scale

    With two replicas, round-robin across the pods works fine. As traffic grows, an even split stops being enough: once routing has to account for which pod has spare capacity or already has the relevant data cached, you need routing built for LLMs. That is the job of the scheduler, which the router Deployment runs.

    Let's deploy an LLMInferenceService with intelligent routing.

    Adding llm-d

    Red Hat AI Inference implements the intelligent routing layer using llm-d, a Kubernetes-native distributed inference framework that routes requests to model servers such as vLLM.

    We can configure llm-d routing by defining a router block.

    router:
      scheduler:
        template:
          containers:
          - name: main
            imagePullSecrets:
            - name: rhai-pull-secret
      route: {}
      gateway: {}

    Add the router block to the LLMInferenceService and reapply.

    apiVersion: serving.kserve.io/v1alpha2
    kind: LLMInferenceService
    metadata:
      name: test
      namespace: llm-test
    spec:
      model:
        uri: hf://Qwen/Qwen2.5-0.5B-Instruct
        name: Qwen/Qwen2.5-0.5B-Instruct
      replicas: 2
    
      # Router configuration (scheduler, route, gateway)
      router:
        scheduler: 
          template:
            imagePullSecrets:
            - name: rhai-pull-secret
        route: {}
        gateway: {}
    
      # Workload configuration (vLLM pods)
      template:
        containers:
        - name: main # vLLM container (needs GPU)
          resources:
            limits:
              nvidia.com/gpu: "1"
    kubectl apply -f test-deploy.yaml
    llminferenceservice.serving.kserve.io/test configured

    When the llmisvc-controller-manager (Red Hat's controller that extends KServe) registers the router field, it creates the llm-d resources in a set order, as shown in Figure 3.

    Three stages showing stage 1 Model server for pod serving, stage 2 llm-d routing layer for intelligent routing, and stage 3 External entry point attached to gateway.
    Figure 3: The three stages the controller builds in order, the model server (always created), the llm-d routing layer (triggered by the router block), and the external entry point (triggered by router.gateway), showing what each stage adds.

    The controller logs from our deployment show the following sequence:

    {"msg": "Reconciling Workload"}
    {"msg": "Reconciling Router"}
    {"msg": "Reconciling Scheduler"}
    {"msg": "Reconciling HTTPRoute"}
    {"msg": "Using InferencePool v1 API for HTTPRoute"}

    Now run kubectl tree again to see everything the router configuration added.

    kubectl tree llminferenceservice test -n llm-test
    LLMInferenceService/test
    ├─Deployment/test-kserve
    │ └─ReplicaSet/test-kserve-rs
    │   ├─Pod/test-kserve-1
    │   └─Pod/test-kserve-2
    ├─Deployment/test-kserve-router-scheduler
    │ └─ReplicaSet/test-kserve-router-scheduler-rs
    │   └─Pod/test-kserve-router-scheduler-1
    ├─DestinationRule/test-kserve-scheduler
    ├─DestinationRule/test-kserve-shadow-svc
    ├─DestinationRule/test-kserve-workload-svc
    ├─HTTPRoute/test-kserve-route
    ├─InferencePool/test-inference-pool
    ├─InferencePool/test-inference-pool
    │ └─Service/test-inference-pool-ip
    │   └─EndpointSlice/test-inference-pool-ip-eps

    Note the tree lists InferencePool/test-inference-pool twice; this is not a duplicate. llm-d registers the pool under two API versions (the generally available inference.networking.k8s.io/v1 and the older inference.networking.x-k8s.io/v1alpha2), and the HTTPRoute references the v1 version, which is why the live backing Service and EndpointSlice hang off that entry.

    Grouped by function, here is the updated resource tree (Figure 4).

    Hierarchy diagram of LLMInferenceService resources grouped into four categories: Serving the model, Routing (llm-d), Traffic policy (Istio), and Identity and security.
    Figure 4: Dependency diagram: the LLMInferenceService and the resources it creates, grouped by function into Serving the model, Routing (llm-d), Traffic policy (Istio), and Identity and security.

    Adding llm-d keeps the base components of our first inference service and adds:

    • The scheduler Deployment and pod, which decides which model pod each request should go to.
    • The InferencePool, the group of model pods the scheduler can choose from.
    • The HTTPRoute, which routes matching requests to a backend (a Service, or here an InferencePool) which maps to internal services, pods, or other workloads.
    • DestinationRule resources, which set the traffic policy (connection limits, retries, encryption) between components.
    • The EPP Service, which gives the scheduler a stable in-cluster address.
    • RBAC resources (Role, RoleBinding, ServiceAccount), the scheduler's identity and read-only permissions.
    • The Transport Layer Security (TLS) Secret, the self-signed certificate that encrypts traffic between components.

    These additional resources allow us to route requests to a pod using scores based on metrics like queue depth and cache locality, as compared in Figure 5.

    Comparison contrasting standalone KServe round-robin Service routing with KServe plus llm-d EPP scheduler intelligent Gateway routing.
    Figure 5: Side-by-side comparison: Standalone KServe, where a Service round-robins across the vLLM pods, next to KServe with llm-d, where the gateway asks the EPP scheduler which pod to use, the scheduler returns the chosen pod, and the gateway forwards the request, with HTTPRoute and InferencePool acting as configuration.

    Router configurations

    Now that we can see everything created via the router configuration, let's walk through the significance of each setting. Recall that the router configuration contains three main components: scheduler, route, and gateway, as illustrated in Figure 6.

      router:
        scheduler:
          template:
            containers:
            - name: main
            imagePullSecrets:
            - name: rhai-pull-secret
        route: {}
        gateway: {}
    • scheduler creates the scheduler pod, the pool of backend model pods it chooses from (the InferencePool), and the read permissions it needs.
    • route creates the routing rules that map external request paths to that pool (the HTTPRoute).
    • gateway attaches those routing rules to the platform's shared gateway, making the model reachable from outside the cluster.
    Diagram mapping router YAML subfields (scheduler, route, and gateway) to the specific Kubernetes resources they generate.
    Figure 6: The router block’s subfields and what each field creates: the scheduler pod, the HTTPRoute, and the gateway attachment.

    Note

    Leaving the route subfield empty (for example, route: {}) tells KServe to use sensible defaults (the full set of options is in the LLMInferenceService configuration guide).

    Up next: Deep dive into endpoint picking and traffic flow

    With the LLMInferenceService deployed and the router block configured, the controller has generated all the core workloads, routing specs, traffic policies, and permissions required by the platform.

    In a follow-up article, we'll take a closer look at how these generated resources process live traffic. We will explore the Endpoint Picker (EPP) scheduler and Envoy ext-proc mechanism, examine HTTPRoute URL rewriting, break down the RBAC security model, and follow an inference request end-to-end from gateway to vLLM pod.

    Learn more

    • Combining KServe and llm-d for optimized generative AI inference (Red Hat Developer)
    • LLMInferenceService configuration guide (KServe docs)
    • Understanding LLMInferenceService (KServe docs)
    • llm-d (the routing project)

    Related Posts

    • Red Hat AI Inference on Amazon EKS: Exploring the Kubernetes resources

    • Batch inference on OpenShift AI with llm-d: Architecture, integration, and workflows

    • Designing distributed AI inference: Core concepts and scaling dimensions

    • llama.cpp vs. vLLM: Choosing the right local LLM inference engine

    • How speculative decoding delivers faster LLM inference

    • Why vLLM is the best choice for AI inference today

    Recent Posts

    • Trace Kubernetes resources for llm-d model serving

    • Testing modern hash table designs in OVN and OVS

    • AutoRAG: Optimizing RAG for small models

    • One kernel feature, 93% system throughput gone: A Red Hat Enterprise Linux 10.2 kernel regression and how to mitigate it

    • Kafka Monthly Digest: July 2026

    What’s up next?

    Learning Path Get started with vLLM feature share

    Get started with vLLM

    Learn how to compress, serve, and benchmark LLMs with vLLM.
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.