...

Source file src/k8s.io/kubernetes/pkg/util/node/node.go

Documentation: k8s.io/kubernetes/pkg/util/node

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package node
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net"
    23  	"time"
    24  
    25  	"k8s.io/klog/v2"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/util/wait"
    30  	clientset "k8s.io/client-go/kubernetes"
    31  	netutils "k8s.io/utils/net"
    32  )
    33  
    34  const (
    35  	// NodeUnreachablePodReason is the reason on a pod when its state cannot be confirmed as kubelet is unresponsive
    36  	// on the node it is (was) running.
    37  	NodeUnreachablePodReason = "NodeLost"
    38  	// NodeUnreachablePodMessage is the message on a pod when its state cannot be confirmed as kubelet is unresponsive
    39  	// on the node it is (was) running.
    40  	NodeUnreachablePodMessage = "Node %v which was running pod %v is unresponsive"
    41  )
    42  
    43  // NoMatchError is a typed implementation of the error interface. It indicates a failure to get a matching Node.
    44  type NoMatchError struct {
    45  	addresses []v1.NodeAddress
    46  }
    47  
    48  // Error is the implementation of the conventional interface for
    49  // representing an error condition, with the nil value representing no error.
    50  func (e *NoMatchError) Error() string {
    51  	return fmt.Sprintf("no preferred addresses found; known addresses: %v", e.addresses)
    52  }
    53  
    54  // GetPreferredNodeAddress returns the address of the provided node, using the provided preference order.
    55  // If none of the preferred address types are found, an error is returned.
    56  func GetPreferredNodeAddress(node *v1.Node, preferredAddressTypes []v1.NodeAddressType) (string, error) {
    57  	for _, addressType := range preferredAddressTypes {
    58  		for _, address := range node.Status.Addresses {
    59  			if address.Type == addressType {
    60  				return address.Address, nil
    61  			}
    62  		}
    63  	}
    64  	return "", &NoMatchError{addresses: node.Status.Addresses}
    65  }
    66  
    67  // GetNodeHostIPs returns the provided node's IP(s); either a single "primary IP" for the
    68  // node in a single-stack cluster, or a dual-stack pair of IPs in a dual-stack cluster
    69  // (for nodes that actually have dual-stack IPs). Among other things, the IPs returned
    70  // from this function are used as the `.status.PodIPs` values for host-network pods on the
    71  // node, and the first IP is used as the `.status.HostIP` for all pods on the node.
    72  func GetNodeHostIPs(node *v1.Node) ([]net.IP, error) {
    73  	// Re-sort the addresses with InternalIPs first and then ExternalIPs
    74  	allIPs := make([]net.IP, 0, len(node.Status.Addresses))
    75  	for _, addr := range node.Status.Addresses {
    76  		if addr.Type == v1.NodeInternalIP {
    77  			ip := netutils.ParseIPSloppy(addr.Address)
    78  			if ip != nil {
    79  				allIPs = append(allIPs, ip)
    80  			}
    81  		}
    82  	}
    83  	for _, addr := range node.Status.Addresses {
    84  		if addr.Type == v1.NodeExternalIP {
    85  			ip := netutils.ParseIPSloppy(addr.Address)
    86  			if ip != nil {
    87  				allIPs = append(allIPs, ip)
    88  			}
    89  		}
    90  	}
    91  	if len(allIPs) == 0 {
    92  		return nil, fmt.Errorf("host IP unknown; known addresses: %v", node.Status.Addresses)
    93  	}
    94  
    95  	nodeIPs := []net.IP{allIPs[0]}
    96  	for _, ip := range allIPs {
    97  		if netutils.IsIPv6(ip) != netutils.IsIPv6(nodeIPs[0]) {
    98  			nodeIPs = append(nodeIPs, ip)
    99  			break
   100  		}
   101  	}
   102  
   103  	return nodeIPs, nil
   104  }
   105  
   106  // GetNodeHostIP returns the provided node's "primary" IP; see GetNodeHostIPs for more details
   107  func GetNodeHostIP(node *v1.Node) (net.IP, error) {
   108  	ips, err := GetNodeHostIPs(node)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	// GetNodeHostIPs always returns at least one IP if it didn't return an error
   113  	return ips[0], nil
   114  }
   115  
   116  // GetNodeIP returns an IP (as with GetNodeHostIP) for the node with the provided name.
   117  // If required, it will wait for the node to be created.
   118  func GetNodeIP(client clientset.Interface, name string) net.IP {
   119  	var nodeIP net.IP
   120  	backoff := wait.Backoff{
   121  		Steps:    6,
   122  		Duration: 1 * time.Second,
   123  		Factor:   2.0,
   124  		Jitter:   0.2,
   125  	}
   126  
   127  	err := wait.ExponentialBackoff(backoff, func() (bool, error) {
   128  		node, err := client.CoreV1().Nodes().Get(context.TODO(), name, metav1.GetOptions{})
   129  		if err != nil {
   130  			klog.Errorf("Failed to retrieve node info: %v", err)
   131  			return false, nil
   132  		}
   133  		nodeIP, err = GetNodeHostIP(node)
   134  		if err != nil {
   135  			klog.Errorf("Failed to retrieve node IP: %v", err)
   136  			return false, err
   137  		}
   138  		return true, nil
   139  	})
   140  	if err == nil {
   141  		klog.Infof("Successfully retrieved node IP: %v", nodeIP)
   142  	}
   143  	return nodeIP
   144  }
   145  
   146  // IsNodeReady returns true if a node is ready; false otherwise.
   147  func IsNodeReady(node *v1.Node) bool {
   148  	for _, c := range node.Status.Conditions {
   149  		if c.Type == v1.NodeReady {
   150  			return c.Status == v1.ConditionTrue
   151  		}
   152  	}
   153  	return false
   154  }
   155  

View as plain text