kubelet_client.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package client
  14. import (
  15. "context"
  16. "net/http"
  17. "strconv"
  18. "time"
  19. "k8s.io/api/core/v1"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. "k8s.io/apimachinery/pkg/types"
  22. utilnet "k8s.io/apimachinery/pkg/util/net"
  23. restclient "k8s.io/client-go/rest"
  24. "k8s.io/client-go/transport"
  25. nodeutil "k8s.io/kubernetes/pkg/util/node"
  26. )
  27. type KubeletClientConfig struct {
  28. // Default port - used if no information about Kubelet port can be found in Node.NodeStatus.DaemonEndpoints.
  29. Port uint
  30. ReadOnlyPort uint
  31. EnableHttps bool
  32. // PreferredAddressTypes - used to select an address from Node.NodeStatus.Addresses
  33. PreferredAddressTypes []string
  34. // TLSClientConfig contains settings to enable transport layer security
  35. restclient.TLSClientConfig
  36. // Server requires Bearer authentication
  37. BearerToken string
  38. // HTTPTimeout is used by the client to timeout http requests to Kubelet.
  39. HTTPTimeout time.Duration
  40. // Dial is a custom dialer used for the client
  41. Dial utilnet.DialFunc
  42. }
  43. // ConnectionInfo provides the information needed to connect to a kubelet
  44. type ConnectionInfo struct {
  45. Scheme string
  46. Hostname string
  47. Port string
  48. Transport http.RoundTripper
  49. }
  50. // ConnectionInfoGetter provides ConnectionInfo for the kubelet running on a named node
  51. type ConnectionInfoGetter interface {
  52. GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error)
  53. }
  54. func MakeTransport(config *KubeletClientConfig) (http.RoundTripper, error) {
  55. tlsConfig, err := transport.TLSConfigFor(config.transportConfig())
  56. if err != nil {
  57. return nil, err
  58. }
  59. rt := http.DefaultTransport
  60. if config.Dial != nil || tlsConfig != nil {
  61. rt = utilnet.SetOldTransportDefaults(&http.Transport{
  62. DialContext: config.Dial,
  63. TLSClientConfig: tlsConfig,
  64. })
  65. }
  66. return transport.HTTPWrappersForConfig(config.transportConfig(), rt)
  67. }
  68. // transportConfig converts a client config to an appropriate transport config.
  69. func (c *KubeletClientConfig) transportConfig() *transport.Config {
  70. cfg := &transport.Config{
  71. TLS: transport.TLSConfig{
  72. CAFile: c.CAFile,
  73. CAData: c.CAData,
  74. CertFile: c.CertFile,
  75. CertData: c.CertData,
  76. KeyFile: c.KeyFile,
  77. KeyData: c.KeyData,
  78. },
  79. BearerToken: c.BearerToken,
  80. }
  81. if c.EnableHttps && !cfg.HasCA() {
  82. cfg.TLS.Insecure = true
  83. }
  84. return cfg
  85. }
  86. // NodeGetter defines an interface for looking up a node by name
  87. type NodeGetter interface {
  88. Get(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error)
  89. }
  90. // NodeGetterFunc allows implementing NodeGetter with a function
  91. type NodeGetterFunc func(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error)
  92. func (f NodeGetterFunc) Get(ctx context.Context, name string, options metav1.GetOptions) (*v1.Node, error) {
  93. return f(ctx, name, options)
  94. }
  95. // NodeConnectionInfoGetter obtains connection info from the status of a Node API object
  96. type NodeConnectionInfoGetter struct {
  97. // nodes is used to look up Node objects
  98. nodes NodeGetter
  99. // scheme is the scheme to use to connect to all kubelets
  100. scheme string
  101. // defaultPort is the port to use if no Kubelet endpoint port is recorded in the node status
  102. defaultPort int
  103. // transport is the transport to use to send a request to all kubelets
  104. transport http.RoundTripper
  105. // preferredAddressTypes specifies the preferred order to use to find a node address
  106. preferredAddressTypes []v1.NodeAddressType
  107. }
  108. func NewNodeConnectionInfoGetter(nodes NodeGetter, config KubeletClientConfig) (ConnectionInfoGetter, error) {
  109. scheme := "http"
  110. if config.EnableHttps {
  111. scheme = "https"
  112. }
  113. transport, err := MakeTransport(&config)
  114. if err != nil {
  115. return nil, err
  116. }
  117. types := []v1.NodeAddressType{}
  118. for _, t := range config.PreferredAddressTypes {
  119. types = append(types, v1.NodeAddressType(t))
  120. }
  121. return &NodeConnectionInfoGetter{
  122. nodes: nodes,
  123. scheme: scheme,
  124. defaultPort: int(config.Port),
  125. transport: transport,
  126. preferredAddressTypes: types,
  127. }, nil
  128. }
  129. func (k *NodeConnectionInfoGetter) GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error) {
  130. node, err := k.nodes.Get(ctx, string(nodeName), metav1.GetOptions{})
  131. if err != nil {
  132. return nil, err
  133. }
  134. // Find a kubelet-reported address, using preferred address type
  135. host, err := nodeutil.GetPreferredNodeAddress(node, k.preferredAddressTypes)
  136. if err != nil {
  137. return nil, err
  138. }
  139. // Use the kubelet-reported port, if present
  140. port := int(node.Status.DaemonEndpoints.KubeletEndpoint.Port)
  141. if port <= 0 {
  142. port = k.defaultPort
  143. }
  144. return &ConnectionInfo{
  145. Scheme: k.scheme,
  146. Hostname: host,
  147. Port: strconv.Itoa(port),
  148. Transport: k.transport,
  149. }, nil
  150. }