kubelet: Set dual-stack hostNetwork pod IPs on dual-stack nodes

Add nodeutil.GetNodeHostIPs to return dual-stack node IPs (in
dual-stack clusters), and make kubelet use it.
This commit is contained in:
Dan Winship
2020-10-01 10:55:38 -04:00
parent 0b43753be7
commit 971477d9b5
7 changed files with 346 additions and 27 deletions

View File

@@ -33,8 +33,11 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientset "k8s.io/client-go/kubernetes"
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/kubernetes/pkg/features"
utilnet "k8s.io/utils/net"
)
const (
@@ -90,22 +93,55 @@ func GetPreferredNodeAddress(node *v1.Node, preferredAddressTypes []v1.NodeAddre
return "", &NoMatchError{addresses: node.Status.Addresses}
}
// GetNodeHostIP returns the provided node's IP, based on the priority:
// 1. NodeInternalIP
// 2. NodeExternalIP
// GetNodeHostIPs returns the provided node's IP(s); either a single "primary IP" for the
// node in a single-stack cluster, or a dual-stack pair of IPs in a dual-stack cluster
// (for nodes that actually have dual-stack IPs). Among other things, the IPs returned
// from this function are used as the `.status.PodIPs` values for host-network pods on the
// node, and the first IP is used as the `.status.HostIP` for all pods on the node.
func GetNodeHostIPs(node *v1.Node) ([]net.IP, error) {
// Re-sort the addresses with InternalIPs first and then ExternalIPs
allIPs := make([]net.IP, 0, len(node.Status.Addresses))
for _, addr := range node.Status.Addresses {
if addr.Type == v1.NodeInternalIP {
ip := net.ParseIP(addr.Address)
if ip != nil {
allIPs = append(allIPs, ip)
}
}
}
for _, addr := range node.Status.Addresses {
if addr.Type == v1.NodeExternalIP {
ip := net.ParseIP(addr.Address)
if ip != nil {
allIPs = append(allIPs, ip)
}
}
}
if len(allIPs) == 0 {
return nil, fmt.Errorf("host IP unknown; known addresses: %v", node.Status.Addresses)
}
nodeIPs := []net.IP{allIPs[0]}
if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) {
for _, ip := range allIPs {
if utilnet.IsIPv6(ip) != utilnet.IsIPv6(nodeIPs[0]) {
nodeIPs = append(nodeIPs, ip)
break
}
}
}
return nodeIPs, nil
}
// GetNodeHostIP returns the provided node's "primary" IP; see GetNodeHostIPs for more details
func GetNodeHostIP(node *v1.Node) (net.IP, error) {
addresses := node.Status.Addresses
addressMap := make(map[v1.NodeAddressType][]v1.NodeAddress)
for i := range addresses {
addressMap[addresses[i].Type] = append(addressMap[addresses[i].Type], addresses[i])
ips, err := GetNodeHostIPs(node)
if err != nil {
return nil, err
}
if addresses, ok := addressMap[v1.NodeInternalIP]; ok {
return net.ParseIP(addresses[0].Address), nil
}
if addresses, ok := addressMap[v1.NodeExternalIP]; ok {
return net.ParseIP(addresses[0].Address), nil
}
return nil, fmt.Errorf("host IP unknown; known addresses: %v", addresses)
// GetNodeHostIPs always returns at least one IP if it didn't return an error
return ips[0], nil
}
// GetNodeIP returns an IP (as with GetNodeHostIP) for the node with the provided name.