-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net: InterfaceAddrs() "no such network interface" with rapidly changes interfaces #51934
Comments
A work-around may be to read interfaces with net.Interfaces and then read addresses per interface with net.Interface.Addrs and create our own "safe InterfaceAddrs". But IMO we shouldn't have to do that. |
So the problem is kind of TOCTOU, writing my notes down Lines 129 to 130 in a9922d0
gets all Addresses from the RIB Lines 123 to 124 in a9922d0
and later gets all the Links Line 135 in a9922d0
Lines 16 to 17 in a9922d0
and finally it merges the information Line 140 in a9922d0
Lines 159 to 162 in a9922d0
Lines 157 to 163 in a9922d0
So between We have 2 datasets, addresses that reference interfaces by index
and interfaces
If we list interfaces first and new interfaces are added with Addresses we have the same problem in the opposite direction, as the new interface will not be present in the list of new addresses. Meanwhile the list of Addresses contains a subsets of the Interfaces list there is no problem Some ideas:
|
👍 Just ignore the error internally if the interface doesn't exist. For the user it's the same as if |
It seems that in the |
Sent fix https://go-review.googlesource.com/c/go/+/635196 Tested with package main
import (
"fmt"
"net"
"github.com/vishvananda/netlink"
)
func main() {
go func() {
for {
err := linkAddDel("test-interface", &net.IPNet{IP: net.ParseIP("127.0.0.77"), Mask: net.CIDRMask(32, 32)})
if err != nil {
panic(err)
}
}
}()
go func() {
for {
addr, err := net.InterfaceAddrs()
if err != nil {
panic(err)
}
fmt.Println(addr)
}
}()
select {}
}
func linkAddDel(name string, addr *net.IPNet) error {
lnk := &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: "name",
},
}
err := netlink.LinkAdd(lnk)
if err != nil {
return err
}
ipConfig := &netlink.Addr{
IPNet: addr,
}
if err = netlink.AddrAdd(lnk, ipConfig); err != nil {
return err
}
err = netlink.LinkDel(lnk)
if err != nil {
return err
}
return nil
} without the fix, after a few seconds it panics trying to list the interfaces, with the fix never panics
|
Change https://go.dev/cl/635196 mentions this issue: |
What version of Go are you using (
go version
)?The problem is in Kubernetes v1.23.3 which I think uses go1.17.6, but at least go1.17.x.
Does this issue reproduce with the latest release?
N/A. Have to wait for K8s.
What operating system and processor architecture are you using (
go env
)?go env
OutputSystem is
openstack
with;What did you do?
In heavy stress tests on a very large K8s cluster (159 nodes) the update of addresses made by the internal k8s load-balancer (kube-proxy) sometimed (very infrequent) fails to read all addresses with net.InterfaceAddrs. The error is;
The stress test contantly reboot nodes and interfaces are created and removed all the time. At very infrequent times the error above i thrown.
Please see the K8s issue for more info, kubernetes/kubernetes#108065
What did you expect to see?
No interface related errors thrown by net.InterfaceAddrs, even if interfaces are created/removed all the time.
My interpretation is that the error is thrown if net.InterfaceAddrs firsts reads an interface name, then when to read addresses, the interface is gone.
A "no such network interface" must be handled (ignored) internally in net.InterfaceAddrs.
We as a users can of course add re-tries, but how many and for how long? Since interfaces are created/removed all the time we may never be able to read the addresses.
What did you see instead?
The error described above.
The text was updated successfully, but these errors were encountered: