Skip to content

Commit 7afa8dc

Browse files
authored
feat: allow disabling pod locality in xDS (#10404)
1 parent b937894 commit 7afa8dc

File tree

4 files changed

+66
-13
lines changed

4 files changed

+66
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
changelog:
2+
- type: NON_USER_FACING
3+
issueLink: https://github.com/solo-io/solo-projects/issues/7302
4+
description: >-
5+
Allow disabling pod locality considerations in xDS using undocumented env-var `DISABLE_POD_LOCALITY_XDS`.

projects/gateway2/krtcollections/uniqueclients.go

+30-8
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,20 @@ func labeledRole(role string, labels map[string]string) string {
6464
return fmt.Sprintf("%s%s%d", role, xds.KeyDelimiter, utils.HashLabels(labels))
6565
}
6666

67+
// note: if `ns“ is empty, we assume the user doesn't want to use pod locality info, so we won't modify the role.
6768
func newUniqlyConnectedClient(node *envoy_config_core_v3.Node, ns string, labels map[string]string, locality PodLocality) UniqlyConnectedClient {
6869
role := node.GetMetadata().GetFields()[xds.RoleKey].GetStringValue()
69-
snapshotKey := labeledRole(role, labels)
70+
resourceName := role
71+
if ns != "" {
72+
snapshotKey := labeledRole(role, labels)
73+
resourceName = fmt.Sprintf("%s%s%s", snapshotKey, xds.KeyDelimiter, ns)
74+
}
7075
return UniqlyConnectedClient{
7176
Role: role,
7277
Namespace: ns,
7378
Locality: locality,
7479
Labels: labels,
75-
resourceName: fmt.Sprintf("%s%s%s", snapshotKey, xds.KeyDelimiter, ns),
80+
resourceName: resourceName,
7681
}
7782
}
7883

@@ -91,6 +96,7 @@ type callbacks struct {
9196
collection atomic.Pointer[callbacksCollection]
9297
}
9398

99+
// If augmentedPods is nil, we won't use the pod locality info, and all pods for the same gateway will receive the same config.
94100
type UniquelyConnectedClientsBulider func(ctx context.Context, handler *krt.DebugHandler, augmentedPods krt.Collection[LocalityPod]) krt.Collection[UniqlyConnectedClient]
95101

96102
// THIS IS THE SET OF THINGS WE RUN TRANSLATION FOR
@@ -173,7 +179,9 @@ func (x *callbacksCollection) del(sid int64) *UniqlyConnectedClient {
173179
func (x *callbacksCollection) add(sid int64, r *envoy_service_discovery_v3.DiscoveryRequest) (string, bool, error) {
174180

175181
var pod *LocalityPod
176-
if r.GetNode() != nil {
182+
// see if user wants to use pod locality info
183+
usePod := x.augmentedPods != nil
184+
if usePod && r.GetNode() != nil {
177185
podRef := getRef(r.GetNode())
178186
k := krt.Key[LocalityPod](krt.Named{Name: podRef.Name, Namespace: podRef.Namespace}.ResourceName())
179187
pod = x.augmentedPods.GetKey(k)
@@ -183,13 +191,22 @@ func (x *callbacksCollection) add(sid int64, r *envoy_service_discovery_v3.Disco
183191
defer x.stateLock.Unlock()
184192
c, ok := x.clients[sid]
185193
if !ok {
186-
if pod == nil {
187-
// error if we can't get the pod
188-
return "", false, fmt.Errorf("pod not found for node %v", r.GetNode())
194+
var locality PodLocality
195+
var ns string
196+
var labels map[string]string
197+
if usePod {
198+
if pod == nil {
199+
// we need to use the pod locality info, so it's an error if we can't get the pod
200+
return "", false, fmt.Errorf("pod not found for node %v", r.GetNode())
201+
} else {
202+
locality = pod.Locality
203+
ns = pod.Namespace
204+
labels = pod.AugmentedLabels
205+
}
189206
}
190-
x.logger.Debug("adding xds client", zap.Any("locality", pod.Locality), zap.String("ns", pod.Namespace), zap.Any("labels", pod.AugmentedLabels))
207+
x.logger.Debug("adding xds client", zap.Any("locality", locality), zap.String("ns", ns), zap.Any("labels", labels))
191208
// TODO: modify request to include the label that are relevant for the client?
192-
ucc := newUniqlyConnectedClient(r.GetNode(), pod.Namespace, pod.AugmentedLabels, pod.Locality)
209+
ucc := newUniqlyConnectedClient(r.GetNode(), ns, labels, locality)
193210
c = newConnectedClient(ucc.resourceName)
194211
x.clients[sid] = c
195212
currentUnique := x.uniqClientsCount[ucc.resourceName]
@@ -277,6 +294,11 @@ func (x *callbacks) OnFetchRequest(ctx context.Context, r *envoy_service_discove
277294
}
278295

279296
func (x *callbacksCollection) fetchRequest(_ context.Context, r *envoy_service_discovery_v3.DiscoveryRequest) error {
297+
// nothing special to do in a fetch request, as we don't need to maintain state
298+
if x.augmentedPods == nil {
299+
return nil
300+
}
301+
280302
var pod *LocalityPod
281303
podRef := getRef(r.GetNode())
282304
k := krt.Key[LocalityPod](krt.Named{Name: podRef.Name, Namespace: podRef.Namespace}.ResourceName())

projects/gateway2/krtcollections/uniqueclients_test.go

+25-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/solo-io/gloo/projects/gloo/pkg/xds"
1515
"google.golang.org/protobuf/proto"
1616
"google.golang.org/protobuf/types/known/structpb"
17+
"istio.io/istio/pkg/kube/krt"
1718
"istio.io/istio/pkg/kube/krt/krttest"
1819
corev1 "k8s.io/api/core/v1"
1920
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -65,15 +66,35 @@ func TestUniqueClients(t *testing.T) {
6566
},
6667
result: sets.New(fmt.Sprintf("gloo-kube-gateway-api~best-proxy-role~%d~ns", utils.HashLabels(map[string]string{corev1.LabelTopologyRegion: "region", corev1.LabelTopologyZone: "zone", "a": "b"}))),
6768
},
69+
{
70+
name: "no-pods",
71+
inputs: nil,
72+
requests: []*envoy_service_discovery_v3.DiscoveryRequest{
73+
{
74+
Node: &corev3.Node{
75+
Id: "podname.ns",
76+
Metadata: &structpb.Struct{
77+
Fields: map[string]*structpb.Value{
78+
xds.RoleKey: structpb.NewStringValue(glooutils.GatewayApiProxyValue + "~best-proxy-role"),
79+
},
80+
},
81+
},
82+
},
83+
},
84+
result: sets.New(fmt.Sprintf(glooutils.GatewayApiProxyValue + "~best-proxy-role")),
85+
},
6886
}
6987

7088
for _, tc := range testCases {
7189
t.Run(tc.name, func(t *testing.T) {
7290
g := NewWithT(t)
73-
mock := krttest.NewMock(t, tc.inputs)
74-
nodes := NewNodeMetadataCollection(krttest.GetMockCollection[*corev1.Node](mock))
75-
pods := NewLocalityPodsCollection(nodes, krttest.GetMockCollection[*corev1.Pod](mock), nil)
76-
pods.Synced().WaitUntilSynced(context.Background().Done())
91+
var pods krt.Collection[LocalityPod]
92+
if tc.inputs != nil {
93+
mock := krttest.NewMock(t, tc.inputs)
94+
nodes := NewNodeMetadataCollection(krttest.GetMockCollection[*corev1.Node](mock))
95+
pods = NewLocalityPodsCollection(nodes, krttest.GetMockCollection[*corev1.Pod](mock), nil)
96+
pods.Synced().WaitUntilSynced(context.Background().Done())
97+
}
7798

7899
cb, uccBuilder := NewUniquelyConnectedClients()
79100
ucc := uccBuilder(context.Background(), nil, pods)

projects/gateway2/setup/ggv2setup.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,12 @@ func StartGGv2WithConfig(ctx context.Context,
118118
settingsGVR,
119119
krt.WithName("GlooSettings"))
120120

121-
ucc := uccBuilder(ctx, setupOpts.KrtDebugger, augmentedPods)
121+
augmentedPodsForUcc := augmentedPods
122+
if envutils.IsEnvTruthy("DISABLE_POD_LOCALITY_XDS") {
123+
augmentedPodsForUcc = nil
124+
}
125+
126+
ucc := uccBuilder(ctx, setupOpts.KrtDebugger, augmentedPodsForUcc)
122127

123128
settingsSingle := krt.NewSingleton(func(ctx krt.HandlerContext) *glookubev1.Settings {
124129
s := krt.FetchOne(ctx, setting,

0 commit comments

Comments
 (0)