Label & Selector
为什么单独有这篇文档
AIDY 当前把“候选 upstream / model 的收紧规则”统一建模为 label selector。
这套语义会同时影响:
route.upstreams[]之后还能剩下哪些 upstream- 请求携带
model时,哪些upstream_models还能继续参与匹配 /v1/models最终能返回哪些模型名
因此,Label & Selector 不是某一个资源的局部字段说明,而是一套贯穿 route、consumer、api key、upstream、upstream model 的通用约束。
哪些地方有 labels
当前只有两类资源可被打 label:
upstreams.labelsupstream_models.labels
其中:
upstreams.labels用于给 upstream 打业务标签,例如tier=defaultupstream_models.labels用于给某条模型映射打标签,例如family=chat
route 本身没有 labels 字段。
哪些地方可以写 selector
当前可配置 selector 的地方有:
routes.upstream_selectorroutes.model_selectorconsumers.upstream_selectorconsumers.model_selectorconsumer_api_keys.upstream_selectorconsumer_api_keys.model_selector
语义上:
upstream_selector作用于 upstream labelsmodel_selector作用于 upstream model labels- 多层 selector 叠加时,始终是逐层收紧,必须全部命中
另外,route.upstreams[] 永远是基础集合。
也就是说:
selector 只能在 route 已绑定的 upstream 集合上继续过滤,不能绕过
route.upstreams[]凭空选出一个未绑定 upstream。
如果 route.upstreams[] 为空,则当前 route 没有任何可用 upstream。
Selector 结构
当前 selector 尽量对齐 Kubernetes LabelSelector,只支持:
match_labelsmatch_expressions
示例:
upstream_selector:
match_labels:
tier: default
match_expressions:
- key: region
operator: In
values: ["us-east", "us-west"]
语义:
match_labels内部是 ANDmatch_expressions内部是 ANDmatch_labels与match_expressions之间也是 ANDIn/NotIn的values列表内部是 OR- 空 selector 表示“不额外限制”
当前支持的 operator 只有四种:
InNotInExistsDoesNotExist
Label key / value 规则
label key / value 语法参考 Kubernetes labels。
key
label key 由两部分组成:
- 可选 prefix
- 必选 name
格式是:
[prefix/]<name>
约束:
name必须非空name最长 63 字符name必须以字母或数字开头和结尾- 中间可包含字母、数字、
-、_、. prefix可选;如果存在,必须是合法 DNS subdomainprefix与name之间最多只能有一个/
合法示例:
tierregionexample.com/tierml.example.com/family
非法示例:
/tierexample.com/Example.com/tierexample.com/-tier
value
label value 可以为空字符串。
如果非空,则:
- 最长 63 字符
- 必须以字母或数字开头和结尾
- 中间可包含字母、数字、
-、_、.
内部保留前缀
下面两类前缀是 AIDY 内部预留的,用户不能写入自定义 labels:
aidy/*aidy.*/*
也就是说,这些 key 可以出现在 selector 里做匹配,但不能出现在:
upstreams.labelsupstream_models.labels
这样做是为了给运行时保留系统内置 label 空间,避免与用户自定义标签冲突。
当前内置系统 labels
运行时当前会额外注入三个内置 label:
aidy/upstream-idaidy/model-nameaidy/protocol
含义:
aidy/upstream-id:当前候选 upstream 的资源 IDaidy/model-name:当前命中的客户端模型名,也就是upstream_models.modelaidy/protocol:当前候选 upstream 的运行时协议,例如chat-completions/open-responses/claude-messages
因此,如果你想按“某个固定 upstream”“某个固定客户端模型名”或“某个 upstream 协议”做 selector,可以直接匹配这些系统 key。
例如:
upstream_selector:
match_labels:
aidy/upstream-id: ups_primary
model_selector:
match_labels:
aidy/model-name: gpt-4o-mini
运行时如何应用
一条带 model 的请求在运行时大致按这个顺序应用:
- 先取
route.upstreams[]作为基础 upstream 集合 - 对 upstream 依次应用 route / consumer / api key 的
upstream_selector - 再在
upstream_models中按请求模型名查候选 - 对 upstream model 依次应用 route / consumer / api key 的
model_selector - 过滤 provider / upstream 不可用、协议不兼容、凭证无效等候选
- 最后再进入 priority / lb_weight 排序与 fallback
如果请求不带 model,则不会走 model_selector 那层,只继续在 route 已绑定的 upstream 集合里应用 upstream selector。
常见用法
用业务标签做灰度
upstream_selector:
match_labels:
tier: beta
只允许聊天模型
model_selector:
match_labels:
family: chat
排除某个区域
upstream_selector:
match_expressions:
- key: region
operator: NotIn
values: ["cn-north"]
精确锁定某个 upstream
upstream_selector:
match_labels:
aidy/upstream-id: ups_01ARZ3NDEKTSV4RRFFQ69G5FB3