Skip to main content
Version: Dev 🚧

Usage

Heimdall is the request entrypoint of the MoAI Inference Framework. The Heimdall operator runs the gateway from an AIGateway resource, and the gateway routes each request to an inference pod according to a SchedulingProfile. This page documents the custom resources an operator works with.

AIGateway​

An AIGateway (group heimdall.moreh.io/v1alpha1, namespaced) describes a gateway deployment. The Heimdall operator reconciles it into a gateway Deployment and Service and binds request models to scheduling profiles through spec.schedulingProfiles. The reserved model name default is the gateway-wide fallback.

FieldTypeRequiredDescription
affinityobjectnoAffinity for the gateway pod.
extraArgsarraynoExtraArgs are merged onto the gateway container's chart-default args by flag key (see "Args Merge Contract").
extraEnvVarsarraynoExtraEnvVars is a list of additional environment variables to inject into the gateway container. User-defined entries override controller-managed defaults when names collide.
extraVolumeMountsarraynoExtraVolumeMounts is a list of additional volume mounts for the gateway container, merged onto chart defaults by mountPath (whole-entry replacement on collision).
extraVolumesarraynoExtraVolumes is a list of additional volumes for the gateway pods, merged onto chart defaults by name (whole-entry replacement on collision).
imageobjectnoImage specifies the container image configuration for the gateway.
nodeSelectorobjectnoNodeSelector for the gateway pod.
replicasintegernoReplicas is the number of desired gateway pods.
resourcesobjectnoResources specifies the compute resource requirements for the gateway pods.
revisionHistoryLimitintegernoRevisionHistoryLimit is the number of old ReplicaSets to retain for this gateway's Deployment.
schedulingProfilesarraynoSchedulingProfiles binds request models to SchedulingProfile names, evaluated and preserved in list order. The reserved model name "default" is the lowest-priority fallback regardless of its position; every other entry is a per-model override.
serviceobjectnoService configures the Service fronting the gateway pods.
sidecarobjectnoSidecar overrides for the sidecar init container injected into bound InferenceService pods by the pod mutating webhook.
tolerationsarraynoTolerations for the gateway pod.
updateStrategyobjectnoUpdateStrategy is the Deployment rollout strategy for the gateway pods.

extraEnvVars​

FieldTypeRequiredDescription
namestringyesName of the environment variable. May consist of any printable ASCII characters except '='.
valuestringnoVariable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".
valueFromobjectnoSource for the environment variable's value. Cannot be used if value is not empty.

extraVolumeMounts​

FieldTypeRequiredDescription
mountPathstringyesPath within the container at which the volume should be mounted. Must not contain ':'.
mountPropagationstringnomountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified (which defaults to None).
namestringyesThis must match the Name of a Volume.
readOnlybooleannoMounted read-only if true, read-write otherwise (false or unspecified). Defaults to false.
recursiveReadOnlystringnoRecursiveReadOnly specifies whether read-only mounts should be handled recursively. If ReadOnly is false, this field has no meaning and must be unspecified. If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this field is set to Enabled, the mount is made recursively read-only if it is supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). If this field is not specified, it is treated as an equivalent of Disabled.
subPathstringnoPath within the volume from which the container's volume should be mounted. Defaults to "" (volume's root).
subPathExprstringnoExpanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive.

image​

FieldTypeRequiredDescription
pullPolicystringnoPullPolicy is the image pull policy.
pullSecretsarraynoPullSecrets are added to pod.spec.imagePullSecrets.
registrystringnoRegistry is the container image registry. Empty means no prefix.
repositorystringnoRepository is the image name (no registry, no tag).
tagstringnoTag is the container image tag.

resources​

FieldTypeRequiredDescription
claimsarraynoClaims lists the names of resources, defined in spec.resourceClaims, that are used by this container. This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers.
limitsobjectnoLimits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
requestsobjectnoRequests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

schedulingProfiles​

FieldTypeRequiredDescription
modelstringyesModel is the request model name, or the reserved value "default" for the gateway-wide default profile.
profilestringyesProfile is the SchedulingProfile name to use for this model.

service​

FieldTypeRequiredDescription
annotationsobjectnoAnnotations to set on the Service, merged onto any annotations already present on the Service (CR entries win on collision).
typestringnoType is the Service type. Defaults to ClusterIP.

sidecar​

FieldTypeRequiredDescription
extraArgsarraynoExtraArgs are merged onto the sidecar container's chart-default args by flag key (see "Args Merge Contract").
extraEnvVarsarraynoExtraEnvVars are env vars for the sidecar container, merged onto chart defaults by Name; CR entries win on collision.
imageobjectnoImage is the sidecar container image config. Each unset field falls back at render time per "Sidecar Image Resolution" in the spec PRD: registry / tag / pullPolicy / pullSecrets fall back to the gateway image; repository falls back to the constant "heimdall-aigateway-sidecar". The defaulting webhook does NOT persist these fallbacks.
resourcesobjectnoResources are compute requirements for the sidecar container, merged per resource name.

tolerations​

FieldTypeRequiredDescription
effectstringnoEffect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
keystringnoKey is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.
operatorstringnoOperator represents a key's relationship to the value. Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
tolerationSecondsintegernoTolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.
valuestringnoValue is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.

updateStrategy​

FieldTypeRequiredDescription
rollingUpdateobjectnoRolling update config params. Present only if DeploymentStrategyType = RollingUpdate.
typestringnoType of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate.

SchedulingProfile​

A SchedulingProfile (group heimdall.moreh.io/v1alpha1, cluster-scoped) defines how the gateway selects a destination pod. spec.profileHandler is e2e or pd. spec.plugins declares the scorer and picker plugins, and spec.profiles.<name>.pluginRefs lists them in evaluation order with an optional weight.

If no SchedulingProfile is bound, the gateway falls back to a built-in default profile. For the available scorer and picker plugins, see Plugins.

FieldTypeRequiredDescription
pluginsarrayyesPlugins declares the available scorer and picker plugins. (Role filtering for prefill/decode profiles is applied internally and is not configured here.)
profileHandlerstringyesProfileHandler selects the scheduling mode: "e2e" for a single profile, "pd" for separate prefill and decode profiles.
profilesobjectyesProfiles maps profile names (e.g., "default", "prefill", "decode") to their plugin reference lists. For "e2e" mode a single "default" profile is expected; for "pd" mode, "prefill" and "decode" profiles are expected.

plugins​

FieldTypeRequiredDescription
configobjectnoConfig holds arbitrary plugin-specific configuration (e.g., {"transform": "logistic"} for "prefix-cache-scorer").
namestringnoName is an optional alias for this plugin instance; it must be non-empty when set. Defaults to Type when omitted.
typestringyesType is the plugin type identifier (e.g., "running-requests-scorer", "max-score-picker").

InferenceWorker​

An InferenceWorker (group heimdall.moreh.io/v1alpha1, namespaced) advertises a single inference pod to the gateway — its address, framework, serving role, and the models it hosts. It is created and maintained by the gateway sidecar, so you do not author it directly.

An inference pod joins a gateway through the mif.moreh.io/aigateway label, whose value is the target AIGateway's name. You set this label on the InferenceService; Odin propagates it to the pods, and the Heimdall operator injects the gateway sidecar into the labeled pods. The sidecar then registers each pod as an InferenceWorker, and the gateway routes requests to the workers that carry its name in that label.

FieldTypeRequiredDescription
frameworkstringyesFramework is the inference engine running on this pod (e.g., "vllm", "trt-llm").
gpuKvCacheBlocksintegernoGpuKvCacheBlocks is the total number of GPU KV cache blocks the engine allocated (vLLM num_gpu_blocks). Fixed at engine init; sourced by the sidecar from the engine cache-config metric. Used by the kv-cache-utilization scorer as the occupancy denominator. Optional — unset means "no advertised capacity" (scorer is neutral for this worker).
instancesarrayyesInstances is the list of serving instances on this pod, one per listening port. A data-parallel deployment has multiple instances on a single pod.
modelCardobjectyesModelCard pins the codec policy for the base model this worker serves.
optimalMinTokensintegernoOptimalMinTokens is the smallest prompt (in tokens) this worker is well-suited for. Sourced from the pod label mif.moreh.io/aigateway.optimal-min-tokens. Omitting the field or setting it to 0 are equivalent — both mean "no advertised minimum" to the token-length scorer.
podIPstringyesPodIP is the IP address of the inference worker pod.
rolestringnoRole indicates whether this worker handles prefill, decode, or both (e2e).

instances​

FieldTypeRequiredDescription
modelsarrayyesModels is the list of models served by this instance.
portintegeryesPort is the TCP port this instance listens on.

modelCard​

FieldTypeRequiredDescription
kvCacheBlockSizeintegernoKvCacheBlockSize is the engine's KV block size in tokens per block; it must match the serving engine's configured block size. Defaults to 16.
maxModelLenintegernoMaxModelLen overrides config.json::max_position_embeddings.
namestringyesName is the base model identifier (e.g., "meta-llama/Llama-3-8B").
reasoningParserstringnoReasoningParser selects the reasoning parser, if any.
rendererstringyesRenderer selects the prompt renderer.
servedNamestringnoServedName overrides the client-facing model identity for this worker's serving configuration. Unset means the base model name is served.
thinkingTemplateArgsobjectnoThinkingTemplateArgs projects thinking state into template arguments.
toolCallParserstringnoToolCallParser selects the tool-call parser, if any.