metrics_grabber.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. Copyright 2015 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 metrics
  14. import (
  15. "context"
  16. "fmt"
  17. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  18. "k8s.io/apimachinery/pkg/fields"
  19. clientset "k8s.io/client-go/kubernetes"
  20. api "k8s.io/kubernetes/pkg/apis/core"
  21. "k8s.io/kubernetes/pkg/master/ports"
  22. "k8s.io/kubernetes/test/e2e/system"
  23. "k8s.io/klog"
  24. )
  25. // Collection is metrics collection of components
  26. type Collection struct {
  27. APIServerMetrics APIServerMetrics
  28. ControllerManagerMetrics ControllerManagerMetrics
  29. KubeletMetrics map[string]KubeletMetrics
  30. SchedulerMetrics SchedulerMetrics
  31. ClusterAutoscalerMetrics ClusterAutoscalerMetrics
  32. }
  33. // Grabber provides functions which grab metrics from components
  34. type Grabber struct {
  35. client clientset.Interface
  36. externalClient clientset.Interface
  37. grabFromAPIServer bool
  38. grabFromControllerManager bool
  39. grabFromKubelets bool
  40. grabFromScheduler bool
  41. grabFromClusterAutoscaler bool
  42. masterName string
  43. registeredMaster bool
  44. }
  45. // NewMetricsGrabber returns new metrics which are initialized.
  46. func NewMetricsGrabber(c clientset.Interface, ec clientset.Interface, kubelets bool, scheduler bool, controllers bool, apiServer bool, clusterAutoscaler bool) (*Grabber, error) {
  47. registeredMaster := false
  48. masterName := ""
  49. nodeList, err := c.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
  50. if err != nil {
  51. return nil, err
  52. }
  53. if len(nodeList.Items) < 1 {
  54. klog.Warning("Can't find any Nodes in the API server to grab metrics from")
  55. }
  56. for _, node := range nodeList.Items {
  57. if system.DeprecatedMightBeMasterNode(node.Name) {
  58. registeredMaster = true
  59. masterName = node.Name
  60. break
  61. }
  62. }
  63. if !registeredMaster {
  64. scheduler = false
  65. controllers = false
  66. clusterAutoscaler = ec != nil
  67. if clusterAutoscaler {
  68. klog.Warningf("Master node is not registered. Grabbing metrics from Scheduler, ControllerManager is disabled.")
  69. } else {
  70. klog.Warningf("Master node is not registered. Grabbing metrics from Scheduler, ControllerManager and ClusterAutoscaler is disabled.")
  71. }
  72. }
  73. return &Grabber{
  74. client: c,
  75. externalClient: ec,
  76. grabFromAPIServer: apiServer,
  77. grabFromControllerManager: controllers,
  78. grabFromKubelets: kubelets,
  79. grabFromScheduler: scheduler,
  80. grabFromClusterAutoscaler: clusterAutoscaler,
  81. masterName: masterName,
  82. registeredMaster: registeredMaster,
  83. }, nil
  84. }
  85. // HasRegisteredMaster returns if metrics grabber was able to find a master node
  86. func (g *Grabber) HasRegisteredMaster() bool {
  87. return g.registeredMaster
  88. }
  89. // GrabFromKubelet returns metrics from kubelet
  90. func (g *Grabber) GrabFromKubelet(nodeName string) (KubeletMetrics, error) {
  91. nodes, err := g.client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{FieldSelector: fields.Set{api.ObjectNameField: nodeName}.AsSelector().String()})
  92. if err != nil {
  93. return KubeletMetrics{}, err
  94. }
  95. if len(nodes.Items) != 1 {
  96. return KubeletMetrics{}, fmt.Errorf("Error listing nodes with name %v, got %v", nodeName, nodes.Items)
  97. }
  98. kubeletPort := nodes.Items[0].Status.DaemonEndpoints.KubeletEndpoint.Port
  99. return g.grabFromKubeletInternal(nodeName, int(kubeletPort))
  100. }
  101. func (g *Grabber) grabFromKubeletInternal(nodeName string, kubeletPort int) (KubeletMetrics, error) {
  102. if kubeletPort <= 0 || kubeletPort > 65535 {
  103. return KubeletMetrics{}, fmt.Errorf("Invalid Kubelet port %v. Skipping Kubelet's metrics gathering", kubeletPort)
  104. }
  105. output, err := g.getMetricsFromNode(nodeName, int(kubeletPort))
  106. if err != nil {
  107. return KubeletMetrics{}, err
  108. }
  109. return parseKubeletMetrics(output)
  110. }
  111. // GrabFromScheduler returns metrics from scheduler
  112. func (g *Grabber) GrabFromScheduler() (SchedulerMetrics, error) {
  113. if !g.registeredMaster {
  114. return SchedulerMetrics{}, fmt.Errorf("Master's Kubelet is not registered. Skipping Scheduler's metrics gathering")
  115. }
  116. output, err := g.getMetricsFromPod(g.client, fmt.Sprintf("%v-%v", "kube-scheduler", g.masterName), metav1.NamespaceSystem, ports.InsecureSchedulerPort)
  117. if err != nil {
  118. return SchedulerMetrics{}, err
  119. }
  120. return parseSchedulerMetrics(output)
  121. }
  122. // GrabFromClusterAutoscaler returns metrics from cluster autoscaler
  123. func (g *Grabber) GrabFromClusterAutoscaler() (ClusterAutoscalerMetrics, error) {
  124. if !g.registeredMaster && g.externalClient == nil {
  125. return ClusterAutoscalerMetrics{}, fmt.Errorf("Master's Kubelet is not registered. Skipping ClusterAutoscaler's metrics gathering")
  126. }
  127. var client clientset.Interface
  128. var namespace string
  129. if g.externalClient != nil {
  130. client = g.externalClient
  131. namespace = "kubemark"
  132. } else {
  133. client = g.client
  134. namespace = metav1.NamespaceSystem
  135. }
  136. output, err := g.getMetricsFromPod(client, "cluster-autoscaler", namespace, 8085)
  137. if err != nil {
  138. return ClusterAutoscalerMetrics{}, err
  139. }
  140. return parseClusterAutoscalerMetrics(output)
  141. }
  142. // GrabFromControllerManager returns metrics from controller manager
  143. func (g *Grabber) GrabFromControllerManager() (ControllerManagerMetrics, error) {
  144. if !g.registeredMaster {
  145. return ControllerManagerMetrics{}, fmt.Errorf("Master's Kubelet is not registered. Skipping ControllerManager's metrics gathering")
  146. }
  147. output, err := g.getMetricsFromPod(g.client, fmt.Sprintf("%v-%v", "kube-controller-manager", g.masterName), metav1.NamespaceSystem, ports.InsecureKubeControllerManagerPort)
  148. if err != nil {
  149. return ControllerManagerMetrics{}, err
  150. }
  151. return parseControllerManagerMetrics(output)
  152. }
  153. // GrabFromAPIServer returns metrics from API server
  154. func (g *Grabber) GrabFromAPIServer() (APIServerMetrics, error) {
  155. output, err := g.getMetricsFromAPIServer()
  156. if err != nil {
  157. return APIServerMetrics{}, nil
  158. }
  159. return parseAPIServerMetrics(output)
  160. }
  161. // Grab returns metrics from corresponding component
  162. func (g *Grabber) Grab() (Collection, error) {
  163. result := Collection{}
  164. var errs []error
  165. if g.grabFromAPIServer {
  166. metrics, err := g.GrabFromAPIServer()
  167. if err != nil {
  168. errs = append(errs, err)
  169. } else {
  170. result.APIServerMetrics = metrics
  171. }
  172. }
  173. if g.grabFromScheduler {
  174. metrics, err := g.GrabFromScheduler()
  175. if err != nil {
  176. errs = append(errs, err)
  177. } else {
  178. result.SchedulerMetrics = metrics
  179. }
  180. }
  181. if g.grabFromControllerManager {
  182. metrics, err := g.GrabFromControllerManager()
  183. if err != nil {
  184. errs = append(errs, err)
  185. } else {
  186. result.ControllerManagerMetrics = metrics
  187. }
  188. }
  189. if g.grabFromClusterAutoscaler {
  190. metrics, err := g.GrabFromClusterAutoscaler()
  191. if err != nil {
  192. errs = append(errs, err)
  193. } else {
  194. result.ClusterAutoscalerMetrics = metrics
  195. }
  196. }
  197. if g.grabFromKubelets {
  198. result.KubeletMetrics = make(map[string]KubeletMetrics)
  199. nodes, err := g.client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
  200. if err != nil {
  201. errs = append(errs, err)
  202. } else {
  203. for _, node := range nodes.Items {
  204. kubeletPort := node.Status.DaemonEndpoints.KubeletEndpoint.Port
  205. metrics, err := g.grabFromKubeletInternal(node.Name, int(kubeletPort))
  206. if err != nil {
  207. errs = append(errs, err)
  208. }
  209. result.KubeletMetrics[node.Name] = metrics
  210. }
  211. }
  212. }
  213. if len(errs) > 0 {
  214. return result, fmt.Errorf("Errors while grabbing metrics: %v", errs)
  215. }
  216. return result, nil
  217. }
  218. func (g *Grabber) getMetricsFromPod(client clientset.Interface, podName string, namespace string, port int) (string, error) {
  219. rawOutput, err := client.CoreV1().RESTClient().Get().
  220. Namespace(namespace).
  221. Resource("pods").
  222. SubResource("proxy").
  223. Name(fmt.Sprintf("%v:%v", podName, port)).
  224. Suffix("metrics").
  225. Do(context.TODO()).Raw()
  226. if err != nil {
  227. return "", err
  228. }
  229. return string(rawOutput), nil
  230. }