Skip to content

Commit bae3fce

Browse files
authored
Merge pull request #2271 from datamattsson/cms/datamattsson/hpe-dev-portal/blog/working-with-benk-a-storage-provisioning-and-io-performance-benchmark-suite-for-kubernetes
Create Blog “working-with-benk-a-storage-provisioning-and-io-performance-benchmark-suite-for-kubernetes”
2 parents d564ba3 + 8b6037e commit bae3fce

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
---
2+
title: "Working with Benk: A storage provisioning and IO performance benchmark
3+
suite for Kubernetes"
4+
date: 2024-01-12T20:03:16.376Z
5+
author: Michael Mattsson
6+
authorimage: /img/portrait-192.jpg
7+
thumbnailimage: /img/benk-some.png
8+
disable: false
9+
tags:
10+
- kubernetes
11+
- devops
12+
- hpe-alletra
13+
- hpe-nimble-storage
14+
- hpe-3par-and-primera
15+
---
16+
Recently Hewlett Packard Enterprise (HPE) published an open source benchmark suite for storage drivers capable of dynamically provisioning persistent volumes to Kubernetes. The suite is called [Benk](https://github.com/hpe-storage/benk) and it is an acronym that plays with the word bench as in benchmark and Kubernetes. Benk is used internally at HPE for mapping performance metrics around the provisioning process itself as well as for IO performance. It’s still a bit rough around the edges and not feature complete, but it’s still a very useful tool to capture performance across large swaths of configurations with a high degree of automation and repeatability without too much user attendance.
17+
18+
A few of the features include:
19+
20+
* Highly customizable rendering of Kubernetes resources through kustomize templates
21+
* A simple Kubernetes batch job that manage all the provisioning, decommissioning and benchmarking
22+
* A single configuration file per job that abstracts Kubernetes constructs and IO parameters
23+
* Use of industry standard Flexible I/O tester (FIO) for filesystem benchmarking
24+
* Easy-to-build-your-own output templates using Jinja2 with the rich metrics in JSON format
25+
26+
Let’s walk through a practical example of configuring, running and reporting a benchmark with Benk.
27+
28+
# Prerequisites
29+
30+
At the time of writing, parts of Benk can only be run on Mac and Linux due to a dependency on Bash. It will of course run in WSL on Windows. Besides cloning the [GitHub repository](https://github.com/hpe-storage/benk) with `git`, a recent version of `kubectl` and Python 3.x needs to be installed.
31+
32+
Some pro-efficiency working with scripts, JSON and Kubernetes is helpful to better understand the workflows.
33+
34+
# Hello Benk!
35+
36+
The synopsis section of Benk on GitHub highlights the main steps to run the default job. It’s a good measure stick to understand if the lights come on and determine if the system under test is ready for a more complex job.
37+
38+
Let’s walk through each step and explain as we go along. Descriptions are below the commands unless noted.
39+
40+
```text
41+
git clone https://github.com/hpe-storage/benk && cd benk
42+
```
43+
44+
Cloning and entering the benk directory is now considered your home. Your logs will go into `logs`, your workload configurations are in `kustomize/overlays` and the Jinja2 templates are in `jinja2`.
45+
46+
```text
47+
pip3 install -r requirements.txt
48+
```
49+
50+
This will install the required Python packages for the Benk `outputter.py` script. Python is not required if you don’t intend to render any output and you just want to use Benk for load generation.
51+
52+
```text
53+
cp kustomize/base/config-dist.env kustomize/base/config.env
54+
cp kustomize/base/storageclass-dist.yaml kustomize/base/storageclass.yaml
55+
```
56+
57+
The two “dist” files are the base of your configuration. A `config.env` file that contains information that will be inserted into the `StorageClass` `Secret` reference. While the base configuration is heavily biased towards the HPE CSI Driver for Kubernetes, any storage driver that uses a `StorageClass` for dynamic provisioning for filesystems `Persistent Volume Claims` (PVC) can be used. Using the `storageclass.yaml` to configure your driver and pertinent details is at your discretion.
58+
59+
```text
60+
kubectl create ns benk
61+
```
62+
63+
All `Namespace` resources will be provisioned into the “benk” `Namespace`.
64+
65+
```text
66+
kubectl apply -k kustomize/overlays/default
67+
kubectl wait -n benk --for=condition=complete job/benk
68+
```
69+
70+
This will create the default job and wait for it to complete. It runs a 80/20 read/write random 8K workload for 30 seconds on a single replica `Deployment` using a single `PVC`.
71+
72+
```text
73+
kubectl logs -n benk job/benk | jq
74+
```
75+
76+
This will render the log in pretty JSON. The log is pretty substantial and intentionally left out from the blog. An example log entry from the above job is available [on GitHub](https://github.com/hpe-storage/benk/tree/main/jinja2).
77+
78+
There’s also tiny output template provided in the repository `jinja2/example-default.yaml.j2` that pulls some data out of the log file.
79+
80+
```text
81+
kubectl logs -n benk job/benk | ./src/benk/outputter.py -t jinja2/example-default.yaml.j2 -l-
82+
---
83+
report:
84+
name: Example YAML template
85+
logfile: <stdin>
86+
jobs:
87+
- threads: 1
88+
runtime: 49s
89+
iops: 1258
90+
bandwidth: 10MB/s
91+
bs: 8k
92+
```
93+
94+
Now we’ve completed the three corners of running Benk. Configured the environment and a job, ran the job successfully and distilled the results into something human readable for our demonstration.
95+
96+
# The sequencer
97+
98+
The core of Benk for now, is to run preconfigured jobs with kustomize. It may seem a lot of work for very little output. That’s why the repository contain two important scripts, `sequencer.sh` and `sequencer-cluster.sh`. These scripts will help you run multiple jobs and structure the output to create more meaty reports.
99+
100+
First, copy the “default” kustomize directory into eight separate directories.
101+
102+
```text
103+
for i in {1..8}; do cp -a kustomize/overlays/default kustomize/overlays/mytest-${i}; done
104+
```
105+
106+
Now, edit each `config.env` in each directory. I use `vi` to “:wn” myself through the templates.
107+
108+
```text
109+
vi kustomize/overlays/mytest-*/config.env
110+
```
111+
112+
In each iteration, we’ll double `workloadThreads` so we end up with a sequence like 1, 2, 4, 8, 16, 32, 64 and 128. Would it not be useful if we could run these in sequence and report the results in the same template we used previously to understand if the system scales to when adding more threads to the workload? (The entire demo environment runs in virtual machines on decade old hardware, please don’t judge.)
113+
114+
Run the sequence:
115+
116+
```text
117+
./sequencer.sh mytest-
118+
```
119+
120+
What happens here is that the sequencer script will use globbing to find all overlays that has the prefix “mytest-”. Be mindful how you name things to avoid unexpected jobs to be executed.
121+
122+
Next we can use the same report for all the jobs.
123+
124+
```text
125+
./src/benk/outputter.py -l logs/run-mytest-<unique timestamp>.log -t jinja2/example-default.yaml.j2
126+
---
127+
report:
128+
name: Example YAML template
129+
logfile: logs/run-mytest-20240111161937.log
130+
jobs:
131+
- threads: 1
132+
runtime: 55s
133+
iops: 1664
134+
bandwidth: 13MB/s
135+
bs: 8k
136+
- threads: 2
137+
runtime: 49s
138+
iops: 3291
139+
bandwidth: 26MB/s
140+
bs: 8k
141+
- threads: 4
142+
runtime: 48s
143+
iops: 8044
144+
bandwidth: 63MB/s
145+
bs: 8k
146+
- threads: 8
147+
runtime: 53s
148+
iops: 12075
149+
bandwidth: 94MB/s
150+
bs: 8k
151+
- threads: 16
152+
runtime: 46s
153+
iops: 16357
154+
bandwidth: 128MB/s
155+
bs: 8k
156+
- threads: 32
157+
runtime: 51s
158+
iops: 17284
159+
bandwidth: 135MB/s
160+
bs: 8k
161+
- threads: 64
162+
runtime: 48s
163+
iops: 17489
164+
bandwidth: 137MB/s
165+
bs: 8k
166+
- threads: 128
167+
runtime: 54s
168+
iops: 18761
169+
bandwidth: 147MB/s
170+
bs: 8k
171+
```
172+
173+
We can now observe that we’re seeing diminishing returns by adding more than 16 threads to this workload.
174+
175+
# A/B comparison
176+
177+
A/B testing is something that has gained popularity in human interaction testing for websites. This is also a crucial testing methodology to analyze systems performance by simply changing a single parameter and rerun the exact same test to compare the outcomes. We’re in luck as Benk allows reporting on two log files at once with just a slightly different data structures being fed to the Jinja2 templates.
178+
179+
Let’s change block size for our previous workload example. We’re going to summarize if increasing the block size will increase the bandwidth for the workload.
180+
181+
Change the “workloadBlockSize” to “64k” with the `vi` ceremony.
182+
183+
```text
184+
vi kustomize/overlays/mytest-*/config.env
185+
```
186+
187+
Re-run the sequencer.
188+
189+
```text
190+
./sequencer.sh mytest-
191+
```
192+
193+
We’ll have to use a different template as Jinja2 now has to deal with managing two log files at a time. The syntax for the `outputter.py` script is also slightly different.
194+
195+
```text
196+
./src/benk/outputter.py -a logs/run-mytest-<unique timestamp>.log -b logs/run-mytest-<unique timestamp>.log -t jinja2/example-default-ab.md.j2
197+
```
198+
199+
This report template will summarize the findings in a markdown table, suitable to include in a GitHub pull request or similar to illustrate a certain discovery.
200+
201+
```text
202+
| Threads | A (MB/s) | B (MB/s) | Diff |
203+
| ------- | -------- | -------- | ---- |
204+
| 1 | 13 | 55 | 4.2x |
205+
| 2 | 26 | 106 | 4.1x |
206+
| 4 | 63 | 181 | 2.9x |
207+
| 8 | 94 | 450 | 4.8x |
208+
| 16 | 128 | 661 | 5.2x |
209+
| 32 | 135 | 748 | 5.5x |
210+
| 64 | 137 | 840 | 6.1x |
211+
| 128 | 147 | 833 | 5.7x |
212+
```
213+
214+
Clearly, the performance increases nearly 5x across the board. We also have a discrepancy in the dataset. Which one?
215+
216+
A good exercise would be to factor in latency into the report in order to understand the impact, which there will be, as performance plateaus when you add more workloads – usually as a result of higher latency. But, how high?
217+
218+
# More sequencers and examples!
219+
220+
There’s also a `sequencer-cluster.sh` script that allows users to orchestrate load generation across multiple clusters attached to one or many storage systems to isolate problems with high concurrency. The possibilities are quite endless.
221+
222+
You can learn more about multi-cluster scaling in [the GitHub repository](https://github.com/hpe-storage/benk#multi-cluster-testing).
223+
224+
You'll also find more practical examples in [the GitHub repository](https://github.com/hpe-storage/benk/tree/main/examples) stemming from real world performance testing conducted by the HPE Hybrid Cloud solutions team.
225+
226+
# Summary
227+
228+
Hopefully, this blog post gets you started on ideas you’d like to build and use cases you want to explore. The possibilities are endless. Bear in mind that Benk is, by all means, provided as-is. In addition, to be fully transparent, this is a very early implementation that HPE chose to open source in order to better collaborate with customers and partners to isolate performance bottlenecks. For example, not all advertised features in `config.env` have been implemented yet and the CLI is not yet completed.
229+
230+
HPE invites collaboration and accepts pull requests to Benk on GitHub. The [first issue](https://github.com/hpe-storage/benk/issues/2) discusses a solution on how to collapse initial configuration and reporting into a single intuitive Python CLI.
231+
232+
Let us know what you’re building or have questions. The team behind the tool is available on HPE Developer Community Slack in the [#Kubernetes](https://hpedev.slack.com/archives/C81QZ4X62) channel. Sign up [here](https://developer.hpe.com/slack-signup) and sign in at [hpedev.slack.com](https://hpedev.slack.com).

static/img/benk-some.png

345 KB
Loading

0 commit comments

Comments
 (0)