Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scalability and Performance Test Cases for Ephemeral Volumes #601

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clusterloader2/pkg/config/template_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ func GetFuncs() template.FuncMap {
"DefaultParam": defaultParam,
"IncludeFile": includeFile,
"YamlQuote": yamlQuote,
"Seq": seq,
}
}

func seq(size interface{}) []int {
return make([]int, int(toFloat64(size)))
}

func toFloat64(val interface{}) float64 {
switch i := val.(type) {
case float64:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Below test cases can be run with the parameters like;

- 1 pod with X volumes and 1 node
-- `.Nodes := 1`, `$TOTAL_PODS := 1`, `$VOLUMES_PER_POD := <X>`
- X pods with 1 volume each on 1 node in parallel
-- `.Nodes := 1`, `$TOTAL_PODS := <X>`, `$VOLUMES_PER_POD := 1`

To test with different volume types please use the override file for the specific volume type, default volume type is `EmptyDir`
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# ASSUMPTIONS:
# - this test cases should be run on only 1 node

#Constants
{{$TOTAL_PODS := DefaultParam .TOTAL_PODS 1}}
{{$POD_TEMPLATE_PATH := DefaultParam .POD_TEMPLATE_PATH "pod_with_EmptyDirs.yaml"}}
{{$LOAD_TEST_THROUGHPUT := DefaultParam .LOAD_TEST_THROUGHPUT 10}}

{{$VOLUMES_PER_POD := DefaultParam .VOLUMES_PER_POD 4}}
{{$VOLUME_TEMPLATE_PATH := .VOLUME_TEMPLATE_PATH}}
{{$PROVISION_VOLUME := DefaultParam .PROVISION_VOLUME false}}

{{$APP_NAME := "pod-load"}}
{{$GROUP := "pod-with-ephemeral-volume-startup-latency"}}

#Variables
# used stateless pod SLO for initial run
{{$podStartupTimeout := 5}}
{{$totalVolumes := MultiplyInt $TOTAL_PODS $VOLUMES_PER_POD}}

name: pod-with-ephemeral-volume-startup-latency
automanagedNamespaces: 1
tuningSets:
- name: UniformQPS
qpsLoad:
qps: {{$LOAD_TEST_THROUGHPUT}}
steps:
- measurements:
- Identifier: APIResponsiveness
Method: APIResponsiveness
Params:
action: reset
{{ if $PROVISION_VOLUME }}
# Provision volumes
- phases:
- namespaceRange:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krzysied - I was thinking about it in the past, but I don't know if we ever did that (and if I ever shared with you that I was thinking about it).
In majority of cases, we're setting "namespaceRange" to basically all automanaged-namespaces.
What I would like to do is to remove all of those and say:
"if you don't specify namespaceRange, we default to all automanaged namespaces"

Is that done? If not, would you be able to add that (should be quite simple to do).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if namespaceRange == nil {
// Returns "" which represents cluster level.
return []string{""}
}

If namespaceRange is unset, the cluster level object will be created. IIRC currently we are not using this feature. The question is if we want to create non-namespace objects in the future...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh ok - we definitely would like to be able to create non-namespaced objects (e.g. CRD is non-namespaced).

We should probably come up with some "allNamespaces" thing to reduce amount of boilerplate...

min: 1
max: 1
replicasPerNamespace: {{$totalVolumes}}
tuningSet: UniformQPS
objectBundle:
- basename: vol-{{$APP_NAME}}
objectTemplatePath: {{$VOLUME_TEMPLATE_PATH}}
{{ end }}
# Start measurements
- measurements:
- Identifier: PodWithMultiVolumeStartupLatency
Method: PodStartupLatency
Params:
action: start
labelSelector: group = {{$GROUP}}
threshold: {{$podStartupTimeout}}s
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium-term (or maybe even not that medium), we should merge the logic of detecting whether the pod is stateful or stateless into the measurement and use thresholds automatically.

@mm4tt @oxddr - do you know if we have an issue opened for that?

# Create pods
- phases:
- namespaceRange:
min: 1
max: 1
replicasPerNamespace: {{$TOTAL_PODS}}
tuningSet: UniformQPS
objectBundle:
- basename: {{$APP_NAME}}
objectTemplatePath: {{$POD_TEMPLATE_PATH}}
templateFillMap:
Group: {{$GROUP}}
VolumesPerPod: {{$VOLUMES_PER_POD}}
AppName: {{$APP_NAME}}
- measurements:
- Identifier: WaitForRunningPodsWithStorage
Method: WaitForRunningPods
Params:
desiredPodCount: {{$TOTAL_PODS}}
labelSelector: group = {{$GROUP}}
# TODO decide this after test roll-out phase
timeout: 15m
- measurements:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly as for starting measurement, can you also move it to the bottom?

[As I mentioned somewhere else, medium term, we will simply bake all the necessary thresholds into the measurement itself and we will bundle all SLO-related ones together to limit boilerplate. It will just be simpler to do then :)]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok., I think deleting pods before the gather action of PodStartupLatency measurement has no effect?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PodStartupLatency measurement can only change if when pods are being created - so yes, that will have no effect.

- Identifier: PodWithMultiVolumeStartupLatency
Method: PodStartupLatency
Params:
action: gather
# Delete pods
- phases:
- namespaceRange:
min: 1
max: 1
replicasPerNamespace: 0
tuningSet: UniformQPS
objectBundle:
- basename: {{$APP_NAME}}
objectTemplatePath: {{$POD_TEMPLATE_PATH}}
# Collect measurements
- measurements:
- Identifier: APIResponsiveness
Method: APIResponsiveness
Params:
action: gather
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{.Name}}
data:
TEST_KEY1: testData1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PROVISION_VOLUME: true
POD_TEMPLATE_PATH: "configmap/pod_with_ConfigMaps.yaml"
VOLUME_TEMPLATE_PATH: "configmap/ConfigMap.yaml"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you somewhere use the assumption that the file names are capitalized ConfigMap (I don't see that, but maybe I'm missing something).
If not, it would be more natural to have:
configmap/config_map.yaml
configmap/pod_with_config_map.yaml

[Same for secrets and others]

Copy link
Contributor Author

@mucahitkurt mucahitkurt Jul 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was but no longer, I'll rename them, but volume names are not used as separate words generally, usages are like ConfigMap, EmptyDir etc. I'll rename them as like configmap/configmap.yaml, configmap/pod_with_configmap.yaml etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure that sounds fine, thanks!

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{{$index := .Index}}
{{$appName := .AppName}}
{{$volumesPerPod := .VolumesPerPod}}
apiVersion: v1
kind: Pod
metadata:
name: {{.Name}}
labels:
app: {{.Name}}
group: {{.Group}}
spec:
containers:
- name: {{.Name}}
image: k8s.gcr.io/pause:3.1
imagePullPolicy: IfNotPresent
volumeMounts:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
mountPath: /usr/share/{{$volumeIndex}}
{{ end }}
volumes:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
configMap:
name: vol-{{$appName}}-{{AddInt $volumeIndex (MultiplyInt $index $volumesPerPod)}}
{{ end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
POD_TEMPLATE_PATH: "downwardapi/pod_with_DownwardAPIs.yaml"
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{$index := .Index}}
{{$appName := .AppName}}
{{$volumesPerPod := .VolumesPerPod}}
apiVersion: v1
kind: Pod
metadata:
name: {{.Name}}
labels:
app: {{.Name}}
group: {{.Group}}
spec:
containers:
- name: {{.Name}}
image: k8s.gcr.io/pause:3.1
imagePullPolicy: IfNotPresent
volumeMounts:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
mountPath: /usr/share/{{$volumeIndex}}
{{ end }}
volumes:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
downwardAPI:
items:
- path: "pod_name"
fieldRef:
fieldPath: metadata.name
- path: "pod_namespace"
fieldRef:
fieldPath: metadata.namespace
{{ end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{{$index := .Index}}
{{$appName := .AppName}}
{{$volumesPerPod := .VolumesPerPod}}
apiVersion: v1
kind: Pod
metadata:
name: {{.Name}}
labels:
app: {{.Name}}
group: {{.Group}}
spec:
containers:
- name: {{.Name}}
image: k8s.gcr.io/pause:3.1
imagePullPolicy: IfNotPresent
volumeMounts:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
mountPath: /usr/share/{{$volumeIndex}}
{{ end }}
volumes:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
emptyDir: {}
{{ end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: {{.Name}}
type: Opaque
data:
username: dXNlcm5hbWVfCg==
password: cGFzc3dvcmRfCg==
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PROVISION_VOLUME: true
POD_TEMPLATE_PATH: "secret/pod_with_Secrets.yaml"
VOLUME_TEMPLATE_PATH: "secret/Secret.yaml"
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{{$index := .Index}}
{{$appName := .AppName}}
{{$volumesPerPod := .VolumesPerPod}}
apiVersion: v1
kind: Pod
metadata:
name: {{.Name}}
labels:
app: {{.Name}}
group: {{.Group}}
spec:
containers:
- name: {{.Name}}
image: k8s.gcr.io/pause:3.1
imagePullPolicy: IfNotPresent
volumeMounts:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
mountPath: /usr/share/{{$volumeIndex}}
{{ end }}
volumes:
{{ range $volumeIndex, $vol := Seq .VolumesPerPod }}
- name: vol-{{$volumeIndex}}
secret:
secretName: vol-{{$appName}}-{{AddInt $volumeIndex (MultiplyInt $index $volumesPerPod)}}
{{ end }}