Grafana K6

Grafana K6

K6 is an open-source load-testing tool that allows developers and DevOps engineers to measure the performance and scalability of web applications and APIs.

It is written in Go and allows for both scripting and execution of load tests, making it easy for developers to create and run tests without the need for specialized knowledge.

Installing K6

By default, your package repository on Ubuntu won’t know where to download k6 from, so you first need to set that up.

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61
echo "deb https://dl.bintray.com/loadimpact/deb stable main" | sudo tee -a /etc/apt/sources.list

With that in place, you can install k6 with apt-get (after doing an update first).

sudo apt-get update
sudo apt-get install k6
  • One of the key features of k6 is its ability to generate realistic and customizable loads. This is achieved through the use of virtual users, or VUs, which simulate the behavior of actual users visiting your website or web application.

  • These VUs can be configured to perform different actions, such as visiting pages, submitting forms, and making API calls, allowing you to test different parts of your application.

  • K6 also includes a built-in test runner that allows you to configure and execute load tests from the command line.

  • You can set various parameters, such as the number of VUs, the duration of the test, and the rate of requests, making it easy to test your application under different loads.

  • Another advantage of k6 is that it supports multiple protocols, including HTTP, WebSockets, and gRPC, making it a versatile tool that can be used to test a wide variety of applications.

  • Additionally, k6 provides a rich set of metrics and analytics, including response times, throughput, and error rates, which can be used to identify bottlenecks and optimize performance.

    Let’s make a very basic k6 Javascript test. Create a file called script.js with the following content.

import http from 'k6/http';
import { sleep } from 'k6';
export default function() {
  http.get('http://127.0.0.1/');
  sleep(1);
}

Replace the IP address on line 5 with the domain or URL that you want to test.

Execute the script with the k6 command.

k6 run script.js

This will make one request to the URL.

The output of this will be like this:

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  (‾)  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: scriptttt.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


running (00m01.1s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [========================] 1 VUs  00m01.1s/10m0s  1/1 iters, 1 per VU

     data_received..................: 52 kB 49 kB/s
     data_sent......................: 78 B  73 B/s
     http_req_blocked...............: avg=387.52µs min=387.52µs med=387.52µs max=387.52µs p(90)=387.52µs p(95)=387.52µs
     http_req_connecting............: avg=315.43µs min=315.43µs med=315.43µs max=315.43µs p(90)=315.43µs p(95)=315.43µs
     http_req_duration..............: avg=70.17ms  min=70.17ms  med=70.17ms  max=70.17ms  p(90)=70.17ms  p(95)=70.17ms 
       { expected_response:true }...: avg=70.17ms  min=70.17ms  med=70.17ms  max=70.17ms  p(90)=70.17ms  p(95)=70.17ms 
     http_req_failed................: 0.00% ✓ 0        ✗ 1  
     http_req_receiving.............: avg=8.43ms   min=8.43ms   med=8.43ms   max=8.43ms   p(90)=8.43ms   p(95)=8.43ms  
     http_req_sending...............: avg=62.08µs  min=62.08µs  med=62.08µs  max=62.08µs  p(90)=62.08µs  p(95)=62.08µs 
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=61.67ms  min=61.67ms  med=61.67ms  max=61.67ms  p(90)=61.67ms  p(95)=61.67ms 
     http_reqs......................: 1     0.932894/s
     iteration_duration.............: avg=1.07s    min=1.07s    med=1.07s    max=1.07s    p(90)=1.07s    p(95)=1.07s   
     iterations.....................: 1     0.932894/s
     vus............................: 1     min=1      max=1
     vus_max........................: 1     min=1      max=1

In order to consistently make 10 concurrent requests over the course of 30 seconds, you can pass in the –vus (virtual users) and –duration arguments as follows.

k6 run --vus 10 --duration 30s script.js

In order to simulate a gradual increase in traffic, we can define options in our Javascript file with multiple stages.

import http from 'k6/http';
import { check, sleep } from 'k6';
export let options = {
  stages: [
    { duration: '15s', target: 100 },
    { duration: '30s', target: 100 },
    { duration: '15s', target: 0 },
  ],
};
export default function() {
  let res = http.get('http://192.168.1.14/');
  check(res, { 'status was 200': r => r.status == 200 });
  sleep(1);
}

Run the script using this command:

k6 run script.js

The output will be:

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  (‾)  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: script.js
     output: -

  scenarios: (100.00%) 1 scenario, 100 max VUs, 1m30s max duration (incl. graceful stop):
           * default: Up to 100 looping VUs for 1m0s over 3 stages (gracefulRampDown: 30s, gracefulStop: 30s)

running (1m00.2s), 000/100 VUs, 941 complete and 0 interrupted iterations
default ✓ [======================================] 000/100 VUs  1m0s

     ✓ status was 200

     checks.........................: 100.00% ✓ 941       ✗ 0    
     data_received..................: 49 MB   814 kB/s
     data_sent......................: 74 kB   1.2 kB/s
     http_req_blocked...............: avg=48.32µs  min=3.01µs  med=5.02µs  max=1.84ms   p(90)=301.52µs p(95)=335.73µs
     http_req_connecting............: avg=34.81µs  min=0s      med=0s      max=1.74ms   p(90)=235.96µs p(95)=266.14µs
     http_req_duration..............: avg=4.02s    min=59.2ms  med=4.87s   max=5.37s    p(90)=5.19s    p(95)=5.22s   
       { expected_response:true }...: avg=4.02s    min=59.2ms  med=4.87s   max=5.37s    p(90)=5.19s    p(95)=5.22s   
     http_req_failed................: 0.00%   ✓ 0         ✗ 941  
     http_req_receiving.............: avg=50.64ms  min=2.91ms  med=52.25ms max=158.88ms p(90)=77.93ms  p(95)=85.66ms 
     http_req_sending...............: avg=154.12µs min=11.22µs med=19.98µs max=122.15ms p(90)=43.88µs  p(95)=54.66µs 
     http_req_tls_handshaking.......: avg=0s       min=0s      med=0s      max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=3.97s    min=53.21ms med=4.82s   max=5.31s    p(90)=5.13s    p(95)=5.17s   
     http_reqs......................: 941     15.618949/s
     iteration_duration.............: avg=5.02s    min=1.06s   med=5.87s   max=6.37s    p(90)=6.19s    p(95)=6.22s   
     iterations.....................: 941     15.618949/s
     vus............................: 8       min=7       max=100
     vus_max........................: 100     min=100     max=100

In summary, k6 is a powerful and versatile load-testing tool that allows developers and DevOps engineers to measure the performance and scalability of web applications and APIs. Its customizable virtual user generation, support for multiple protocols, and rich set of metrics make it a useful tool for optimizing the performance of your application.

Did you find this article valuable?

Support Nikhil Chauhan by becoming a sponsor. Any amount is appreciated!