Skip to search

AIGatewayRoute

aigateway.envoyproxy.io / v1beta1

apiVersion: aigateway.envoyproxy.io/v1beta1 kind: AIGatewayRoute metadata: name: example
View raw schema
apiVersion string
APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
kind string
Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata object
spec object
Spec defines the details of the AIGatewayRoute.
hostnames []string
Hostnames is a list of hostnames matched against the HTTP Host header to select an AIGatewayRoute used to process the request. This is equivalent to the Hostnames field in the Gateway API HTTPRouteSpec. When specified, the generated HTTPRoute will include these hostnames for hostname-based filtering. See https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPRouteSpec for the details of the Hostnames field in the Gateway API.
maxItems: 16
llmRequestCosts []object
LLMRequestCosts specifies how to capture the cost of the LLM-related request, notably the token usage. The AI Gateway filter will capture each specified number and store it in the Envoy's dynamic metadata per HTTP request. The namespaced key is "io.envoy.ai_gateway". These route-level costs override any global defaults defined in GatewayConfig.Spec.GlobalLLMRequestCosts for the same metadataKey. If a metadataKey is not defined in either place, no cost is calculated for it. This allows you to define common cost formulas once at the gateway level (e.g., via GatewayConfig) and only override them in specific routes when needed (e.g., premium routes with different pricing). For example, let's say we have the following LLMRequestCosts configuration: ```yaml llmRequestCosts: - metadataKey: llm_input_token type: InputToken - metadataKey: llm_output_token type: OutputToken - metadataKey: llm_total_token type: TotalToken - metadataKey: llm_cached_input_token type: CachedInputToken - metadataKey: llm_cache_creation_input_token type: CacheCreationInputToken ``` Then, with the following BackendTrafficPolicy of Envoy Gateway, you can have three rate limit buckets for each unique x-tenant-id header value. One bucket is for the input token, the other is for the output token, and the last one is for the total token. Each bucket will be reduced by the corresponding token usage captured by the AI Gateway filter. ```yaml apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: some-example-token-rate-limit namespace: default spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: usage-rate-limit rateLimit: type: Global global: rules: - clientSelectors: # Do the rate limiting based on the x-tenant-id header. - headers: - name: x-tenant-id type: Distinct limit: # Configures the number of "tokens" allowed per hour. requests: 10000 unit: Hour cost: request: from: Number # Setting the request cost to zero allows to only check the rate limit budget, # and not consume the budget on the request path. number: 0 # This specifies the cost of the response retrieved from the dynamic metadata set by the AI Gateway filter. # The extracted value will be used to consume the rate limit budget, and subsequent requests will be rate limited # if the budget is exhausted. response: from: Metadata metadata: namespace: io.envoy.ai_gateway key: llm_input_token - clientSelectors: - headers: - name: x-tenant-id type: Distinct limit: requests: 10000 unit: Hour cost: request: from: Number number: 0 response: from: Metadata metadata: namespace: io.envoy.ai_gateway key: llm_output_token - clientSelectors: - headers: - name: x-tenant-id type: Distinct limit: requests: 10000 unit: Hour cost: request: from: Number number: 0 response: from: Metadata metadata: namespace: io.envoy.ai_gateway key: llm_total_token ``` Note that when multiple AIGatewayRoute resources are attached to the same Gateway, and different costs are configured for the same metadata key, each route's rule is carried in the filter configuration with the route identity; the data plane selects the matching rule per request (by route), so each route can define its own cost for the same metadata key.
maxItems: 36
cel string
CEL is the CEL expression to calculate the cost of the request. The CEL expression must return a signed or unsigned integer. If the return value is negative, it will be error. The expression can use the following variables: * model: the model name extracted from the request content. Type: string. * backend: the backend name in the form of "name.namespace". Type: string. * input_tokens: the number of input tokens. Type: unsigned integer. * cached_input_tokens: the number of cached read input tokens. Type: unsigned integer. * cache_creation_input_tokens: the number of cache creation input tokens. Type: unsigned integer. * output_tokens: the number of output tokens. Type: unsigned integer. * total_tokens: the total number of tokens. Type: unsigned integer. * reasoning_tokens: the number of reasoning tokens. Type: unsigned integer. For example, the following expressions are valid: * "model == 'llama' ? input_tokens + output_token * 0.5 : total_tokens" * "backend == 'foo.default' ? input_tokens + output_tokens : total_tokens" * "backend == 'bar.default' ? (input_tokens - cached_input_tokens) + cached_input_tokens * 0.1 + cache_creation_input_tokens * 1.25 + output_tokens : total_tokens" * "input_tokens + output_tokens + total_tokens" * "input_tokens * output_tokens"
metadataKey string required
MetadataKey is the key of the metadata to store this cost of the request.
type string required
Type specifies the type of the request cost. The default is "OutputToken", and it uses "output token" as the cost. The other types are "InputToken", "TotalToken", "CachedInputToken", "CacheCreationInputToken", "ReasoningToken", and "CEL".
enum: OutputToken, InputToken, CachedInputToken, CacheCreationInputToken, TotalToken, ReasoningToken, CEL
parentRefs []object
ParentRefs are the names of the Gateway resources this AIGatewayRoute is being attached to. Currently, each reference's Kind must be Gateway.
maxItems: 16
group string
Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core
pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
maxLength: 253
kind string
Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific.
pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
minLength: 1
maxLength: 63
name string required
Name is the name of the referent. Support: Core
minLength: 1
maxLength: 253
namespace string
Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. <gateway:experimental:description> ParentRefs from a Route to a Service in the same namespace are "producer" routes, which apply default routing rules to inbound connections from any namespace to the Service. ParentRefs from a Route to a Service in a different namespace are "consumer" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. </gateway:experimental:description> Support: Core
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
minLength: 1
maxLength: 63
port integer
Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. <gateway:experimental:description> When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. </gateway:experimental:description> Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended
format: int32
minimum: 1
maximum: 65535
sectionName string
SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
minLength: 1
maxLength: 253
rules []object required
Rules is the list of AIGatewayRouteRule that this AIGatewayRoute will match the traffic to. Each rule is a subset of the HTTPRoute in the Gateway API (https://gateway-api.sigs.k8s.io/api-types/httproute/). AI Gateway controller will generate a HTTPRoute based on the configuration given here with the additional modifications to achieve the necessary jobs, notably inserting the AI Gateway filter responsible for the transformation of the request and response, etc. In the matching conditions in the AIGatewayRouteRule, `x-ai-eg-model` header is available if we want to describe the routing behavior based on the model name. The model name is extracted from the request content before the routing decision. How multiple rules are matched is the same as the Gateway API. See for the details: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPRoute At most 15 rules are allowed per AIGatewayRoute, corresponding to the Gateway API's limit on HTTPRoute.spec.rules (one slot is reserved for a controller-injected catch-all rule). To configure more rules on the same Gateway, split them across multiple AIGatewayRoute resources.
maxItems: 15
backendRefs []object
BackendRefs is the list of backends that this rule will route the traffic to. Each backend can have a weight that determines the traffic distribution. The namespace of each backend defaults to the same namespace as the AIGatewayRoute when not specified. Cross-namespace references are supported by specifying the namespace field. When a namespace different than the AIGatewayRoute's namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. BackendRefs can reference either AIServiceBackend resources (default) or InferencePool resources from the Gateway API Inference Extension. When referencing InferencePool resources: - Only one InferencePool backend is allowed per rule - Cannot mix InferencePool with AIServiceBackend references in the same rule - Fallback behavior is handled by the InferencePool's endpoint picker For AIServiceBackend references, you can achieve fallback behavior by configuring multiple backends combined with the BackendTrafficPolicy of Envoy Gateway. Please refer to https://gateway.envoyproxy.io/docs/tasks/traffic/failover/ as well as https://gateway.envoyproxy.io/docs/tasks/traffic/retry/.
maxItems: 128
bodyMutation object
BodyMutation defines the request body mutation to be applied to this backend. This allows modification of JSON fields in the request body before sending to the backend. When both route-level and backend-level BodyMutation are defined, route-level takes precedence over backend-level for conflicting operations. This field is ignored when referencing InferencePool resources.
remove []string
Remove the given JSON field(s) from the HTTP request body before sending to the backend. The value of Remove is a list of top-level field names to remove. Input: { "model": "gpt-4", "service_tier": "default", "internal_flag": true } Config: remove: ["service_tier", "internal_flag"] Output: { "model": "gpt-4" }
maxItems: 16
set []object
Set overwrites/adds the request body with the given JSON field (name, value) before sending to the backend. Only top-level fields are currently supported. Input: { "model": "gpt-4", "service_tier": "default" } Config: set: - path: "service_tier" value: "scale" Output: { "model": "gpt-4", "service_tier": "scale" }
maxItems: 16
path string required
Path is the top-level field name to set in the request body. Examples: "service_tier", "max_tokens", "temperature"
minLength: 1
value string required
Value is the JSON value to set at the specified field. This can be any valid JSON value: string, number, boolean, object, array, or null. The value will be parsed as JSON and inserted at the specified field. Examples: - "\"scale\"" (string) - "42" (number) - "true" (boolean) - "{\"key\": \"value\"}" (object) - "[1, 2, 3]" (array) - "null" (null)
group string
Group is the group of the backend resource. When not specified, defaults to aigateway.envoyproxy.io (AIServiceBackend). Currently, only "inference.networking.k8s.io" is supported for InferencePool resources.
pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
maxLength: 253
headerMutation object
HeaderMutation defines the request header mutation to be applied to this backend. When both route-level and backend-level HeaderMutation are defined, route-level takes precedence over backend-level for conflicting operations. This field is ignored when referencing InferencePool resources.
remove []string
Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar
maxItems: 16
set []object
Set overwrites/adds the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar
maxItems: 16
name string required
Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent.
pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
minLength: 1
maxLength: 256
value string required
Value is the value of HTTP Header to be matched. <gateway:experimental:description> Must consist of printable US-ASCII characters, optionally separated by single tabs or spaces. See: https://tools.ietf.org/html/rfc7230#section-3.2 </gateway:experimental:description> <gateway:experimental:validation:Pattern=`^[!-~]+([\t ]?[!-~]+)*$`>
minLength: 1
maxLength: 4096
kind string
Kind is the kind of the backend resource. When not specified, defaults to AIServiceBackend. Currently, only "InferencePool" is supported when Group is specified.
pattern: ^$|^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
maxLength: 63
modelNameOverride string
Name of the model in the backend. If provided this will override the name provided in the request. This field is ignored when referencing InferencePool resources.
name string required
Name is the name of the backend resource. When Group and Kind are not specified, this refers to an AIServiceBackend. When Group and Kind are specified, this refers to the resource of the specified type.
minLength: 1
namespace string
Namespace is the namespace of the backend resource. When unspecified (or empty string), this refers to the local namespace of the AIGatewayRoute. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
minLength: 1
maxLength: 63
priority integer
Priority is the priority of the backend. This sets the priority on the underlying endpoints. See: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/priority Note: This will override the `faillback` property of the underlying Envoy Gateway Backend This field is ignored when referencing InferencePool resources. Default is 0.
format: int32
minimum: 0
weight integer
Weight is the weight of the backend. This is exactly the same as the weight in the BackendRef in the Gateway API. See for the details: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.BackendRef Default is 1.
format: int32
minimum: 0
matches []object
Matches is the list of AIGatewayRouteMatch that this rule will match the traffic to. This is a subset of the HTTPRouteMatch in the Gateway API. See for the details: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPRouteMatch
maxItems: 128
headers []object
Headers specifies HTTP request header matchers. See HeaderMatch in the Gateway API for the details: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPHeaderMatch
maxItems: 16
name string required
Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. When a header is repeated in an HTTP request, it is implementation-specific behavior as to how this is represented. Generally, proxies should follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding processing a repeated header, with special handling for "Set-Cookie".
pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
minLength: 1
maxLength: 256
type string
Type specifies how to match against the value of the header. Support: Core (Exact) Support: Implementation-specific (RegularExpression) Since RegularExpression HeaderMatchType has implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect.
enum: Exact, RegularExpression
value string required
Value is the value of HTTP Header to be matched. <gateway:experimental:description> Must consist of printable US-ASCII characters, optionally separated by single tabs or spaces. See: https://tools.ietf.org/html/rfc7230#section-3.2 </gateway:experimental:description> <gateway:experimental:validation:Pattern=`^[!-~]+([\t ]?[!-~]+)*$`>
minLength: 1
maxLength: 4096
modelsCreatedAt string
ModelsCreatedAt represents the creation timestamp of the running models serving by the backends, which will be exported as the field of "Created" in openai-compatible API "/models". It follows the format of RFC 3339, for example "2024-05-21T10:00:00Z". This is used only when this rule contains "x-ai-eg-model" in its header matching where the header value will be recognized as a "model" in "/models" endpoint. All the matched models will share the same creation time. Default to the creation timestamp of the AIGatewayRoute if not set.
format: date-time
modelsOwnedBy string
ModelsOwnedBy represents the owner of the running models serving by the backends, which will be exported as the field of "OwnedBy" in openai-compatible API "/models". This is used only when this rule contains "x-ai-eg-model" in its header matching where the header value will be recognized as a "model" in "/models" endpoint. All the matched models will share the same owner. Default to "Envoy AI Gateway" if not set.
timeouts object
Timeouts defines the timeouts that can be configured for an HTTP request. If this field is not set, or the timeout.requestTimeout is nil, Envoy AI Gateway defaults to set 60s for the request timeout as opposed to 15s of the Envoy Gateway's default value. For streaming responses (like chat completions with stream=true), consider setting longer timeouts as the response may take time until the completion.
backendRequest string
BackendRequest specifies a timeout for an individual request from the gateway to a backend. This covers the time from when the request first starts being sent from the gateway to when the full response has been received from the backend. Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout completely. Implementations that cannot completely disable the timeout MUST instead interpret the zero duration as the longest possible value to which the timeout can be set. An entire client HTTP transaction with a gateway, covered by the Request timeout, may result in more than one call from the gateway to the destination backend, for example, if automatic retries are supported. The value of BackendRequest must be a Gateway API Duration string as defined by GEP-2257. When this field is unspecified, its behavior is implementation-specific; when specified, the value of BackendRequest must be no more than the value of the Request timeout (since the Request timeout encompasses the BackendRequest timeout). Support: Extended
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
request string
Request specifies the maximum duration for a gateway to respond to an HTTP request. If the gateway has not been able to respond before this deadline is met, the gateway MUST return a timeout error. For example, setting the `rules.timeouts.request` field to the value `10s` in an `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds to complete. Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout completely. Implementations that cannot completely disable the timeout MUST instead interpret the zero duration as the longest possible value to which the timeout can be set. This timeout is intended to cover as close to the whole request-response transaction as possible although an implementation MAY choose to start the timeout after the entire request stream has been received instead of immediately after the transaction is initiated by the client. The value of Request is a Gateway API Duration string as defined by GEP-2257. When this field is unspecified, request timeout behavior is implementation-specific. Support: Extended
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
status object
Status defines the status details of the AIGatewayRoute.
conditions []object
Conditions is the list of conditions by the reconciliation result. Currently, at most one condition is set. Known .status.conditions.type are: "Accepted", "NotAccepted".
lastTransitionTime string required
lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
message string required
message is a human readable message indicating details about the transition. This may be an empty string.
maxLength: 32768
observedGeneration integer
observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
format: int64
minimum: 0
reason string required
reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
minLength: 1
maxLength: 1024
status string required
status of the condition, one of True, False, Unknown.
enum: True, False, Unknown
type string required
type of condition in CamelCase or in foo.example.com/CamelCase.
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
maxLength: 316

No matches. Try .spec.hostnames for an exact path