Commit d797c219 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #47260 from yguo0905/perf-dash

Automatic merge from submit-queue (batch tested with PRs 47470, 47260, 47411, 46852, 46135) Logs node e2e perf data to standalone json files Fixes the node-dash-perf issue in https://github.com/kubernetes/kubernetes/issues/44003. - Move perf data types to `test/e2e/perftype/perftype.go` so that the node-perf-dash can depend on. - Logs the perf data to standalone json files so that node-perf-dash can consume it easily. A sample run of `ci-kubernetes-node-kubelet-benchmark` is at https://console.cloud.google.com/storage/browser/ygg-gke-dev-bucket/e2e-node-test/ci-kubernetes-node-kubelet-benchmark/1. The corresponding changes in node-perf-dash is at https://github.com/kubernetes/contrib/pull/2628. **Release note**: `None` /sig node /area node-e2e /assign @Random-Liu
parents 037330c3 29b2db5a
...@@ -458,6 +458,7 @@ staging/src/k8s.io/metrics/pkg/apis/metrics/install ...@@ -458,6 +458,7 @@ staging/src/k8s.io/metrics/pkg/apis/metrics/install
staging/src/k8s.io/sample-apiserver staging/src/k8s.io/sample-apiserver
staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install
test/e2e/perftype test/e2e/perftype
test/e2e_node/perftype
test/e2e_node/runner/local test/e2e_node/runner/local
test/images/clusterapi-tester test/images/clusterapi-tester
test/images/entrypoint-tester test/images/entrypoint-tester
......
...@@ -71,9 +71,10 @@ func PodStartupLatencyToPerfData(latency *PodStartupLatency) *perftype.PerfData ...@@ -71,9 +71,10 @@ func PodStartupLatencyToPerfData(latency *PodStartupLatency) *perftype.PerfData
return perfData return perfData
} }
// currentKubeletPerfMetricsVersion is the current kubelet performance metrics version. We should // CurrentKubeletPerfMetricsVersion is the current kubelet performance metrics
// bump up the version each time we make incompatible change to the metrics. // version. This is used by mutiple perf related data structures. We should
const currentKubeletPerfMetricsVersion = "v2" // bump up the version each time we make an incompatible change to the metrics.
const CurrentKubeletPerfMetricsVersion = "v2"
// ResourceUsageToPerfData transforms ResourceUsagePerNode to PerfData. Notice that this function // ResourceUsageToPerfData transforms ResourceUsagePerNode to PerfData. Notice that this function
// only cares about memory usage, because cpu usage information will be extracted from NodesCPUSummary. // only cares about memory usage, because cpu usage information will be extracted from NodesCPUSummary.
...@@ -119,7 +120,7 @@ func ResourceUsageToPerfDataWithLabels(usagePerNode ResourceUsagePerNode, labels ...@@ -119,7 +120,7 @@ func ResourceUsageToPerfDataWithLabels(usagePerNode ResourceUsagePerNode, labels
} }
} }
return &perftype.PerfData{ return &perftype.PerfData{
Version: currentKubeletPerfMetricsVersion, Version: CurrentKubeletPerfMetricsVersion,
DataItems: items, DataItems: items,
Labels: labels, Labels: labels,
} }
...@@ -149,7 +150,7 @@ func CPUUsageToPerfDataWithLabels(usagePerNode NodesCPUSummary, labels map[strin ...@@ -149,7 +150,7 @@ func CPUUsageToPerfDataWithLabels(usagePerNode NodesCPUSummary, labels map[strin
} }
} }
return &perftype.PerfData{ return &perftype.PerfData{
Version: currentKubeletPerfMetricsVersion, Version: CurrentKubeletPerfMetricsVersion,
DataItems: items, DataItems: items,
Labels: labels, Labels: labels,
} }
......
...@@ -41,6 +41,7 @@ go_library( ...@@ -41,6 +41,7 @@ go_library(
"//test/e2e/common:go_default_library", "//test/e2e/common:go_default_library",
"//test/e2e/framework:go_default_library", "//test/e2e/framework:go_default_library",
"//test/e2e/perftype:go_default_library", "//test/e2e/perftype:go_default_library",
"//test/e2e_node/perftype:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/google/cadvisor/client/v2:go_default_library", "//vendor/github.com/google/cadvisor/client/v2:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library", "//vendor/github.com/google/cadvisor/info/v2:go_default_library",
...@@ -165,6 +166,7 @@ filegroup( ...@@ -165,6 +166,7 @@ filegroup(
":package-srcs", ":package-srcs",
"//test/e2e_node/builder:all-srcs", "//test/e2e_node/builder:all-srcs",
"//test/e2e_node/environment:all-srcs", "//test/e2e_node/environment:all-srcs",
"//test/e2e_node/perftype:all-srcs",
"//test/e2e_node/remote:all-srcs", "//test/e2e_node/remote:all-srcs",
"//test/e2e_node/runner/local:all-srcs", "//test/e2e_node/runner/local:all-srcs",
"//test/e2e_node/runner/remote:all-srcs", "//test/e2e_node/runner/remote:all-srcs",
......
...@@ -20,36 +20,57 @@ package e2e_node ...@@ -20,36 +20,57 @@ package e2e_node
import ( import (
"fmt" "fmt"
"io/ioutil"
"path"
"sort" "sort"
"strconv"
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/e2e/perftype" "k8s.io/kubernetes/test/e2e/perftype"
nodeperftype "k8s.io/kubernetes/test/e2e_node/perftype"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
const ( const (
// TODO(coufon): be consistent with perf_util.go version TimeSeriesTag = "[Result:TimeSeries]"
currentDataVersion = "v1" TimeSeriesEnd = "[Finish:TimeSeries]"
TimeSeriesTag = "[Result:TimeSeries]"
TimeSeriesEnd = "[Finish:TimeSeries]"
) )
type NodeTimeSeries struct { // dumpDataToFile inserts the current timestamp into the labels and writes the
// value in OperationData is an array of timestamps // data for the test into the file with the specified prefix.
OperationData map[string][]int64 `json:"op_series,omitempty"` func dumpDataToFile(data interface{}, labels map[string]string, prefix string) {
ResourceData map[string]*ResourceSeries `json:"resource_series,omitempty"` testName := labels["test"]
Labels map[string]string `json:"labels"` fileName := path.Join(framework.TestContext.ReportDir, fmt.Sprintf("%s-%s.json", prefix, testName))
Version string `json:"version"` labels["timestamp"] = strconv.FormatInt(time.Now().UTC().Unix(), 10)
framework.Logf("Dumping perf data for test %q to %q.", testName, fileName)
if err := ioutil.WriteFile(fileName, []byte(framework.PrettyPrintJSON(data)), 0644); err != nil {
framework.Logf("Failed to write perf data for test %q to %q: %v", testName, fileName, err)
}
}
// logPerfData writes the perf data to a standalone json file if the
// framework.TestContext.ReportDir is non-empty, or to the general build log
// otherwise. The perfType identifies which type of the perf data it is, such
// as "cpu" and "memory". If an error occurs, no perf data will be logged.
func logPerfData(p *perftype.PerfData, perfType string) {
if framework.TestContext.ReportDir == "" {
framework.PrintPerfData(p)
return
}
dumpDataToFile(p, p.Labels, "performance-"+perfType)
} }
// logDensityTimeSeries logs the time series data of operation and resource usage // logDensityTimeSeries writes the time series data of operation and resource
// usage to a standalone json file if the framework.TestContext.ReportDir is
// non-empty, or to the general build log otherwise. If an error occurs,
// no perf data will be logged.
func logDensityTimeSeries(rc *ResourceCollector, create, watch map[string]metav1.Time, testInfo map[string]string) { func logDensityTimeSeries(rc *ResourceCollector, create, watch map[string]metav1.Time, testInfo map[string]string) {
timeSeries := &NodeTimeSeries{ timeSeries := &nodeperftype.NodeTimeSeries{
Labels: testInfo, Labels: testInfo,
Version: currentDataVersion, Version: framework.CurrentKubeletPerfMetricsVersion,
} }
// Attach operation time series. // Attach operation time series.
timeSeries.OperationData = map[string][]int64{ timeSeries.OperationData = map[string][]int64{
...@@ -58,8 +79,12 @@ func logDensityTimeSeries(rc *ResourceCollector, create, watch map[string]metav1 ...@@ -58,8 +79,12 @@ func logDensityTimeSeries(rc *ResourceCollector, create, watch map[string]metav1
} }
// Attach resource time series. // Attach resource time series.
timeSeries.ResourceData = rc.GetResourceTimeSeries() timeSeries.ResourceData = rc.GetResourceTimeSeries()
// Log time series with tags
framework.Logf("%s %s\n%s", TimeSeriesTag, framework.PrettyPrintJSON(timeSeries), TimeSeriesEnd) if framework.TestContext.ReportDir == "" {
framework.Logf("%s %s\n%s", TimeSeriesTag, framework.PrettyPrintJSON(timeSeries), TimeSeriesEnd)
return
}
dumpDataToFile(timeSeries, timeSeries.Labels, "time_series")
} }
type int64arr []int64 type int64arr []int64
...@@ -82,7 +107,7 @@ func getCumulatedPodTimeSeries(timePerPod map[string]metav1.Time) []int64 { ...@@ -82,7 +107,7 @@ func getCumulatedPodTimeSeries(timePerPod map[string]metav1.Time) []int64 {
// getLatencyPerfData returns perf data of pod startup latency. // getLatencyPerfData returns perf data of pod startup latency.
func getLatencyPerfData(latency framework.LatencyMetric, testInfo map[string]string) *perftype.PerfData { func getLatencyPerfData(latency framework.LatencyMetric, testInfo map[string]string) *perftype.PerfData {
return &perftype.PerfData{ return &perftype.PerfData{
Version: currentDataVersion, Version: framework.CurrentKubeletPerfMetricsVersion,
DataItems: []perftype.DataItem{ DataItems: []perftype.DataItem{
{ {
Data: map[string]float64{ Data: map[string]float64{
...@@ -105,7 +130,7 @@ func getLatencyPerfData(latency framework.LatencyMetric, testInfo map[string]str ...@@ -105,7 +130,7 @@ func getLatencyPerfData(latency framework.LatencyMetric, testInfo map[string]str
// getThroughputPerfData returns perf data of pod creation startup throughput. // getThroughputPerfData returns perf data of pod creation startup throughput.
func getThroughputPerfData(batchLag time.Duration, e2eLags []framework.PodLatencyData, podsNr int, testInfo map[string]string) *perftype.PerfData { func getThroughputPerfData(batchLag time.Duration, e2eLags []framework.PodLatencyData, podsNr int, testInfo map[string]string) *perftype.PerfData {
return &perftype.PerfData{ return &perftype.PerfData{
Version: currentDataVersion, Version: framework.CurrentKubeletPerfMetricsVersion,
DataItems: []perftype.DataItem{ DataItems: []perftype.DataItem{
{ {
Data: map[string]float64{ Data: map[string]float64{
...@@ -123,8 +148,10 @@ func getThroughputPerfData(batchLag time.Duration, e2eLags []framework.PodLatenc ...@@ -123,8 +148,10 @@ func getThroughputPerfData(batchLag time.Duration, e2eLags []framework.PodLatenc
} }
} }
// getTestNodeInfo fetches the capacity of a node from API server and returns a map of labels. // getTestNodeInfo returns a label map containing the test name and
func getTestNodeInfo(f *framework.Framework, testName string) map[string]string { // description, the name of the node on which the test will be run, the image
// name of the node, and the node capacities.
func getTestNodeInfo(f *framework.Framework, testName, testDesc string) map[string]string {
nodeName := framework.TestContext.NodeName nodeName := framework.TestContext.NodeName
node, err := f.ClientSet.Core().Nodes().Get(nodeName, metav1.GetOptions{}) node, err := f.ClientSet.Core().Nodes().Get(nodeName, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
...@@ -154,5 +181,6 @@ func getTestNodeInfo(f *framework.Framework, testName string) map[string]string ...@@ -154,5 +181,6 @@ func getTestNodeInfo(f *framework.Framework, testName string) map[string]string
"test": testName, "test": testName,
"image": node.Status.NodeInfo.OSImage, "image": node.Status.NodeInfo.OSImage,
"machine": fmt.Sprintf("cpu:%dcore,memory:%.1fGB", cpuValue, float32(memoryValue)/(1024*1024*1024)), "machine": fmt.Sprintf("cpu:%dcore,memory:%.1fGB", cpuValue, float32(memoryValue)/(1024*1024*1024)),
"desc": testDesc,
} }
} }
...@@ -94,10 +94,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { ...@@ -94,10 +94,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() {
for _, testArg := range dTests { for _, testArg := range dTests {
itArg := testArg itArg := testArg
It(fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval", desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval", itArg.podsNr, itArg.interval)
itArg.podsNr, itArg.interval), func() { It(desc, func() {
itArg.createMethod = "batch" itArg.createMethod = "batch"
testInfo := getTestNodeInfo(f, itArg.getTestName()) testInfo := getTestNodeInfo(f, itArg.getTestName(), desc)
batchLag, e2eLags := runDensityBatchTest(f, rc, itArg, testInfo, false) batchLag, e2eLags := runDensityBatchTest(f, rc, itArg, testInfo, false)
...@@ -152,10 +152,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { ...@@ -152,10 +152,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() {
for _, testArg := range dTests { for _, testArg := range dTests {
itArg := testArg itArg := testArg
It(fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval [Benchmark]", desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval [Benchmark]", itArg.podsNr, itArg.interval)
itArg.podsNr, itArg.interval), func() { It(desc, func() {
itArg.createMethod = "batch" itArg.createMethod = "batch"
testInfo := getTestNodeInfo(f, itArg.getTestName()) testInfo := getTestNodeInfo(f, itArg.getTestName(), desc)
batchLag, e2eLags := runDensityBatchTest(f, rc, itArg, testInfo, true) batchLag, e2eLags := runDensityBatchTest(f, rc, itArg, testInfo, true)
...@@ -189,10 +189,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { ...@@ -189,10 +189,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() {
for _, testArg := range dTests { for _, testArg := range dTests {
itArg := testArg itArg := testArg
It(fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval (QPS %d) [Benchmark]", desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %v interval (QPS %d) [Benchmark]", itArg.podsNr, itArg.interval, itArg.APIQPSLimit)
itArg.podsNr, itArg.interval, itArg.APIQPSLimit), func() { It(desc, func() {
itArg.createMethod = "batch" itArg.createMethod = "batch"
testInfo := getTestNodeInfo(f, itArg.getTestName()) testInfo := getTestNodeInfo(f, itArg.getTestName(), desc)
// The latency caused by API QPS limit takes a large portion (up to ~33%) of e2e latency. // The latency caused by API QPS limit takes a large portion (up to ~33%) of e2e latency.
// It makes the pod startup latency of Kubelet (creation throughput as well) under-estimated. // It makes the pod startup latency of Kubelet (creation throughput as well) under-estimated.
// Here we set API QPS limit from default 5 to 60 in order to test real Kubelet performance. // Here we set API QPS limit from default 5 to 60 in order to test real Kubelet performance.
...@@ -232,10 +232,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { ...@@ -232,10 +232,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() {
for _, testArg := range dTests { for _, testArg := range dTests {
itArg := testArg itArg := testArg
It(fmt.Sprintf("latency/resource should be within limit when create %d pods with %d background pods", desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %d background pods", itArg.podsNr, itArg.bgPodsNr)
itArg.podsNr, itArg.bgPodsNr), func() { It(desc, func() {
itArg.createMethod = "sequence" itArg.createMethod = "sequence"
testInfo := getTestNodeInfo(f, itArg.getTestName()) testInfo := getTestNodeInfo(f, itArg.getTestName(), desc)
batchlag, e2eLags := runDensitySeqTest(f, rc, itArg, testInfo) batchlag, e2eLags := runDensitySeqTest(f, rc, itArg, testInfo)
By("Verifying latency") By("Verifying latency")
...@@ -265,10 +265,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() { ...@@ -265,10 +265,10 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() {
for _, testArg := range dTests { for _, testArg := range dTests {
itArg := testArg itArg := testArg
It(fmt.Sprintf("latency/resource should be within limit when create %d pods with %d background pods [Benchmark]", desc := fmt.Sprintf("latency/resource should be within limit when create %d pods with %d background pods [Benchmark]", itArg.podsNr, itArg.bgPodsNr)
itArg.podsNr, itArg.bgPodsNr), func() { It(desc, func() {
itArg.createMethod = "sequence" itArg.createMethod = "sequence"
testInfo := getTestNodeInfo(f, itArg.getTestName()) testInfo := getTestNodeInfo(f, itArg.getTestName(), desc)
batchlag, e2eLags := runDensitySeqTest(f, rc, itArg, testInfo) batchlag, e2eLags := runDensitySeqTest(f, rc, itArg, testInfo)
By("Verifying latency") By("Verifying latency")
...@@ -551,7 +551,7 @@ func logAndVerifyLatency(batchLag time.Duration, e2eLags []framework.PodLatencyD ...@@ -551,7 +551,7 @@ func logAndVerifyLatency(batchLag time.Duration, e2eLags []framework.PodLatencyD
podCreateLatency := framework.PodStartupLatency{Latency: framework.ExtractLatencyMetrics(e2eLags)} podCreateLatency := framework.PodStartupLatency{Latency: framework.ExtractLatencyMetrics(e2eLags)}
// log latency perf data // log latency perf data
framework.PrintPerfData(getLatencyPerfData(podCreateLatency.Latency, testInfo)) logPerfData(getLatencyPerfData(podCreateLatency.Latency, testInfo), "latency")
if isVerify { if isVerify {
// check whether e2e pod startup time is acceptable. // check whether e2e pod startup time is acceptable.
...@@ -567,7 +567,7 @@ func logAndVerifyLatency(batchLag time.Duration, e2eLags []framework.PodLatencyD ...@@ -567,7 +567,7 @@ func logAndVerifyLatency(batchLag time.Duration, e2eLags []framework.PodLatencyD
// logThroughput calculates and logs pod creation throughput. // logThroughput calculates and logs pod creation throughput.
func logPodCreateThroughput(batchLag time.Duration, e2eLags []framework.PodLatencyData, podsNr int, testInfo map[string]string) { func logPodCreateThroughput(batchLag time.Duration, e2eLags []framework.PodLatencyData, podsNr int, testInfo map[string]string) {
framework.PrintPerfData(getThroughputPerfData(batchLag, e2eLags, podsNr, testInfo)) logPerfData(getThroughputPerfData(batchLag, e2eLags, podsNr, testInfo), "throughput")
} }
// increaseKubeletAPIQPSLimit sets Kubelet API QPS via ConfigMap. Kubelet will restart with the new QPS. // increaseKubeletAPIQPSLimit sets Kubelet API QPS via ConfigMap. Kubelet will restart with the new QPS.
......
...@@ -119,7 +119,7 @@ for upload_attempt in $(seq 3); do ...@@ -119,7 +119,7 @@ for upload_attempt in $(seq 3); do
if [[ -d "${ARTIFACTS}" && -n $(ls -A "${ARTIFACTS}") ]]; then if [[ -d "${ARTIFACTS}" && -n $(ls -A "${ARTIFACTS}") ]]; then
V=2 kube::log::status "Uploading artifacts" V=2 kube::log::status "Uploading artifacts"
gsutil -m -q -o "GSUtil:use_magicfile=True" cp -a "${gcs_acl}" -r -c \ gsutil -m -q -o "GSUtil:use_magicfile=True" cp -a "${gcs_acl}" -r -c \
-z log,xml,xml "${ARTIFACTS}" "${GCS_LOGS_PATH}/artifacts" || continue -z log,xml,json "${ARTIFACTS}" "${GCS_LOGS_PATH}/artifacts" || continue
fi fi
break break
done done
......
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["perftype.go"],
tags = ["automanaged"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package perftype
// ResourceSeries defines the time series of the resource usage.
type ResourceSeries struct {
Timestamp []int64 `json:"ts"`
CPUUsageInMilliCores []int64 `json:"cpu"`
MemoryRSSInMegaBytes []int64 `json:"memory"`
Units map[string]string `json:"unit"`
}
// NodeTimeSeries defines the time series of the operations and the resource
// usage.
type NodeTimeSeries struct {
OperationData map[string][]int64 `json:"op_series,omitempty"`
ResourceData map[string]*ResourceSeries `json:"resource_series,omitempty"`
Labels map[string]string `json:"labels"`
Version string `json:"version"`
}
...@@ -143,6 +143,13 @@ func getTestArtifacts(host, testDir string) error { ...@@ -143,6 +143,13 @@ func getTestArtifacts(host, testDir string) error {
if err != nil { if err != nil {
return err return err
} }
// Copy json files (if any) to artifacts.
if _, err = SSH(host, "ls", fmt.Sprintf("%s/results/*.json", testDir)); err == nil {
_, err = runSSHCommand("scp", "-r", fmt.Sprintf("%s:%s/results/*.json", GetHostnameOrIp(host), testDir), *resultsDir)
if err != nil {
return err
}
}
// Copy junit to the top of artifacts // Copy junit to the top of artifacts
_, err = runSSHCommand("scp", fmt.Sprintf("%s:%s/results/junit*", GetHostnameOrIp(host), testDir), *resultsDir) _, err = runSSHCommand("scp", fmt.Sprintf("%s:%s/results/junit*", GetHostnameOrIp(host), testDir), *resultsDir)
if err != nil { if err != nil {
......
...@@ -43,6 +43,7 @@ import ( ...@@ -43,6 +43,7 @@ import (
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
"k8s.io/kubernetes/pkg/util/procfs" "k8s.io/kubernetes/pkg/util/procfs"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/e2e_node/perftype"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
...@@ -440,19 +441,11 @@ func newTestPods(numPods int, volume bool, imageName, podType string) []*v1.Pod ...@@ -440,19 +441,11 @@ func newTestPods(numPods int, volume bool, imageName, podType string) []*v1.Pod
return pods return pods
} }
// Time series of resource usage
type ResourceSeries struct {
Timestamp []int64 `json:"ts"`
CPUUsageInMilliCores []int64 `json:"cpu"`
MemoryRSSInMegaBytes []int64 `json:"memory"`
Units map[string]string `json:"unit"`
}
// GetResourceSeriesWithLabels gets the time series of resource usage of each container. // GetResourceSeriesWithLabels gets the time series of resource usage of each container.
func (r *ResourceCollector) GetResourceTimeSeries() map[string]*ResourceSeries { func (r *ResourceCollector) GetResourceTimeSeries() map[string]*perftype.ResourceSeries {
resourceSeries := make(map[string]*ResourceSeries) resourceSeries := make(map[string]*perftype.ResourceSeries)
for key, name := range systemContainers { for key, name := range systemContainers {
newSeries := &ResourceSeries{Units: map[string]string{ newSeries := &perftype.ResourceSeries{Units: map[string]string{
"cpu": "mCPU", "cpu": "mCPU",
"memory": "MB", "memory": "MB",
}} }}
......
...@@ -79,9 +79,9 @@ var _ = framework.KubeDescribe("Resource-usage [Serial] [Slow]", func() { ...@@ -79,9 +79,9 @@ var _ = framework.KubeDescribe("Resource-usage [Serial] [Slow]", func() {
for _, testArg := range rTests { for _, testArg := range rTests {
itArg := testArg itArg := testArg
desc := fmt.Sprintf("resource tracking for %d pods per node", itArg.podsNr)
It(fmt.Sprintf("resource tracking for %d pods per node", itArg.podsNr), func() { It(desc, func() {
testInfo := getTestNodeInfo(f, itArg.getTestName()) testInfo := getTestNodeInfo(f, itArg.getTestName(), desc)
runResourceUsageTest(f, rc, itArg) runResourceUsageTest(f, rc, itArg)
...@@ -109,9 +109,9 @@ var _ = framework.KubeDescribe("Resource-usage [Serial] [Slow]", func() { ...@@ -109,9 +109,9 @@ var _ = framework.KubeDescribe("Resource-usage [Serial] [Slow]", func() {
for _, testArg := range rTests { for _, testArg := range rTests {
itArg := testArg itArg := testArg
desc := fmt.Sprintf("resource tracking for %d pods per node [Benchmark]", itArg.podsNr)
It(fmt.Sprintf("resource tracking for %d pods per node [Benchmark]", itArg.podsNr), func() { It(desc, func() {
testInfo := getTestNodeInfo(f, itArg.getTestName()) testInfo := getTestNodeInfo(f, itArg.getTestName(), desc)
runResourceUsageTest(f, rc, itArg) runResourceUsageTest(f, rc, itArg)
...@@ -202,8 +202,8 @@ func logAndVerifyResource(f *framework.Framework, rc *ResourceCollector, cpuLimi ...@@ -202,8 +202,8 @@ func logAndVerifyResource(f *framework.Framework, rc *ResourceCollector, cpuLimi
cpuSummaryPerNode[nodeName] = cpuSummary cpuSummaryPerNode[nodeName] = cpuSummary
// Print resource usage // Print resource usage
framework.PrintPerfData(framework.ResourceUsageToPerfDataWithLabels(usagePerNode, testInfo)) logPerfData(framework.ResourceUsageToPerfDataWithLabels(usagePerNode, testInfo), "memory")
framework.PrintPerfData(framework.CPUUsageToPerfDataWithLabels(cpuSummaryPerNode, testInfo)) logPerfData(framework.CPUUsageToPerfDataWithLabels(cpuSummaryPerNode, testInfo), "cpu")
// Verify resource usage // Verify resource usage
if isVerify { if isVerify {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment