Change:
Is this a BUG REPORT or FEATURE REQUEST?: /kind bug /area ipv6 /area ipvs /sig network What happened: In an ipv6-only cluster with proxy-mode=ipvs the entries for NodePort in ipvs are created for ipv4 addresses. The target's (if there are any) consists of ipv6 addresses (wrongly) interpreted as ipv4; Attempts to use the NodePort with ipv6 addresses are black-holed. What you expected to happen: Ipv6 addresses to the nodes should be used for NotePort and the LB-targets shall be the ipv6 address of the pods. Traffic to NodePorts shall be distributed among the (ipv6) endpoints. How to reproduce it (as minimally and precisely as possible): Setup an ipv6-only cluster Create a service with type with endpoints Try to connect to the NodePort Do Anything else we need to know?: The nodes have both ipv4 and ipv6 addresses and it is possible that if the nodes only had ipv6 addresses it would work (I havn't tested). But even in an ipv6-only k8s cluster the nodes almost always need ipv4 addresses for other purposes. Environment: Kubernetes version (use ):Cloud provider or hardware configuration: Kvm VMs on Ubuntu 18.04.01 LTS OS (e.g. from /etc/os-release): Own BusyBox based system Kernel (e.g. ):Install tools: None Others:
The NodeIPs() function seem to return only ipv4 addresses.
I can't see why (yet) since is used in the GetLocalAddresses function
/cc Please give a hint before I dive into the netlink code.
This issue is used as an example here;
The functions filters on Src != nil . But ipv6 addresses seems to have Src == nil always. As it is this function will never return any ipv6 addresses.

Discussion:
type netlinkHandle struct { netlink.Handle <ins> isIPv6 bool </ins> } // NewNetLinkHandle will crate a new NetLinkHandle <del> func NewNetLinkHandle() NetLinkHandle { return &netlinkHandle{netlink.Handle{}} </del> <ins> func NewNetLinkHandle(isIPv6 bool) NetLinkHandle { return &netlinkHandle{netlink.Handle{}, isIPv6} </ins> } // EnsureAddressBind checks if address is bound to the interface and, if not, binds it. If the address is already bound, return true.

if route.LinkIndex == filterLinkIndex { continue } <del> if route.Src != nil { </del> <ins> if h.isIPv6 { if route.Dst.IP.To4() == nil && !route.Dst.IP.IsLinkLocalUnicast() { res.Insert(route.Dst.IP.String()) } } else if route.Src != nil { </ins> res.Insert(route.Src.String()) } }

} // NewNetLinkHandle will create an EmptyHandle <del> func NewNetLinkHandle() NetLinkHandle { </del> <ins> func NewNetLinkHandle(ipv6 bool) NetLinkHandle { </ins> return &emptyHandle{} }

healthzServer:         healthzServer, ipvs:                  ipvs, ipvsScheduler:         scheduler, <del> ipGetter:              &realIPGetter{nl: NewNetLinkHandle()}, </del> <ins> ipGetter:              &realIPGetter{nl: NewNetLinkHandle(isIPv6)}, </ins> iptablesData:          bytes.NewBuffer(nil), filterChainsData:      bytes.NewBuffer(nil), natChains:             bytes.NewBuffer(nil), natRules:              bytes.NewBuffer(nil), filterChains:          bytes.NewBuffer(nil), filterRules:           bytes.NewBuffer(nil), <del> netlinkHandle:         NewNetLinkHandle(), </del> <ins> netlinkHandle:         NewNetLinkHandle(isIPv6), </ins> ipset:                 ipset, nodePortAddresses:     nodePortAddresses, networkInterfacer:     utilproxy.RealNetwork{},

} } // Delete dummy interface created by ipvs Proxier. <del> nl := NewNetLinkHandle() </del> <ins> nl := NewNetLinkHandle(false) </ins> err := nl.DeleteDummyDevice(DefaultDummyDevice) if err != nil { klog.Errorf("Error deleting dummy device %s created by IPVS proxier: %v", DefaultDummyDevice, err)