From 867da77c734adfe010e1244c123e8213f7278ed6 Mon Sep 17 00:00:00 2001 From: Maximilian Geberl Date: Fri, 5 Jun 2026 09:29:40 +0200 Subject: [PATCH 1/2] Sanitize K8s node names to meet load balancer target displayname requirements --- pkg/ccm/loadbalancer_spec.go | 30 ++++++++++++++++++++++++++- pkg/ccm/loadbalancer_spec_test.go | 34 +++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/pkg/ccm/loadbalancer_spec.go b/pkg/ccm/loadbalancer_spec.go index b957bdd1..754f7895 100644 --- a/pkg/ccm/loadbalancer_spec.go +++ b/pkg/ccm/loadbalancer_spec.go @@ -1,8 +1,10 @@ package ccm import ( + "crypto/sha256" "fmt" "net/netip" + "regexp" "slices" "strconv" "strings" @@ -200,6 +202,11 @@ var appoximateFlavorsMap = map[string]string{ "22b37153-8817-4c85-9805-92426b2f903c": p10, // t2i.1 } +var ( + // invalidTargetDisplayNameCharsRegexp matches any character that is NOT alphanumeric or a hyphen + invalidTargetDisplayNameCharsRegexp = regexp.MustCompile(`[^a-zA-Z0-9-]`) +) + // proxyProtocolEnableForPort determines whether portNumber should use the TCP proxy protocol (instead of TCP). func proxyProtocolEnableForPort(tcpProxyProtocolEnabled bool, tcpProxyProtocolPortFilter []uint16, portNumber int32) bool { if !tcpProxyProtocolEnabled { @@ -480,7 +487,7 @@ func lbSpecFromService( address := node.Status.Addresses[j] if address.Type == corev1.NodeInternalIP { targets = append(targets, loadbalancer.Target{ - DisplayName: &node.Name, + DisplayName: new(getSanitizeNodeNameForTarget(node.Name)), Ip: &address.Address, }) break @@ -754,3 +761,24 @@ func compareLBwithSpec(lb *loadbalancer.LoadBalancer, spec *loadbalancer.CreateL return fulfills, immutableChanged } + +// getSanitizeNodeNameForTarget returns a node name which fits in the DisplayName of a target. +// Replaces not allowed chars with +func getSanitizeNodeNameForTarget(nodeName string) string { + var cleanName string + cleanName = invalidTargetDisplayNameCharsRegexp.ReplaceAllString(nodeName, "-") + + // return node name if not to long and if not contain any invalid chars + if len(cleanName) <= 63 && + nodeName == cleanName { + return nodeName + } + + if len(cleanName) > 54 { + cleanName = cleanName[0:54] + } + + cleanName += fmt.Sprintf("-%x", sha256.Sum256([]byte(nodeName)))[:8] + + return cleanName +} diff --git a/pkg/ccm/loadbalancer_spec_test.go b/pkg/ccm/loadbalancer_spec_test.go index aa33cf35..b7b950bd 100644 --- a/pkg/ccm/loadbalancer_spec_test.go +++ b/pkg/ccm/loadbalancer_spec_test.go @@ -1989,3 +1989,37 @@ var _ = DescribeTable("compareLBwithSpec", }, }), ) + +var _ = DescribeTable("getSafeNodeName", + func(name, safe string) { + Expect(getSanitizeNodeNameForTarget(name)).To(Equal(safe)) + }, + Entry("Already safe", + "localhost", + "localhost", + ), + Entry("Already safe", + "node-01", + "node-01", + ), + Entry("Already safe exact 63 chars", + "node-0123456789012345678901234567890123456789001234567890123456", + "node-0123456789012345678901234567890123456789001234567890123456", + ), + Entry("replace dots", + "node-01.example.com", + "node-01-example-com-7c98300", + ), + Entry("shorten", + "a-very-long-node-01234567890123456789012345678901234567890.example.com", + "a-very-long-node-0123456789012345678901234567890123456-519d04d", + ), + Entry("shorten and replace dots", + "a.very.long.node-01234567890123456789012345678901234567890.example.com", + "a-very-long-node-0123456789012345678901234567890123456-f80f0fa", + ), + Entry("replace dots exact 54 chars", + "a.very.long.node-0123456789012345678901234.example.com", + "a-very-long-node-0123456789012345678901234-example-com-e241059", + ), +) From ccc4bbf132e4612711f32fab15c1d6bdf0fffdf0 Mon Sep 17 00:00:00 2001 From: Maximilian Geberl Date: Fri, 5 Jun 2026 14:19:26 +0200 Subject: [PATCH 2/2] Add PR Review suggestions --- pkg/ccm/loadbalancer_spec.go | 22 +++++++++++----------- pkg/ccm/loadbalancer_spec_test.go | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/ccm/loadbalancer_spec.go b/pkg/ccm/loadbalancer_spec.go index 754f7895..e88ff129 100644 --- a/pkg/ccm/loadbalancer_spec.go +++ b/pkg/ccm/loadbalancer_spec.go @@ -487,7 +487,7 @@ func lbSpecFromService( address := node.Status.Addresses[j] if address.Type == corev1.NodeInternalIP { targets = append(targets, loadbalancer.Target{ - DisplayName: new(getSanitizeNodeNameForTarget(node.Name)), + DisplayName: new(sanitizeNodeName(node.Name)), Ip: &address.Address, }) break @@ -762,23 +762,23 @@ func compareLBwithSpec(lb *loadbalancer.LoadBalancer, spec *loadbalancer.CreateL return fulfills, immutableChanged } -// getSanitizeNodeNameForTarget returns a node name which fits in the DisplayName of a target. +// sanitizeNodeName returns a node name which fits in the DisplayName of a target. // Replaces not allowed chars with -func getSanitizeNodeNameForTarget(nodeName string) string { - var cleanName string - cleanName = invalidTargetDisplayNameCharsRegexp.ReplaceAllString(nodeName, "-") +func sanitizeNodeName(nodeName string) string { + var sanitizedNodeName string + sanitizedNodeName = invalidTargetDisplayNameCharsRegexp.ReplaceAllString(nodeName, "-") // return node name if not to long and if not contain any invalid chars - if len(cleanName) <= 63 && - nodeName == cleanName { + if len(sanitizedNodeName) <= 63 && + nodeName == sanitizedNodeName { return nodeName } - if len(cleanName) > 54 { - cleanName = cleanName[0:54] + if len(sanitizedNodeName) > 54 { + sanitizedNodeName = sanitizedNodeName[0:54] } - cleanName += fmt.Sprintf("-%x", sha256.Sum256([]byte(nodeName)))[:8] + sanitizedNodeName += fmt.Sprintf("-%x", sha256.Sum256([]byte(nodeName)))[:8] - return cleanName + return sanitizedNodeName } diff --git a/pkg/ccm/loadbalancer_spec_test.go b/pkg/ccm/loadbalancer_spec_test.go index b7b950bd..c5f5fa48 100644 --- a/pkg/ccm/loadbalancer_spec_test.go +++ b/pkg/ccm/loadbalancer_spec_test.go @@ -1990,9 +1990,9 @@ var _ = DescribeTable("compareLBwithSpec", }), ) -var _ = DescribeTable("getSafeNodeName", +var _ = DescribeTable("sanitizeNodeName", func(name, safe string) { - Expect(getSanitizeNodeNameForTarget(name)).To(Equal(safe)) + Expect(sanitizeNodeName(name)).To(Equal(safe)) }, Entry("Already safe", "localhost",