From 47ae7cbf522af448f8e78949244ebb8289559f25 Mon Sep 17 00:00:00 2001 From: Patrik Cyvoct Date: Fri, 19 Jun 2020 19:04:49 +0200 Subject: [PATCH] Add route type field to loadbalancer status ingress Signed-off-by: Patrik Cyvoct --- pkg/apis/core/types.go | 15 +++++++++++ pkg/proxy/iptables/proxier.go | 34 +++++++++++++------------ pkg/proxy/ipvs/proxier.go | 20 +++++++-------- pkg/proxy/service.go | 10 +++----- pkg/proxy/types.go | 4 +-- staging/src/k8s.io/api/core/v1/types.go | 15 +++++++++++ 6 files changed, 63 insertions(+), 35 deletions(-) diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index a2064817a64..cbf4aedbe90 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -3508,6 +3508,11 @@ type LoadBalancerIngress struct { // (typically AWS load-balancers) // +optional Hostname string + + // RouteType specifies the type of route to use for this ingress + // Defaults to `VIP` + // +optional + RouteType LoadBalancerRouteType } const ( @@ -3515,6 +3520,16 @@ const ( MaxServiceTopologyKeys = 16 ) +// LoadBalancerRouteType represents the type of route available for a LoadBalancer ingress +type LoadBalancerRouteType string + +const ( + // LoadBalancerRouteTypeVIP is the type of route used by a LoadBalancer where dstIP = lbIP + LoadBalancerRouteTypeVIP LoadBalancerRouteType = "VIP" + // LoadBalancerRouteTypeProxy is the type of route used by a proxy like LoadBalancer + LoadBalancerRouteTypeProxy LoadBalancerRouteType = "Proxy" +) + // IPFamily represents the IP Family (IPv4 or IPv6). This type is used // to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). type IPFamily string diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index 50d13c57308..a8e28dddfdc 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -782,10 +782,10 @@ func (proxier *Proxier) deleteEndpointConnections(connectionMap []proxy.ServiceE klog.Errorf("Failed to delete %s endpoint connections for externalIP %s, error: %v", epSvcPair.ServicePortName.String(), extIP, err) } } - for _, lbIP := range svcInfo.LoadBalancerIPStrings() { - err := conntrack.ClearEntriesForNAT(proxier.exec, lbIP, endpointIP, svcProto) + for _, lbIngress := range svcInfo.LoadBalancerIngress() { + err := conntrack.ClearEntriesForNAT(proxier.exec, lbIngress.IP, endpointIP, svcProto) if err != nil { - klog.Errorf("Failed to delete %s endpoint connections for LoabBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIP, err) + klog.Errorf("Failed to delete %s endpoint connections for LoabBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIngress.IP, err) } } } @@ -1161,8 +1161,8 @@ func (proxier *Proxier) syncProxyRules() { // Capture load-balancer ingress. fwChain := svcInfo.serviceFirewallChainName - for _, ingress := range svcInfo.LoadBalancerIPStrings() { - if ingress != "" { + for _, ingress := range svcInfo.LoadBalancerIngress() { + if ingress.IP != "" { if hasEndpoints { // create service firewall chain if chain, ok := existingNATChains[fwChain]; ok { @@ -1175,15 +1175,17 @@ func (proxier *Proxier) syncProxyRules() { // This currently works for loadbalancers that preserves source ips. // For loadbalancers which direct traffic to service NodePort, the firewall rules will not apply. - args = append(args[:0], - "-A", string(kubeServicesChain), - "-m", "comment", "--comment", fmt.Sprintf(`"%s loadbalancer IP"`, svcNameString), - "-m", protocol, "-p", protocol, - "-d", utilproxy.ToCIDR(net.ParseIP(ingress)), - "--dport", strconv.Itoa(svcInfo.Port()), - ) - // jump to service firewall chain - writeLine(proxier.natRules, append(args, "-j", string(fwChain))...) + if ingress.RouteType != v1.LoadBalancerRouteTypeProxy { + args = append(args[:0], + "-A", string(kubeServicesChain), + "-m", "comment", "--comment", fmt.Sprintf(`"%s loadbalancer IP"`, svcNameString), + "-m", protocol, "-p", protocol, + "-d", utilproxy.ToCIDR(net.ParseIP(ingress.IP)), + "--dport", strconv.Itoa(svcInfo.Port()), + ) + // jump to service firewall chain + writeLine(proxier.natRules, append(args, "-j", string(fwChain))...) + } args = append(args[:0], "-A", string(fwChain), @@ -1218,7 +1220,7 @@ func (proxier *Proxier) syncProxyRules() { // loadbalancer's backend hosts. In this case, request will not hit the loadbalancer but loop back directly. // Need to add the following rule to allow request on host. if allowFromNode { - writeLine(proxier.natRules, append(args, "-s", utilproxy.ToCIDR(net.ParseIP(ingress)), "-j", string(chosenChain))...) + writeLine(proxier.natRules, append(args, "-s", utilproxy.ToCIDR(net.ParseIP(ingress.IP)), "-j", string(chosenChain))...) } } @@ -1231,7 +1233,7 @@ func (proxier *Proxier) syncProxyRules() { "-A", string(kubeExternalServicesChain), "-m", "comment", "--comment", fmt.Sprintf(`"%s has no endpoints"`, svcNameString), "-m", protocol, "-p", protocol, - "-d", utilproxy.ToCIDR(net.ParseIP(ingress)), + "-d", utilproxy.ToCIDR(net.ParseIP(ingress.IP)), "--dport", strconv.Itoa(svcInfo.Port()), "-j", "REJECT", ) diff --git a/pkg/proxy/ipvs/proxier.go b/pkg/proxy/ipvs/proxier.go index 7d67008332c..df8370f4181 100644 --- a/pkg/proxy/ipvs/proxier.go +++ b/pkg/proxy/ipvs/proxier.go @@ -1332,11 +1332,11 @@ func (proxier *Proxier) syncProxyRules() { } // Capture load-balancer ingress. - for _, ingress := range svcInfo.LoadBalancerIPStrings() { - if ingress != "" { + for _, ingress := range svcInfo.LoadBalancerIngress() { + if ingress.IP != "" && ingress.RouteType != v1.LoadBalancerRouteTypeProxy { // ipset call entry = &utilipset.Entry{ - IP: ingress, + IP: ingress.IP, Port: svcInfo.Port(), Protocol: protocol, SetType: utilipset.HashIPPort, @@ -1371,7 +1371,7 @@ func (proxier *Proxier) syncProxyRules() { for _, src := range svcInfo.LoadBalancerSourceRanges() { // ipset call entry = &utilipset.Entry{ - IP: ingress, + IP: ingress.IP, Port: svcInfo.Port(), Protocol: protocol, Net: src, @@ -1395,10 +1395,10 @@ func (proxier *Proxier) syncProxyRules() { // Need to add the following rule to allow request on host. if allowFromNode { entry = &utilipset.Entry{ - IP: ingress, + IP: ingress.IP, Port: svcInfo.Port(), Protocol: protocol, - IP2: ingress, + IP2: ingress.IP, SetType: utilipset.HashIPPortIP, } // enumerate all white list source ip @@ -1412,7 +1412,7 @@ func (proxier *Proxier) syncProxyRules() { // ipvs call serv := &utilipvs.VirtualServer{ - Address: net.ParseIP(ingress), + Address: net.ParseIP(ingress.IP), Port: uint16(svcInfo.Port()), Protocol: string(svcInfo.Protocol()), Scheduler: proxier.ipvsScheduler, @@ -1957,10 +1957,10 @@ func (proxier *Proxier) deleteEndpointConnections(connectionMap []proxy.ServiceE klog.Errorf("Failed to delete %s endpoint connections for externalIP %s, error: %v", epSvcPair.ServicePortName.String(), extIP, err) } } - for _, lbIP := range svcInfo.LoadBalancerIPStrings() { - err := conntrack.ClearEntriesForNAT(proxier.exec, lbIP, endpointIP, svcProto) + for _, lbIngress := range svcInfo.LoadBalancerIngress() { + err := conntrack.ClearEntriesForNAT(proxier.exec, lbIngress.IP, endpointIP, svcProto) if err != nil { - klog.Errorf("Failed to delete %s endpoint connections for LoadBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIP, err) + klog.Errorf("Failed to delete %s endpoint connections for LoadBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIngress.IP, err) } } } diff --git a/pkg/proxy/service.go b/pkg/proxy/service.go index a00b2ddab1c..d8c2e0a9c5e 100644 --- a/pkg/proxy/service.go +++ b/pkg/proxy/service.go @@ -105,13 +105,9 @@ func (info *BaseServiceInfo) ExternalIPStrings() []string { return info.externalIPs } -// LoadBalancerIPStrings is part of ServicePort interface. -func (info *BaseServiceInfo) LoadBalancerIPStrings() []string { - var ips []string - for _, ing := range info.loadBalancerStatus.Ingress { - ips = append(ips, ing.IP) - } - return ips +// LoadBalancerIngress is part of ServicePort interface. +func (info *BaseServiceInfo) LoadBalancerIngress() []v1.LoadBalancerIngress { + return info.loadBalancerStatus.Ingress } // OnlyNodeLocalEndpoints is part of ServicePort interface. diff --git a/pkg/proxy/types.go b/pkg/proxy/types.go index 2d0f9e42856..db6c8b12828 100644 --- a/pkg/proxy/types.go +++ b/pkg/proxy/types.go @@ -73,8 +73,8 @@ type ServicePort interface { StickyMaxAgeSeconds() int // ExternalIPStrings returns service ExternalIPs as a string array. ExternalIPStrings() []string - // LoadBalancerIPStrings returns service LoadBalancerIPs as a string array. - LoadBalancerIPStrings() []string + // LoadBalancerIngress returns service an array of LoadBalancerIngress. + LoadBalancerIngress() []v1.LoadBalancerIngress // GetProtocol returns service protocol. Protocol() v1.Protocol // LoadBalancerSourceRanges returns service LoadBalancerSourceRanges if present empty array if not diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 45fd5d82367..dae1d0330ab 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -3971,6 +3971,11 @@ type LoadBalancerIngress struct { // (typically AWS load-balancers) // +optional Hostname string `json:"hostname,omitempty" protobuf:"bytes,2,opt,name=hostname"` + + // RouteType specifies the type of route to use for this ingress + // Defaults to `VIP` + // +optional + RouteType LoadBalancerRouteType `json:"routeType,omitempty" protobuf:"bytes,3,opt,name=routeType"` } const ( @@ -3978,6 +3983,16 @@ const ( MaxServiceTopologyKeys = 16 ) +// LoadBalancerRouteType represents the type of route available for a LoadBalancer ingress +type LoadBalancerRouteType string + +const ( + // LoadBalancerRouteTypeVIP is the type of route used by a LoadBalancer where dstIP = lbIP + LoadBalancerRouteTypeVIP LoadBalancerRouteType = "VIP" + // LoadBalancerRouteTypeProxy is the type of route used by a proxy like LoadBalancer + LoadBalancerRouteTypeProxy LoadBalancerRouteType = "Proxy" +) + // IPFamily represents the IP Family (IPv4 or IPv6). This type is used // to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). type IPFamily string