metrics_grabber.go 8.0 KB

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