Run a load test with k6
These instructions are based on this blog post.
Determine the name of the Kubernetes context to use:
kubectl config get-contexts
The output will list the environments and their names (e.g.
integration
,staging
orproduction
, or however they are named in your~/.kube/config
file).Log into AWS and set the context to the environment you wish to test (this is the context name from the previous step):
ENVIRONMENT=staging ROLE=admin eval $(gds aws govuk-${ENVIRONMENT}-${ROLE} -e --art 8h) kubectl config use-context $ENVIRONMENT
You will need to assume the
admin
role in order to deploy k6 to the cluster.Clone the
k6-operator
repo and make this:git clone git@github.com:grafana/k6-operator.git && cd k6-operator make deploy
If you get an error similar to
invalid go version '1.22.0': must match format 1.23
then you need to upgradego
to the correct version. This can be done by using Homebrew, e.g.brew install go@1.23
Write your test script, for example to test 3000 virtual users against the Collections app’s
/world
page over 30 seconds (bypassing router):import http from 'k6/http'; import { check } from 'k6'; export const options = { vus: 3000, duration: '30s', } export default function() { const res = http.get('http://collections.apps.svc.cluster.local/world'); check(res, { 'is status 200': (r) => r.status === 200, 'is status 2xx, not 200': (r) => r.status >= 201 && r.status <= 299, 'is status 3xx': (r) => r.status >= 300 && r.status <= 399, 'is status 4xx': (r) => r.status >= 400 && r.status <= 499, 'is status 5xx': (r) => r.status >= 500 && r.status <= 599, }); }
Run your code locally to make sure it works:
k6 run test.js
You may see errors related to connections as you may not be able to establish the correct number of connections from your machine.
Deploy the test script:
kubectl create configmap my-test-name --from-file /path/to/our/test.js
Replace
my-test-name
with a name for this load test. The name will be used later on, e.g. in the name of the pods that run the test.Create a YAML file to contain your custom resource:
apiVersion: k6.io/v1alpha1 kind: K6 metadata: name: k6-load-test spec: parallelism: 4 script: configMap: name: my-test-name file: test.js
This resource will spawn 4 test runners. You may need to increase this value to run a large scale test.
Deploy your custom resource:
kubectl apply -f /path/to/our/k6/custom-resource.yml
At this point, your test will have started. You can track progress using
kubectl get pods
.Once all the pods are marked as
completed
, you can retrieve the output of each runner by requesting the logs.First get the names of each pod:
kubectl get pods
For each runner pod, retrieve the logs:
kubectl logs my-test-name-1-abcde
After running the tests, tidy up by deleting your custom resource:
kubectl delete -f /path/to/our/k6/custom-resource.yml