aibrix
aibrix copied to clipboard
Add external-filter in Header for advanced routing
🚀 Feature Description and Motivation
AFAIK currently aibrix-gateway-plugins use pod.Label model.aibrix.ai/name filtering pods in cluster, I want to filter pods besides that, by using external filter in header or somewhere
Use Case
my cloud-edge openyurt k8s cluster need filter pods by nodepools, which i usually label pods like: node-pool:a or other topo-types labels i need by adding external-filters in headers, i can filter pod in exact area or for some tenant
Proposed Solution
- add external-filter(k8s label-selector type string) in selectTargetPod in gateway.go
// gateway.go
func (s *Server) selectTargetPod(ctx *types.RoutingContext, pods types.PodList, externalFilterExpr string) (string, error) {
// ......
// filter pod by header ext-filter
// k8s labelSelector format, eg: "k=v"、"env in (prod,stg)"
if externalFilterExpr != "" {
sel, err := labels.Parse(externalFilterExpr)
if err != nil {
return "", err
}
out := make([]*corev1.Pod, 0, len(readyPods))
for _, p := range readyPods {
klog.V(3).InfoS("filtering pod", "pod", p.Name)
if sel.Matches(labels.Set(p.Labels)) {
out = append(out, p)
klog.V(3).InfoS("filter passed", "pod", p.Name)
}
}
readyPods = out
}
// ......
return router.Route(ctx, &utils.PodArray{Pods: readyPods})
}
- get filter from header
// pkg/plugins/gateway/gateway_req_body.go line:78
// external filter in header
externalFilter := routingCtx.ReqHeaders[HeaderExternalFilter]
klog.InfoS("found external filter", "filter", externalFilter)
targetPodIP, err := s.selectTargetPod(routingCtx, podsArr, externalFilter)
- handle that header
// pkg/plugins/gateway/gateway_req_headers.go
func (s *Server) HandleRequestHeaders(ctx context.Context, requestID string, req *extProcPb.ProcessingRequest) (*extProcPb.ProcessingResponse, utils.User, int64, *types.RoutingContext) {
// ......
for _, n := range h.RequestHeaders.Headers.Headers {
if strings.ToLower(n.Key) == "user" {
username = string(n.RawValue)
}
if strings.ToLower(n.Key) == ":path" {
requestPath = string(n.RawValue)
}
if strings.ToLower(n.Key) == "authorization" {
reqHeaders[n.Key] = string(n.RawValue)
}
// add that
if strings.ToLower(n.Key) == HeaderExternalFilter {
reqHeaders[n.Key] = string(n.RawValue)
}
klog.InfoS("header", "key", n.Key, "value", string(n.RawValue))
}
i will add my PR below
this looks like a very reasonable requirements. thanks for driving the efforts!