To load test something with the k6 charm, you should:
- write a load test;
- deploy the
k6-k8s
charm; - set the script and environment;
- run the test!
Let’s explore each step in more detail.
Writing a load test
Explaining how to write load tests is out of the scope for this document, but let’s take a look at a simple load test for Loki.
// Load test for pushing logs to Loki
import loki from 'k6/x/loki';
import sleep from 'k6';
// import http from 'k6/http'; // Arbitrary HTTP requests
export const options = {
vus: 1000, // Virtual Users that are pushing logs
duration: "30m", // Total duration of the test
}
export default function () {
const conf = loki.Config(`http://fake@10.1.15.133:3100`); // 'fake' is the default tenant for Loki
const client = loki.Client(conf);
const streams = 4 // How many log streams per client
const minSize = 1024 // log line minimum size: 1kb
const maxSize = 2048 // log line maximum size: 2kb
const thinkTime = randInt(1, 3) // Waiting time in-between log pushes
const res = client.pushParameterized(streams, minSize, maxSize) // Push the logs
sleep(thinkTime)
};
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
};
When executed, k6
will spin up a total of 1000 virtual users. Each of them will open 4 log streams with Loki, sending between 1kb and 2kb of data every 1–3 seconds.
Can I make the script configurable?
Yes, by using template literals, Javascript's version of f-strings:
...
const conf = loki.Config(`http://fake@${__ENV.LOKI_IP}:3100`);
...
You can then pass the environment variables you need to k6 via:
LOKI_IP="$(juju status --format=json | jq '.applications.loki.address')"
juju config k6 environment=LOKI_IP=$LOKI_IP
To learn more about k6
and how to write load test scripts, check out grafana/k6-learn or my blog post summarizing the key points I learned from it.
Deploying the charms
The k6 charm uses Prometheus and Loki to store the results of its tests, and Grafana to display them: deploy all of them and cross-relate them.
Manual commands
# Deploy the charms
∮ juju deploy k6-k8s k6
∮ juju deploy prometheus-k8s prometheus
∮ juju deploy loki-k8s loki
∮ juju deploy grafana-k8s grafana
# Add the relations
∮ juju relate k6 prometheus # send metrics
∮ juju relate k6 loki # send logs
∮ juju relate k6 grafana # send dashboards
∮ juju relate prometheus:grafana-source grafana
∮ juju relate loki:grafana-source grafana
Juju bundle (ready to go!)
bundle: kubernetes
applications:
grafana:
charm: grafana-k8s
channel: latest/edge
revision: 143
base: ubuntu@20.04/stable
resources:
grafana-image: 71
litestream-image: 46
scale: 1
constraints: arch=amd64
storage:
database: kubernetes,1,1024M
trust: true
k6:
charm: local:k6-k8s-11
base: ubuntu@24.04/stable
scale: 1
constraints: arch=amd64
loki:
charm: loki-k8s
channel: latest/edge
revision: 191
base: ubuntu@20.04/stable
resources:
loki-image: 100
node-exporter-image: 3
scale: 1
constraints: arch=amd64
storage:
active-index-directory: kubernetes,1,1024M
loki-chunks: kubernetes,1,1024M
trust: true
prometheus:
charm: prometheus-k8s
channel: latest/edge
revision: 237
base: ubuntu@20.04/stable
resources:
prometheus-image: 151
scale: 1
constraints: arch=amd64
storage:
database: kubernetes,1,1024M
trust: true
relations:
- - k6:send-remote-write
- prometheus:receive-remote-write
- - loki:grafana-source
- grafana:grafana-source
- - prometheus:grafana-source
- grafana:grafana-source
- - k6:logging
- loki:logging
Easy as that!
Configuring the script and environment
Now you need to configure the k6 charm with the load test you want to run, and the environment variables you want to pass to it. There are two ways of doing so:
- adding a charmed load test;
- side-loading a test via
juju config
.
Adding a charmed load test
The k6 charm offers a k6_test
library, which can be used by charms to send load tests (and their environment) over relation data.
After saving your k6 script in tests/load
(by default), simply add the following to your charm.py
file:
from charms.k6_k8s.v0.k6_tests import K6TestsProvider
def __init__(self, *args):
...
env = {"LOKI_IP": self.external_url}
self.k6_tests = K6TestsProvider(self, environment=env)
self.k6_tests.reconcile() # read the tests into relation data
...
Don’t forget to add the relation in charmcraft.yaml
:
provides:
send-k6-tests: # default name
interface: k6_tests
You can now relate your charm to k6
and the tests will be sent over!
Side-loading a test
You can easily do that via juju config
:
∮ juju config k6 load-test=@loki-test.js
∮ juju config k6 environment=LOKI_IP=10.1.15.133
Now we’re ready to run the tests!
Running the test
You can interact with the k6 charm (and the load test) via Juju actions:
∮ juju run k6/leader start # runs the side-loaded test
∮ juju run k6/leader start app=loki test=test.js # runs a test from a charm
The test progress can be observed in the juju status
, and the metrics and logs can be inspected live in Prometheus and Loki, or directly via the Grafana dashboard.
(insert beautiful Grafana dashboard image once we have it)
Congratulations, you’ve load tested Loki!