Skip to content

Commit

Permalink
fix(upstreams) deduplicate like targets
Browse files Browse the repository at this point in the history
Combine targets with the same address or hostname by summing their
weights into a single target. Previously, same address targets would
result in duplicates and would be rejected by Kong.
  • Loading branch information
rainest committed Apr 5, 2024
1 parent 17786d0 commit 4ab8a6c
Showing 1 changed file with 18 additions and 3 deletions.
21 changes: 18 additions & 3 deletions internal/dataplane/translator/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/kong/go-kong/kong"
"github.com/samber/lo"
"github.com/samber/mo"
"golang.org/x/exp/maps"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
netv1 "k8s.io/api/networking/v1"
Expand Down Expand Up @@ -340,8 +341,8 @@ func (t *Translator) getUpstreams(serviceMap map[string]kongstate.Service) ([]ko
name := *service.Host

if _, exists := upstreamDedup[name]; !exists {
targetMap := map[string]kongstate.Target{}
// populate all the kong targets for the upstream given all the backends
var targets []kongstate.Target
for _, backend := range service.Backends {
// gather the Kubernetes service for the backend
backendNamespace := backend.Namespace()
Expand Down Expand Up @@ -414,10 +415,24 @@ func (t *Translator) getUpstreams(serviceMap map[string]kongstate.Service) ([]ko
}
}

// add the new targets to the existing pool of targets for the Upstream.
targets = append(targets, newTargets...)
for _, t := range newTargets {
// See https://github.com/Kong/kubernetes-ingress-controller/issues/5761:
// Duplicate targets will appear in configurations that use Services with the same selector, which are used
// by some rollout systems. We need to deduplicate them while honoring the total weight.
//
// Because kongstate.Target is a nested kong.Target and the target IP is also a field named Target, the
// key names are a bit silly.
if existing, ok := targetMap[*t.Target.Target]; ok {
sum := *existing.Weight + *t.Weight
existing.Target.Weight = &sum
targetMap[*t.Target.Target] = existing
} else {
targetMap[*t.Target.Target] = t
}
}
}

targets := maps.Values(targetMap)
// warn if an upstream was created with 0 targets
if len(targets) == 0 {
t.logger.V(util.InfoLevel).Info("No targets found to create upstream", "service_name", *service.Name)
Expand Down

0 comments on commit 4ab8a6c

Please sign in to comment.