Revert "Merge pull request #92312 from Sh4d1/kep_1860"

This reverts commit ef16faf409, reversing
changes made to 2343b8a68b.
This commit is contained in:
Patrik Cyvoct
2020-11-11 10:26:53 +01:00
parent 1cd2ed816a
commit d29665cc17
37 changed files with 915 additions and 1548 deletions

View File

@@ -3508,15 +3508,6 @@ type LoadBalancerIngress struct {
// (typically AWS load-balancers)
// +optional
Hostname string
// IPMode specifies how the load-balancer's IP behaves.
// Setting this to "VIP" indicates that the traffic passing through
// this load-balancer is delivered with the destination IP and port set to the load-balancer's IP and port.
// Setting this to "Proxy" indicates that the load-balancer acts like a proxy,
// delivering traffic with the destination IP and port set to the node's IP and nodePort or to the pod's IP and targetPort.
// This field can only be set when the ip field is also set, and defaults to "VIP" if not specified.
// +optional
IPMode *LoadBalancerIPMode
}
const (
@@ -3524,18 +3515,6 @@ const (
MaxServiceTopologyKeys = 16
)
// LoadBalancerIPMode represents the mode of the LoadBalancer ingress IP
type LoadBalancerIPMode string
const (
// LoadBalancerIPModeVIP indicates that the traffic passing through this LoadBalancer
// is delivered with the destination IP set to the specified LoadBalancer IP
LoadBalancerIPModeVIP LoadBalancerIPMode = "VIP"
// LoadBalancerIPModeProxy indicates that the specified LoadBalancer acts like a proxy,
// changing the destination IP to the node IP and the source IP to the LoadBalancer (mostly private) IP
LoadBalancerIPModeProxy LoadBalancerIPMode = "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

View File

@@ -19,7 +19,7 @@ package v1
import (
"time"
v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/kubernetes/pkg/util/parsers"
@@ -166,17 +166,6 @@ func SetDefaults_Service(obj *v1.Service) {
// further IPFamilies, IPFamilyPolicy defaulting is in ClusterIP alloc/reserve logic
// note: conversion logic handles cases where ClusterIPs is used (but not ClusterIP).
}
if utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) &&
obj.Spec.Type == v1.ServiceTypeLoadBalancer {
ipMode := v1.LoadBalancerIPModeVIP
for i, ing := range obj.Status.LoadBalancer.Ingress {
if ing.IP != "" && ing.IPMode == nil {
obj.Status.LoadBalancer.Ingress[i].IPMode = &ipMode
}
}
}
}
func SetDefaults_Pod(obj *v1.Pod) {
// If limits are specified, but requests are not, default requests to limits

View File

@@ -4291,7 +4291,6 @@ func Convert_core_List_To_v1_List(in *core.List, out *v1.List, s conversion.Scop
func autoConvert_v1_LoadBalancerIngress_To_core_LoadBalancerIngress(in *v1.LoadBalancerIngress, out *core.LoadBalancerIngress, s conversion.Scope) error {
out.IP = in.IP
out.Hostname = in.Hostname
out.IPMode = (*core.LoadBalancerIPMode)(unsafe.Pointer(in.IPMode))
return nil
}
@@ -4303,7 +4302,6 @@ func Convert_v1_LoadBalancerIngress_To_core_LoadBalancerIngress(in *v1.LoadBalan
func autoConvert_core_LoadBalancerIngress_To_v1_LoadBalancerIngress(in *core.LoadBalancerIngress, out *v1.LoadBalancerIngress, s conversion.Scope) error {
out.IP = in.IP
out.Hostname = in.Hostname
out.IPMode = (*v1.LoadBalancerIPMode)(unsafe.Pointer(in.IPMode))
return nil
}

View File

@@ -5983,10 +5983,6 @@ func ValidatePodLogOptions(opts *core.PodLogOptions) field.ErrorList {
return allErrs
}
var (
supportedLoadBalancerIPMode = sets.NewString(string(core.LoadBalancerIPModeVIP), string(core.LoadBalancerIPModeProxy))
)
// ValidateLoadBalancerStatus validates required fields on a LoadBalancerStatus
func ValidateLoadBalancerStatus(status *core.LoadBalancerStatus, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
@@ -5997,23 +5993,6 @@ func ValidateLoadBalancerStatus(status *core.LoadBalancerStatus, fldPath *field.
allErrs = append(allErrs, field.Invalid(idxPath.Child("ip"), ingress.IP, "must be a valid IP address"))
}
}
if utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) {
if len(ingress.IP) > 0 && ingress.IPMode == nil {
allErrs = append(allErrs, field.Required(idxPath.Child("ipMode"), "must be specified when `ip` is set"))
}
}
if ingress.IPMode != nil {
if len(ingress.IP) == 0 {
allErrs = append(allErrs, field.Forbidden(idxPath.Child("ipMode"), "may not be used when `ip` is not set"))
}
if !supportedLoadBalancerIPMode.Has(string(*ingress.IPMode)) {
allErrs = append(allErrs, field.NotSupported(idxPath.Child("ipMode"), ingress.IPMode, supportedLoadBalancerIPMode.List()))
}
}
if len(ingress.Hostname) > 0 {
for _, msg := range validation.IsDNS1123Subdomain(ingress.Hostname) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("hostname"), ingress.Hostname, msg))

View File

@@ -11189,90 +11189,6 @@ func TestValidateServiceCreate(t *testing.T) {
}
}
func TestValidateLoadBalancerStatus(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LoadBalancerIPMode, true)()
ipModeVIP := core.LoadBalancerIPModeVIP
ipModeProxy := core.LoadBalancerIPModeProxy
ipModeDummy := core.LoadBalancerIPMode("dummy")
testCases := []struct {
name string
tweakLBStatus func(s *core.LoadBalancerStatus)
numErrs int
}{
/* LoadBalancerIPMode*/
{
name: `valid vip ipMode`,
tweakLBStatus: func(s *core.LoadBalancerStatus) {
s.Ingress = []core.LoadBalancerIngress{
{
IP: "1.2.3.4",
IPMode: &ipModeVIP,
},
}
},
numErrs: 0,
},
{
name: `valid proxy ipMode`,
tweakLBStatus: func(s *core.LoadBalancerStatus) {
s.Ingress = []core.LoadBalancerIngress{
{
IP: "1.2.3.4",
IPMode: &ipModeProxy,
},
}
},
numErrs: 0,
},
{
name: `invalid ipMode`,
tweakLBStatus: func(s *core.LoadBalancerStatus) {
s.Ingress = []core.LoadBalancerIngress{
{
IP: "1.2.3.4",
IPMode: &ipModeDummy,
},
}
},
numErrs: 1,
},
{
name: `missing ipMode`,
tweakLBStatus: func(s *core.LoadBalancerStatus) {
s.Ingress = []core.LoadBalancerIngress{
{
IP: "1.2.3.4",
},
}
},
numErrs: 1,
},
{
name: `missing ip with ipMode present`,
tweakLBStatus: func(s *core.LoadBalancerStatus) {
s.Ingress = []core.LoadBalancerIngress{
{
IPMode: &ipModeProxy,
},
}
},
numErrs: 1,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
s := core.LoadBalancerStatus{}
tc.tweakLBStatus(&s)
errs := ValidateLoadBalancerStatus(&s, field.NewPath("status"))
if len(errs) != tc.numErrs {
t.Errorf("Unexpected error list for case %q(expected:%v got %v) - Errors:\n %v", tc.name, tc.numErrs, len(errs), errs.ToAggregate())
}
})
}
}
func TestValidateServiceExternalTrafficFieldsCombination(t *testing.T) {
testCases := []struct {
name string

View File

@@ -2146,11 +2146,6 @@ func (in *List) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LoadBalancerIngress) DeepCopyInto(out *LoadBalancerIngress) {
*out = *in
if in.IPMode != nil {
in, out := &in.IPMode, &out.IPMode
*out = new(LoadBalancerIPMode)
**out = **in
}
return
}
@@ -2170,9 +2165,7 @@ func (in *LoadBalancerStatus) DeepCopyInto(out *LoadBalancerStatus) {
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = make([]LoadBalancerIngress, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
copy(*out, *in)
}
return
}

View File

@@ -663,11 +663,6 @@ const (
// Enables kubelet support to size memory backed volumes
SizeMemoryBackedVolumes featuregate.Feature = "SizeMemoryBackedVolumes"
// owner: @Sh4d1
// alpha: v1.21
// LoadBalancerIPMode enables the IPMode field in the LoadBalancerIngress status of a Service
LoadBalancerIPMode featuregate.Feature = "LoadBalancerIPMode"
// owner: @andrewsykim @SergeyKanzhelev
// GA: v1.20
//
@@ -775,7 +770,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
HPAContainerMetrics: {Default: false, PreRelease: featuregate.Alpha},
RootCAConfigMap: {Default: true, PreRelease: featuregate.Beta},
SizeMemoryBackedVolumes: {Default: false, PreRelease: featuregate.Alpha},
LoadBalancerIPMode: {Default: false, PreRelease: featuregate.Alpha},
ExecProbeTimeout: {Default: true, PreRelease: featuregate.GA}, // lock to default in v1.21 and remove in v1.22
// inherited features from generic apiserver, relisted here to get a conflict if it is changed

View File

@@ -39,7 +39,6 @@ go_test(
srcs = ["proxier_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/features:go_default_library",
"//pkg/proxy:go_default_library",
"//pkg/proxy/healthcheck:go_default_library",
"//pkg/proxy/util:go_default_library",
@@ -54,8 +53,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/klog/v2:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",

View File

@@ -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 _, lbIngress := range svcInfo.LoadBalancerIngress() {
err := conntrack.ClearEntriesForNAT(proxier.exec, lbIngress.IP, endpointIP, svcProto)
for _, lbIP := range svcInfo.LoadBalancerIPStrings() {
err := conntrack.ClearEntriesForNAT(proxier.exec, lbIP, endpointIP, svcProto)
if err != nil {
klog.Errorf("Failed to delete %s endpoint connections for LoabBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIngress.IP, err)
klog.Errorf("Failed to delete %s endpoint connections for LoabBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIP, err)
}
}
}
@@ -1161,8 +1161,8 @@ func (proxier *Proxier) syncProxyRules() {
// Capture load-balancer ingress.
fwChain := svcInfo.serviceFirewallChainName
for _, ingress := range svcInfo.LoadBalancerIngress() {
if ingress.IP != "" {
for _, ingress := range svcInfo.LoadBalancerIPStrings() {
if ingress != "" {
if hasEndpoints {
// create service firewall chain
if chain, ok := existingNATChains[fwChain]; ok {
@@ -1175,17 +1175,15 @@ 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.
if !utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) || *ingress.IPMode == v1.LoadBalancerIPModeVIP {
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(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))...)
args = append(args[:0],
"-A", string(fwChain),
@@ -1220,7 +1218,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.IP)), "-j", string(chosenChain))...)
writeLine(proxier.natRules, append(args, "-s", utilproxy.ToCIDR(net.ParseIP(ingress)), "-j", string(chosenChain))...)
}
}
@@ -1233,7 +1231,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.IP)),
"-d", utilproxy.ToCIDR(net.ParseIP(ingress)),
"--dport", strconv.Itoa(svcInfo.Port()),
"-j", "REJECT",
)

View File

@@ -26,7 +26,6 @@ import (
"testing"
"time"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog/v2"
"github.com/stretchr/testify/assert"
@@ -35,7 +34,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/proxy"
"k8s.io/kubernetes/pkg/proxy/healthcheck"
utilproxy "k8s.io/kubernetes/pkg/proxy/util"
@@ -48,8 +46,6 @@ import (
"k8s.io/utils/exec"
fakeexec "k8s.io/utils/exec/testing"
utilpointer "k8s.io/utils/pointer"
featuregatetesting "k8s.io/component-base/featuregate/testing"
)
func checkAllLines(t *testing.T, table utiliptables.Table, save []byte, expectedLines map[utiliptables.Chain]string) {
@@ -2686,85 +2682,4 @@ COMMIT
assert.NotEqual(t, expectedIPTablesWithSlice, fp.iptablesData.String())
}
func TestLoadBalancerIngressRouteTypeProxy(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LoadBalancerIPMode, true)()
ipModeProxy := v1.LoadBalancerIPModeProxy
ipModeVIP := v1.LoadBalancerIPModeVIP
testCases := []struct {
svcIP string
svcLBIP string
ipMode *v1.LoadBalancerIPMode
expectedRule bool
}{
{
svcIP: "10.20.30.41",
svcLBIP: "1.2.3.4",
ipMode: &ipModeProxy,
expectedRule: false,
},
{
svcIP: "10.20.30.42",
svcLBIP: "1.2.3.5",
ipMode: &ipModeVIP,
expectedRule: true,
},
}
svcPort := 80
svcNodePort := 3001
svcPortName := proxy.ServicePortName{
NamespacedName: makeNSN("ns1", "svc1"),
Port: "p80",
Protocol: v1.ProtocolTCP,
}
for _, testCase := range testCases {
ipt := iptablestest.NewFake()
fp := NewFakeProxier(ipt, false)
makeServiceMap(fp,
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
svc.Spec.Type = "LoadBalancer"
svc.Spec.ClusterIP = testCase.svcIP
svc.Spec.Ports = []v1.ServicePort{{
Name: svcPortName.Port,
Port: int32(svcPort),
Protocol: v1.ProtocolTCP,
NodePort: int32(svcNodePort),
}}
svc.Status.LoadBalancer.Ingress = []v1.LoadBalancerIngress{{
IP: testCase.svcLBIP,
IPMode: testCase.ipMode,
}}
}),
)
epIP := "10.180.0.1"
makeEndpointsMap(fp,
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
ept.Subsets = []v1.EndpointSubset{{
Addresses: []v1.EndpointAddress{{
IP: epIP,
}},
Ports: []v1.EndpointPort{{
Name: svcPortName.Port,
Port: int32(svcPort),
Protocol: v1.ProtocolTCP,
}},
}}
}),
)
fp.syncProxyRules()
proto := strings.ToLower(string(v1.ProtocolTCP))
fwChain := string(serviceFirewallChainName(svcPortName.String(), proto))
kubeSvcRules := ipt.GetRules(string(kubeServicesChain))
if hasJump(kubeSvcRules, fwChain, testCase.svcLBIP, svcPort) != testCase.expectedRule {
errorf(fmt.Sprintf("Found jump to firewall chain %v", fwChain), kubeSvcRules, t)
}
}
}
// TODO(thockin): add *more* tests for syncProxyRules() or break it down further and test the pieces.

View File

@@ -15,7 +15,6 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//pkg/features:go_default_library",
"//pkg/proxy:go_default_library",
"//pkg/proxy/healthcheck:go_default_library",
"//pkg/proxy/ipvs/testing:go_default_library",
@@ -35,8 +34,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",

View File

@@ -1332,11 +1332,11 @@ func (proxier *Proxier) syncProxyRules() {
}
// Capture load-balancer ingress.
for _, ingress := range svcInfo.LoadBalancerIngress() {
if ingress.IP != "" && (!utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) || *ingress.IPMode == v1.LoadBalancerIPModeVIP) {
for _, ingress := range svcInfo.LoadBalancerIPStrings() {
if ingress != "" {
// ipset call
entry = &utilipset.Entry{
IP: ingress.IP,
IP: ingress,
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,
IP: ingress,
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,
IP: ingress,
Port: svcInfo.Port(),
Protocol: protocol,
IP2: ingress.IP,
IP2: ingress,
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.IP),
Address: net.ParseIP(ingress),
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 _, lbIngress := range svcInfo.LoadBalancerIngress() {
err := conntrack.ClearEntriesForNAT(proxier.exec, lbIngress.IP, endpointIP, svcProto)
for _, lbIP := range svcInfo.LoadBalancerIPStrings() {
err := conntrack.ClearEntriesForNAT(proxier.exec, lbIP, endpointIP, svcProto)
if err != nil {
klog.Errorf("Failed to delete %s endpoint connections for LoadBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIngress.IP, err)
klog.Errorf("Failed to delete %s endpoint connections for LoadBalancerIP %s, error: %v", epSvcPair.ServicePortName.String(), lbIP, err)
}
}
}

View File

@@ -33,8 +33,6 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/proxy"
"k8s.io/kubernetes/pkg/proxy/healthcheck"
netlinktest "k8s.io/kubernetes/pkg/proxy/ipvs/testing"
@@ -53,8 +51,6 @@ import (
utilpointer "k8s.io/utils/pointer"
utilnet "k8s.io/utils/net"
featuregatetesting "k8s.io/component-base/featuregate/testing"
)
const testHostname = "test-hostname"
@@ -4324,81 +4320,3 @@ func TestFilterCIDRs(t *testing.T) {
t.Errorf("cidrs %v is not expected %v", cidrs, expected)
}
}
func TestLoadBalancerIngressRouteTypeProxy(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LoadBalancerIPMode, true)()
ipModeProxy := v1.LoadBalancerIPModeProxy
ipModeVIP := v1.LoadBalancerIPModeVIP
testCases := []struct {
svcIP string
svcLBIP string
ipMode *v1.LoadBalancerIPMode
expectedServices int
}{
{
svcIP: "10.20.30.41",
svcLBIP: "1.2.3.4",
ipMode: &ipModeProxy,
expectedServices: 1,
},
{
svcIP: "10.20.30.42",
svcLBIP: "1.2.3.5",
ipMode: &ipModeVIP,
expectedServices: 2,
},
}
svcPort := 80
svcNodePort := 3001
svcPortName := proxy.ServicePortName{
NamespacedName: makeNSN("ns1", "svc1"),
Port: "p80",
}
for _, testCase := range testCases {
_, fp := buildFakeProxier()
makeServiceMap(fp,
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
svc.Spec.Type = "LoadBalancer"
svc.Spec.ClusterIP = testCase.svcIP
svc.Spec.Ports = []v1.ServicePort{{
Name: svcPortName.Port,
Port: int32(svcPort),
Protocol: v1.ProtocolTCP,
NodePort: int32(svcNodePort),
}}
svc.Status.LoadBalancer.Ingress = []v1.LoadBalancerIngress{{
IP: testCase.svcLBIP,
IPMode: testCase.ipMode,
}}
}),
)
epIP := "10.180.0.1"
makeEndpointsMap(fp,
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
ept.Subsets = []v1.EndpointSubset{{
Addresses: []v1.EndpointAddress{{
IP: epIP,
}},
Ports: []v1.EndpointPort{{
Name: svcPortName.Port,
Port: int32(svcPort),
}},
}}
}),
)
fp.syncProxyRules()
services, err := fp.ipvs.GetVirtualServers()
if err != nil {
t.Errorf("Failed to get ipvs services, err: %v", err)
}
if len(services) != testCase.expectedServices {
t.Errorf("Expected %d ipvs services, got %d", testCase.expectedServices, len(services))
}
}
}

View File

@@ -105,9 +105,13 @@ func (info *BaseServiceInfo) ExternalIPStrings() []string {
return info.externalIPs
}
// LoadBalancerIngress is part of ServicePort interface.
func (info *BaseServiceInfo) LoadBalancerIngress() []v1.LoadBalancerIngress {
return info.loadBalancerStatus.Ingress
// 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
}
// OnlyNodeLocalEndpoints is part of ServicePort interface.
@@ -163,16 +167,23 @@ func (sct *ServiceChangeTracker) newBaseServiceInfo(port *v1.ServicePort, servic
klog.V(4).Infof("service change tracker(%v) ignored the following load balancer source ranges(%s) for service %v/%v as they don't match IPFamily", sct.ipFamily, strings.Join(incorrectIPs, ","), service.Namespace, service.Name)
}
correctIngresses, incorrectIngresses := utilproxy.FilterIncorrectLoadBalancerIngress(service.Status.LoadBalancer.Ingress, sct.ipFamily)
// Obtain Load Balancer Ingress IPs
var ips []string
for _, ing := range service.Status.LoadBalancer.Ingress {
ips = append(ips, ing.IP)
}
info.loadBalancerStatus.Ingress = correctIngresses
if len(ips) > 0 {
correctIPs, incorrectIPs := utilproxy.FilterIncorrectIPVersion(ips, sct.ipFamily)
if len(incorrectIPs) > 0 {
klog.V(4).Infof("service change tracker(%v) ignored the following load balancer(%s) ingress ips for service %v/%v as they don't match IPFamily", sct.ipFamily, strings.Join(incorrectIPs, ","), service.Namespace, service.Name)
if len(incorrectIngresses) > 0 {
var incorrectIPs []string
for _, incorrectIng := range incorrectIngresses {
incorrectIPs = append(incorrectIPs, incorrectIng.IP)
}
klog.V(4).Infof("service change tracker(%v) ignored the following load balancer(%s) ingress ips for service %v/%v as they don't match IPFamily", sct.ipFamily, strings.Join(incorrectIPs, ","), service.Namespace, service.Name)
// Create the LoadBalancerStatus with the filtered IPs
for _, ip := range correctIPs {
info.loadBalancerStatus.Ingress = append(info.loadBalancerStatus.Ingress, v1.LoadBalancerIngress{IP: ip})
}
}
if apiservice.NeedsHealthCheck(service) {

View File

@@ -73,8 +73,8 @@ type ServicePort interface {
StickyMaxAgeSeconds() int
// ExternalIPStrings returns service ExternalIPs as a string array.
ExternalIPStrings() []string
// LoadBalancerIngress returns service an array of LoadBalancerIngress.
LoadBalancerIngress() []v1.LoadBalancerIngress
// LoadBalancerIPStrings returns service LoadBalancerIPs as a string array.
LoadBalancerIPStrings() []string
// GetProtocol returns service protocol.
Protocol() v1.Protocol
// LoadBalancerSourceRanges returns service LoadBalancerSourceRanges if present empty array if not

View File

@@ -403,26 +403,3 @@ func GetClusterIPByFamily(ipFamily v1.IPFamily, service *v1.Service) string {
return ""
}
// FilterIncorrectLoadBalancerIngress filters out the ingresses with an IP version different from the given one
func FilterIncorrectLoadBalancerIngress(ingresses []v1.LoadBalancerIngress, ipFamily v1.IPFamily) ([]v1.LoadBalancerIngress, []v1.LoadBalancerIngress) {
var validIngresses []v1.LoadBalancerIngress
var invalidIngresses []v1.LoadBalancerIngress
for _, ing := range ingresses {
// []string{ing.IP} have a len of 1, so len(correctIPs) + len(incorrectIPs) == 1
correctIPs, _ := FilterIncorrectIPVersion([]string{ing.IP}, ipFamily)
// len is either 1 or 0
if len(correctIPs) == 1 {
// Update the LoadBalancerStatus with the filtered IP
validIngresses = append(validIngresses, ing)
continue
}
// here len(incorrectIPs) == 1 since len(correctIPs) == 0
invalidIngresses = append(invalidIngresses, ing)
}
return validIngresses, invalidIngresses
}

View File

@@ -822,179 +822,3 @@ func TestGetClusterIPByFamily(t *testing.T) {
}
}
func TestFilterIncorrectLoadBalancerIngress(t *testing.T) {
ipModeVIP := v1.LoadBalancerIPModeVIP
testCases := []struct {
name string
ingresses []v1.LoadBalancerIngress
ipFamily v1.IPFamily
expectedCorrect []v1.LoadBalancerIngress
expectedIncorrect []v1.LoadBalancerIngress
}{
{
name: "IPv4 only valid ingresses",
ipFamily: v1.IPv4Protocol,
ingresses: []v1.LoadBalancerIngress{
{
IP: "1.2.3.4",
IPMode: &ipModeVIP,
},
{
IP: "1.2.3.5",
},
},
expectedCorrect: []v1.LoadBalancerIngress{
{
IP: "1.2.3.4",
IPMode: &ipModeVIP,
},
{
IP: "1.2.3.5",
},
},
expectedIncorrect: nil,
},
{
name: "IPv4 some invalid ingresses",
ipFamily: v1.IPv4Protocol,
ingresses: []v1.LoadBalancerIngress{
{
IP: "1.2.3.4",
IPMode: &ipModeVIP,
},
{
IP: "2000::1",
},
{
Hostname: "dummy",
},
},
expectedCorrect: []v1.LoadBalancerIngress{
{
IP: "1.2.3.4",
IPMode: &ipModeVIP,
},
{
Hostname: "dummy", // weirdly no IP is a valid IPv4 but invalid IPv6
},
},
expectedIncorrect: []v1.LoadBalancerIngress{
{
IP: "2000::1",
},
},
},
{
name: "IPv4 only invalid ingresses",
ipFamily: v1.IPv4Protocol,
ingresses: []v1.LoadBalancerIngress{
{
IP: "2000::1",
},
{
IP: "2000::1",
IPMode: &ipModeVIP,
},
},
expectedCorrect: nil,
expectedIncorrect: []v1.LoadBalancerIngress{
{
IP: "2000::1",
},
{
IP: "2000::1",
IPMode: &ipModeVIP,
},
},
},
{
name: "IPv6 only valid ingresses",
ipFamily: v1.IPv6Protocol,
ingresses: []v1.LoadBalancerIngress{
{
IP: "2000::1",
IPMode: &ipModeVIP,
},
{
IP: "2000::2",
},
},
expectedCorrect: []v1.LoadBalancerIngress{
{
IP: "2000::1",
IPMode: &ipModeVIP,
},
{
IP: "2000::2",
},
},
expectedIncorrect: nil,
},
{
name: "IPv6 some invalid ingresses",
ipFamily: v1.IPv6Protocol,
ingresses: []v1.LoadBalancerIngress{
{
IP: "2000::1",
IPMode: &ipModeVIP,
},
{
IP: "1.2.3.4",
},
{
Hostname: "dummy",
},
},
expectedCorrect: []v1.LoadBalancerIngress{
{
IP: "2000::1",
IPMode: &ipModeVIP,
},
},
expectedIncorrect: []v1.LoadBalancerIngress{
{
IP: "1.2.3.4",
},
{
Hostname: "dummy", // weirdly no IP is a valid IPv4 but invalid IPv6
},
},
},
{
name: "IPv6 only invalid ingresses",
ipFamily: v1.IPv6Protocol,
ingresses: []v1.LoadBalancerIngress{
{
IP: "1.2.3.4",
},
{
IP: "1.2.3.5",
IPMode: &ipModeVIP,
},
},
expectedCorrect: nil,
expectedIncorrect: []v1.LoadBalancerIngress{
{
IP: "1.2.3.4",
},
{
IP: "1.2.3.5",
IPMode: &ipModeVIP,
},
},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
correctIngresses, incorrectIngresses := FilterIncorrectLoadBalancerIngress(testCase.ingresses, testCase.ipFamily)
if !reflect.DeepEqual(correctIngresses, testCase.expectedCorrect) {
t.Errorf("Test %v failed: expected %v, got %v", testCase.name, testCase.expectedCorrect, correctIngresses)
}
if !reflect.DeepEqual(incorrectIngresses, testCase.expectedIncorrect) {
t.Errorf("Test %v failed: expected %v, got %v", testCase.name, testCase.expectedIncorrect, incorrectIngresses)
}
})
}
}

View File

@@ -179,12 +179,6 @@ func dropServiceDisabledFields(newSvc *api.Service, oldSvc *api.Service) {
if !utilfeature.DefaultFeatureGate.Enabled(features.ServiceTopology) && !topologyKeysInUse(oldSvc) {
newSvc.Spec.TopologyKeys = nil
}
if !utilfeature.DefaultFeatureGate.Enabled(features.LoadBalancerIPMode) && !loadbalancerIPModeInUse(oldSvc) {
for _, ing := range newSvc.Status.LoadBalancer.Ingress {
ing.IPMode = nil
}
}
}
// returns true if svc.Spec.ServiceIPFamily field is in use
@@ -208,19 +202,6 @@ func topologyKeysInUse(svc *api.Service) bool {
return len(svc.Spec.TopologyKeys) > 0
}
// returns true when the LoadBalancer Ingress IPMode fields are in use.
func loadbalancerIPModeInUse(svc *api.Service) bool {
if svc == nil {
return false
}
for _, ing := range svc.Status.LoadBalancer.Ingress {
if ing.IPMode != nil {
return true
}
}
return false
}
type serviceStatusStrategy struct {
Strategy
}