In my previous article, I explained how to scale up or down the number of pod replicas based on workload metrics and their importance. However, how can we perform workload testing in a Kubernetes-based deployment to get the optimal amount of resources? In the past, we worked with tools like jMeter to do this in classic server-based deployments, but how can we measure this in modern environments like Kubernetes?

This article documents a practical implementation of load testing using Grafana k6 in a Kubernetes environment, including step-by-step installation on Red Hat Enterprise Linux (RHEL) and sample tests with expected outputs.

Why Load Testing is Important

Load testing enables teams to:

  • Confirm that the application meets defined performance benchmarks.
  • Detect performance bottlenecks in infrastructure or application code.
  • Validate Kubernetes autoscaling behavior under different load patterns.
  • Prevent performance regressions during new releases.

Without load testing, systems risk experiencing unexpected failures during high-traffic periods, leading to degraded user experience and potential downtime.

What is Grafana k6?

Grafana k6 is an open-source, developer-centric load testing tool with scripting support in JavaScript. It offers:

  • Support for multiple protocols: HTTP, WebSocket, gRPC.
  • Ability to run locally or in distributed mode via Kubernetes.
  • Grafana integration for real-time visualization.

Installing k6 on RHEL

On RHEL 8+, install k6 from the official package repository:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo yum install -y dnf
sudo dnf install -y gnupg2 curl

# Add k6 repo
sudo rpm --import https://dl.k6.io/key.gpg
cat <<EOF | sudo tee /etc/yum.repos.d/k6.repo
[k6]
name=k6
baseurl=https://dl.k6.io/rpm/x86_64
enabled=1
gpgcheck=1
gpgkey=https://dl.k6.io/key.gpg
EOF

# Install k6
sudo dnf install -y k6

Verify installation:

1
2
3
k6 version
# Example output:
# k6 v0.51.0 (2025-07-22T12:34:56+0000/v0.51.0-0-gabcdef)

Running k6 Locally

Example test.js script:

1
2
3
4
5
6
7
8
9
10
11
12
13
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 5,
  duration: '10s',
};

export default function () {
  let res = http.get('https://httpbin.org/status/200');
  check(res, { 'status was 200': (r) => r.status === 200 });
  sleep(1);
}

Run:

1
k6 run test.js

Expected console output:

1
2
3
4
5
6
7
     data_received........: 5.6 kB  560 B/s
     data_sent............: 1.3 kB  130 B/s
     http_req_blocked.....: avg=142µs  min=2µs     med=3µs    max=12.5ms  p(90)=5µs    p(95)=8µs   
     http_req_connecting..: avg=48µs   min=0s      med=0s     max=6.1ms   p(90)=0s     p(95)=0s    
     http_req_duration....: avg=215ms  min=142ms   med=210ms  max=380ms   p(90)=290ms  p(95)=320ms 
     http_req_failed......: 0.00%   ✓ 0        ✗ 50
     vus..................: 1       min=1        max=5

Deploying k6 in Kubernetes

Install the k6 operator for distributed testing:

1
kubectl apply -f https://github.com/grafana/k6-operator/releases/latest/download/k6-operator.yaml

Check deployment:

1
kubectl get pods -n k6-operator-system

Example Kubernetes Test

Create the test script test.js

1
2
3
4
5
6
7
8
9
10
11
12
import http from 'k6/http';
import { sleep } from 'k6';

export const options = {
  vus: 20,
  duration: '1m',
};

export default function () {
  http.get('https://httpbin.org/get');
  sleep(0.5);
}

Create a ConfigMap

1
kubectl create configmap sample-test --from-file=test.js

Create k6-test.yaml

1
2
3
4
5
6
7
8
9
10
apiVersion: k6.io/v1alpha1
kind: K6
metadata:
  name: sample-test
spec:
  parallelism: 2
  script:
    configMap:
      name: sample-test
      file: test.js

Deploy

1
kubectl apply -f k6-test.yaml

Expected Kubernetes Output

Check job status

1
2
3
kubectl get k6
# NAME           AGE   PARALLELISM   STATUS
# sample-test    2m    2             finished

Retrieve logs

1
2
3
4
5
kubectl logs job/sample-test-0
# Example:
# running (00m30.0s), 20/20 VUs, 500 complete and 0 interrupted iterations
# http_reqs................: 500    16.666667/s
# http_req_failed..........: 0.00%  ✓ 0      ✗ 500

Benefits

  • Repeatable tests across local and Kubernetes environments.
  • Distributed load generation for scaling to thousands of VUs.
  • Immediate visibility in Grafana dashboards.
  • Verified Kubernetes autoscaling and ensured stable performance under load.

Conclusion

Grafana k6 is a reliable choice for load testing Kubernetes workloads. By running tests both locally and in-cluster, teams can detect performance issues early and ensure production readiness.