mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-05 17:27:51 +00:00
Merge pull request #521 from dgrisonnet/bump-k8s-deps-1.24
Update dependencies
This commit is contained in:
commit
47ca16ef50
9 changed files with 1098 additions and 953 deletions
2
Makefile
2
Makefile
|
|
@ -7,7 +7,7 @@ VERSION=$(shell cat VERSION)
|
||||||
TAG_PREFIX=v
|
TAG_PREFIX=v
|
||||||
TAG?=$(TAG_PREFIX)$(VERSION)
|
TAG?=$(TAG_PREFIX)$(VERSION)
|
||||||
|
|
||||||
GO_VERSION?=1.16.4
|
GO_VERSION?=1.18.5
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: prometheus-adapter
|
all: prometheus-adapter
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/metadata"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/metadata/metadatainformer"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
"k8s.io/client-go/transport"
|
"k8s.io/client-go/transport"
|
||||||
|
|
@ -238,15 +238,15 @@ func (cmd *PrometheusAdapter) addResourceMetricsAPI(promClient prom.Client, stop
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := kubernetes.NewForConfig(rest)
|
client, err := metadata.NewForConfig(rest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
podInformerFactory := informers.NewFilteredSharedInformerFactory(client, 0, corev1.NamespaceAll, func(options *metav1.ListOptions) {
|
podInformerFactory := metadatainformer.NewFilteredSharedInformerFactory(client, 0, corev1.NamespaceAll, func(options *metav1.ListOptions) {
|
||||||
options.FieldSelector = "status.phase=Running"
|
options.FieldSelector = "status.phase=Running"
|
||||||
})
|
})
|
||||||
podInformer := podInformerFactory.Core().V1().Pods()
|
podInformer := podInformerFactory.ForResource(corev1.SchemeGroupVersion.WithResource("pods"))
|
||||||
|
|
||||||
informer, err := cmd.Informers()
|
informer, err := cmd.Informers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
121
go.mod
121
go.mod
|
|
@ -1,23 +1,110 @@
|
||||||
module sigs.k8s.io/prometheus-adapter
|
module sigs.k8s.io/prometheus-adapter
|
||||||
|
|
||||||
go 1.16
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/onsi/ginkgo v1.16.4
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/onsi/gomega v1.15.0
|
github.com/onsi/gomega v1.20.0
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.12.1
|
||||||
github.com/prometheus/common v0.26.0
|
github.com/prometheus/common v0.32.1
|
||||||
github.com/spf13/cobra v1.2.1
|
github.com/spf13/cobra v1.5.0
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.8.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
k8s.io/api v0.22.0
|
k8s.io/api v0.24.3
|
||||||
k8s.io/apimachinery v0.22.0
|
k8s.io/apimachinery v0.24.3
|
||||||
k8s.io/apiserver v0.22.0
|
k8s.io/apiserver v0.24.3
|
||||||
k8s.io/client-go v0.22.0
|
k8s.io/client-go v0.24.3
|
||||||
k8s.io/component-base v0.22.0
|
k8s.io/component-base v0.24.3
|
||||||
k8s.io/klog/v2 v2.9.0
|
k8s.io/klog/v2 v2.70.1
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
|
k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6
|
||||||
k8s.io/metrics v0.22.0
|
k8s.io/metrics v0.24.3
|
||||||
sigs.k8s.io/custom-metrics-apiserver v1.22.0
|
sigs.k8s.io/custom-metrics-apiserver v1.24.0
|
||||||
sigs.k8s.io/metrics-server v0.5.0
|
sigs.k8s.io/metrics-server v0.6.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||||
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
|
github.com/coreos/go-semver v0.3.0 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/emicklei/go-restful v2.16.0+incompatible // indirect
|
||||||
|
github.com/emicklei/go-restful-swagger12 v0.0.0-20201014110547-68ccff494617 // indirect
|
||||||
|
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||||
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||||
|
github.com/go-logr/logr v1.2.0 // indirect
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
|
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||||
|
github.com/go-openapi/swag v0.19.15 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/google/gnostic v0.6.9 // indirect
|
||||||
|
github.com/google/go-cmp v0.5.8 // indirect
|
||||||
|
github.com/google/gofuzz v1.1.0 // indirect
|
||||||
|
github.com/google/uuid v1.1.2 // indirect
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||||
|
github.com/imdario/mergo v0.3.5 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
github.com/nxadm/tail v1.4.8 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.7.3 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.1 // indirect
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.5.1 // indirect
|
||||||
|
go.etcd.io/etcd/client/v3 v3.5.1 // indirect
|
||||||
|
go.opentelemetry.io/contrib v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v0.20.0 // indirect
|
||||||
|
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
|
||||||
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
|
go.uber.org/zap v1.19.0 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
|
golang.org/x/tools v0.1.10 // indirect
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect
|
||||||
|
google.golang.org/grpc v1.40.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.28.0 // indirect
|
||||||
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect
|
||||||
|
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 // indirect
|
||||||
|
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:build tools
|
||||||
// +build tools
|
// +build tools
|
||||||
|
|
||||||
// Package tools tracks dependencies for tools that used in the build process.
|
// Package tools tracks dependencies for tools that used in the build process.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build codegen
|
||||||
// +build codegen
|
// +build codegen
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
apitypes "k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
metrics "k8s.io/metrics/pkg/apis/metrics"
|
metrics "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
|
||||||
|
|
@ -123,12 +123,11 @@ type nsQueryResults struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPodMetrics implements the api.MetricsProvider interface.
|
// GetPodMetrics implements the api.MetricsProvider interface.
|
||||||
func (p *resourceProvider) GetPodMetrics(pods ...apitypes.NamespacedName) ([]api.TimeInfo, [][]metrics.ContainerMetrics, error) {
|
func (p *resourceProvider) GetPodMetrics(pods ...*metav1.PartialObjectMetadata) ([]metrics.PodMetrics, error) {
|
||||||
resTimes := make([]api.TimeInfo, len(pods))
|
resMetrics := make([]metrics.PodMetrics, 0, len(pods))
|
||||||
resMetrics := make([][]metrics.ContainerMetrics, len(pods))
|
|
||||||
|
|
||||||
if len(pods) == 0 {
|
if len(pods) == 0 {
|
||||||
return resTimes, resMetrics, nil
|
return resMetrics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(directxman12): figure out how well this scales if we go to list 1000+ pods
|
// TODO(directxman12): figure out how well this scales if we go to list 1000+ pods
|
||||||
|
|
@ -168,37 +167,40 @@ func (p *resourceProvider) GetPodMetrics(pods ...apitypes.NamespacedName) ([]api
|
||||||
|
|
||||||
// convert the unorganized per-container results into results grouped
|
// convert the unorganized per-container results into results grouped
|
||||||
// together by namespace, pod, and container
|
// together by namespace, pod, and container
|
||||||
for i, pod := range pods {
|
for _, pod := range pods {
|
||||||
p.assignForPod(pod, resultsByNs, &resMetrics[i], &resTimes[i])
|
podMetric := p.assignForPod(pod, resultsByNs)
|
||||||
|
if podMetric != nil {
|
||||||
|
resMetrics = append(resMetrics, *podMetric)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resTimes, resMetrics, nil
|
return resMetrics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// assignForPod takes the resource metrics for all containers in the given pod
|
// assignForPod takes the resource metrics for all containers in the given pod
|
||||||
// from resultsByNs, and places them in MetricsProvider response format in resMetrics,
|
// from resultsByNs, and places them in MetricsProvider response format in resMetrics,
|
||||||
// also recording the earliest time in resTime. It will return without operating if
|
// also recording the earliest time in resTime. It will return without operating if
|
||||||
// any data is missing.
|
// any data is missing.
|
||||||
func (p *resourceProvider) assignForPod(pod apitypes.NamespacedName, resultsByNs map[string]nsQueryResults, resMetrics *[]metrics.ContainerMetrics, resTime *api.TimeInfo) {
|
func (p *resourceProvider) assignForPod(pod *metav1.PartialObjectMetadata, resultsByNs map[string]nsQueryResults) *metrics.PodMetrics {
|
||||||
// check to make sure everything is present
|
// check to make sure everything is present
|
||||||
nsRes, nsResPresent := resultsByNs[pod.Namespace]
|
nsRes, nsResPresent := resultsByNs[pod.Namespace]
|
||||||
if !nsResPresent {
|
if !nsResPresent {
|
||||||
klog.Errorf("unable to fetch metrics for pods in namespace %q, skipping pod %s", pod.Namespace, pod.String())
|
klog.Errorf("unable to fetch metrics for pods in namespace %q, skipping pod %s", pod.Namespace, pod.String())
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
cpuRes, hasResult := nsRes.cpu[pod.Name]
|
cpuRes, hasResult := nsRes.cpu[pod.Name]
|
||||||
if !hasResult {
|
if !hasResult {
|
||||||
klog.Errorf("unable to fetch CPU metrics for pod %s, skipping", pod.String())
|
klog.Errorf("unable to fetch CPU metrics for pod %s, skipping", pod.String())
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
memRes, hasResult := nsRes.mem[pod.Name]
|
memRes, hasResult := nsRes.mem[pod.Name]
|
||||||
if !hasResult {
|
if !hasResult {
|
||||||
klog.Errorf("unable to fetch memory metrics for pod %s, skipping", pod.String())
|
klog.Errorf("unable to fetch memory metrics for pod %s, skipping", pod.String())
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
earliestTs := pmodel.Latest
|
|
||||||
containerMetrics := make(map[string]metrics.ContainerMetrics)
|
containerMetrics := make(map[string]metrics.ContainerMetrics)
|
||||||
|
earliestTs := pmodel.Latest
|
||||||
|
|
||||||
// organize all the CPU results
|
// organize all the CPU results
|
||||||
for _, cpu := range cpuRes {
|
for _, cpu := range cpuRes {
|
||||||
|
|
@ -241,40 +243,50 @@ func (p *resourceProvider) assignForPod(pod apitypes.NamespacedName, resultsByNs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// store the time in the final format
|
podMetric := &metrics.PodMetrics{
|
||||||
*resTime = api.TimeInfo{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Timestamp: earliestTs.Time(),
|
Name: pod.Name,
|
||||||
Window: p.window,
|
Namespace: pod.Namespace,
|
||||||
|
Labels: pod.Labels,
|
||||||
|
CreationTimestamp: metav1.Now(),
|
||||||
|
},
|
||||||
|
// store the time in the final format
|
||||||
|
Timestamp: metav1.NewTime(earliestTs.Time()),
|
||||||
|
Window: metav1.Duration{Duration: p.window},
|
||||||
}
|
}
|
||||||
|
|
||||||
// store the container metrics in the final format
|
// store the container metrics in the final format
|
||||||
containerMetricsList := make([]metrics.ContainerMetrics, 0, len(containerMetrics))
|
podMetric.Containers = make([]metrics.ContainerMetrics, 0, len(containerMetrics))
|
||||||
for _, containerMetric := range containerMetrics {
|
for _, containerMetric := range containerMetrics {
|
||||||
containerMetricsList = append(containerMetricsList, containerMetric)
|
podMetric.Containers = append(podMetric.Containers, containerMetric)
|
||||||
}
|
}
|
||||||
*resMetrics = containerMetricsList
|
|
||||||
|
return podMetric
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNodeMetrics implements the api.MetricsProvider interface.
|
// GetNodeMetrics implements the api.MetricsProvider interface.
|
||||||
func (p *resourceProvider) GetNodeMetrics(nodes ...string) ([]api.TimeInfo, []corev1.ResourceList, error) {
|
func (p *resourceProvider) GetNodeMetrics(nodes ...*corev1.Node) ([]metrics.NodeMetrics, error) {
|
||||||
resTimes := make([]api.TimeInfo, len(nodes))
|
resMetrics := make([]metrics.NodeMetrics, 0, len(nodes))
|
||||||
resMetrics := make([]corev1.ResourceList, len(nodes))
|
|
||||||
|
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
return resTimes, resMetrics, nil
|
return resMetrics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
now := pmodel.Now()
|
now := pmodel.Now()
|
||||||
|
nodeNames := make([]string, 0, len(nodes))
|
||||||
|
for _, node := range nodes {
|
||||||
|
nodeNames = append(nodeNames, node.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// run the actual query
|
// run the actual query
|
||||||
qRes := p.queryBoth(now, nodeResource, "", nodes...)
|
qRes := p.queryBoth(now, nodeResource, "", nodeNames...)
|
||||||
if qRes.err != nil {
|
if qRes.err != nil {
|
||||||
klog.Errorf("failed querying node metrics: %v", qRes.err)
|
klog.Errorf("failed querying node metrics: %v", qRes.err)
|
||||||
return resTimes, resMetrics, nil
|
return resMetrics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// organize the results
|
// organize the results
|
||||||
for i, nodeName := range nodes {
|
for i, nodeName := range nodeNames {
|
||||||
// skip if any data is missing
|
// skip if any data is missing
|
||||||
rawCPUs, gotResult := qRes.cpu[nodeName]
|
rawCPUs, gotResult := qRes.cpu[nodeName]
|
||||||
if !gotResult {
|
if !gotResult {
|
||||||
|
|
@ -290,28 +302,30 @@ func (p *resourceProvider) GetNodeMetrics(nodes ...string) ([]api.TimeInfo, []co
|
||||||
rawMem := rawMems[0]
|
rawMem := rawMems[0]
|
||||||
rawCPU := rawCPUs[0]
|
rawCPU := rawCPUs[0]
|
||||||
|
|
||||||
// store the results
|
|
||||||
resMetrics[i] = corev1.ResourceList{
|
|
||||||
corev1.ResourceCPU: *resource.NewMilliQuantity(int64(rawCPU.Value*1000.0), resource.DecimalSI),
|
|
||||||
corev1.ResourceMemory: *resource.NewMilliQuantity(int64(rawMem.Value*1000.0), resource.BinarySI),
|
|
||||||
}
|
|
||||||
|
|
||||||
// use the earliest timestamp available (in order to be conservative
|
// use the earliest timestamp available (in order to be conservative
|
||||||
// when determining if metrics are tainted by startup)
|
// when determining if metrics are tainted by startup)
|
||||||
if rawMem.Timestamp.Before(rawCPU.Timestamp) {
|
ts := rawCPU.Timestamp.Time()
|
||||||
resTimes[i] = api.TimeInfo{
|
if ts.After(rawMem.Timestamp.Time()) {
|
||||||
Timestamp: rawMem.Timestamp.Time(),
|
ts = rawMem.Timestamp.Time()
|
||||||
Window: p.window,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resTimes[i] = api.TimeInfo{
|
|
||||||
Timestamp: rawCPU.Timestamp.Time(),
|
|
||||||
Window: 1 * time.Minute,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store the results
|
||||||
|
resMetrics = append(resMetrics, metrics.NodeMetrics{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: nodes[i].Name,
|
||||||
|
Labels: nodes[i].Labels,
|
||||||
|
CreationTimestamp: metav1.Now(),
|
||||||
|
},
|
||||||
|
Usage: corev1.ResourceList{
|
||||||
|
corev1.ResourceCPU: *resource.NewMilliQuantity(int64(rawCPU.Value*1000.0), resource.DecimalSI),
|
||||||
|
corev1.ResourceMemory: *resource.NewMilliQuantity(int64(rawMem.Value*1000.0), resource.BinarySI),
|
||||||
|
},
|
||||||
|
Timestamp: metav1.NewTime(ts),
|
||||||
|
Window: metav1.Duration{Duration: p.window},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return resTimes, resMetrics, nil
|
return resMetrics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// queryBoth queries for both CPU and memory metrics on the given
|
// queryBoth queries for both CPU and memory metrics on the given
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/metrics/pkg/apis/metrics"
|
"k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
|
||||||
"sigs.k8s.io/metrics-server/pkg/api"
|
"sigs.k8s.io/metrics-server/pkg/api"
|
||||||
|
|
@ -122,10 +122,10 @@ var _ = Describe("Resource Metrics Provider", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should be able to list metrics pods across different namespaces", func() {
|
It("should be able to list metrics pods across different namespaces", func() {
|
||||||
pods := []types.NamespacedName{
|
pods := []*metav1.PartialObjectMetadata{
|
||||||
{Namespace: "some-ns", Name: "pod1"},
|
{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod1"}},
|
||||||
{Namespace: "some-ns", Name: "pod3"},
|
{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod3"}},
|
||||||
{Namespace: "other-ns", Name: "pod27"},
|
{ObjectMeta: metav1.ObjectMeta{Namespace: "other-ns", Name: "pod27"}},
|
||||||
}
|
}
|
||||||
fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{
|
fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{
|
||||||
mustBuild(cpuQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod1", "pod3")): buildQueryRes("container_cpu_usage_seconds_total",
|
mustBuild(cpuQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod1", "pod3")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||||
|
|
@ -149,28 +149,34 @@ var _ = Describe("Resource Metrics Provider", func() {
|
||||||
}
|
}
|
||||||
|
|
||||||
By("querying for metrics for some pods")
|
By("querying for metrics for some pods")
|
||||||
times, metricVals, err := prov.GetPodMetrics(pods...)
|
podMetrics, err := prov.GetPodMetrics(pods...)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("verifying that metrics have been fetched for all the pods")
|
||||||
|
Expect(podMetrics).To(HaveLen(3))
|
||||||
|
|
||||||
By("verifying that the reported times for each are the earliest times for each pod")
|
By("verifying that the reported times for each are the earliest times for each pod")
|
||||||
Expect(times).To(Equal([]api.TimeInfo{
|
Expect(podMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
|
Expect(podMetrics[0].Window.Duration).To(Equal(time.Minute))
|
||||||
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
|
|
||||||
{Timestamp: pmodel.Time(270).Time(), Window: 1 * time.Minute},
|
Expect(podMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
}))
|
Expect(podMetrics[1].Window.Duration).To(Equal(time.Minute))
|
||||||
|
|
||||||
|
Expect(podMetrics[2].Timestamp.Time).To(Equal(pmodel.Time(270).Time()))
|
||||||
|
Expect(podMetrics[2].Window.Duration).To(Equal(time.Minute))
|
||||||
|
|
||||||
By("verifying that the right metrics were fetched")
|
By("verifying that the right metrics were fetched")
|
||||||
Expect(metricVals).To(HaveLen(3))
|
Expect(podMetrics).To(HaveLen(3))
|
||||||
Expect(metricVals[0]).To(ConsistOf(
|
Expect(podMetrics[0].Containers).To(ConsistOf(
|
||||||
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)},
|
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)},
|
||||||
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)},
|
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)},
|
||||||
))
|
))
|
||||||
Expect(metricVals[1]).To(ConsistOf(
|
Expect(podMetrics[1].Containers).To(ConsistOf(
|
||||||
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1300.0, 3300.0)},
|
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1300.0, 3300.0)},
|
||||||
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 3310.0)},
|
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 3310.0)},
|
||||||
))
|
))
|
||||||
|
|
||||||
Expect(metricVals[2]).To(ConsistOf(
|
Expect(podMetrics[2].Containers).To(ConsistOf(
|
||||||
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(2200.0, 4200.0)},
|
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(2200.0, 4200.0)},
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
@ -188,23 +194,22 @@ var _ = Describe("Resource Metrics Provider", func() {
|
||||||
}
|
}
|
||||||
|
|
||||||
By("querying for metrics for some pods, one of which is missing")
|
By("querying for metrics for some pods, one of which is missing")
|
||||||
times, metricVals, err := prov.GetPodMetrics(
|
podMetrics, err := prov.GetPodMetrics(
|
||||||
types.NamespacedName{Namespace: "some-ns", Name: "pod1"},
|
&metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod1"}},
|
||||||
types.NamespacedName{Namespace: "some-ns", Name: "pod-nonexistant"},
|
&metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod-nonexistant"}},
|
||||||
)
|
)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("verifying that the missing pod had nil metrics")
|
By("verifying that the missing pod had no metrics")
|
||||||
Expect(metricVals).To(HaveLen(2))
|
Expect(podMetrics).To(HaveLen(1))
|
||||||
Expect(metricVals[1]).To(BeNil())
|
|
||||||
|
|
||||||
By("verifying that the rest of time metrics and times are correct")
|
By("verifying that the rest of time metrics and times are correct")
|
||||||
Expect(metricVals[0]).To(ConsistOf(
|
Expect(podMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
|
Expect(podMetrics[0].Window.Duration).To(Equal(time.Minute))
|
||||||
|
Expect(podMetrics[0].Containers).To(ConsistOf(
|
||||||
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)},
|
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)},
|
||||||
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)},
|
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)},
|
||||||
))
|
))
|
||||||
Expect(times).To(HaveLen(2))
|
|
||||||
Expect(times[0]).To(Equal(api.TimeInfo{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute}))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should return metrics of value zero when pod metrics have NaN or negative values", func() {
|
It("should return metrics of value zero when pod metrics have NaN or negative values", func() {
|
||||||
|
|
@ -224,25 +229,27 @@ var _ = Describe("Resource Metrics Provider", func() {
|
||||||
}
|
}
|
||||||
|
|
||||||
By("querying for metrics for some pods")
|
By("querying for metrics for some pods")
|
||||||
times, metricVals, err := prov.GetPodMetrics(
|
podMetrics, err := prov.GetPodMetrics(
|
||||||
types.NamespacedName{Namespace: "some-ns", Name: "pod1"},
|
&metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod1"}},
|
||||||
types.NamespacedName{Namespace: "some-ns", Name: "pod3"},
|
&metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod3"}},
|
||||||
)
|
)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("verifying that metrics have been fetched for all the pods")
|
||||||
|
Expect(podMetrics).To(HaveLen(2))
|
||||||
|
|
||||||
By("verifying that the reported times for each are the earliest times for each pod")
|
By("verifying that the reported times for each are the earliest times for each pod")
|
||||||
Expect(times).To(Equal([]api.TimeInfo{
|
Expect(podMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
|
Expect(podMetrics[0].Window.Duration).To(Equal(time.Minute))
|
||||||
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
|
Expect(podMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
}))
|
Expect(podMetrics[1].Window.Duration).To(Equal(time.Minute))
|
||||||
|
|
||||||
By("verifying that NaN and negative values were replaced by zero")
|
By("verifying that NaN and negative values were replaced by zero")
|
||||||
Expect(metricVals).To(HaveLen(2))
|
Expect(podMetrics[0].Containers).To(ConsistOf(
|
||||||
Expect(metricVals[0]).To(ConsistOf(
|
|
||||||
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 3100.0)},
|
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 3100.0)},
|
||||||
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(0, 0)},
|
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(0, 0)},
|
||||||
))
|
))
|
||||||
Expect(metricVals[1]).To(ConsistOf(
|
Expect(podMetrics[1].Containers).To(ConsistOf(
|
||||||
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 0)},
|
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 0)},
|
||||||
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 0)},
|
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 0)},
|
||||||
))
|
))
|
||||||
|
|
@ -260,20 +267,24 @@ var _ = Describe("Resource Metrics Provider", func() {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
By("querying for metrics for some nodes")
|
By("querying for metrics for some nodes")
|
||||||
times, metricVals, err := prov.GetNodeMetrics("node1", "node2")
|
nodeMetrics, err := prov.GetNodeMetrics(
|
||||||
|
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node1"}},
|
||||||
|
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}},
|
||||||
|
)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("verifying that the reported times for each are the earliest times for each pod")
|
By("verifying that metrics have been fetched for all the nodes")
|
||||||
Expect(times).To(Equal([]api.TimeInfo{
|
Expect(nodeMetrics).To(HaveLen(2))
|
||||||
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
|
|
||||||
{Timestamp: pmodel.Time(12).Time(), Window: 1 * time.Minute},
|
By("verifying that the reported times for each are the earliest times for each node")
|
||||||
}))
|
Expect(nodeMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
|
Expect(nodeMetrics[0].Window.Duration).To(Equal(time.Minute))
|
||||||
|
Expect(nodeMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(12).Time()))
|
||||||
|
Expect(nodeMetrics[1].Window.Duration).To(Equal(time.Minute))
|
||||||
|
|
||||||
By("verifying that the right metrics were fetched")
|
By("verifying that the right metrics were fetched")
|
||||||
Expect(metricVals).To(Equal([]corev1.ResourceList{
|
Expect(nodeMetrics[0].Usage).To(Equal(buildResList(1100.0, 2100.0)))
|
||||||
buildResList(1100.0, 2100.0),
|
Expect(nodeMetrics[1].Usage).To(Equal(buildResList(1200.0, 2200.0)))
|
||||||
buildResList(1200.0, 2200.0),
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should return nil metrics for missing nodes, but still return partial results", func() {
|
It("should return nil metrics for missing nodes, but still return partial results", func() {
|
||||||
|
|
@ -288,24 +299,23 @@ var _ = Describe("Resource Metrics Provider", func() {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
By("querying for metrics for some nodes, one of which is missing")
|
By("querying for metrics for some nodes, one of which is missing")
|
||||||
times, metricVals, err := prov.GetNodeMetrics("node1", "node2", "node3")
|
nodeMetrics, err := prov.GetNodeMetrics(
|
||||||
|
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node1"}},
|
||||||
|
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}},
|
||||||
|
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node3"}},
|
||||||
|
)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("verifying that the missing pod had nil metrics")
|
By("verifying that the missing pod had no metrics")
|
||||||
Expect(metricVals).To(HaveLen(3))
|
Expect(nodeMetrics).To(HaveLen(2))
|
||||||
Expect(metricVals[2]).To(BeNil())
|
|
||||||
|
|
||||||
By("verifying that the rest of time metrics and times are correct")
|
By("verifying that the rest of time metrics and times are correct")
|
||||||
Expect(metricVals).To(Equal([]corev1.ResourceList{
|
Expect(nodeMetrics[0].Usage).To(Equal(buildResList(1100.0, 2100.0)))
|
||||||
buildResList(1100.0, 2100.0),
|
Expect(nodeMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
buildResList(1200.0, 2200.0),
|
Expect(nodeMetrics[0].Window.Duration).To(Equal(time.Minute))
|
||||||
nil,
|
Expect(nodeMetrics[1].Usage).To(Equal(buildResList(1200.0, 2200.0)))
|
||||||
}))
|
Expect(nodeMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(12).Time()))
|
||||||
Expect(times).To(Equal([]api.TimeInfo{
|
Expect(nodeMetrics[1].Window.Duration).To(Equal(time.Minute))
|
||||||
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
|
|
||||||
{Timestamp: pmodel.Time(12).Time(), Window: 1 * time.Minute},
|
|
||||||
{},
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should return metrics of value zero when node metrics have NaN or negative values", func() {
|
It("should return metrics of value zero when node metrics have NaN or negative values", func() {
|
||||||
|
|
@ -320,19 +330,23 @@ var _ = Describe("Resource Metrics Provider", func() {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
By("querying for metrics for some nodes")
|
By("querying for metrics for some nodes")
|
||||||
times, metricVals, err := prov.GetNodeMetrics("node1", "node2")
|
nodeMetrics, err := prov.GetNodeMetrics(
|
||||||
|
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node1"}},
|
||||||
|
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}},
|
||||||
|
)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("verifying that metrics have been fetched for all the nodes")
|
||||||
|
Expect(nodeMetrics).To(HaveLen(2))
|
||||||
|
|
||||||
By("verifying that the reported times for each are the earliest times for each pod")
|
By("verifying that the reported times for each are the earliest times for each pod")
|
||||||
Expect(times).To(Equal([]api.TimeInfo{
|
Expect(nodeMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
|
||||||
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
|
Expect(nodeMetrics[0].Window.Duration).To(Equal(time.Minute))
|
||||||
{Timestamp: pmodel.Time(12).Time(), Window: 1 * time.Minute},
|
Expect(nodeMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(12).Time()))
|
||||||
}))
|
Expect(nodeMetrics[1].Window.Duration).To(Equal(time.Minute))
|
||||||
|
|
||||||
By("verifying that NaN and negative values were replaced by zero")
|
By("verifying that NaN and negative values were replaced by zero")
|
||||||
Expect(metricVals).To(Equal([]corev1.ResourceList{
|
Expect(nodeMetrics[0].Usage).To(Equal(buildResList(0, 2100.0)))
|
||||||
buildResList(0, 2100.0),
|
Expect(nodeMetrics[1].Usage).To(Equal(buildResList(1200.0, 0)))
|
||||||
buildResList(1200.0, 0),
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue