• Stars
    star
    506
  • Rank 83,851 (Top 2 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 3 years ago
  • Updated 26 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An operator for running distributed k6 tests.

data flow

k6 Operator

grafana/k6-operator is a Kubernetes operator for running distributed k6 tests in your cluster.

Read also the complete tutorial to learn more about how to use this project.

Setup

Prerequisites

The minimal prerequisite for k6-operator is a Kubernetes cluster and access to it with kubectl.

Deploying the operator

Bundle deployment

The easiest way to install the operator is with bundle:

curl https://raw.githubusercontent.com/grafana/k6-operator/main/bundle.yaml | kubectl apply -f -

Bundle includes default manifests for k6-operator, including k6-operator-system namespace and k6-operator Deployment with latest tagged Docker image. Customizations can be made on top of this manifest as needs be, e.g. with kustomize.

Makefile deployment

In order to install the operator with Makefile, the following additional tooling must be installed:

A more manual, low-level way to install the operator is by running the command below:

make deploy

This method may be more useful for development of k6-operator, depending on specifics of the setup.

Installing the CRD

The k6 operator includes custom resources called K6 and PrivateLoadZone. These will be automatically installed when you do a deployment or install a bundle, but in case you want to do it yourself, you may run the command below:

make install

Usage

Two samples are available in config/samples, one for a test script and one for an actual test run.

Adding test scripts

The operator utilises ConfigMaps and LocalFile to serve test scripts to the jobs. To upload your own test script, run the following command to configure through ConfigMap:

ConfigMap

kubectl create configmap my-test --from-file /path/to/my/test.js

Note: there is a character limit of 1048576 bytes to a single configmap. If you need to have a larger test file, you'll need to use a volumeClaim or a LocalFile instead

VolumeClaim

There is a sample avaiable in config/samples/k6_v1alpha1_k6_with_volumeClaim.yaml on how to configure to run a test script with a volumeClaim.

If you have a PVC with the name stress-test-volumeClaim containing your script and any other supporting file(s), you can pass it to the test like this:

spec:
  parallelism: 2
  script:
    volumeClaim:
      name: "stress-test-volumeClaim"
      file: "test.js"

Note: the pods will expect to find script files in /test/ folder. If volumeClaim fails, it's the first place to check: the latest initializer pod does not generate any logs and when it can't find the file, it will terminate with error. So missing file may not be that obvious and it makes sense to check it manually. See #143 for potential improvements.

Example directory structure while using volumeClaim
โ”œโ”€โ”€ test
โ”‚   โ”œโ”€โ”€ requests
โ”‚   โ”‚   โ”œโ”€โ”€ stress-test.js
โ”‚   โ”œโ”€โ”€ test.js

In the above example, test.js imports a function from stress-test.js and they would look like this:

// test.js
import stressTest from "./requests/stress-test.js";

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

export default function () {
  stressTest();
}
// stress-test.js
import { sleep, check } from 'k6';
import http from 'k6/http';


export default () => {
  const res = http.get('https://test-api.k6.io');
  check(res, {
    'status is 200': () => res.status === 200,
  });
  sleep(1);
};

LocalFile

There is a sample avaiable in config/samples/k6_v1alpha1_k6_with_localfile.yaml on how to configure to run a test script inside the docker image.

Note: if there is any limitation on usage of volumeClaim in your cluster you can use this option, but always prefer the usage of volumeClaim.

Executing tests

Tests are executed by applying the custom resource K6 to a cluster where the operator is running. The properties of a test run are few, but allow you to control some key aspects of a distributed execution.

# k6-resource.yml

apiVersion: k6.io/v1alpha1
kind: K6
metadata:
  name: k6-sample
spec:
  parallelism: 4
  script:
    configMap:
      name: k6-test
      file: test.js
  separate: false
  runner:
    image: <custom-image>
    metadata:
      labels:
        cool-label: foo
      annotations:
        cool-annotation: bar
    securityContext:
      runAsUser: 1000
      runAsGroup: 1000
      runAsNonRoot: true
    resources:
      limits:
        cpu: 200m
        memory: 1000Mi
      requests:
        cpu: 100m
        memory: 500Mi
  starter:
    image: <custom-image>
    metadata:
      labels:
        cool-label: foo
      annotations:
        cool-annotation: bar
    securityContext:
      runAsUser: 2000
      runAsGroup: 2000
      runAsNonRoot: true

The test configuration is applied using

kubectl apply -f /path/to/your/k6-resource.yml

Parallelism

How many instances of k6 you want to create. Each instance will be assigned an equal execution segment. For instance, if your test script is configured to run 200 VUs and parallelism is set to 4, as in the example above, the operator will create four k6 jobs, each running 50 VUs to achieve the desired VU count.

Script

The name of the config map that includes our test script. In the example in the adding test scripts section, this is set to my-test.

Separate

Toggles whether the jobs created need to be distributed across different nodes. This is useful if you're running a test with a really high VU count and want to make sure the resources of each node won't become a bottleneck.

Serviceaccount

If you want to use a custom Service Account you'll need to pass it into both the starter and runner object:

apiVersion: k6.io/v1alpha1
kind: K6
metadata:
  name: <test-name>
spec:
  script:
    configMap:
      name: "<configmap>"
  runner:
    serviceAccountName: <service-account>
  starter:
    serviceAccountName: <service-account>

Runner

Defines options for the test runner pods. This includes:

  • passing resource limits and requests
  • passing in labels and annotations
  • passing in affinity and anti-affinity
  • passing in a custom image

Starter

Defines options for the starter pod. This includes:

  • passing in custom image
  • passing in labels and annotations

k6 outputs

k6 Cloud output

k6 supports output to its Cloud with k6 run --out cloud script.js command. This feature is available in k6-operator as well for subscribed users. Note that it supports only parallelism: 20 or less.

To use this option in k6-operator, set the argument in yaml:

# ...
  script:
    configMap:
      name: "<configmap>"
  arguments: --out cloud
# ...

Then, if you installed operator with bundle, create a secret with the following command:

kubectl -n k6-operator-system create secret generic my-cloud-token \
    --from-literal=token=<COPY YOUR TOKEN HERE> && kubectl -n k6-operator-system label secret my-cloud-token "k6cloud=token"

Alternatively, if you installed operator with Makefile, you can uncomment cloud output section in config/default/kustomization.yaml and copy your token from the Cloud there:

# Uncomment this section if you need cloud output and copy-paste your token
secretGenerator:
- name: cloud-token
  literals:
  - token=<copy-paste-token-string-here>
  options:
    annotations:
      kubernetes.io/service-account.name: k6-operator-controller
    labels:
      k6cloud: token

And re-run make deploy.

This is sufficient to run k6 with the Cloud output and default values of projectID and name. For non-default values, extended script options can be used like this:

export let options = {
  // ...
  ext: {
    loadimpact: {
      name: 'Configured k6-operator test',
      projectID: 1234567,
    }
  }
};

Cleaning up between test runs

After completing a test run, you need to clean up the test jobs created. This is done by running the following command:

kubectl delete -f /path/to/your/k6-resource.yml

Multi-file tests

In case your k6 script is split between more than one JS file, you can simply create a configmap with several data entries like this:

kubectl create configmap scenarios-test --from-file test.js --from-file utils.js

If there are too many files to specify manually, kubectl with folder might be an option:

kubectl create configmap scenarios-test --from-file=./test

Alternatively, you can create an archive with k6:

k6 archive test.js [args]

The above command will create an archive.tar in your current folder unless -O option is used to change the name of the output archive. Then it is possible to put that archive into configmap similarly to JS script:

kubectl create configmap scenarios-test --from-file=archive.tar

In case of using an archive it must be additionally specified in your yaml for K6 deployment:

# ...
spec:
  parallelism: 1
  script:
    configMap:
      name: "crocodile-stress-test"
      file: "archive.tar" # <-- change here

In other words, file option must be the correct entrypoint for k6 run.

Using extensions

By default, the operator will use grafana/k6:latest as the container image for the test jobs. If you want to use extensions built with xk6 you'll need to create your own image and override the image property on the K6 kubernetes resource.

For example, create a Dockerfile with the following content:

# Build the k6 binary with the extension
FROM golang:1.20 as builder

RUN go install go.k6.io/xk6/cmd/xk6@latest
# For our example, we'll add support for output of test metrics to InfluxDB v2.
# Feel free to add other extensions using the '--with ...'.
RUN xk6 build \
    --with github.com/grafana/xk6-output-influxdb@latest \
    --output /k6

# Use the operator's base image and override the k6 binary
FROM grafana/k6:latest
COPY --from=builder /k6 /usr/bin/k6

Build the image based on this Dockerfile by executing:

docker build -t k6-extended:local .

Once the build is completed, push the resulting k6-extended:local image to an image repository accessible to your Kubernetes cluster. We can now use it as follows:

# k6-resource-with-extensions.yml

apiVersion: k6.io/v1alpha1
kind: K6
metadata:
  name: k6-sample-with-extensions
spec:
  parallelism: 4
  script:
    configMap:
      name: crocodile-stress-test
      file: test.js
  runner:
    image: k6-extended:local
    env:
      - name: K6_OUT
        value: xk6-influxdb=http://influxdb.somewhere:8086/demo

Note that we are overriding the default image with k6-extended:latest, providing the test runner with environment variables used by our included extensions.

Scheduling Tests

While the k6 operator doesn't support scheduling k6 tests directly, the recommended path for scheduling tests is to use the cronjobs object from k8s directly. The cron job should run on a schedule and run a delete and then apply of a k6 object

Running these tests requires a little more setup, the basic steps are:

  1. Create a configmap of js test files (Covered above)
  2. Create a configmap of the yaml for the k6 job
  3. Create a service account that lets k6 objects be created and deleted
  4. Create a cron job that deletes and applys the yaml

Add a configMapGenerator to the kustomization.yaml:

configMapGenerator:
  - name: <test-name>-config
    files:
      - <test-name>.yaml

Then we are going to create a service account for the cron job to use:

This is required to allow the cron job to actually delete and create the k6 objects.

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: k6-<namespace>
rules:
  - apiGroups:
      - k6.io
    resources:
      - k6s
    verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: k6-<namespace>
roleRef:
  kind: Role
  name: k6-<namespace>
  apiGroup: rbac.authorization.k8s.io
subjects:
  - kind: ServiceAccount
    name: k6-<namespace>
    namespace: <namespace>
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: k6-<namespace>

We're going to create a cron job:

# snapshotter.yml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: <test-name>-cron
spec:
  schedule: "<cron-schedule>"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccount: k6
          containers:
            - name: kubectl
              image: bitnami/kubectl
              volumeMounts:
                - name: k6-yaml
                  mountPath: /tmp/
              command:
                - /bin/bash
              args:
                - -c
                - "kubectl delete -f /tmp/<test-name>.yaml; kubectl apply -f /tmp/<test-name>.yaml"
          restartPolicy: OnFailure
          volumes:
            - name: k6-yaml
              configMap:
                name: <test-name>-config

Uninstallation

You can remove the all resources created by the operator with bundle:

curl https://raw.githubusercontent.com/grafana/k6-operator/main/bundle.yaml | kubectl delete -f -

Or with make command:

make delete

Developing Locally

Run Tests

Pre-Requisites

Test Setup

  • make test-setup (only need to run once)

Run Unit Tests

  • make test

Run e2e Tests

See also

More Repositories

1

grafana

The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
TypeScript
60,280
star
2

k6

A modern load testing tool, using Go and JavaScript - https://k6.io
Go
22,905
star
3

loki

Like Prometheus, but for logs.
Go
22,069
star
4

pyroscope

Continuous Profiling Platform. Debug performance issues down to a single line of code
C
9,361
star
5

mimir

Grafana Mimir provides horizontally scalable, highly available, multi-tenant, long-term storage for Prometheus.
Go
3,634
star
6

tempo

Grafana Tempo is a high volume, minimal dependency distributed tracing backend.
Go
3,561
star
7

oncall

Developer-friendly incident response with brilliant Slack integration
Python
3,223
star
8

tanka

Flexible, reusable and concise configuration for Kubernetes
Go
2,235
star
9

phlare

๐Ÿ”ฅ horizontally-scalable, highly-available, multi-tenant continuous profiling aggregation system
Go
2,059
star
10

grafana-zabbix

Zabbix plugin for Grafana dashboard
TypeScript
2,020
star
11

agent

Vendor-neutral programmable observability pipelines.
Go
1,544
star
12

helm-charts

Smarty
1,494
star
13

grafonnet-lib

Jsonnet library for generating Grafana dashboard files.
Jsonnet
1,079
star
14

beyla

eBPF-based autoinstrumentation of HTTP and HTTPS services
C
1,032
star
15

grafana-operator

An operator for Grafana that installs and manages Grafana instances, Dashboards and Datasources through Kubernetes/OpenShift CRs
Go
756
star
16

alloy

OpenTelemetry Collector distribution with programmable pipelines
Go
711
star
17

grafana-docker

Grafana docker container
Shell
638
star
18

metrictank

metrics2.0 based, multi-tenant timeseries store for Graphite and friends.
Go
623
star
19

faro-web-sdk

The Grafana Faro Web SDK, part of the Grafana Faro project, is a highly configurable web SDK for real user monitoring (RUM) that instruments browser frontend applications to capture observability signals. Frontend telemetry can then be correlated with backend and infrastructure data for full-stack observability.
TypeScript
623
star
20

grafana-infinity-datasource

CSV, JSON, GraphQL, XML and HTML datasource for grafana.
TypeScript
591
star
21

jsonnet-libs

Grafana Labs' Jsonnet libraries
Jsonnet
516
star
22

simple-json-datasource

Datasource that sends generic http requests to give url
JavaScript
502
star
23

awesome-k6

A curated list of awesome tools, content and projects using k6
493
star
24

carbon-relay-ng

Fast carbon relay+aggregator with admin interfaces for making changes online - production ready
Go
455
star
25

grizzly

A utility for managing Jsonnet dashboards against the Grafana API
Go
424
star
26

terraform-provider-grafana

Terraform Grafana provider
Go
391
star
27

grafana-image-renderer

A Grafana backend plugin that handles rendering of panels & dashboards to PNGs using headless browser (Chromium/Chrome)
TypeScript
335
star
28

dskit

Distributed systems kit
Go
316
star
29

grafana-kiosk

Kiosk Utility for Grafana
Go
314
star
30

xk6-browser

k6 extension that adds support for browser automation and end-to-end web testing via the Chrome Devtools Protocol
Go
310
star
31

worldmap-panel

Worldmap panel plugin for Grafana 3.0 that can be overlaid with circles for data points.
JavaScript
301
star
32

postman-to-k6

Converts Postman collections to k6 script code
JavaScript
286
star
33

xk6-dashboard

A k6 extension that makes k6 metrics available on a web-based dashboard.
HTML
278
star
34

grafana-json-datasource

A data source plugin for loading JSON APIs into Grafana.
TypeScript
261
star
35

k6-learn

JavaScript
255
star
36

k6-template-typescript

Template to use TypeScript with k6
TypeScript
250
star
37

grafonnet

Jsonnet library for generating Grafana dashboards.
Jsonnet
229
star
38

dashboard-linter

A tool to lint Grafana dashboards
Go
187
star
39

thema

A CUE-based framework for portable, evolvable schema
Go
185
star
40

tns

Observability Demo App
Jsonnet
185
star
41

intro-to-mltp

Introduction to Metrics, Logs, Traces and Profiles session companion code.
JavaScript
181
star
42

strava-datasource

Strava datasource for Grafana dashboard
TypeScript
171
star
43

xk6

Build k6 with extensions
Go
169
star
44

github-datasource

Grafana data source plugin using the Github API to retrieve and visualize Github data.
Go
169
star
45

grafana-plugin-sdk-go

A Go SDK for building backend plugins for Grafana
Go
165
star
46

jsonnet-language-server

A Language Server Protocol (LSP) server for Jsonnet (https://jsonnet.org)
Go
154
star
47

grafana-plugin-examples

Shell
152
star
48

django-saml2-auth

Django SAML2 Authentication Made Easy. Easily integrate with SAML2 SSO identity providers like Okta, Azure AD and others.
Python
151
star
49

cortex-tools

If you're using this tool with Grafana Mimir, please switch to "mimirtool" instead: https://github.com/grafana/mimir
Go
150
star
50

piechart-panel

Pie Chart Panel Plugin
JavaScript
150
star
51

grafana-plugin-repository

The plugin repository for plugins that are published on grafana.com.
JavaScript
147
star
52

mqtt-datasource

MQTT Datasource for Grafana allows streaming data from any MQTT broker running either locally or remotely.
Go
143
star
53

xk6-output-prometheus-remote

k6 extension to output real-time test metrics using Prometheus Remote Write.
Go
139
star
54

scribe

A tool for building elaborate CI pipelines using a familiar programming language
Go
124
star
55

kubernetes-diff-logger

Logs updates to Kubernetes Objects for storing and querying with Loki
Go
122
star
56

pyroscope-rs

Pyroscope Profiler for Rust. Profile your Rust applications.
Rust
119
star
57

synthetic-monitoring-agent

Synthetic Monitoring Agent
Go
118
star
58

har-to-k6

JSON config representation of K6 script
JavaScript
114
star
59

scenes

Build Grafana dashboards directly in your Grafana app plugins.
TypeScript
114
star
60

faro

Grafana Faro is a project for frontend application observability. It includes a highly configurable web SDK that instruments browser frontend applications to capture observability signals.
113
star
61

google-sheets-datasource

Load Google Sheets in grafana
Go
112
star
62

tutorials

A series of tutorials for helping you make the most out of Grafana.
Makefile
109
star
63

synthetic-monitoring-app

Synthetic Monitoring frontend application
TypeScript
107
star
64

grafana-api-golang-client

Grafana HTTP API Client for Go
Go
105
star
65

k6-action

k6 is now available as a GitHub Action
JavaScript
101
star
66

clickhouse-datasource

Grafana Plugin for ClickHouse
TypeScript
101
star
67

k8s-monitoring-helm

Shell
96
star
68

cuetsy

Experimental CUE->TypeScript exporter
Go
96
star
69

rollout-operator

Kubernetes Rollout Operator
Go
96
star
70

azure-monitor-datasource

Grafana data source for Azure Monitor/Application Insights (deprecated - now included in core Grafana)
TypeScript
92
star
71

dashboard-spec

Go
91
star
72

clock-panel

Clock Panel Plugin for Grafana
TypeScript
88
star
73

grafana-polystat-panel

D3-Based hexagon layout multi-stat panel
TypeScript
86
star
74

docker-otel-lgtm

Dockerfile
82
star
75

k6-docs

The k6 documentation website.
JavaScript
80
star
76

xk6-disruptor

Extension for injecting faults into k6 tests
Go
80
star
77

k6-template-es6

Template using Webpack and Babel to enable ES6 features in k6 tests
JavaScript
77
star
78

cortex-jsonnet

Deprecated: see https://github.com/grafana/mimir/tree/main/operations/mimir instead
Jsonnet
74
star
79

doom-datasource

Hackathon project
C
71
star
80

tutorial-environment

Environment for tutorial excercises
Go
70
star
81

pyroscope-go

This is the golang client integration for Pyroscope
Go
69
star
82

grafana-ansible-collection

grafana.grafana Ansible collection provides modules and roles for managing various resources on Grafana Cloud and roles to manage and deploy Grafana Agent and Grafana
Python
69
star
83

database-migrator

Code to export grafana.db (sqlite) to MySQL-compatible SQL file, to assist in migration of Grafana data to MySQL-compatible DB.
Shell
67
star
84

grafana-csv-datasource

A data source for loading CSV data into Grafana.
TypeScript
67
star
85

mimir-proxies

Proxies to help you ingest your metrics into Grafana Mimir.
Go
65
star
86

pyroscope-java

pyroscope java integration
Java
65
star
87

otel-profiling-go

Open Telemetry integration for Grafana Pyroscope and tracing solutions such as Grafana Tempo, Honeycomb, or Jaeger
Go
65
star
88

memo

easily save grafana annotations from slack mentions and the cli
Go
65
star
89

JPProf

Go Pprof but for Java runtime.
Java
65
star
90

grafana-starter-panel

A starter for Grafana panel plugins
TypeScript
65
star
91

xk6-sql

k6 extension to load test RDBMSs (PostgreSQL, MySQL, MS SQL and SQLite3)
Go
64
star
92

vscode-jsonnet

Full code support (formatting, highlighting, navigation, etc) for Jsonnet
JavaScript
64
star
93

jmeter-to-k6

Converts JMeter .jmx files to k6 JS code
JavaScript
63
star
94

xk6-distributed-tracing

A k6 extension for distributed tracing.
Go
62
star
95

github-to-es

GitHub Analytics With Elasticsearch And Grafana
JavaScript
54
star
96

opcua-datasource

An OPC UA datasource for reading from OPC UA servers (DA/HDA/AE) into Grafana directly
CSS
54
star
97

grafana-plugin-sdk-rust

Grafana Plugin SDK for Rust
Rust
53
star
98

xk6-kubernetes

Client extension for interacting with Kubernetes clusters from your k6 tests.
Go
52
star
99

regexp

Faster version of the Go regexp package
Go
51
star
100

influxdb-flux-datasource

Grafana datasource plugin for Flux (InfluxDB)
Go
51
star