metrics_client.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. Copyright 2016 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 metricsutil
  14. import (
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "k8s.io/apimachinery/pkg/api/validation"
  19. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  20. "k8s.io/apimachinery/pkg/labels"
  21. "k8s.io/apimachinery/pkg/runtime/schema"
  22. corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
  23. metricsapi "k8s.io/metrics/pkg/apis/metrics"
  24. metricsv1alpha1api "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
  25. )
  26. const (
  27. DefaultHeapsterNamespace = "kube-system"
  28. DefaultHeapsterScheme = "http"
  29. DefaultHeapsterService = "heapster"
  30. DefaultHeapsterPort = "" // use the first exposed port on the service
  31. )
  32. var (
  33. prefix = "/apis"
  34. groupVersion = fmt.Sprintf("%s/%s", metricsGv.Group, metricsGv.Version)
  35. metricsRoot = fmt.Sprintf("%s/%s", prefix, groupVersion)
  36. // TODO: get this from metrics api once it's finished
  37. metricsGv = schema.GroupVersion{Group: "metrics", Version: "v1alpha1"}
  38. )
  39. type HeapsterMetricsClient struct {
  40. SVCClient corev1client.ServicesGetter
  41. HeapsterNamespace string
  42. HeapsterScheme string
  43. HeapsterService string
  44. HeapsterPort string
  45. }
  46. func NewHeapsterMetricsClient(svcClient corev1client.ServicesGetter, namespace, scheme, service, port string) *HeapsterMetricsClient {
  47. return &HeapsterMetricsClient{
  48. SVCClient: svcClient,
  49. HeapsterNamespace: namespace,
  50. HeapsterScheme: scheme,
  51. HeapsterService: service,
  52. HeapsterPort: port,
  53. }
  54. }
  55. func podMetricsURL(namespace string, name string) (string, error) {
  56. if namespace == metav1.NamespaceAll {
  57. return fmt.Sprintf("%s/pods", metricsRoot), nil
  58. }
  59. errs := validation.ValidateNamespaceName(namespace, false)
  60. if len(errs) > 0 {
  61. message := fmt.Sprintf("invalid namespace: %s - %v", namespace, errs)
  62. return "", errors.New(message)
  63. }
  64. if len(name) > 0 {
  65. errs = validation.NameIsDNSSubdomain(name, false)
  66. if len(errs) > 0 {
  67. message := fmt.Sprintf("invalid pod name: %s - %v", name, errs)
  68. return "", errors.New(message)
  69. }
  70. }
  71. return fmt.Sprintf("%s/namespaces/%s/pods/%s", metricsRoot, namespace, name), nil
  72. }
  73. func nodeMetricsURL(name string) (string, error) {
  74. if len(name) > 0 {
  75. errs := validation.NameIsDNSSubdomain(name, false)
  76. if len(errs) > 0 {
  77. message := fmt.Sprintf("invalid node name: %s - %v", name, errs)
  78. return "", errors.New(message)
  79. }
  80. }
  81. return fmt.Sprintf("%s/nodes/%s", metricsRoot, name), nil
  82. }
  83. func (cli *HeapsterMetricsClient) GetNodeMetrics(nodeName string, selector string) (*metricsapi.NodeMetricsList, error) {
  84. params := map[string]string{"labelSelector": selector}
  85. path, err := nodeMetricsURL(nodeName)
  86. if err != nil {
  87. return nil, err
  88. }
  89. resultRaw, err := GetHeapsterMetrics(cli, path, params)
  90. if err != nil {
  91. return nil, err
  92. }
  93. versionedMetrics := metricsv1alpha1api.NodeMetricsList{}
  94. if len(nodeName) == 0 {
  95. err = json.Unmarshal(resultRaw, &versionedMetrics)
  96. if err != nil {
  97. return nil, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  98. }
  99. } else {
  100. var singleMetric metricsv1alpha1api.NodeMetrics
  101. err = json.Unmarshal(resultRaw, &singleMetric)
  102. if err != nil {
  103. return nil, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  104. }
  105. versionedMetrics.Items = []metricsv1alpha1api.NodeMetrics{singleMetric}
  106. }
  107. metrics := &metricsapi.NodeMetricsList{}
  108. err = metricsv1alpha1api.Convert_v1alpha1_NodeMetricsList_To_metrics_NodeMetricsList(&versionedMetrics, metrics, nil)
  109. if err != nil {
  110. return nil, err
  111. }
  112. return metrics, nil
  113. }
  114. func (cli *HeapsterMetricsClient) GetPodMetrics(namespace string, podName string, allNamespaces bool, selector labels.Selector) (*metricsapi.PodMetricsList, error) {
  115. if allNamespaces {
  116. namespace = metav1.NamespaceAll
  117. }
  118. path, err := podMetricsURL(namespace, podName)
  119. if err != nil {
  120. return nil, err
  121. }
  122. params := map[string]string{"labelSelector": selector.String()}
  123. versionedMetrics := metricsv1alpha1api.PodMetricsList{}
  124. resultRaw, err := GetHeapsterMetrics(cli, path, params)
  125. if err != nil {
  126. return nil, err
  127. }
  128. if len(podName) == 0 {
  129. err = json.Unmarshal(resultRaw, &versionedMetrics)
  130. if err != nil {
  131. return nil, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  132. }
  133. } else {
  134. var singleMetric metricsv1alpha1api.PodMetrics
  135. err = json.Unmarshal(resultRaw, &singleMetric)
  136. if err != nil {
  137. return nil, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  138. }
  139. versionedMetrics.Items = []metricsv1alpha1api.PodMetrics{singleMetric}
  140. }
  141. metrics := &metricsapi.PodMetricsList{}
  142. err = metricsv1alpha1api.Convert_v1alpha1_PodMetricsList_To_metrics_PodMetricsList(&versionedMetrics, metrics, nil)
  143. if err != nil {
  144. return nil, err
  145. }
  146. return metrics, nil
  147. }
  148. func GetHeapsterMetrics(cli *HeapsterMetricsClient, path string, params map[string]string) ([]byte, error) {
  149. return cli.SVCClient.Services(cli.HeapsterNamespace).
  150. ProxyGet(cli.HeapsterScheme, cli.HeapsterService, cli.HeapsterPort, path, params).
  151. DoRaw()
  152. }