mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 05:40:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			228 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| Copyright 2014 The Kubernetes Authors.
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package client
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"strconv"
 | |
| 	"time"
 | |
| 
 | |
| 	v1 "k8s.io/api/core/v1"
 | |
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | |
| 	"k8s.io/apimachinery/pkg/types"
 | |
| 	utilnet "k8s.io/apimachinery/pkg/util/net"
 | |
| 	"k8s.io/apiserver/pkg/server/egressselector"
 | |
| 	restclient "k8s.io/client-go/rest"
 | |
| 	"k8s.io/client-go/transport"
 | |
| 	nodeutil "k8s.io/kubernetes/pkg/util/node"
 | |
| )
 | |
| 
 | |
| // KubeletClientConfig defines config parameters for the kubelet client
 | |
| type KubeletClientConfig struct {
 | |
| 	// Port specifies the default port - used if no information about Kubelet port can be found in Node.NodeStatus.DaemonEndpoints.
 | |
| 	Port uint
 | |
| 
 | |
| 	// ReadOnlyPort specifies the Port for ReadOnly communications.
 | |
| 	ReadOnlyPort uint
 | |
| 
 | |
| 	// PreferredAddressTypes - used to select an address from Node.NodeStatus.Addresses
 | |
| 	PreferredAddressTypes []string
 | |
| 
 | |
| 	// TLSClientConfig contains settings to enable transport layer security
 | |
| 	restclient.TLSClientConfig
 | |
| 
 | |
| 	// Server requires Bearer authentication
 | |
| 	BearerToken string
 | |
| 
 | |
| 	// HTTPTimeout is used by the client to timeout http requests to Kubelet.
 | |
| 	HTTPTimeout time.Duration
 | |
| 
 | |
| 	// Dial is a custom dialer used for the client
 | |
| 	Dial utilnet.DialFunc
 | |
| 
 | |
| 	// Lookup will give us a dialer if the egress selector is configured for it
 | |
| 	Lookup egressselector.Lookup
 | |
| }
 | |
| 
 | |
| // ConnectionInfo provides the information needed to connect to a kubelet
 | |
| type ConnectionInfo struct {
 | |
| 	Scheme                         string
 | |
| 	Hostname                       string
 | |
| 	Port                           string
 | |
| 	Transport                      http.RoundTripper
 | |
| 	InsecureSkipTLSVerifyTransport http.RoundTripper
 | |
| }
 | |
| 
 | |
| // ConnectionInfoGetter provides ConnectionInfo for the kubelet running on a named node
 | |
| type ConnectionInfoGetter interface {
 | |
| 	GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error)
 | |
| }
 | |
| 
 | |
| // MakeTransport creates a secure RoundTripper for HTTP Transport.
 | |
| func MakeTransport(config *KubeletClientConfig) (http.RoundTripper, error) {
 | |
| 	return makeTransport(config, false)
 | |
| }
 | |
| 
 | |
| // MakeInsecureTransport creates an insecure RoundTripper for HTTP Transport.
 | |
| func MakeInsecureTransport(config *KubeletClientConfig) (http.RoundTripper, error) {
 | |
| 	return makeTransport(config, true)
 | |
| }
 | |
| 
 | |
| // makeTransport creates a RoundTripper for HTTP Transport.
 | |
| func makeTransport(config *KubeletClientConfig, insecureSkipTLSVerify bool) (http.RoundTripper, error) {
 | |
| 	// do the insecureSkipTLSVerify on the pre-transport *before* we go get a potentially cached connection.
 | |
| 	// transportConfig always produces a new struct pointer.
 | |
| 	preTLSConfig := config.transportConfig()
 | |
| 	if insecureSkipTLSVerify && preTLSConfig != nil {
 | |
| 		preTLSConfig.TLS.Insecure = true
 | |
| 		preTLSConfig.TLS.CAData = nil
 | |
| 		preTLSConfig.TLS.CAFile = ""
 | |
| 	}
 | |
| 
 | |
| 	tlsConfig, err := transport.TLSConfigFor(preTLSConfig)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	rt := http.DefaultTransport
 | |
| 	dialer := config.Dial
 | |
| 	if dialer == nil && config.Lookup != nil {
 | |
| 		// Assuming EgressSelector if SSHTunnel is not turned on.
 | |
| 		// We will not get a dialer if egress selector is disabled.
 | |
| 		networkContext := egressselector.Cluster.AsNetworkContext()
 | |
| 		dialer, err = config.Lookup(networkContext)
 | |
| 		if err != nil {
 | |
| 			return nil, fmt.Errorf("failed to get context dialer for 'cluster': got %v", err)
 | |
| 		}
 | |
| 	}
 | |
| 	if dialer != nil || tlsConfig != nil {
 | |
| 		// If SSH Tunnel is turned on
 | |
| 		rt = utilnet.SetOldTransportDefaults(&http.Transport{
 | |
| 			DialContext:     dialer,
 | |
| 			TLSClientConfig: tlsConfig,
 | |
| 		})
 | |
| 	}
 | |
| 
 | |
| 	return transport.HTTPWrappersForConfig(config.transportConfig(), rt)
 | |
| }
 | |
| 
 | |
| // transportConfig converts a client config to an appropriate transport config.
 | |
| func (c *KubeletClientConfig) transportConfig() *transport.Config {
 | |
| 	cfg := &transport.Config{
 | |
| 		TLS: transport.TLSConfig{
 | |
| 			CAFile:     c.CAFile,
 | |
| 			CAData:     c.CAData,
 | |
| 			CertFile:   c.CertFile,
 | |
| 			CertData:   c.CertData,
 | |
| 			KeyFile:    c.KeyFile,
 | |
| 			KeyData:    c.KeyData,
 | |
| 			NextProtos: c.NextProtos,
 | |
| 		},
 | |
| 		BearerToken: c.BearerToken,
 | |
| 	}
 | |
| 	if !cfg.HasCA() {
 | |
| 		cfg.TLS.Insecure = true
 | |
| 	}
 | |
| 	return cfg
 | |
| }
 | |
| 
 | |
| // NodeGetter defines an interface for looking up a node by name
 | |
| type NodeGetter interface {
 | |
| 	Get(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error)
 | |
| }
 | |
| 
 | |
| // NodeGetterFunc allows implementing NodeGetter with a function
 | |
| type NodeGetterFunc func(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error)
 | |
| 
 | |
| // Get fetches information via NodeGetterFunc.
 | |
| func (f NodeGetterFunc) Get(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error) {
 | |
| 	return f(ctx, name, options)
 | |
| }
 | |
| 
 | |
| // NodeConnectionInfoGetter obtains connection info from the status of a Node API object
 | |
| type NodeConnectionInfoGetter struct {
 | |
| 	// nodes is used to look up Node objects
 | |
| 	nodes NodeGetter
 | |
| 	// scheme is the scheme to use to connect to all kubelets
 | |
| 	scheme string
 | |
| 	// defaultPort is the port to use if no Kubelet endpoint port is recorded in the node status
 | |
| 	defaultPort int
 | |
| 	// transport is the transport to use to send a request to all kubelets
 | |
| 	transport http.RoundTripper
 | |
| 	// insecureSkipTLSVerifyTransport is the transport to use if the kube-apiserver wants to skip verifying the TLS certificate of the kubelet
 | |
| 	insecureSkipTLSVerifyTransport http.RoundTripper
 | |
| 	// preferredAddressTypes specifies the preferred order to use to find a node address
 | |
| 	preferredAddressTypes []v1.NodeAddressType
 | |
| }
 | |
| 
 | |
| // NewNodeConnectionInfoGetter creates a new NodeConnectionInfoGetter.
 | |
| func NewNodeConnectionInfoGetter(nodes NodeGetter, config KubeletClientConfig) (ConnectionInfoGetter, error) {
 | |
| 	transport, err := MakeTransport(&config)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	insecureSkipTLSVerifyTransport, err := MakeInsecureTransport(&config)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	types := []v1.NodeAddressType{}
 | |
| 	for _, t := range config.PreferredAddressTypes {
 | |
| 		types = append(types, v1.NodeAddressType(t))
 | |
| 	}
 | |
| 
 | |
| 	return &NodeConnectionInfoGetter{
 | |
| 		nodes:                          nodes,
 | |
| 		scheme:                         "https",
 | |
| 		defaultPort:                    int(config.Port),
 | |
| 		transport:                      transport,
 | |
| 		insecureSkipTLSVerifyTransport: insecureSkipTLSVerifyTransport,
 | |
| 
 | |
| 		preferredAddressTypes: types,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // GetConnectionInfo retrieves connection info from the status of a Node API object.
 | |
| func (k *NodeConnectionInfoGetter) GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error) {
 | |
| 	node, err := k.nodes.Get(ctx, string(nodeName), metav1.GetOptions{})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	// Find a kubelet-reported address, using preferred address type
 | |
| 	host, err := nodeutil.GetPreferredNodeAddress(node, k.preferredAddressTypes)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	// Use the kubelet-reported port, if present
 | |
| 	port := int(node.Status.DaemonEndpoints.KubeletEndpoint.Port)
 | |
| 	if port <= 0 {
 | |
| 		port = k.defaultPort
 | |
| 	}
 | |
| 
 | |
| 	return &ConnectionInfo{
 | |
| 		Scheme:                         k.scheme,
 | |
| 		Hostname:                       host,
 | |
| 		Port:                           strconv.Itoa(port),
 | |
| 		Transport:                      k.transport,
 | |
| 		InsecureSkipTLSVerifyTransport: k.insecureSkipTLSVerifyTransport,
 | |
| 	}, nil
 | |
| }
 |