From f060c9f51ddf907216dc504c852adb0bda2db950 Mon Sep 17 00:00:00 2001 From: EndlessSeeker <153817598+EndlessSeeker@users.noreply.github.com> Date: Mon, 22 Jun 2026 11:34:38 +0800 Subject: [PATCH] fix: preserve ingress load balancer hostnames (#3994) Signed-off-by: EndlessSeeker <1766508902@qq.com> --- pkg/ingress/kube/common/tool.go | 36 +++++-- pkg/ingress/kube/common/tool_test.go | 150 ++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 23 deletions(-) diff --git a/pkg/ingress/kube/common/tool.go b/pkg/ingress/kube/common/tool.go index 7d893a025..63e0492d7 100644 --- a/pkg/ingress/kube/common/tool.go +++ b/pkg/ingress/kube/common/tool.go @@ -364,6 +364,8 @@ func getLoadBalancerIp(svc *v1.Service) []string { hostName := strings.TrimSuffix(ingress.Hostname, SvcHostNameSuffix) if net.ParseIP(hostName) != nil { out = append(out, hostName) + } else { + out = append(out, ingress.Hostname) } } } @@ -389,7 +391,8 @@ func getSvcIpList(svcList []*v1.Service) []string { func SortLbIngressList(lbi []v1.LoadBalancerIngress) func(int, int) bool { return func(i int, j int) bool { - return lbi[i].IP < lbi[j].IP + return loadBalancerIngressAddress(lbi[i].IP, lbi[i].Hostname) < + loadBalancerIngressAddress(lbi[j].IP, lbi[j].Hostname) } } @@ -397,7 +400,11 @@ func GetLbStatusList(svcList []*v1.Service) []v1.LoadBalancerIngress { svcIpList := getSvcIpList(svcList) lbi := make([]v1.LoadBalancerIngress, 0, len(svcIpList)) for _, ep := range svcIpList { - lbi = append(lbi, v1.LoadBalancerIngress{IP: ep}) + if net.ParseIP(ep) != nil { + lbi = append(lbi, v1.LoadBalancerIngress{IP: ep}) + } else { + lbi = append(lbi, v1.LoadBalancerIngress{Hostname: ep}) + } } sort.SliceStable(lbi, SortLbIngressList(lbi)) @@ -406,7 +413,8 @@ func GetLbStatusList(svcList []*v1.Service) []v1.LoadBalancerIngress { func SortLbIngressListV1(lbi []networkingv1.IngressLoadBalancerIngress) func(int, int) bool { return func(i int, j int) bool { - return lbi[i].IP < lbi[j].IP + return loadBalancerIngressAddress(lbi[i].IP, lbi[i].Hostname) < + loadBalancerIngressAddress(lbi[j].IP, lbi[j].Hostname) } } @@ -414,7 +422,11 @@ func GetLbStatusListV1(svcList []*v1.Service) []networkingv1.IngressLoadBalancer svcIpList := getSvcIpList(svcList) lbi := make([]networkingv1.IngressLoadBalancerIngress, 0, len(svcIpList)) for _, ep := range svcIpList { - lbi = append(lbi, networkingv1.IngressLoadBalancerIngress{IP: ep}) + if net.ParseIP(ep) != nil { + lbi = append(lbi, networkingv1.IngressLoadBalancerIngress{IP: ep}) + } else { + lbi = append(lbi, networkingv1.IngressLoadBalancerIngress{Hostname: ep}) + } } sort.SliceStable(lbi, SortLbIngressListV1(lbi)) @@ -423,7 +435,8 @@ func GetLbStatusListV1(svcList []*v1.Service) []networkingv1.IngressLoadBalancer func SortLbIngressListV1Beta1(lbi []networkingv1beta1.IngressLoadBalancerIngress) func(int, int) bool { return func(i int, j int) bool { - return lbi[i].IP < lbi[j].IP + return loadBalancerIngressAddress(lbi[i].IP, lbi[i].Hostname) < + loadBalancerIngressAddress(lbi[j].IP, lbi[j].Hostname) } } @@ -431,9 +444,20 @@ func GetLbStatusListV1Beta1(svcList []*v1.Service) []networkingv1beta1.IngressLo svcIpList := getSvcIpList(svcList) lbi := make([]networkingv1beta1.IngressLoadBalancerIngress, 0, len(svcIpList)) for _, ep := range svcIpList { - lbi = append(lbi, networkingv1beta1.IngressLoadBalancerIngress{IP: ep}) + if net.ParseIP(ep) != nil { + lbi = append(lbi, networkingv1beta1.IngressLoadBalancerIngress{IP: ep}) + } else { + lbi = append(lbi, networkingv1beta1.IngressLoadBalancerIngress{Hostname: ep}) + } } sort.SliceStable(lbi, SortLbIngressListV1Beta1(lbi)) return lbi } + +func loadBalancerIngressAddress(ip, hostname string) string { + if ip != "" { + return ip + } + return hostname +} diff --git a/pkg/ingress/kube/common/tool_test.go b/pkg/ingress/kube/common/tool_test.go index 0b5249996..481a94626 100644 --- a/pkg/ingress/kube/common/tool_test.go +++ b/pkg/ingress/kube/common/tool_test.go @@ -21,6 +21,8 @@ import ( "istio.io/istio/pilot/pkg/model" "istio.io/istio/pkg/config" v1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" + networkingv1beta1 "k8s.io/api/networking/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/alibaba/higress/v2/pkg/ingress/kube/annotations" @@ -206,6 +208,9 @@ func TestGenerateUniqueRouteName(t *testing.T) { func TestGetLbStatusList(t *testing.T) { clusterPrefix = "gw-123-" svcName := clusterPrefix + aliyunHostname := "higress.cn-hangzhou.alb.aliyuncs.com" + awsHostname := "k8s-kubeingr-higressg-1234567890.eu-north-1.elb.amazonaws.com" + tencentHostname := "lb-12345678.clb.ap-guangzhou.tencentclb.com" svcList := []*v1.Service{ { ObjectMeta: metav1.ObjectMeta{ @@ -224,6 +229,57 @@ func TestGetLbStatusList(t *testing.T) { }, }, }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + }, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeLoadBalancer, + }, + Status: v1.ServiceStatus{ + LoadBalancer: v1.LoadBalancerStatus{ + Ingress: []v1.LoadBalancerIngress{ + { + Hostname: awsHostname, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + }, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeLoadBalancer, + }, + Status: v1.ServiceStatus{ + LoadBalancer: v1.LoadBalancerStatus{ + Ingress: []v1.LoadBalancerIngress{ + { + Hostname: aliyunHostname, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + }, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeLoadBalancer, + }, + Status: v1.ServiceStatus{ + LoadBalancer: v1.LoadBalancerStatus{ + Ingress: []v1.LoadBalancerIngress{ + { + Hostname: tencentHostname, + }, + }, + }, + }, + }, { ObjectMeta: metav1.ObjectMeta{ Name: svcName, @@ -295,17 +351,15 @@ func TestGetLbStatusList(t *testing.T) { } lbiList := GetLbStatusList(svcList) - if len(lbiList) != 4 { - t.Fatal("len should be 4") - } - - if lbiList[0].IP != "1.1.1.1" { - t.Fatal("should be 1.1.1.1") - } - - if lbiList[3].IP != "4.4.4.4" { - t.Fatal("should be 4.4.4.4") - } + assert.Equal(t, []v1.LoadBalancerIngress{ + {IP: "1.1.1.1"}, + {IP: "2.2.2.2"}, + {IP: "3.3.3.3"}, + {IP: "4.4.4.4"}, + {Hostname: aliyunHostname}, + {Hostname: awsHostname}, + {Hostname: tencentHostname}, + }, lbiList) } func TestSortRoutes(t *testing.T) { @@ -1012,6 +1066,9 @@ func TestPartMd5(t *testing.T) { func TestGetLbStatusListV1AndV1Beta1(t *testing.T) { clusterPrefix = "gw-123-" svcName := clusterPrefix + aliyunHostname := "higress.cn-hangzhou.alb.aliyuncs.com" + awsHostname := "k8s-kubeingr-higressg-1234567890.eu-north-1.elb.amazonaws.com" + tencentHostname := "lb-12345678.clb.ap-guangzhou.tencentclb.com" svcList := []*v1.Service{ { ObjectMeta: metav1.ObjectMeta{ @@ -1047,23 +1104,82 @@ func TestGetLbStatusListV1AndV1Beta1(t *testing.T) { }, }, }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + }, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeLoadBalancer, + }, + Status: v1.ServiceStatus{ + LoadBalancer: v1.LoadBalancerStatus{ + Ingress: []v1.LoadBalancerIngress{ + { + Hostname: awsHostname, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + }, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeLoadBalancer, + }, + Status: v1.ServiceStatus{ + LoadBalancer: v1.LoadBalancerStatus{ + Ingress: []v1.LoadBalancerIngress{ + { + Hostname: aliyunHostname, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: svcName, + }, + Spec: v1.ServiceSpec{ + Type: v1.ServiceTypeLoadBalancer, + }, + Status: v1.ServiceStatus{ + LoadBalancer: v1.LoadBalancerStatus{ + Ingress: []v1.LoadBalancerIngress{ + { + Hostname: tencentHostname, + }, + }, + }, + }, + }, } // Test the V1 version t.Run("GetLbStatusListV1", func(t *testing.T) { lbiList := GetLbStatusListV1(svcList) - assert.Equal(t, 2, len(lbiList), "There should be 2 entry points") - assert.Equal(t, "1.1.1.1", lbiList[0].IP, "The first IP should be 1.1.1.1") - assert.Equal(t, "2.2.2.2", lbiList[1].IP, "The second IP should be 2.2.2.2") + assert.Equal(t, []networkingv1.IngressLoadBalancerIngress{ + {IP: "1.1.1.1"}, + {IP: "2.2.2.2"}, + {Hostname: aliyunHostname}, + {Hostname: awsHostname}, + {Hostname: tencentHostname}, + }, lbiList) }) // Test the V1Beta1 version t.Run("GetLbStatusListV1Beta1", func(t *testing.T) { lbiList := GetLbStatusListV1Beta1(svcList) - assert.Equal(t, 2, len(lbiList), "There should be 2 entry points") - assert.Equal(t, "1.1.1.1", lbiList[0].IP, "The first IP should be 1.1.1.1") - assert.Equal(t, "2.2.2.2", lbiList[1].IP, "The second IP should be 2.2.2.2") + assert.Equal(t, []networkingv1beta1.IngressLoadBalancerIngress{ + {IP: "1.1.1.1"}, + {IP: "2.2.2.2"}, + {Hostname: aliyunHostname}, + {Hostname: awsHostname}, + {Hostname: tencentHostname}, + }, lbiList) }) }