Skip to content

Commit 3d1ae9a

Browse files
authored
Merge branch 'main' into fix/fc-config-defaults
2 parents 6c1387b + efb4db5 commit 3d1ae9a

4 files changed

Lines changed: 64 additions & 36 deletions

File tree

docs/architecture.md

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44

55
- [Overview](#overview)
66
- [Core Goals](#core-goals)
7-
- [Filters, Scorers, and Scrapers](#filters-scorers-and-scrapers)
7+
- [Filters, Scorers, and the Data Layer](#filters-scorers-and-the-data-layer)
88
- [Core Design Principles](#core-design-principles)
99
- [Routing Flow](#routing-flow)
1010
- [Configuration](#configuration)
1111
- [`Plugins` Configuration](#plugins-configuration)
1212
- [`SchedulingProfiles` Configuration](#schedulingprofiles-configuration)
1313
- [Available plugins](#available-plugins)
14-
- [Metric Scraping](#metric-scraping)
14+
- [Metric Scraping and the Data Layer](#metric-scraping-and-the-data-layer)
1515
- [Disaggregated Encode/Prefill/Decode (E/P/D)](#disaggregated-encodeprefilldecode-epd)
1616
- [InferencePool & InferenceModel Design](#inferencepool--inferencemodel-design)
1717
- [Current Assumptions](#current-assumptions)
@@ -31,7 +31,7 @@ The design enables:
3131
**model metadata**
3232
- Disaggregated **Prefill/Decode (P/D)** execution
3333
- We have introduced experimental **Encode/Prefill/Decode (E/P/D and all its permutations)** execution. For a detailed explanation, see [Disaggregated Inference Serving](./disaggregation.md)
34-
- Pluggable **filters**, **scorers**, and **scrapers** for extensible scheduling
34+
- Pluggable **filters** and **scorers**, backed by a pluggable **data layer**, for extensible scheduling
3535

3636
---
3737

@@ -42,12 +42,12 @@ The design enables:
4242
- KV cache reuse
4343
- Load balancing
4444
- Support multi-model deployments on heterogeneous hardware
45-
- Enable runtime extensibility with pluggable logic (filters, scorers, scrapers)
45+
- Enable runtime extensibility with pluggable logic (filters, scorers, data layer)
4646
- Community-aligned implementation using GIE and Envoy + External Processing (EPP)
4747

4848
---
4949

50-
## Filters, Scorers, and Scrapers
50+
## Filters, Scorers, and the Data Layer
5151

5252
### Core Design Principles
5353

@@ -58,14 +58,16 @@ The design enables:
5858

5959
### Routing Flow
6060

61+
See the upstream [Request Scheduler](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/scheduling.md) doc for the canonical scheduling model.
62+
6163
1. **Filtering**
6264
- Pods in an `InferencePool` go through a sequential chain of filters
6365
- Pods may be excluded based on criteria like model compatibility, resource usage, or custom logic
6466

6567
2. **Scoring**
6668
- Filtered pods are scored using a weighted set of scorers
6769
- Scorers currently run sequentially (future: parallel execution)
68-
- Scorers access a shared datastore populated by scrapers
70+
- Scorers access a shared datastore populated by the data layer
6971

7072
3. **Pod Selection**
7173
- The highest-scored pod is selected
@@ -77,6 +79,8 @@ The design enables:
7779

7880
The llm-d Endpoint Picker relies on a YAML-based configuration—provided either as a file or an in-line parameter—to determine which lifecycle hooks (plugins) are active.
7981

82+
See the upstream [Configuration](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/configuration.md) doc for the canonical schema.
83+
8084
Specifically, this configuration establishes the following components:
8185

8286
- `Plugins`: The specific plugins to instantiate, along with their parameters. Because each instantiated plugin is assigned a unique name, you can configure the same plugin type multiple times if necessary.
@@ -210,12 +214,18 @@ To learn more about the available plugins, check the plugins [README.md](../pkg/
210214

211215
---
212216

213-
## Metric Scraping
217+
## Metric Scraping and the Data Layer
218+
219+
The data layer follows a Source -> Extract -> Attribute lifecycle:
214220

215-
- Scrapers collect metrics (e.g., memory usage, active adapters)
216-
- Data is injected into the shared datastore for scorers
221+
- Data sources collect per-endpoint data. Some poll pods periodically, for metrics (e.g., memory
222+
usage, active adapters) or served models and LoRA adapters (via `/v1/models`); others react to
223+
endpoint or Kubernetes object change notifications
224+
- Extractors populate per-endpoint attributes in the shared datastore for scorers
217225
- Scoring can rely on numerical metrics or metadata (model ID, adapter tags)
218226

227+
See the upstream [Data Layer](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/datalayer.md) doc for the canonical model.
228+
219229
---
220230

221231
## Disaggregated Encode/Prefill/Decode (E/P/D)
@@ -307,3 +317,14 @@ Enable chunked decode via the pd-sidecar flag:
307317
- [Gateway API Inference Extension](https://github.com/kubernetes-sigs/gateway-api-inference-extension)
308318
- [Envoy External Processing](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_proc_filter)
309319
- [EPP Container Sizing Guide](./operations.md)
320+
321+
### Canonical llm-d architecture (upstream)
322+
323+
- [Router overview](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/README.md)
324+
- [Proxy](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/proxy.md)
325+
- [Endpoint Picker (EPP)](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/README.md)
326+
- [Configuration](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/configuration.md)
327+
- [Request Scheduler](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/scheduling.md)
328+
- [Request Handler](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/request-handling.md)
329+
- [Flow Control](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/flow-control.md)
330+
- [Data Layer](https://github.com/llm-d/llm-d/blob/main/docs/architecture/core/router/epp/datalayer.md)

go.mod

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ require (
4141
go.opentelemetry.io/otel/sdk v1.44.0
4242
go.opentelemetry.io/otel/trace v1.44.0
4343
go.uber.org/zap v1.28.0
44-
golang.org/x/crypto v0.52.0
45-
golang.org/x/sync v0.20.0
44+
golang.org/x/crypto v0.53.0
45+
golang.org/x/sync v0.21.0
4646
golang.org/x/time v0.15.0
4747
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa
48-
google.golang.org/grpc v1.81.1
48+
google.golang.org/grpc v1.82.1
4949
google.golang.org/protobuf v1.36.11
5050
k8s.io/api v0.35.6
5151
k8s.io/apiextensions-apiserver v0.35.6
@@ -130,13 +130,13 @@ require (
130130
go.yaml.in/yaml/v2 v2.4.4 // indirect
131131
go.yaml.in/yaml/v3 v3.0.4 // indirect
132132
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect
133-
golang.org/x/mod v0.35.0 // indirect
134-
golang.org/x/net v0.55.0 // indirect
133+
golang.org/x/mod v0.37.0 // indirect
134+
golang.org/x/net v0.56.0 // indirect
135135
golang.org/x/oauth2 v0.36.0 // indirect
136-
golang.org/x/sys v0.45.0 // indirect
137-
golang.org/x/term v0.43.0 // indirect
138-
golang.org/x/text v0.37.0 // indirect
139-
golang.org/x/tools v0.44.0 // indirect
136+
golang.org/x/sys v0.46.0 // indirect
137+
golang.org/x/term v0.44.0 // indirect
138+
golang.org/x/text v0.39.0 // indirect
139+
golang.org/x/tools v0.47.0 // indirect
140140
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
141141
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect
142142
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect

go.sum

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -283,28 +283,28 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
283283
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
284284
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
285285
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
286-
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
287-
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
286+
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
287+
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
288288
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
289289
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
290-
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
291-
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
292-
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
293-
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
290+
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
291+
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
292+
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
293+
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
294294
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
295295
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
296-
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
297-
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
298-
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
299-
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
300-
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
301-
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
302-
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
303-
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
296+
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
297+
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
298+
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
299+
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
300+
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
301+
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
302+
golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus=
303+
golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM=
304304
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
305305
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
306-
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
307-
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
306+
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
307+
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
308308
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
309309
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
310310
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
@@ -319,8 +319,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:
319319
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
320320
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
321321
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
322-
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
323-
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
322+
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
323+
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
324324
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
325325
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
326326
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

release-notes.d/unreleased/2119.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
pr: 2119
3+
url: https://github.com/llm-d/llm-d-router/pull/2119
4+
author: LukeAVanDrie
5+
date: 2026-07-21
6+
---
7+
The fairness_id metric label is now capped at 1000 distinct values; additional fairness IDs are reported under the `other` label value. Flow control metric series for a fairness ID are removed when its flow is garbage collected. This bounds EPP memory and metrics-pipeline load, which were previously unbounded because the label derives from a client-controlled header.

0 commit comments

Comments
 (0)