...

Source file src/k8s.io/kubernetes/pkg/kubelet/client/kubelet_client.go

Documentation: k8s.io/kubernetes/pkg/kubelet/client

     1  /*
     2  Copyright 2014 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 client
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net/http"
    23  	"strconv"
    24  	"time"
    25  
    26  	v1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/types"
    29  	"k8s.io/apiserver/pkg/server/egressselector"
    30  	"k8s.io/client-go/transport"
    31  	nodeutil "k8s.io/kubernetes/pkg/util/node"
    32  )
    33  
    34  // KubeletClientConfig defines config parameters for the kubelet client
    35  type KubeletClientConfig struct {
    36  	// Port specifies the default port - used if no information about Kubelet port can be found in Node.NodeStatus.DaemonEndpoints.
    37  	Port uint
    38  
    39  	// ReadOnlyPort specifies the Port for ReadOnly communications.
    40  	ReadOnlyPort uint
    41  
    42  	// PreferredAddressTypes - used to select an address from Node.NodeStatus.Addresses
    43  	PreferredAddressTypes []string
    44  
    45  	// TLSClientConfig contains settings to enable transport layer security
    46  	TLSClientConfig KubeletTLSConfig
    47  
    48  	// HTTPTimeout is used by the client to timeout http requests to Kubelet.
    49  	HTTPTimeout time.Duration
    50  
    51  	// Lookup will give us a dialer if the egress selector is configured for it
    52  	Lookup egressselector.Lookup
    53  }
    54  
    55  type KubeletTLSConfig struct {
    56  	// Server requires TLS client certificate authentication
    57  	CertFile string
    58  	// Server requires TLS client certificate authentication
    59  	KeyFile string
    60  	// Trusted root certificates for server
    61  	CAFile string
    62  }
    63  
    64  // ConnectionInfo provides the information needed to connect to a kubelet
    65  type ConnectionInfo struct {
    66  	Scheme                         string
    67  	Hostname                       string
    68  	Port                           string
    69  	Transport                      http.RoundTripper
    70  	InsecureSkipTLSVerifyTransport http.RoundTripper
    71  }
    72  
    73  // ConnectionInfoGetter provides ConnectionInfo for the kubelet running on a named node
    74  type ConnectionInfoGetter interface {
    75  	GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error)
    76  }
    77  
    78  // MakeTransport creates a secure RoundTripper for HTTP Transport.
    79  func MakeTransport(config *KubeletClientConfig) (http.RoundTripper, error) {
    80  	return makeTransport(config, false)
    81  }
    82  
    83  // MakeInsecureTransport creates an insecure RoundTripper for HTTP Transport.
    84  func MakeInsecureTransport(config *KubeletClientConfig) (http.RoundTripper, error) {
    85  	return makeTransport(config, true)
    86  }
    87  
    88  // makeTransport creates a RoundTripper for HTTP Transport.
    89  func makeTransport(config *KubeletClientConfig, insecureSkipTLSVerify bool) (http.RoundTripper, error) {
    90  	// do the insecureSkipTLSVerify on the pre-transport *before* we go get a potentially cached connection.
    91  	// transportConfig always produces a new struct pointer.
    92  	transportConfig := config.transportConfig()
    93  	if insecureSkipTLSVerify {
    94  		transportConfig.TLS.Insecure = true
    95  		transportConfig.TLS.CAFile = "" // we are only using files so we can ignore CAData
    96  	}
    97  
    98  	if config.Lookup != nil {
    99  		// Assuming EgressSelector if SSHTunnel is not turned on.
   100  		// We will not get a dialer if egress selector is disabled.
   101  		networkContext := egressselector.Cluster.AsNetworkContext()
   102  		dialer, err := config.Lookup(networkContext)
   103  		if err != nil {
   104  			return nil, fmt.Errorf("failed to get context dialer for 'cluster': got %v", err)
   105  		}
   106  		if dialer != nil {
   107  			transportConfig.DialHolder = &transport.DialHolder{Dial: dialer}
   108  		}
   109  	}
   110  	return transport.New(transportConfig)
   111  }
   112  
   113  // transportConfig converts a client config to an appropriate transport config.
   114  func (c *KubeletClientConfig) transportConfig() *transport.Config {
   115  	cfg := &transport.Config{
   116  		TLS: transport.TLSConfig{
   117  			CAFile:   c.TLSClientConfig.CAFile,
   118  			CertFile: c.TLSClientConfig.CertFile,
   119  			KeyFile:  c.TLSClientConfig.KeyFile,
   120  			// transport.loadTLSFiles would set this to true because we are only using files
   121  			// it is clearer to set it explicitly here so we remember that this is happening
   122  			ReloadTLSFiles: true,
   123  		},
   124  	}
   125  	if !cfg.HasCA() {
   126  		cfg.TLS.Insecure = true
   127  	}
   128  	return cfg
   129  }
   130  
   131  // NodeGetter defines an interface for looking up a node by name
   132  type NodeGetter interface {
   133  	Get(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error)
   134  }
   135  
   136  // NodeGetterFunc allows implementing NodeGetter with a function
   137  type NodeGetterFunc func(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error)
   138  
   139  // Get fetches information via NodeGetterFunc.
   140  func (f NodeGetterFunc) Get(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error) {
   141  	return f(ctx, name, options)
   142  }
   143  
   144  // NodeConnectionInfoGetter obtains connection info from the status of a Node API object
   145  type NodeConnectionInfoGetter struct {
   146  	// nodes is used to look up Node objects
   147  	nodes NodeGetter
   148  	// scheme is the scheme to use to connect to all kubelets
   149  	scheme string
   150  	// defaultPort is the port to use if no Kubelet endpoint port is recorded in the node status
   151  	defaultPort int
   152  	// transport is the transport to use to send a request to all kubelets
   153  	transport http.RoundTripper
   154  	// insecureSkipTLSVerifyTransport is the transport to use if the kube-apiserver wants to skip verifying the TLS certificate of the kubelet
   155  	insecureSkipTLSVerifyTransport http.RoundTripper
   156  	// preferredAddressTypes specifies the preferred order to use to find a node address
   157  	preferredAddressTypes []v1.NodeAddressType
   158  }
   159  
   160  // NewNodeConnectionInfoGetter creates a new NodeConnectionInfoGetter.
   161  func NewNodeConnectionInfoGetter(nodes NodeGetter, config KubeletClientConfig) (ConnectionInfoGetter, error) {
   162  	transport, err := MakeTransport(&config)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  	insecureSkipTLSVerifyTransport, err := MakeInsecureTransport(&config)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	types := []v1.NodeAddressType{}
   172  	for _, t := range config.PreferredAddressTypes {
   173  		types = append(types, v1.NodeAddressType(t))
   174  	}
   175  
   176  	return &NodeConnectionInfoGetter{
   177  		nodes:                          nodes,
   178  		scheme:                         "https",
   179  		defaultPort:                    int(config.Port),
   180  		transport:                      transport,
   181  		insecureSkipTLSVerifyTransport: insecureSkipTLSVerifyTransport,
   182  
   183  		preferredAddressTypes: types,
   184  	}, nil
   185  }
   186  
   187  // GetConnectionInfo retrieves connection info from the status of a Node API object.
   188  func (k *NodeConnectionInfoGetter) GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error) {
   189  	node, err := k.nodes.Get(ctx, string(nodeName), metav1.GetOptions{})
   190  	if err != nil {
   191  		return nil, err
   192  	}
   193  
   194  	// Find a kubelet-reported address, using preferred address type
   195  	host, err := nodeutil.GetPreferredNodeAddress(node, k.preferredAddressTypes)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	// Use the kubelet-reported port, if present
   201  	port := int(node.Status.DaemonEndpoints.KubeletEndpoint.Port)
   202  	if port <= 0 {
   203  		port = k.defaultPort
   204  	}
   205  
   206  	return &ConnectionInfo{
   207  		Scheme:                         k.scheme,
   208  		Hostname:                       host,
   209  		Port:                           strconv.Itoa(port),
   210  		Transport:                      k.transport,
   211  		InsecureSkipTLSVerifyTransport: k.insecureSkipTLSVerifyTransport,
   212  	}, nil
   213  }
   214  

View as plain text