mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			236 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			7.7 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
 | 
						|
 | 
						|
	// EnableHTTPs specifies if traffic should be encrypted.
 | 
						|
	EnableHTTPS bool
 | 
						|
 | 
						|
	// 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 c.EnableHTTPS && !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) {
 | 
						|
	scheme := "http"
 | 
						|
	if config.EnableHTTPS {
 | 
						|
		scheme = "https"
 | 
						|
	}
 | 
						|
 | 
						|
	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:                         scheme,
 | 
						|
		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
 | 
						|
}
 |