test images: Adds Windows support for resource-consumer

stress was being used for the memory consumption part. This adds a golang equivalent,
which will also work on Windows.
This commit is contained in:
Claudiu Belu 2019-04-18 14:38:12 +00:00
parent 0072d8ae23
commit 28e1dee333
10 changed files with 311 additions and 37 deletions

View File

@ -3,3 +3,8 @@ linux/arm=k8s.gcr.io/debian-base-arm:0.4.1
linux/arm64=k8s.gcr.io/debian-base-arm64:0.4.1
linux/ppc64le=k8s.gcr.io/debian-base-ppc64le:0.4.1
linux/s390x=k8s.gcr.io/debian-base-s390x:0.4.1
windows/amd64/1809=mcr.microsoft.com/windows/nanoserver:1809
windows/amd64/1903=mcr.microsoft.com/windows/nanoserver:1903
windows/amd64/1909=mcr.microsoft.com/windows/nanoserver:1909
windows/amd64/2004=mcr.microsoft.com/windows/nanoserver:2004
windows/amd64/20H2=mcr.microsoft.com/windows/nanoserver:20H2

View File

@ -17,6 +17,8 @@ go_library(
"resource_consumer.go",
"resource_consumer_handler.go",
"utils.go",
"utils_common.go",
"utils_windows.go",
],
importpath = "k8s.io/kubernetes/test/images/resource-consumer",
deps = ["//test/images/resource-consumer/common:go_default_library"],

View File

@ -0,0 +1,33 @@
# Copyright 2021 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.
ARG BASEIMAGE
# We're using a Linux image to unpack the archives, then we're copying them over to Windows.
FROM --platform=linux/amd64 alpine:3.6 as prep
ADD https://download.sysinternals.com/files/Testlimit.zip /Testlimit.zip
RUN unzip /Testlimit.zip -d /
FROM $BASEIMAGE
COPY --from=prep /Testlimit64.exe /bin/testlimit.exe
COPY --from=prep /Eula.txt /bin/
ADD consumer /consumer.exe
ADD consume-cpu/consume-cpu /consume-cpu/consume-cpu.exe
ENV PATH="C:\bin\;C:\curl\;C:\Windows\system32;C:\Windows;C:\Program Files\PowerShell;"
EXPOSE 8080
ENTRYPOINT ["/consumer.exe"]

View File

@ -13,9 +13,60 @@ go_binary(
go_library(
name = "go_default_library",
srcs = ["consume_cpu.go"],
srcs = [
"common.go",
"consume_cpu.go",
"consume_cpu_windows.go",
],
importpath = "k8s.io/kubernetes/test/images/resource-consumer/consume-cpu",
deps = ["//vendor/bitbucket.org/bertimus9/systemstat:go_default_library"],
deps = select({
"@io_bazel_rules_go//go/platform:aix": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:android": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:illumos": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:ios": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:js": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//vendor/bitbucket.org/bertimus9/systemstat:go_default_library",
],
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/golang.org/x/sys/windows:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(

View File

@ -0,0 +1,37 @@
/*
Copyright 2021 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 main
import (
"flag"
"math"
"time"
)
const sleep = time.Duration(10) * time.Millisecond
func doSomething() {
for i := 1; i < 10000000; i++ {
x := float64(0)
x += math.Sqrt(0)
}
}
var (
millicores = flag.Int("millicores", 0, "millicores number")
durationSec = flag.Int("duration-sec", 0, "duration time in seconds")
)

View File

@ -1,3 +1,5 @@
// +build !windows
/*
Copyright 2015 The Kubernetes Authors.
@ -18,26 +20,11 @@ package main
import (
"flag"
"math"
"time"
"bitbucket.org/bertimus9/systemstat"
)
const sleep = time.Duration(10) * time.Millisecond
func doSomething() {
for i := 1; i < 10000000; i++ {
x := float64(0)
x += math.Sqrt(0)
}
}
var (
millicores = flag.Int("millicores", 0, "millicores number")
durationSec = flag.Int("duration-sec", 0, "duration time in seconds")
)
func main() {
flag.Parse()
// convert millicores to percentage

View File

@ -0,0 +1,77 @@
// +build windows
/*
Copyright 2021 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 main
import (
"flag"
"syscall"
"time"
syswin "golang.org/x/sys/windows"
)
type procCPUStats struct {
User int64 // nanoseconds spent in user mode
System int64 // nanoseconds spent in system mode
Time time.Time // when the sample was taken
Total int64 // total of all time fields (nanoseconds)
}
// Retrieves the amount of CPU time this process has used since it started.
func statsNow(handle syscall.Handle) (s procCPUStats) {
var processInfo syscall.Rusage
syscall.GetProcessTimes(handle, &processInfo.CreationTime, &processInfo.ExitTime, &processInfo.KernelTime, &processInfo.UserTime)
s.Time = time.Now()
s.User = processInfo.UserTime.Nanoseconds()
s.System = processInfo.KernelTime.Nanoseconds()
s.Total = s.User + s.System
return s
}
// Given stats from two time points, calculates the millicores used by this
// process between the two samples.
func usageNow(first procCPUStats, second procCPUStats) int64 {
dT := second.Time.Sub(first.Time).Nanoseconds()
dUsage := (second.Total - first.Total)
if dT == 0 {
return 0
}
return 1000 * dUsage / dT
}
func main() {
flag.Parse()
phandle, err := syswin.GetCurrentProcess()
if err != nil {
panic(err)
}
handle := syscall.Handle(phandle)
duration := time.Duration(*durationSec) * time.Second
start := time.Now()
first := statsNow(handle)
for time.Since(start) < duration {
currentMillicores := usageNow(first, statsNow(handle))
if currentMillicores < int64(*millicores) {
doSomething()
} else {
time.Sleep(sleep)
}
}
}

View File

@ -1,5 +1,7 @@
// +build !windows
/*
Copyright 2015 The Kubernetes Authors.
Copyright 2021 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.
@ -17,27 +19,16 @@ limitations under the License.
package main
import (
"fmt"
"log"
"os/exec"
"strconv"
)
const (
var (
consumeCPUBinary = "./consume-cpu/consume-cpu"
consumeMemBinary = "stress"
)
// ConsumeCPU consumes a given number of millicores for the specified duration.
func ConsumeCPU(millicores int, durationSec int) {
log.Printf("ConsumeCPU millicores: %v, durationSec: %v", millicores, durationSec)
// creating new consume cpu process
arg1 := fmt.Sprintf("-millicores=%d", millicores)
arg2 := fmt.Sprintf("-duration-sec=%d", durationSec)
consumeCPU := exec.Command(consumeCPUBinary, arg1, arg2)
consumeCPU.Run()
}
// ConsumeMem consumes a given number of megabytes for the specified duration.
func ConsumeMem(megabytes int, durationSec int) {
log.Printf("ConsumeMem megabytes: %v, durationSec: %v", megabytes, durationSec)
@ -45,11 +36,8 @@ func ConsumeMem(megabytes int, durationSec int) {
durationSecString := strconv.Itoa(durationSec)
// creating new consume memory process
consumeMem := exec.Command(consumeMemBinary, "-m", "1", "--vm-bytes", megabytesString, "--vm-hang", "0", "-t", durationSecString)
consumeMem.Run()
}
// GetCurrentStatus prints out a no-op.
func GetCurrentStatus() {
log.Printf("GetCurrentStatus")
// not implemented
err := consumeMem.Run()
if err != nil {
log.Printf("Error while consuming memory: %v", err)
}
}

View File

@ -0,0 +1,42 @@
/*
Copyright 2015 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 main
import (
"fmt"
"log"
"os/exec"
)
// ConsumeCPU consumes a given number of millicores for the specified duration.
func ConsumeCPU(millicores int, durationSec int) {
log.Printf("ConsumeCPU millicores: %v, durationSec: %v", millicores, durationSec)
// creating new consume cpu process
arg1 := fmt.Sprintf("-millicores=%d", millicores)
arg2 := fmt.Sprintf("-duration-sec=%d", durationSec)
consumeCPU := exec.Command(consumeCPUBinary, arg1, arg2)
err := consumeCPU.Run()
if err != nil {
log.Printf("Error while consuming CPU: %v", err)
}
}
// GetCurrentStatus prints out a no-op.
func GetCurrentStatus() {
log.Printf("GetCurrentStatus")
// not implemented
}

View File

@ -0,0 +1,52 @@
// +build windows
/*
Copyright 2021 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 main
import (
"log"
"os/exec"
"strconv"
"time"
)
var (
consumeCPUBinary = "./consume-cpu/consume-cpu.exe"
consumeMemBinary = "testlimit.exe"
)
// ConsumeMem consumes a given number of megabytes for the specified duration.
func ConsumeMem(megabytes int, durationSec int) {
log.Printf("ConsumeMem megabytes: %v, durationSec: %v", megabytes, durationSec)
megabytesString := strconv.Itoa(megabytes)
durationSecString := strconv.Itoa(durationSec)
// creating new consume memory process
consumeMem := exec.Command(consumeMemBinary, "-accepteula", "-r", megabytesString, "-e", "0", durationSecString, "-c", "1")
err := consumeMem.Start()
if err != nil {
log.Printf("Error while consuming memory: %v", err)
return
}
// testlimit does not end after durationSec elapsed, so we'll stop it ourselves.
time.AfterFunc(time.Duration(durationSec)*time.Second, func() {
if err := consumeMem.Process.Kill(); err != nil {
log.Printf("Could not kill testlimit process! Error: %v", err)
}
})
}