Skip to main content
FlexInfer docs

FlexInfer Configuration

This document describes all environment variables and configuration options for FlexInfer components.

Table of Contents


Controller Manager

The controller manager handles reconciliation of FlexInfer CRDs and manages the lifecycle of inference workloads.

VariableDefaultDescription
POD_NAMESPACEdefaultNamespace where controller resources are deployed
BENCHMARK_SERVICE_ACCOUNT-Service account used for benchmark pods. If not set, benchmark pods won't be created
ENABLE_WEBHOOKStrueEnable admission webhooks for CRD validation
METRICS_BIND_ADDRESS:8080Address for Prometheus metrics endpoint
HEALTH_PROBE_BIND_ADDRESS:8081Address for health and readiness probes
LEADER_ELECTfalseEnable leader election for HA deployments
DEFAULT_SHM_SIZE_LIMIT8GiDefault /dev/shm size limit for v1alpha2 model pods
DEFAULT_FLASH_LOADER_ENABLEDfalseEnable flash-loader init container by default for eligible v1alpha2 models
DEFAULT_FLASH_LOADER_IMAGEregistry.harbor.lan/flexinfer/flexinfer-flash-loader:latestDefault flash-loader image
DEFAULT_FLASH_LOADER_CONCURRENCY4Default flash-loader copy parallelism
DEFAULT_FLASH_LOADER_TMPFS_SIZE_LIMIT-Optional default tmpfs size limit for flash-loader staging volume
DEFAULT_FLASH_LOADER_BUFFER_KB4096Default flash-loader copy buffer size in KiB
DEFAULT_FLASH_LOADER_VERIFYfalseVerify copied files after flash-loader transfer
DEFAULT_FLASH_LOADER_EXCLUDE-Comma-separated flash-loader exclude patterns
FLEXINFER_OTEL_ENABLEDfalseEnable OpenTelemetry tracing export (manager + proxy + scheduler)
FLEXINFER_OTEL_SERVICE_NAMESPACE-Optional service.namespace attribute for exported spans
OTEL_EXPORTER_OTLP_ENDPOINTOTEL SDK defaultOTLP endpoint for tracing exporter (typically http://collector:4318)

Flash-loader defaults can be set globally through Helm at controller.runtime.flashLoader.*. Per-cache and per-model settings override those defaults in this order:

  1. Controller env defaults rendered from Helm.
  2. Matching v1alpha1 ModelCache.spec.flashLoader.
  3. v1alpha2 Model.spec.cache.flashLoader.

The v1alpha2 override is the highest-priority layer. Shared-GPU models with cache.strategy: Local auto-enable flash-loader unless an explicit flash-loader config says otherwise.

Backend Image Overrides

The controller uses these environment variables to override default backend container images:

VariableDefaultDescription
DEFAULT_BACKEND_IMAGE-Default image for NVIDIA GPUs (used if vendor-specific not set)
DEFAULT_BACKEND_IMAGE_NVIDIA-Ollama image for NVIDIA GPUs
DEFAULT_BACKEND_IMAGE_AMD-Ollama image for AMD GPUs
DEFAULT_BACKEND_IMAGE_INTEL-Ollama image for Intel GPUs
DEFAULT_MLC_LLM_IMAGE-MLC-LLM image for NVIDIA/default
DEFAULT_MLC_LLM_IMAGE_AMD-MLC-LLM image for AMD GPUs
DEFAULT_MLC_LLM_IMAGE_MAXWELL-MLC-LLM image for NVIDIA Maxwell GPUs (sm_52)
DEFAULT_LLAMA_CPP_IMAGE-llama.cpp image for NVIDIA/default
DEFAULT_LLAMA_CPP_IMAGE_AMD-llama.cpp image for AMD GPUs
DEFAULT_LLAMA_CPP_IMAGE_CPU-llama.cpp image for CPU-only inference
DEFAULT_COMFYUI_IMAGE-ComfyUI image for NVIDIA/default
DEFAULT_COMFYUI_IMAGE_AMD-ComfyUI image for AMD GPUs
DEFAULT_DIFFUSERS_IMAGE-Diffusers API image for NVIDIA/default
DEFAULT_DIFFUSERS_IMAGE_AMD-Diffusers API image for AMD GPUs
DEFAULT_VLLM_IMAGE-vLLM image for NVIDIA/default
DEFAULT_VLLM_IMAGE_AMD-vLLM image for AMD GPUs
FLEXINFER_QUANTIZER_GGUF_IMAGEghcr.io/flexinfer/quantizer:ggufGGUF quantizer job image for ModelCache.spec.quantization.format=GGUF
FLEXINFER_QUANTIZER_AWQ_IMAGEghcr.io/flexinfer/quantizer:awqAWQ quantizer job image for ModelCache.spec.quantization.format=AWQ
FLEXINFER_QUANTIZER_GPTQ_IMAGEghcr.io/flexinfer/quantizer:gptqGPTQ quantizer job image for ModelCache.spec.quantization.format=GPTQ
FLEXINFER_QUANTIZER_EXL2_IMAGEghcr.io/flexinfer/quantizer:exl2EXL2 quantizer job image for ModelCache.spec.quantization.format=EXL2
FLEXINFER_QUANTIZER_FP8_IMAGEghcr.io/flexinfer/quantizer:fp8FP8 quantizer job image for ModelCache.spec.quantization.format=FP8
FLEXINFER_MODEL_TOOLS_IMAGEghcr.io/flexinfer/model-tools:latestLightweight CPU-only image for ModelCache publish and publish-validator jobs; includes oras, safetensors, huggingface_hub, and FlexInfer helper scripts
FLEXINFER_PUBLISH_IMAGEFLEXINFER_MODEL_TOOLS_IMAGEOptional publish-job image override
FLEXINFER_VALIDATOR_IMAGEFLEXINFER_MODEL_TOOLS_IMAGEOptional pre-publish artifact validator image override
FLEXINFER_RUNTIME_IMAGE-Optional unified runtime image for quantization jobs and legacy validator fallback

Proxy

The proxy handles incoming inference requests, manages serverless scaling, and routes traffic to backend models.

VariableDefaultDescription
POD_NAMESPACEdefaultNamespace where proxy watches for ModelDeployments
PROXY_MAX_QUEUE_SIZE100Maximum number of requests that can be queued per model
PROXY_QUEUE_TIMEOUT60sHow long a request can wait in queue before timeout
PROXY_COLD_START_TIMEOUT60sDefault timeout waiting for a model to become ready after scale-up
PROXY_ROUTING_ENABLEDtrueEnable advanced routing (session affinity, prefix-based)
PROXY_ROUTING_EXPLICIT_KEY_MAX_LENGTH128Maximum accepted length for explicit cache keys (X-Flexinfer-Cache-Key, cache_key, cacheKey)
PROXY_ROUTING_SYSTEM_SEGMENT_MAX_LENGTH512Maximum canonicalized system-context segment length used for prefix keying
PROXY_ROUTING_DOCUMENT_SEGMENT_MAX_LENGTH256Maximum canonicalized document-context segment length used for prefix keying
PROXY_MAX_TOKENS_CLAMP_ENABLEDtrueClamp OpenAI max_tokens so requests leave prompt headroom within the resolved model context window
PROXY_MAX_TOKENS_CLAMP_PROMPT_RESERVE_TOKENS512Prompt-token reserve subtracted from the context window when clamping max_tokens
PROXY_VALIDATE_REQUESTSfalseEnable OpenAI request schema validation (validates required fields, field types, and value ranges)
PROXY_BACKOFF_ENABLEDfalseEnable exponential backoff with jitter for failed activations
PROXY_BACKOFF_MAX_RETRIES3Maximum retry attempts after initial activation failure
PROXY_BACKOFF_INITIAL_WAIT5sInitial wait time before first retry
PROXY_BACKOFF_MAX_WAIT30sMaximum wait time between retries
FLEXINFER_OTEL_ENABLEDfalseEnable OpenTelemetry tracing export for proxy requests
FLEXINFER_OTEL_SERVICE_NAMESPACE-Optional service.namespace attribute for proxy spans
OTEL_EXPORTER_OTLP_ENDPOINTOTEL SDK defaultOTLP endpoint for proxy trace export

Routing Configuration

Enable routing strategies via model annotations:

apiVersion: inference.flexinfer.ai/v1alpha2
kind: Model
metadata:
  name: my-model
  annotations:
    flexinfer.ai/routing: session-affinity  # or: prefix, least-loaded

Available strategies:

  • session-affinity: Route by session ID for KV-cache locality
  • prefix: Route by system prompt for shared prefix caching
  • least-loaded: Route to pod with fewest active connections
  • (default): Kubernetes Service round-robin

See docs/user/routing.md for detailed routing documentation.

Command Line Flags

FlagDefaultDescription
--port8080Port to listen for incoming requests
--log-levelinfoLog level: debug, info, warn, error

Scheduler Extender

The scheduler extender (flexinfer-sched) plugs into kube-scheduler as an extender to filter and score nodes.

VariableDefaultDescription
BENCHMARK_RESULTS_CONFIGMAPflexinfer-benchmark-resultsConfigMap containing benchmark results
SCHED_TPS_WEIGHT0.7Weight for tokens/sec score
SCHED_UTIL_WEIGHT0.2Weight for GPU utilization hint
SCHED_COST_WEIGHT0.1Weight for node “cost” hint
SCHED_CACHE_WEIGHT0.3Weight for KV-cache locality hint
FLEXINFER_OTEL_ENABLEDfalseEnable OpenTelemetry tracing export for filter/score requests
FLEXINFER_OTEL_SERVICE_NAMESPACE-Optional service.namespace attribute for scheduler spans
OTEL_EXPORTER_OTLP_ENDPOINTOTEL SDK defaultOTLP endpoint for scheduler trace export

The scheduler emits scheduler.filter and scheduler.score spans and propagates W3C Trace Context from incoming extender requests. Enable via Helm observability.tracing.enabled=true.

Command Line Flags

FlagDefaultDescription
--port8082Port to listen on for extender HTTP endpoints

Benchmarker

The benchmarker runs inference performance tests against model backends.

VariableRequiredDescription
PROXY_URLYesURL of the FlexInfer proxy endpoint (e.g., http://flexinfer-proxy:8080)
POD_NAMESPACEYesNamespace where benchmarker is running
NODE_NAMEYesName of the node running the benchmark (from downward API)
BENCHMARK_RESULTS_CONFIGMAPYesName of ConfigMap to store benchmark results

Command Line Flags

FlagDefaultDescription
--model-HuggingFace model name to benchmark (required)
--model-name-ModelDeployment name for proxy routing
--configmap-ConfigMap name for storing results (required)
--backendollamaBackend type: ollama, vllm, mlc-llm, tei
--warmup-iterations2Number of warmup iterations before measurement
--min-duration30sMinimum benchmark duration (wall time)
--iterations5Number of measurement iterations
--batch-size128Target tokens to generate per request
--cold-start-timeout5mTimeout waiting for model to become ready

Node Agent

The node agent runs as a DaemonSet and labels nodes with GPU capabilities.

VariableDefaultDescription
NODE_NAME-Name of the node (from downward API)

Command Line Flags

FlagDefaultDescription
--interval30sHow often to re-probe hardware
--metrics-port9100Prometheus scrape port
--label-prefixflexinfer.ai/Prefix for node labels

Backend Images

Default container images for each backend type:

Ollama

  • NVIDIA: ollama/ollama:latest
  • AMD: ollama/ollama:rocm
  • Intel: ollama/ollama:latest

vLLM

  • NVIDIA: vllm/vllm-openai:latest
  • AMD: vllm/vllm-openai:rocm
  • AMD gfx1100 (RDNA3): registry.harbor.lan/library/vllm-api:rocm-gfx1100

MLC-LLM

  • NVIDIA: ghcr.io/mlc-ai/mlc-llm:cuda
  • AMD: ghcr.io/mlc-ai/mlc-llm:rocm
  • AMD gfx1100 (RDNA3): registry.harbor.lan/flexinfer/mlc-llm:rocm64-gfx1100
  • Maxwell (sm_52): registry.harbor.lan/flexinfer/mlc-llm:cuda-maxwell-v7

llama.cpp

  • NVIDIA: ghcr.io/ggml-org/llama.cpp:server-cuda
  • AMD: ghcr.io/ggml-org/llama.cpp:server-rocm
  • CPU: ghcr.io/ggml-org/llama.cpp:server

ComfyUI

  • NVIDIA: comfyanonymous/comfyui:latest
  • AMD: registry.harbor.lan/library/comfyui:rocm6.2.3-v8

Diffusers

  • NVIDIA: registry.harbor.lan/library/diffusers-api:cuda
  • AMD: registry.harbor.lan/library/diffusers-api:rocm-latest

Quantization Jobs

  • GGUF: ghcr.io/flexinfer/quantizer:gguf
  • AWQ: ghcr.io/flexinfer/quantizer:awq
  • GPTQ: ghcr.io/flexinfer/quantizer:gptq
  • EXL2: ghcr.io/flexinfer/quantizer:exl2
  • FP8: ghcr.io/flexinfer/quantizer:fp8

Image Pinning Best Practices

Why image pinning matters

Kubernetes uses imagePullPolicy: IfNotPresent by default for tagged images. This can cause issues when:

  1. Mutable tags (like :latest or :cuda) are used
  2. A node has an older version of the image cached
  3. A new pod schedules to that node and gets the stale cached image
  4. Different nodes in your cluster end up running different image versions

This leads to inconsistent behavior and makes debugging difficult.

For production deployments:

Pin images by digest rather than tag:

# Instead of:
image: ghcr.io/mlc-ai/mlc-llm:cuda

# Use digest:
image: ghcr.io/mlc-ai/mlc-llm@sha256:abc123...

For development/testing:

Use explicit versioned tags with imagePullPolicy: Always:

image: ghcr.io/mlc-ai/mlc-llm:v0.1.0
imagePullPolicy: Always

To force re-pull on all nodes:

If you need to update a mutable tag cluster-wide, either:

  1. Change the image reference to use a digest
  2. Delete the cached image on each node (crictl rmi <image>)
  3. Use a different tag and update the Model spec

Prewarming large serving images

For heavyweight runtime images, configure Helm imagePrewarm profiles so kubelet pulls the image before the first user request:

imagePrewarm:
  enabled: true
  profiles:
    - name: gfx1100-serving
      nodeSelector:
        kubernetes.io/hostname: gpu-node-1
      images:
        - registry.example.com/flexinfer/vllm@sha256:...
        - registry.example.com/flexinfer/diffusers:rocm-gfx1100

Each profile creates a low-priority DaemonSet whose containers sleep after the image is pulled. This keeps the image in use on the selected node, reducing the first activation path to scheduling, cache staging, and backend/model loading.

For release-critical ROCm images, enable the profile's immutable release gate:

imagePrewarm:
  enabled: true
  minReadySeconds: 30
  profiles:
    - name: gfx1100-runtime-candidate
      releaseGate: true
      nodeSelector:
        kubernetes.io/hostname: gpu-node-1
      images:
        - registry.example.com/flexinfer/runtime@sha256:...

releaseGate: true makes Helm reject mutable image references. The DaemonSet also records the candidate images in flexinfer.ai/prewarm-images annotations and must remain Ready for minReadySeconds. Verify the exact digest before promoting a consumer:

scripts/check-image-prewarm.sh gfx1100-runtime-candidate \
  --digest sha256:...

The check waits for the DaemonSet rollout, requires desired, updated, Ready, and available counts to match, and confirms every selected pod reports the candidate digest as an image ID.

Two-phase runtime image promotion

Heavyweight runtime releases use two separate GitOps reconciliations:

  1. Add the candidate digest to one release-gated imagePrewarm profile per target node, commit, reconcile Flux, and wait for the profiles to become Ready. The current runtime keeps serving during this pull.

  2. Promote the same digest to runtime consumers and require the live prewarm checks:

    scripts/promote-runtime-digest.sh gfx1100-serving \
      --digest sha256:... \
      --validation-row "gfx1100 serving canary" \
      --rollback-digest sha256:... \
      --prewarm-profile 5930k-gfx1100-runtime-candidate \
      --prewarm-profile 7900xtx-gfx1100-runtime-candidate \
      --apply

Keep the previous digest in a holder profile through the rollback soak window. After the candidate is stable, remove the old holder and let normal node image garbage collection reclaim it. A pull taking a long time is not by itself a stall: kubelet events and node image-store growth must both stop advancing before treating it as stuck.

Configuring default images

Override default backend images via controller environment variables:

# In your controller Deployment or Helm values:
env:
  - name: DEFAULT_MLC_LLM_IMAGE
    value: "ghcr.io/mlc-ai/mlc-llm@sha256:abc123..."
  - name: DEFAULT_VLLM_IMAGE
    value: "vllm/vllm-openai:v0.4.0"
  - name: DEFAULT_MLC_LLM_IMAGE_GFX1100
    value: "registry.harbor.lan/flexinfer/mlc-llm:rocm64-gfx1100"
  - name: DEFAULT_VLLM_IMAGE_GFX1100
    value: "registry.harbor.lan/library/vllm-api:rocm-gfx1100"

See the Backend Image Overrides section for the complete list of environment variables.

Per-model image override

Individual models can specify a custom image in the spec:

apiVersion: inference.flexinfer.ai/v1alpha2
kind: Model
metadata:
  name: my-model
spec:
  backend: mlc-llm
  source: HF://mlc-ai/Qwen3-8B-q4f16_1-MLC
  image: ghcr.io/mlc-ai/mlc-llm@sha256:abc123...  # Pinned image

CRD Configuration

ModelDeployment Spec

Key configuration fields in the ModelDeployment CRD:

FieldTypeDescription
modelstringModel identifier (e.g., HuggingFace model ID)
backendstringBackend type: ollama, vllm, mlc-llm, llamacpp, comfyui, diffusers
replicas*int32Number of replicas (0 for serverless)
gpuGroupRef*stringReference to a GPUGroup for exclusive scheduling
coldStartTimeoutSeconds*int32Per-model cold start timeout (overrides proxy default)
idleTimeoutSeconds*int32Time before scaling to zero when idle
serviceLabels[]stringService labels for routing (e.g., "textgen", "chat")
configmapBackend-specific configuration

Model Spec (v1alpha2)

Key configuration fields in the Model CRD:

FieldTypeDescription
backendstringBackend type: ollama, vllm, mlc-llm, llamacpp, comfyui, diffusers, vllm-omni
sourcestringSource URI: HF://..., ollama://..., file://..., pvc://...
gpu.sharedstringShared GPU group name for time-sharing
gpu.priorityintPreemption priority within shared group
serverless.*objectScale-to-zero behavior (idle/cold start timeouts)
cache.*objectCache strategy (Memory/SharedPVC/None)
serviceLabels[]stringSemantic labels for routing
config.preloadOnDeployboolWarm a non-shared serverless model on deploy until its first request (see below)

Preload on deploy

Set config.preloadOnDeploy: true on a non-shared, serverless model (serverless.minReplicas: 0) to have the controller proactively keep it warm (one replica) from deploy until it serves its first request, so the first post-deploy request skips cold start:

spec:
  backend: vllm
  serverless:
    enabled: true
    minReplicas: 0      # still scales to zero after first use
  config:
    preloadOnDeploy: true

This differs from serverless.minReplicas: 1 (which pins the model warm forever): once the first request sets LastActiveTime, normal idle scale-to-zero resumes. The model is held warm only until first use, so use it for lanes you expect to be hit shortly after deploy (a never-requested model stays warm indefinitely).

Shared-GPU members are excluded: a model in a gpu.shared group is governed by leadership/warm-pinning (above), and preload is skipped for it so it can never contend with or evict a group leader. Observe the warm state via the flexinfer_model_preload_active{model,namespace} gauge (1 while held warm before first request, 0 otherwise).

Shared-group leadership and warm-pinning

A shared GPU group serves one model at a time (chooseSharedGroupLeader in controllers/model_shared_gpu.go). Leadership resolves in this order: an operator gpu.forcePromotion, the anti-thrashing cooldown, the in-flight cold-start, demand-based preemption (a higher-priority member with recent proxy traffic preempts an idle leader), the Ready/recently-active member, an explicit warmPolicy: primary member, and finally raw priority.

When no member has demand and none is Ready or recently active, a member pinned warm via serverless.minReplicas >= 1 is preferred over an idle minReplicas: 0 member even if the idle member has higher gpu.priority. Without this, a higher-priority idle scale-to-zero member would permanently hold the single slot and starve the warm incumbent. A higher-priority member still preempts the warm incumbent the moment it receives real traffic, so this only changes the otherwise-idle steady state.

GPUGroup Spec

FieldTypeDescription
nodeSelectormapNode selector for the GPU group
models[]GPUGroupMemberList of models and their priorities
antiThrashing*AntiThrashingConfigConfiguration to prevent rapid model swaps

Helm Values

See charts/flexinfer/values.yaml for complete Helm chart configuration options.

Key values:

# Controller settings
controller:
  image: flexinfer/controller:latest
  replicas: 1
  resources:
    limits:
      cpu: 500m
      memory: 256Mi

# Proxy settings
proxy:
  image: flexinfer/proxy:latest
  replicas: 1
  port: 8080
  maxQueueSize: 100
  queueTimeout: 60s
  coldStartTimeout: 60s

# Agent settings
agent:
  image: flexinfer/agent:latest
  labelPrefix: flexinfer.ai/
  probeInterval: 30s
FlexInfer Configuration | FlexInfer docs