From cdacf0bca84d6b727b2412ed3b8cb69b499482de Mon Sep 17 00:00:00 2001 From: Simon Delicata Date: Tue, 8 Jul 2025 11:58:04 +0200 Subject: [PATCH] Respect service.nativelb=false annotation when nativeLBByDefault is enabled --- .../kubernetes/crd/fixtures/services.yml | 32 ++++ .../kubernetes/crd/fixtures/tcp/services.yml | 39 ++++- .../tcp/with_global_native_service_lb.yml | 2 +- .../fixtures/tcp/with_native_service_lb.yml | 2 +- .../tcp/with_native_service_lb_disabled.yml | 12 ++ .../kubernetes/crd/fixtures/udp/services.yml | 37 ++++- .../udp/with_native_service_lb_disabled.yml | 11 ++ .../with_native_service_lb_disabled.yml | 13 ++ .../kubernetes/crd/kubernetes_test.go | 142 +++++++++++++++++- .../kubernetes/gateway/annotations.go | 2 +- .../kubernetes/gateway/annotations_test.go | 3 +- .../httproute/simple_nativelb_disabled.yml | 51 +++++++ .../kubernetes/gateway/fixtures/services.yml | 79 ++++++++++ .../tcproute/simple_nativelb_disabled.yml | 46 ++++++ pkg/provider/kubernetes/gateway/kubernetes.go | 7 +- .../kubernetes/gateway/kubernetes_test.go | 120 +++++++++++++++ ...ault-but-service-has-disabled-nativelb.yml | 53 +++++++ .../kubernetes/ingress/kubernetes_test.go | 31 ++++ 18 files changed, 669 insertions(+), 13 deletions(-) create mode 100644 pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb_disabled.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/udp/with_native_service_lb_disabled.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/with_native_service_lb_disabled.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/httproute/simple_nativelb_disabled.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_nativelb_disabled.yml create mode 100644 pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-lb-by-default-but-service-has-disabled-nativelb.yml diff --git a/pkg/provider/kubernetes/crd/fixtures/services.yml b/pkg/provider/kubernetes/crd/fixtures/services.yml index 86094ef8a..7c33a2c63 100644 --- a/pkg/provider/kubernetes/crd/fixtures/services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/services.yml @@ -301,6 +301,38 @@ spec: type: ClusterIP clusterIP: 10.10.0.1 +--- +apiVersion: v1 +kind: Service +metadata: + name: native-disabled-svc + namespace: default +spec: + ports: + - name: web + port: 80 + type: ClusterIP + clusterIP: 10.10.0.1 + +--- +kind: EndpointSlice +apiVersion: discovery.k8s.io/v1 +metadata: + name: native-disabled-svc-abc + namespace: default + labels: + kubernetes.io/service-name: native-disabled-svc +addressType: IPv4 +ports: + - name: web + port: 80 +endpoints: + - addresses: + - 10.10.0.20 + - 10.10.0.21 + conditions: + ready: true + --- apiVersion: v1 kind: Service diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml index 8c29006e8..05f49a53f 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml @@ -298,11 +298,46 @@ metadata: spec: ports: - - name: myapp - port: 8000 + - name: tcp + protocol: TCP + port: 9000 type: ClusterIP clusterIP: 10.10.0.1 +--- +apiVersion: v1 +kind: Service +metadata: + name: native-disabled-svc-tcp + namespace: default +spec: + ports: + - name: tcp + protocol: TCP + port: 9000 + type: ClusterIP + clusterIP: 10.10.0.1 + +--- +kind: EndpointSlice +apiVersion: discovery.k8s.io/v1 +metadata: + name: native-disabled-tcp-abc + namespace: default + labels: + kubernetes.io/service-name: native-disabled-svc-tcp +addressType: IPv4 +ports: + - name: tcp + protocol: TCP + port: 9000 +endpoints: + - addresses: + - 10.10.0.30 + - 10.10.0.31 + conditions: + ready: true + --- apiVersion: v1 kind: Service diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_global_native_service_lb.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_global_native_service_lb.yml index d8832498e..712119c00 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_global_native_service_lb.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_global_native_service_lb.yml @@ -12,4 +12,4 @@ spec: - match: HostSNI(`foo.com`) services: - name: native-svc-tcp - port: 8000 + port: 9000 diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb.yml index c2dbfca31..ad8305ac7 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb.yml @@ -12,5 +12,5 @@ spec: - match: HostSNI(`foo.com`) services: - name: native-svc-tcp - port: 8000 + port: 9000 nativeLB: true diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb_disabled.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb_disabled.yml new file mode 100644 index 000000000..e54b5b3c0 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb_disabled.yml @@ -0,0 +1,12 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteTCP +metadata: + name: tcp.route.native-disabled + namespace: default +spec: + routes: + - match: HostSNI(`foo.com`) + services: + - name: native-disabled-svc-tcp + port: 9000 + nativeLB: false diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/services.yml b/pkg/provider/kubernetes/crd/fixtures/udp/services.yml index f77643d36..8993ca084 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/services.yml @@ -252,11 +252,46 @@ metadata: spec: ports: - - name: myapp + - name: udp + protocol: UDP port: 8000 type: ClusterIP clusterIP: 10.10.0.1 +--- +apiVersion: v1 +kind: Service +metadata: + name: native-disabled-svc-udp + namespace: default +spec: + ports: + - name: udp + protocol: UDP + port: 8000 + type: ClusterIP + clusterIP: 10.10.0.1 + +--- +kind: EndpointSlice +apiVersion: discovery.k8s.io/v1 +metadata: + name: native-disabled-udp-abc + namespace: default + labels: + kubernetes.io/service-name: native-disabled-svc-udp +addressType: IPv4 +ports: + - name: udp + protocol: UDP + port: 8000 +endpoints: + - addresses: + - 10.10.0.30 + - 10.10.0.31 + conditions: + ready: true + --- apiVersion: v1 kind: Service diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_native_service_lb_disabled.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_native_service_lb_disabled.yml new file mode 100644 index 000000000..f8db343fa --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_native_service_lb_disabled.yml @@ -0,0 +1,11 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteUDP +metadata: + name: udp.route.native-disabled + namespace: default +spec: + routes: + - services: + - name: native-disabled-svc-udp + port: 8000 + nativeLB: false diff --git a/pkg/provider/kubernetes/crd/fixtures/with_native_service_lb_disabled.yml b/pkg/provider/kubernetes/crd/fixtures/with_native_service_lb_disabled.yml new file mode 100644 index 000000000..07a0accf8 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/with_native_service_lb_disabled.yml @@ -0,0 +1,13 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: test.route.native-disabled + namespace: default +spec: + routes: + - match: Host(`foo.com`) + kind: Rule + services: + - name: native-disabled-svc + port: 80 + nativeLB: false diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index d0b196181..da874e7c6 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -7774,7 +7774,7 @@ func TestNativeLB(t *testing.T) { LoadBalancer: &dynamic.TCPServersLoadBalancer{ Servers: []dynamic.TCPServer{ { - Address: "10.10.0.1:8000", + Address: "10.10.0.1:9000", Port: "", }, }, @@ -8371,6 +8371,52 @@ func TestGlobalNativeLB(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "HTTP with global native Service LB but service reference has nativeLB disabled", + paths: []string{"services.yml", "with_native_service_lb_disabled.yml"}, + NativeLBByDefault: true, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{ + "default-test-route-native-disabled-6f97418635c7e18853da": { + Service: "default-test-route-native-disabled-6f97418635c7e18853da", + Rule: "Host(`foo.com`)", + Priority: 0, + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "default-test-route-native-disabled-6f97418635c7e18853da": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Strategy: dynamic.BalancerStrategyWRR, + ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval}, + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.20:80", + }, + { + URL: "http://10.10.0.21:80", + }, + }, + PassHostHeader: pointer(true), + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, { desc: "HTTP with native Service LB in ingressroute", paths: []string{"services.yml", "with_native_service_lb.yml"}, @@ -8444,7 +8490,51 @@ func TestGlobalNativeLB(t *testing.T) { LoadBalancer: &dynamic.TCPServersLoadBalancer{ Servers: []dynamic.TCPServer{ { - Address: "10.10.0.1:8000", + Address: "10.10.0.1:9000", + Port: "", + }, + }, + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "TCP with global native Service LB but service reference has nativeLB disabled", + paths: []string{"tcp/services.yml", "tcp/with_native_service_lb_disabled.yml"}, + NativeLBByDefault: true, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Routers: map[string]*dynamic.TCPRouter{ + "default-tcp.route.native-disabled-fdd3e9338e47a45efefc": { + Service: "default-tcp.route.native-disabled-fdd3e9338e47a45efefc", + Rule: "HostSNI(`foo.com`)", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-tcp.route.native-disabled-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.30:9000", + Port: "", + }, + { + Address: "10.10.0.31:9000", Port: "", }, }, @@ -8484,7 +8574,7 @@ func TestGlobalNativeLB(t *testing.T) { LoadBalancer: &dynamic.TCPServersLoadBalancer{ Servers: []dynamic.TCPServer{ { - Address: "10.10.0.1:8000", + Address: "10.10.0.1:9000", Port: "", }, }, @@ -8574,6 +8664,49 @@ func TestGlobalNativeLB(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "UDP with global native Service LB but service reference has nativeLB disabled", + paths: []string{"udp/services.yml", "udp/with_native_service_lb_disabled.yml"}, + NativeLBByDefault: true, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{ + "default-udp.route.native-disabled-0": { + Service: "default-udp.route.native-disabled-0", + }, + }, + Services: map[string]*dynamic.UDPService{ + "default-udp.route.native-disabled-0": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.30:8000", + Port: "", + }, + { + Address: "10.10.0.31:8000", + Port: "", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, } for _, test := range testCases { @@ -8591,8 +8724,6 @@ func TestGlobalNativeLB(t *testing.T) { objects := k8s.MustParseYaml(yamlContent) for _, obj := range objects { switch o := obj.(type) { - case *corev1.Service, *corev1.Endpoints, *corev1.Secret: - k8sObjects = append(k8sObjects, o) case *traefikv1alpha1.IngressRoute: crdObjects = append(crdObjects, o) case *traefikv1alpha1.IngressRouteTCP: @@ -8608,6 +8739,7 @@ func TestGlobalNativeLB(t *testing.T) { case *traefikv1alpha1.TLSStore: crdObjects = append(crdObjects, o) default: + k8sObjects = append(k8sObjects, o) } } } diff --git a/pkg/provider/kubernetes/gateway/annotations.go b/pkg/provider/kubernetes/gateway/annotations.go index 8e82ae603..b17cc3cb1 100644 --- a/pkg/provider/kubernetes/gateway/annotations.go +++ b/pkg/provider/kubernetes/gateway/annotations.go @@ -16,7 +16,7 @@ type ServiceConfig struct { // Service is the service's configuration from annotations. type Service struct { - NativeLB bool `json:"nativeLB"` + NativeLB *bool `json:"nativeLB"` } func parseServiceAnnotations(annotations map[string]string) (ServiceConfig, error) { diff --git a/pkg/provider/kubernetes/gateway/annotations_test.go b/pkg/provider/kubernetes/gateway/annotations_test.go index 80537526a..5ca8c994d 100644 --- a/pkg/provider/kubernetes/gateway/annotations_test.go +++ b/pkg/provider/kubernetes/gateway/annotations_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "k8s.io/utils/ptr" ) func Test_parseServiceConfig(t *testing.T) { @@ -22,7 +23,7 @@ func Test_parseServiceConfig(t *testing.T) { }, expected: ServiceConfig{ Service: Service{ - NativeLB: true, + NativeLB: ptr.To(true), }, }, }, diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_nativelb_disabled.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_nativelb_disabled.yml new file mode 100644 index 000000000..989de4446 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_nativelb_disabled.yml @@ -0,0 +1,51 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + +--- +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: http-app-1 + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - "foo.com" + rules: + - matches: + - path: + type: Exact + value: /bar + backendRefs: + - name: whoami-native-disabled + port: 80 + weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/services.yml b/pkg/provider/kubernetes/gateway/fixtures/services.yml index 65376431b..2f864c2f5 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/services.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/services.yml @@ -471,3 +471,82 @@ spec: - protocol: TCP port: 10000 name: tcp-2 + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoami-native-disabled + namespace: default + annotations: + traefik.io/service.nativelb: "false" +spec: + clusterIP: 10.10.10.2 + ports: + - name: web + protocol: TCP + port: 80 + targetPort: web + selector: + app: containous + task: whoami + +--- +kind: EndpointSlice +apiVersion: discovery.k8s.io/v1 +metadata: + name: whoami-native-disabled-abc + namespace: default + labels: + kubernetes.io/service-name: whoami-native-disabled +addressType: IPv4 +ports: + - name: web + port: 80 +endpoints: + - addresses: + - 10.10.0.20 + - 10.10.0.21 + conditions: + ready: true + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoamitcp-native-disabled + namespace: default + annotations: + traefik.io/service.nativelb: "false" +spec: + clusterIP: 10.10.10.3 + ports: + - protocol: TCP + port: 9000 + name: tcp-1 + - protocol: TCP + port: 10000 + name: tcp-2 + +--- +kind: EndpointSlice +apiVersion: discovery.k8s.io/v1 +metadata: + name: whoamitcp-native-disabled-abc + namespace: default + labels: + kubernetes.io/service-name: whoamitcp-native-disabled +addressType: IPv4 +ports: + - name: tcp-1 + protocol: TCP + port: 9000 + - name: tcp-2 + protocol: TCP + port: 10000 +endpoints: + - addresses: + - 10.10.0.30 + - 10.10.0.31 + conditions: + ready: true diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_nativelb_disabled.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_nativelb_disabled.yml new file mode 100644 index 000000000..15f2518fd --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_nativelb_disabled.yml @@ -0,0 +1,46 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway-class + namespace: default +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-tcp-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: tcp + protocol: TCP + port: 9000 + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: TCPRoute + group: gateway.networking.k8s.io + +--- +kind: TCPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: tcp-app-1 + namespace: default +spec: + parentRefs: + - name: my-tcp-gateway + kind: Gateway + group: gateway.networking.k8s.io + rules: + - backendRefs: + - name: whoamitcp-native-disabled + port: 9000 + weight: 1 + kind: Service + group: "" \ No newline at end of file diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index 1f31045ca..3edd9d799 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -918,7 +918,12 @@ func (p *Provider) getBackendAddresses(namespace string, ref gatev1.BackendRef) return nil, corev1.ServicePort{}, fmt.Errorf("parsing service annotations config: %w", err) } - if p.NativeLBByDefault || annotationsConfig.Service.NativeLB { + nativeLB := p.NativeLBByDefault + if annotationsConfig.Service.NativeLB != nil { + nativeLB = *annotationsConfig.Service.NativeLB + } + + if nativeLB { if service.Spec.ClusterIP == "" || service.Spec.ClusterIP == "None" { return nil, corev1.ServicePort{}, fmt.Errorf("no clusterIP found for service: %s/%s", service.Namespace, service.Name) } diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index 89101ca45..f16051051 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -2522,6 +2522,69 @@ func TestLoadHTTPRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "Simple HTTPRoute with NativeLBByDefault enabled but service has disabled nativelb", + paths: []string{"services.yml", "httproute/simple_nativelb_disabled.yml"}, + nativeLB: true, + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { + EntryPoints: []string{"web"}, + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, + RuleSyntax: "default", + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "default-whoami-native-disabled-http-80", + Weight: ptr.To(1), + }, + }, + }, + }, + "default-whoami-native-disabled-http-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Strategy: dynamic.BalancerStrategyWRR, + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.20:80", + }, + { + URL: "http://10.10.0.21:80", + }, + }, + PassHostHeader: ptr.To(true), + ResponseForwarding: &dynamic.ResponseForwarding{ + FlushInterval: ptypes.Duration(100 * time.Millisecond), + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, } for _, test := range testCases { @@ -4429,6 +4492,63 @@ func TestLoadTCPRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "Simple TCPRoute with NativeLBByDefault enabled but service has disabled nativelb", + paths: []string{"services.yml", "tcproute/simple_nativelb_disabled.yml"}, + nativeLB: true, + entryPoints: map[string]Entrypoint{ + "tcp": {Address: ":9000"}, + }, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { + EntryPoints: []string{"tcp"}, + Service: "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", + Rule: "HostSNI(`*`)", + RuleSyntax: "default", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-whoamitcp-native-disabled-9000", + Weight: ptr.To(1), + }, + }, + }, + }, + "default-whoamitcp-native-disabled-9000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.30:9000", + }, + { + Address: "10.10.0.31:9000", + }, + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, } for _, test := range testCases { diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-lb-by-default-but-service-has-disabled-nativelb.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-lb-by-default-but-service-has-disabled-nativelb.yml new file mode 100644 index 000000000..a076f3c3e --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-lb-by-default-but-service-has-disabled-nativelb.yml @@ -0,0 +1,53 @@ +kind: Ingress +apiVersion: networking.k8s.io/v1 +metadata: + name: global-native-lb + namespace: default +spec: + rules: + - host: traefik.tchouk + http: + paths: + - path: /bar + backend: + service: + name: native-disabled-svc + port: + name: web + number: 8080 + pathType: Prefix + +--- +kind: Service +apiVersion: v1 +metadata: + name: native-disabled-svc + namespace: default + annotations: + traefik.ingress.kubernetes.io/service.nativelb: "false" +spec: + ports: + - name: web + port: 8080 + clusterIP: 10.0.0.1 + type: ClusterIP + externalName: traefik.wtf + +--- +kind: EndpointSlice +apiVersion: discovery.k8s.io/v1 +metadata: + name: native-disabled-svc-abc + namespace: default + labels: + kubernetes.io/service-name: native-disabled-svc +addressType: IPv4 +ports: + - name: web + port: 8080 +endpoints: + - addresses: + - 10.10.0.20 + - 10.10.0.21 + conditions: + ready: true \ No newline at end of file diff --git a/pkg/provider/kubernetes/ingress/kubernetes_test.go b/pkg/provider/kubernetes/ingress/kubernetes_test.go index 30d581995..34feae138 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress/kubernetes_test.go @@ -2139,6 +2139,37 @@ func TestLoadConfigurationFromIngressesWithNativeLBByDefault(t *testing.T) { }, }, }, + { + desc: "Ingress with native lb by default but service has disabled nativelb", + expected: &dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{ + "default-global-native-lb-traefik-tchouk-bar": { + Rule: "Host(`traefik.tchouk`) && PathPrefix(`/bar`)", + Service: "default-native-disabled-svc-web", + }, + }, + Services: map[string]*dynamic.Service{ + "default-native-disabled-svc-web": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Strategy: dynamic.BalancerStrategyWRR, + ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval}, + PassHostHeader: pointer(true), + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.20:8080", + }, + { + URL: "http://10.10.0.21:8080", + }, + }, + }, + }, + }, + }, + }, + }, } for _, test := range testCases {