k8s-operator: reset service status before append (#17120)

This commit fixes an issue within the service reconciler where we end
up in a constant reconciliation loop. When reconciling, the loadbalancer
status is appended to but not reset between each reconciliation, leading
to an ever growing slice of duplicate statuses.

Fixes https://github.com/tailscale/tailscale/issues/17105
Fixes https://github.com/tailscale/tailscale/issues/17107

Signed-off-by: David Bond <davidsbond93@gmail.com>
This commit is contained in:
David Bond 2025-09-15 12:37:28 +01:00 committed by GitHub
parent 7d2101f352
commit 782c16c513
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 4 deletions

View File

@ -173,6 +173,10 @@ func TestLoadBalancerClass(t *testing.T) {
}, },
}, },
} }
// Perform an additional reconciliation loop here to ensure resources don't change through side effects. Mainly
// to prevent infinite reconciliation
expectReconciled(t, sr, "default", "test")
expectEqual(t, fc, want) expectEqual(t, fc, want)
// Turn the service back into a ClusterIP service, which should make the // Turn the service back into a ClusterIP service, which should make the

View File

@ -348,9 +348,10 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
dev := devices[0] dev := devices[0]
logger.Debugf("setting Service LoadBalancer status to %q, %s", dev.hostname, strings.Join(dev.ips, ", ")) logger.Debugf("setting Service LoadBalancer status to %q, %s", dev.hostname, strings.Join(dev.ips, ", "))
svc.Status.LoadBalancer.Ingress = append(svc.Status.LoadBalancer.Ingress, corev1.LoadBalancerIngress{
Hostname: dev.hostname, ingress := []corev1.LoadBalancerIngress{
}) {Hostname: dev.hostname},
}
clusterIPAddr, err := netip.ParseAddr(svc.Spec.ClusterIP) clusterIPAddr, err := netip.ParseAddr(svc.Spec.ClusterIP)
if err != nil { if err != nil {
@ -365,10 +366,11 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
continue continue
} }
if addr.Is4() == clusterIPAddr.Is4() { // only add addresses of the same family if addr.Is4() == clusterIPAddr.Is4() { // only add addresses of the same family
svc.Status.LoadBalancer.Ingress = append(svc.Status.LoadBalancer.Ingress, corev1.LoadBalancerIngress{IP: ip}) ingress = append(ingress, corev1.LoadBalancerIngress{IP: ip})
} }
} }
svc.Status.LoadBalancer.Ingress = ingress
tsoperator.SetServiceCondition(svc, tsapi.ProxyReady, metav1.ConditionTrue, reasonProxyCreated, reasonProxyCreated, a.clock, logger) tsoperator.SetServiceCondition(svc, tsapi.ProxyReady, metav1.ConditionTrue, reasonProxyCreated, reasonProxyCreated, a.clock, logger)
return nil return nil
} }