proxy/ipvs: add a GetAllLocalAddressesExcept() function

This commit is contained in:
Lars Ekman 2023-04-27 20:45:27 +02:00
parent e8108b5a47
commit 5310305098
6 changed files with 61 additions and 3 deletions

View File

@ -40,4 +40,9 @@ type NetLinkHandle interface {
// Only the addresses of the current family are returned.
// IPv6 link-local and loopback addresses are excluded.
GetLocalAddresses(dev string) (sets.Set[string], error)
// GetAllLocalAddressesExcept return all local addresses on the node, except from the passed dev.
// This is not the same as to take the diff between GetAllLocalAddresses and GetLocalAddresses
// since an address can be assigned to many interfaces. This problem raised
// https://github.com/kubernetes/kubernetes/issues/114815
GetAllLocalAddressesExcept(dev string) (sets.Set[string], error)
}

View File

@ -24,6 +24,7 @@ import (
"net"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
utilproxy "k8s.io/kubernetes/pkg/proxy/util"
netutils "k8s.io/utils/net"
@ -164,3 +165,30 @@ func (h *netlinkHandle) isValidForSet(ip net.IP) bool {
}
return true
}
// GetAllLocalAddressesExcept return all local addresses on the node,
// except from the passed dev. This is not the same as to take the
// diff between GetAllLocalAddresses and GetLocalAddresses since an
// address can be assigned to many interfaces. This problem raised
// https://github.com/kubernetes/kubernetes/issues/114815
func (h *netlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
var addr []net.Addr
for _, iface := range ifaces {
if iface.Name == dev {
continue
}
ifadr, err := iface.Addrs()
if err != nil {
// This may happen if the interface was deleted. Ignore
// but log the error.
klog.ErrorS(err, "Reading addresses", "interface", iface.Name)
continue
}
addr = append(addr, ifadr...)
}
return utilproxy.AddressSet(h.isValidForSet, addr), nil
}

View File

@ -71,6 +71,11 @@ func (h *netlinkHandle) GetLocalAddresses(dev string) (sets.Set[string], error)
return nil, fmt.Errorf("netlink is not supported in this platform")
}
// GetAllLocalAddressesExcept is part of interface.
func (h *netlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) {
return nil, fmt.Errorf("netlink is not supported in this platform")
}
// Must match the one in proxier_test.go
func (h *netlinkHandle) isValidForSet(ip net.IP) bool {
return false

View File

@ -990,11 +990,10 @@ func (proxier *Proxier) syncProxyRules() {
klog.ErrorS(err, "Error listing addresses binded to dummy interface")
}
// nodeAddressSet All addresses *except* those on the dummy interface
nodeAddressSet, err := proxier.netlinkHandle.GetAllLocalAddresses()
nodeAddressSet, err := proxier.netlinkHandle.GetAllLocalAddressesExcept(defaultDummyDevice)
if err != nil {
klog.ErrorS(err, "Error listing node addresses")
}
nodeAddressSet = nodeAddressSet.Difference(alreadyBoundAddrs)
hasNodePort := false
for _, svc := range proxier.svcPortMap {

View File

@ -140,6 +140,21 @@ func (h *FakeNetlinkHandle) GetAllLocalAddresses() (sets.Set[string], error) {
return res, nil
}
func (h *FakeNetlinkHandle) GetAllLocalAddressesExcept(dev string) (sets.Set[string], error) {
res := sets.New[string]()
for linkName := range h.localAddresses {
if linkName == dev {
continue
}
for _, addr := range h.localAddresses[linkName] {
if h.isValidForSet(addr) {
res.Insert(addr)
}
}
}
return res, nil
}
// SetLocalAddresses set IP addresses to the given interface device. It's not part of interface.
func (h *FakeNetlinkHandle) SetLocalAddresses(dev string, ips ...string) error {
if h.localAddresses == nil {

View File

@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/proxy/ipvs"
)
// (I am unsure if this test has any value since it only tests the fake implementation)
func TestSetGetLocalAddresses(t *testing.T) {
fake := NewFakeNetlinkHandle(false)
_ = ipvs.NetLinkHandle(fake) // Ensure that the interface is honored
@ -43,10 +44,15 @@ func TestSetGetLocalAddresses(t *testing.T) {
if !addr.Equal(expected) {
t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
}
fake.SetLocalAddresses("kube-ipvs0", "4.3.2.1")
fake.SetLocalAddresses("kube-ipvs0", "1.2.3.4", "4.3.2.1")
addr, _ = fake.GetAllLocalAddresses()
expected = sets.New("1.2.3.4", "4.3.2.1")
if !addr.Equal(expected) {
t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
}
addr, _ = fake.GetAllLocalAddressesExcept("kube-ipvs0")
expected = sets.New("1.2.3.4")
if !addr.Equal(expected) {
t.Errorf("Unexpected mismatch, expected: %v, got: %v", expected, addr)
}
}