AI Inference Routing with the F5 Endpoint Picker¶
Overview¶
BIG-IP Next for Kubernetes (BNK) version 2.4 adds native support for the Kubernetes Gateway API Inference Extension (GAIE) through the F5 Endpoint Picker (EPP). This feature enables intelligent, dynamic AI load balancing for Large Language Model (LLM) inference workloads.
When client requests arrive, the Traffic Management Microkernel (TMM) consults an F5 Endpoint Picker (EPP) instance to determine the optimal backend endpoint prior to routing traffic to a model-server pod. The EPP evaluates candidate pods using real-time dynamic metrics, selecting the endpoint that offers the lowest time-to-first-token (TTFT) and maximum overall request throughput.
How BNK Addresses AI Inference Routing¶
BNK introduces a declarative, per-pool EPP lifecycle managed by a dedicated Custom Resource Definition (CRD): F5EPP. Instead of manually maintaining an EPP Deployment, Service, ConfigMap, ServiceAccount, and RBAC configuration for each inference pool, administrators define a single F5EPP Custom Resource (CR) per pool. The BNK controller automatically renders, provisions, and reconciles the complete EPP infrastructure stack.
Declarative Workflow¶
Deploy an
F5EPPCR: Define the targetInferencePooland specify the underlying inference engine (vllm,dynamo, orsglang). All remaining parameters default to sensible, engine-aware configurations generated by the controller.Controller Reconciliation: The BNK controller reconciles the
F5EPPresource, generates the per-pool EPP stack, maintains convergence, and exposes operational rollout status on the CR.Dynamic Consultation: TMM performs an
ext_procgRPC consult to the pool-specific EPP for every incoming request matching anHTTPRoutereferencing the targetedInferencePool.
Endpoint Selection Criteria¶
The EPP calculates pod selection scores based on five core telemetry vectors:
Queue Depth: Number of pending requests queued for processing on each endpoint.
Running Requests: Active in-flight requests currently being processed by each endpoint.
KV-Cache Utilization: Percent occupancy of each endpoint’s key-value cache memory.
Prompt-Prefix Affinity: Shared prompt-prefix cache locality to optimize cache re-use.
Engine-Specific Metrics: Engine-native metrics exported by vLLM, NVIDIA Dynamo, or SGLang.
Key Benefits¶
Native GAIE Conformance: Conforms to the core behaviors of the standard Kubernetes Gateway API Inference Extension. See GAIE Conformance for the supported behaviors per API object.’.
Automated Operational Lifecycle: Replaces multi-resource YAML manifests with a unified, declarative CR.
Strict Per-Pool Isolation: Dedicated EPP instances and scheduling profiles per
InferencePool.Engine-Aware Presets: Automatic selection of Prometheus metric signatures, event transport mechanisms, and lifecycle plugins based on specified engine types (
vllm,dynamo, orsglang).Optimized Performance: Substantially reduces TTFT while maximizing total system throughput via dynamic load and cache steering.
Architecture Overview¶
F5 Components¶
Component |
Architecture Role & Responsibilities |
|---|---|
TMM (Traffic Management Microkernel) |
Inference Gateway Data Plane. Terminates incoming client connections, executes gRPC |
CNE Controller |
BNK Control Plane Pod. Reconciles |
F5 Endpoint Picker (EPP) |
Per-Pool Load Balancing Stack. Receives gRPC |
|
Declarative Authoring Interface. Configures engine type, target pool, tokenizer options, pod scheduling constraints, and picker tuning parameters. |
Non-F5 / External Components¶
Component |
Architecture Role & Responsibilities |
|---|---|
Kubernetes Gateway API Standard. Defines entry points and routing rules. An |
|
GAIE Resource Binding. Binds backend serving pods ( |
|
Model-Server Engines |
LLM Execution Frameworks (vLLM, NVIDIA Dynamo, SGLang). Serve models and expose |
Request Path Lifecycle¶
[ Client ]
│ (1. POST /v1/chat/completions)
▼
[ Gateway VIP / TMM Data Plane ]
│
│ (2. Match HTTPRoute -> backendRef: InferencePool; gRPC ext_proc consult)
▼
[ F5 Endpoint Picker (EPP) ] ◄── (Scrapes /metrics & subscribes to KV events) ── [ Candidate Model Pods ]
│
│ (3. Evaluate queue depth, running requests, KV-cache & prefix affinity -> Return best pod IP)
▼
[ Gateway VIP / TMM Data Plane ]
│
│ (4. Forward request to chosen backend model pod)
▼
[ Selected Model-Server Pod ]
Request Flow Execution Steps¶
Client Request Ingestion: A client sends an HTTP request (e.g.,
POST /v1/chat/completions) to the Gateway VIP.Route Matching & EPP Consult: TMM matches the request against an
HTTPRouteconfigured with a backend reference (backendRef) pointing to anInferencePool. TMM initiates an asynchronousext_procgRPC consult to the pool’s dedicated EPP service.Real-Time Endpoint Scoring: The EPP calculates real-time fitness scores for all candidate pods using collected Prometheus
/metricsand real-time KV-cache events. It selects and returns the optimal endpoint IP.Proxy Forwarding & Failure Handling: TMM proxies the client payload directly to the selected model-server pod.
Failure Mode Enforcement: If the EPP consultation times out or errors, TMM evaluates
InferencePool.spec.endpointPickerRef.failureMode:FailOpen: Traffic is forwarded to backends using standard round-robin/fallback routing.FailClose(Default GAIE behavior): The request is aborted and a failure response is returned to the client.
GAIE Conformance¶
BNK conforms to the following behaviors defined by the Kubernetes Gateway API Inference Extension (GAIE).
InferencePool¶
Reports an
Acceptedstatus condition once created.Reports per-parent
ResolvedRefsconditions correctly — they appear when anHTTPRouteon a Gateway references the pool and clear when noHTTPRoutereferences it anymore (including across multiple/shared Gateways).Routes traffic only to endpoints selected by the pool’s configured endpoint picker (EPP).
HTTPRoute¶
Reports correct
Accepted/ResolvedRefsconditions when it references a validInferencePool.Reports
Accepted=True/ResolvedRefs=Falsewhen it references anInferencePoolthat does not exist, and correctly blocks traffic to it.Handles
backendRefport on anInferencePoolcorrectly whether the port is unspecified, matching, or non-matching (the port is correctly ignored, per spec).Two
HTTPRoutes on two different Gateways can each route independently to their ownInferencePool.
Gateway¶
Sends traffic only to the endpoint(s) selected by the EPP, for both single- and multi-pod selections.
Correctly reports which endpoint actually served each request.
When the endpoint picker is unavailable, continues forwarding traffic (fails open) rather than dropping all requests, though individual requests may still fail depending on backend requirements.
Prerequisites and Cluster Preparation¶
Verify and fulfill all requirements listed in the matrix below prior to creating F5EPP instances.
Verification Matrix¶
# |
Requirement |
Scope / Target Engines |
Mandatory Output / Check |
|---|---|---|---|
1 |
BNK installed with Gateway & Inference features |
All Deployments |
TMM & CNE Controller pods in |
2 |
Gateway API & GAIE CRDs installed (v1.4.0) |
All Deployments |
|
3 |
Provisioned |
All Deployments |
Gateway status reports |
4 |
Model pods exposing |
All Deployments |
Model pods match pool selector and output metrics |
5 |
EPP namespace scoping enabled on |
All Deployments |
EPP |
6 |
Reachable NATS Server |
NVIDIA Dynamo Backends |
Accessible NATS URI (e.g., |
7 |
ZMQ KV-Cache event streaming enabled |
vLLM & SGLang Backends |
Pod engine processes configured with ZMQ event publishing |
8 |
Pre-staged PVC / Tokenizer Volume |
Local / Air-Gapped Tokenizers |
Bound PVC available in target pool namespace |
Step 1: Verify BNK Installation¶
Confirm that TMM and control-plane components are fully operational:
kubectl get pods -o wide -n <bnk-namespace>
Requirement: All BNK pods must report status Running with all containers READY.
Step 2: Install or Verify GAIE CRDs¶
BNK 2.4 integrates with standard GAIE specifications built against GAIE v1.4.0. Apply the official v1.4.0 manifests to ensure API compatibility:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v1.4.0/manifests.yaml
Verify that the InferencePool CRD is registered:
kubectl get crd inferencepools.inference.networking.k8s.io
Note: GAIE CRDs (including optional
InferenceObjectiveandInferenceModelRewriteCRDs) are not packaged inside the default BNK installation bundle and must be installed separately.
Step 3: Verify Gateway Provisioning¶
Ensure the target Gateway instance has successfully bound to cluster networking resources:
kubectl get gatewayclass
kubectl get gateway -n <gateway-namespace>
Expected Output:
NAME CLASS ADDRESS PROGRAMMED AGE
inference-gateway gateway-class 10.10.10.100 True 34m
Important: The
PROGRAMMEDcolumn must displayTrue. TMM cannot attach inference routing profiles to unprogrammed Gateways.
Step 4: Verify Backend Model-Server Pods¶
Ensure serving pods exist in the target namespace and match the label selector that will be defined in the InferencePool.
kubectl -n <pool-namespace> get pods -l <your-selector-labels>
Each serving pod must expose an active /metrics endpoint compatible with the declared engine.
Step 5: Prepare Namespaces and Enable EPP Scope¶
The BNK controller automatically provisions EPP-related resources (Deployment, Service, ConfigMap, ServiceAccount, Role, RoleBinding) into namespaces hosting an F5EPP resource. You must explicitly authorize controller scope per namespace via the CNEInstance CR.
Namespace Co-Location Rule¶
The F5EPP CR, its corresponding InferencePool, and the backend serving pods must reside within the same Kubernetes namespace. Multi-tenant deployments across distinct namespaces are supported by listing each individual namespace in spec.eppNamespaces. Cross-namespace pool-to-pod references are strictly unsupported.
Configuration Steps¶
Create all intended target namespaces:
kubectl create namespace inference kubectl create namespace ns-a kubectl create namespace ns-b
Edit the active
CNEInstanceresource:kubectl edit cneinstance <cneinstance-name> -n <bnk-namespace>
Configure
spec.eppNamespaceswith target namespace names:apiVersion: k8s.f5.com/v1 kind: CNEInstance metadata: name: "f5-bnk-f5-cne-controller" namespace: f5-bnk spec: eppNamespaces: # ← Add these lines - inference # ← - ns-a # ← - ns-b # ← # ... rest of your existing configuration remains unchanged
Alternatively, grant the controller cluster-wide EPP RBAC through a
ClusterRole/ClusterRoleBindingby using the wildcard"All"value:spec: eppNamespaces: - "All"
Verify RBAC generation in target namespaces:
kubectl -n <pool-namespace> get role,rolebinding | grep epp
Constraints:
Leaving
spec.eppNamespacesempty or omitted disables EPP reconciliation cluster-wide.Adding new namespaces requires updating the
CNEInstancemanifest.
Step 6: (NVIDIA Dynamo Only) Provide a Reachable NATS Server¶
NVIDIA Dynamo backends emit KV-cache state updates over NATS. The NATS service endpoint must be provided via spec.natsURL upon F5EPP creation.
Verify NATS connectivity from the pool namespace:
kubectl -n <nats-namespace> get svc
Example URI: nats://nats.dynamo.svc.cluster.local:4222
Note: If NATS becomes unreachable at runtime, the EPP falls back to speculative cache tracking to prevent traffic interruption.
Step 7: (vLLM and SGLang Only) Publish KV-Cache Events on ZMQ¶
For vLLM and SGLang backends, KV-cache events are transferred via ZeroMQ (ZMQ). Transport configuration occurs automatically based on spec.engine. Model pods must be executed with ZMQ event publishing active on their designated output sockets.
vLLM: Enable the built-in KV-event publisher flag during container startup.
SGLang: Launch serving processes with KV-event publishing enabled.
Note: While event publishing is optional for baseline load balancing, omitting ZMQ causes the EPP to fallback to speculative cache tracking, reducing prefix-cache alignment accuracy.
Step 8: (Optional) Pre-stage a Local Tokenizer Volume¶
The EPP tokenizes input prompts to calculate prefix affinity. By default, tokenizers are downloaded dynamically from HuggingFace during pod startup. For persistent caching or air-gapped environments:
Create a PVC in the pool’s namespace and reference it from
spec.tokenizer.cacheClaim. The controller only mounts it — it never creates, resizes, or deletes storage.
If the claim cannot bind at all (misspelled name, no matching PV, misconfigured StorageClass), the EPP pod stays
PendingwithPodScheduled=False/Unschedulable. The scheduler’s message names the claim, and the F5EPP reports the pod-scheduling failure on itsAvailablecondition.
When using
spec.tokenizer.source: local, load the tokenizer files into the volume yourself at the path you set inspec.tokenizer.path, and make surespec.tokenizer.nameexactly matches the model your engine serves — a mismatch silently breaks cache matching.
kubectl -n <pool-namespace> get pvc
Private / Gated Models: For gated HuggingFace models on connected clusters, create a Kubernetes Secret containing your access token and reference it in
spec.tokenizer.hfTokenSecret.name. The secret default key istoken(override viaspec.tokenizer.hfTokenSecret.key).
Documentation Map¶
Refer to the following structured guide sequence when implementing AI inference routing:
Order |
Section / Document |
Description & Key Topics Covered |
|---|---|---|
1 |
Overview & Prerequisites (This Document) |
Architecture overview, request flows, and prerequisite cluster preparation. |
2 |
Step-by-step golden path setup ( |
|
3 |
Exhaustive API schema, default values, validation rules, and field limits. |
|
4 |
Advanced optimization parameters, score weighting, and transport options. |
|
5 |
Operational diagnostics using TMM |
|
6 |
Advanced GAIE routing policy configuration. |