Merge pull request #96488 from basantsa1989/kproxy_cleanup

Kube-proxy cleanup: Changing FilterIncorrectIP/CIDR functions to MapIPsToIPFamily that returns a map
This commit is contained in:
Kubernetes Prow Robot 2020-12-08 17:28:52 -08:00 committed by GitHub
commit d2662b9842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 203 additions and 49 deletions

View File

@ -294,10 +294,11 @@ func NewProxier(ipt utiliptables.Interface,
ipFamily = v1.IPv6Protocol
}
var incorrectAddresses []string
nodePortAddresses, incorrectAddresses = utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, ipFamily)
if len(incorrectAddresses) > 0 {
klog.Warningf("NodePortAddresses of wrong family; %s", incorrectAddresses)
ipFamilyMap := utilproxy.MapCIDRsByIPFamily(nodePortAddresses)
nodePortAddresses = ipFamilyMap[ipFamily]
// Log the IPs not matching the ipFamily
if ips, ok := ipFamilyMap[utilproxy.OtherIPFamily(ipFamily)]; ok && len(ips) > 0 {
klog.Warningf("IP Family: %s, NodePortAddresses of wrong family; %s", ipFamily, strings.Join(ips, ","))
}
proxier := &Proxier{
@ -367,17 +368,17 @@ func NewDualStackProxier(
nodePortAddresses []string,
) (proxy.Provider, error) {
// Create an ipv4 instance of the single-stack proxier
nodePortAddresses4, nodePortAddresses6 := utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, v1.IPv4Protocol)
ipFamilyMap := utilproxy.MapCIDRsByIPFamily(nodePortAddresses)
ipv4Proxier, err := NewProxier(ipt[0], sysctl,
exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[0], hostname,
nodeIP[0], recorder, healthzServer, nodePortAddresses4)
nodeIP[0], recorder, healthzServer, ipFamilyMap[v1.IPv4Protocol])
if err != nil {
return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
}
ipv6Proxier, err := NewProxier(ipt[1], sysctl,
exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[1], hostname,
nodeIP[1], recorder, healthzServer, nodePortAddresses6)
nodeIP[1], recorder, healthzServer, ipFamilyMap[v1.IPv6Protocol])
if err != nil {
return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err)
}

View File

@ -450,11 +450,13 @@ func NewProxier(ipt utiliptables.Interface,
endpointSlicesEnabled := utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceProxying)
var incorrectAddresses []string
nodePortAddresses, incorrectAddresses = utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, ipFamily)
if len(incorrectAddresses) > 0 {
klog.Warningf("NodePortAddresses of wrong family; %s", incorrectAddresses)
ipFamilyMap := utilproxy.MapCIDRsByIPFamily(nodePortAddresses)
nodePortAddresses = ipFamilyMap[ipFamily]
// Log the IPs not matching the ipFamily
if ips, ok := ipFamilyMap[utilproxy.OtherIPFamily(ipFamily)]; ok && len(ips) > 0 {
klog.Warningf("IP Family: %s, NodePortAddresses of wrong family; %s", ipFamily, strings.Join(ips, ","))
}
proxier := &Proxier{
ipFamily: ipFamily,
portsMap: make(map[utilproxy.LocalPort]utilproxy.Closeable),
@ -532,14 +534,14 @@ func NewDualStackProxier(
safeIpset := newSafeIpset(ipset)
nodePortAddresses4, nodePortAddresses6 := utilproxy.FilterIncorrectCIDRVersion(nodePortAddresses, v1.IPv4Protocol)
ipFamilyMap := utilproxy.MapCIDRsByIPFamily(nodePortAddresses)
// Create an ipv4 instance of the single-stack proxier
ipv4Proxier, err := NewProxier(ipt[0], ipvs, safeIpset, sysctl,
exec, syncPeriod, minSyncPeriod, filterCIDRs(false, excludeCIDRs), strictARP,
tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit,
localDetectors[0], hostname, nodeIP[0],
recorder, healthzServer, scheduler, nodePortAddresses4, kernelHandler)
recorder, healthzServer, scheduler, ipFamilyMap[v1.IPv4Protocol], kernelHandler)
if err != nil {
return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
}
@ -548,7 +550,7 @@ func NewDualStackProxier(
exec, syncPeriod, minSyncPeriod, filterCIDRs(true, excludeCIDRs), strictARP,
tcpTimeout, tcpFinTimeout, udpTimeout, masqueradeAll, masqueradeBit,
localDetectors[1], hostname, nodeIP[1],
nil, nil, scheduler, nodePortAddresses6, kernelHandler)
nil, nil, scheduler, ipFamilyMap[v1.IPv6Protocol], kernelHandler)
if err != nil {
return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err)
}

View File

@ -156,15 +156,19 @@ func (sct *ServiceChangeTracker) newBaseServiceInfo(port *v1.ServicePort, servic
// services, this is actually expected. Hence we downgraded from reporting by events
// to just log lines with high verbosity
var incorrectIPs []string
info.externalIPs, incorrectIPs = utilproxy.FilterIncorrectIPVersion(service.Spec.ExternalIPs, sct.ipFamily)
if len(incorrectIPs) > 0 {
klog.V(4).Infof("service change tracker(%v) ignored the following external IPs(%s) for service %v/%v as they don't match IPFamily", sct.ipFamily, strings.Join(incorrectIPs, ","), service.Namespace, service.Name)
ipFamilyMap := utilproxy.MapIPsByIPFamily(service.Spec.ExternalIPs)
info.externalIPs = ipFamilyMap[sct.ipFamily]
// Log the IPs not matching the ipFamily
if ips, ok := ipFamilyMap[utilproxy.OtherIPFamily(sct.ipFamily)]; ok && len(ips) > 0 {
klog.V(4).Infof("service change tracker(%v) ignored the following external IPs(%s) for service %v/%v as they don't match IPFamily", sct.ipFamily, strings.Join(ips, ","), service.Namespace, service.Name)
}
info.loadBalancerSourceRanges, incorrectIPs = utilproxy.FilterIncorrectCIDRVersion(loadBalancerSourceRanges, sct.ipFamily)
if len(incorrectIPs) > 0 {
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)
ipFamilyMap = utilproxy.MapCIDRsByIPFamily(loadBalancerSourceRanges)
info.loadBalancerSourceRanges = ipFamilyMap[sct.ipFamily]
// Log the CIDRs not matching the ipFamily
if cidrs, ok := ipFamilyMap[utilproxy.OtherIPFamily(sct.ipFamily)]; ok && len(cidrs) > 0 {
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(cidrs, ","), service.Namespace, service.Name)
}
// Obtain Load Balancer Ingress IPs
@ -174,14 +178,14 @@ func (sct *ServiceChangeTracker) newBaseServiceInfo(port *v1.ServicePort, servic
}
if len(ips) > 0 {
correctIPs, incorrectIPs := utilproxy.FilterIncorrectIPVersion(ips, sct.ipFamily)
ipFamilyMap = utilproxy.MapIPsByIPFamily(ips)
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 ipList, ok := ipFamilyMap[utilproxy.OtherIPFamily(sct.ipFamily)]; ok && len(ipList) > 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(ipList, ","), service.Namespace, service.Name)
}
// Create the LoadBalancerStatus with the filtered IPs
for _, ip := range correctIPs {
for _, ip := range ipFamilyMap[sct.ipFamily] {
info.loadBalancerStatus.Ingress = append(info.loadBalancerStatus.Ingress, v1.LoadBalancerIngress{IP: ip})
}
}

View File

@ -434,7 +434,9 @@ func TestServiceToServiceMap(t *testing.T) {
},
},
{
desc: "service with extra space in LoadBalancerSourceRanges",
desc: "service with extra space in LoadBalancerSourceRanges",
ipFamily: v1.IPv4Protocol,
service: &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "extra-space",

View File

@ -255,26 +255,64 @@ func LogAndEmitIncorrectIPVersionEvent(recorder record.EventRecorder, fieldName,
}
}
// FilterIncorrectIPVersion filters out the incorrect IP version case from a slice of IP strings.
func FilterIncorrectIPVersion(ipStrings []string, ipfamily v1.IPFamily) ([]string, []string) {
return filterWithCondition(ipStrings, (ipfamily == v1.IPv6Protocol), utilnet.IsIPv6String)
}
// FilterIncorrectCIDRVersion filters out the incorrect IP version case from a slice of CIDR strings.
func FilterIncorrectCIDRVersion(ipStrings []string, ipfamily v1.IPFamily) ([]string, []string) {
return filterWithCondition(ipStrings, (ipfamily == v1.IPv6Protocol), utilnet.IsIPv6CIDRString)
}
func filterWithCondition(strs []string, expectedCondition bool, conditionFunc func(string) bool) ([]string, []string) {
var corrects, incorrects []string
for _, str := range strs {
if conditionFunc(str) != expectedCondition {
incorrects = append(incorrects, str)
// MapIPsByIPFamily maps a slice of IPs to their respective IP families (v4 or v6)
func MapIPsByIPFamily(ipStrings []string) map[v1.IPFamily][]string {
ipFamilyMap := map[v1.IPFamily][]string{}
for _, ip := range ipStrings {
// Handle only the valid IPs
if ipFamily, err := getIPFamilyFromIP(ip); err == nil {
ipFamilyMap[ipFamily] = append(ipFamilyMap[ipFamily], ip)
} else {
corrects = append(corrects, str)
klog.Errorf("Skipping invalid IP: %s", ip)
}
}
return corrects, incorrects
return ipFamilyMap
}
// MapCIDRsByIPFamily maps a slice of IPs to their respective IP families (v4 or v6)
func MapCIDRsByIPFamily(cidrStrings []string) map[v1.IPFamily][]string {
ipFamilyMap := map[v1.IPFamily][]string{}
for _, cidr := range cidrStrings {
// Handle only the valid CIDRs
if ipFamily, err := getIPFamilyFromCIDR(cidr); err == nil {
ipFamilyMap[ipFamily] = append(ipFamilyMap[ipFamily], cidr)
} else {
klog.Errorf("Skipping invalid cidr: %s", cidr)
}
}
return ipFamilyMap
}
func getIPFamilyFromIP(ipStr string) (v1.IPFamily, error) {
netIP := net.ParseIP(ipStr)
if netIP == nil {
return "", ErrAddressNotAllowed
}
if utilnet.IsIPv6(netIP) {
return v1.IPv6Protocol, nil
}
return v1.IPv4Protocol, nil
}
func getIPFamilyFromCIDR(cidrStr string) (v1.IPFamily, error) {
_, netCIDR, err := net.ParseCIDR(cidrStr)
if err != nil {
return "", ErrAddressNotAllowed
}
if utilnet.IsIPv6CIDR(netCIDR) {
return v1.IPv6Protocol, nil
}
return v1.IPv4Protocol, nil
}
// OtherIPFamily returns the other ip family
func OtherIPFamily(ipFamily v1.IPFamily) v1.IPFamily {
if ipFamily == v1.IPv6Protocol {
return v1.IPv4Protocol
}
return v1.IPv6Protocol
}
// AppendPortIfNeeded appends the given port to IP address unless it is already in

View File

@ -567,7 +567,7 @@ func TestShuffleStrings(t *testing.T) {
}
}
func TestFilterIncorrectIPVersion(t *testing.T) {
func TestMapIPsByIPFamily(t *testing.T) {
testCases := []struct {
desc string
ipString []string
@ -650,15 +650,122 @@ func TestFilterIncorrectIPVersion(t *testing.T) {
for _, testcase := range testCases {
t.Run(testcase.desc, func(t *testing.T) {
ipFamily := v1.IPv4Protocol
otherIPFamily := v1.IPv6Protocol
if testcase.wantIPv6 {
ipFamily = v1.IPv6Protocol
otherIPFamily = v1.IPv4Protocol
}
correct, incorrect := FilterIncorrectIPVersion(testcase.ipString, ipFamily)
if !reflect.DeepEqual(testcase.expectCorrect, correct) {
t.Errorf("Test %v failed: expected %v, got %v", testcase.desc, testcase.expectCorrect, correct)
ipMap := MapIPsByIPFamily(testcase.ipString)
if !reflect.DeepEqual(testcase.expectCorrect, ipMap[ipFamily]) {
t.Errorf("Test %v failed: expected %v, got %v", testcase.desc, testcase.expectCorrect, ipMap[ipFamily])
}
if !reflect.DeepEqual(testcase.expectIncorrect, incorrect) {
t.Errorf("Test %v failed: expected %v, got %v", testcase.desc, testcase.expectIncorrect, incorrect)
if !reflect.DeepEqual(testcase.expectIncorrect, ipMap[otherIPFamily]) {
t.Errorf("Test %v failed: expected %v, got %v", testcase.desc, testcase.expectIncorrect, ipMap[otherIPFamily])
}
})
}
}
func TestMapCIDRsByIPFamily(t *testing.T) {
testCases := []struct {
desc string
ipString []string
wantIPv6 bool
expectCorrect []string
expectIncorrect []string
}{
{
desc: "empty input IPv4",
ipString: []string{},
wantIPv6: false,
expectCorrect: nil,
expectIncorrect: nil,
},
{
desc: "empty input IPv6",
ipString: []string{},
wantIPv6: true,
expectCorrect: nil,
expectIncorrect: nil,
},
{
desc: "want IPv4 and receive IPv6",
ipString: []string{"fd00:20::1/64"},
wantIPv6: false,
expectCorrect: nil,
expectIncorrect: []string{"fd00:20::1/64"},
},
{
desc: "want IPv6 and receive IPv4",
ipString: []string{"192.168.200.2/24"},
wantIPv6: true,
expectCorrect: nil,
expectIncorrect: []string{"192.168.200.2/24"},
},
{
desc: "want IPv6 and receive IPv4 and IPv6",
ipString: []string{"192.168.200.2/24", "192.1.34.23/24", "fd00:20::1/64", "2001:db9::3/64"},
wantIPv6: true,
expectCorrect: []string{"fd00:20::1/64", "2001:db9::3/64"},
expectIncorrect: []string{"192.168.200.2/24", "192.1.34.23/24"},
},
{
desc: "want IPv4 and receive IPv4 and IPv6",
ipString: []string{"192.168.200.2/24", "192.1.34.23/24", "fd00:20::1/64", "2001:db9::3/64"},
wantIPv6: false,
expectCorrect: []string{"192.168.200.2/24", "192.1.34.23/24"},
expectIncorrect: []string{"fd00:20::1/64", "2001:db9::3/64"},
},
{
desc: "want IPv4 and receive IPv4 only",
ipString: []string{"192.168.200.2/24", "192.1.34.23/24"},
wantIPv6: false,
expectCorrect: []string{"192.168.200.2/24", "192.1.34.23/24"},
expectIncorrect: nil,
},
{
desc: "want IPv6 and receive IPv4 only",
ipString: []string{"192.168.200.2/24", "192.1.34.23/24"},
wantIPv6: true,
expectCorrect: nil,
expectIncorrect: []string{"192.168.200.2/24", "192.1.34.23/24"},
},
{
desc: "want IPv4 and receive IPv6 only",
ipString: []string{"fd00:20::1/64", "2001:db9::3/64"},
wantIPv6: false,
expectCorrect: nil,
expectIncorrect: []string{"fd00:20::1/64", "2001:db9::3/64"},
},
{
desc: "want IPv6 and receive IPv6 only",
ipString: []string{"fd00:20::1/64", "2001:db9::3/64"},
wantIPv6: true,
expectCorrect: []string{"fd00:20::1/64", "2001:db9::3/64"},
expectIncorrect: nil,
},
}
for _, testcase := range testCases {
t.Run(testcase.desc, func(t *testing.T) {
ipFamily := v1.IPv4Protocol
otherIPFamily := v1.IPv6Protocol
if testcase.wantIPv6 {
ipFamily = v1.IPv6Protocol
otherIPFamily = v1.IPv4Protocol
}
cidrMap := MapCIDRsByIPFamily(testcase.ipString)
if !reflect.DeepEqual(testcase.expectCorrect, cidrMap[ipFamily]) {
t.Errorf("Test %v failed: expected %v, got %v", testcase.desc, testcase.expectCorrect, cidrMap[ipFamily])
}
if !reflect.DeepEqual(testcase.expectIncorrect, cidrMap[otherIPFamily]) {
t.Errorf("Test %v failed: expected %v, got %v", testcase.desc, testcase.expectIncorrect, cidrMap[otherIPFamily])
}
})
}