@assertrx/dino 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/prompts/generate-k6-test-from-endpoint.md +68 -0
- package/prompts/generate-k6-test-from-openapi.md +85 -0
- package/prompts/setup-k6.md +130 -0
- package/prompts/setup-promptfoo.md +103 -0
- package/scripts/api-server.mjs +28 -0
- package/skills/analyzing-test-results/SKILL.md +150 -0
- package/skills/analyzing-test-results/reference/bottleneck-patterns.md +130 -0
- package/skills/analyzing-test-results/reference/metrics.md +134 -0
- package/skills/analyzing-test-results/reference/visualization.md +152 -0
- package/skills/designing-test-scenarios/SKILL.md +247 -0
- package/skills/designing-test-scenarios/reference/executors.md +215 -0
- package/skills/designing-test-scenarios/reference/test-types.md +215 -0
- package/skills/designing-test-scenarios/reference/thresholds.md +208 -0
- package/skills/generating-api-load-tests/SKILL.md +199 -0
- package/skills/generating-api-load-tests/reference/data-parameterization.md +343 -0
- package/skills/generating-api-load-tests/reference/grpc.md +315 -0
- package/skills/generating-api-load-tests/reference/http.md +380 -0
- package/skills/generating-api-load-tests/reference/websocket.md +369 -0
- package/skills/generating-browser-tests/SKILL.md +269 -0
- package/skills/generating-browser-tests/reference/browser-api.md +251 -0
- package/skills/generating-browser-tests/reference/web-vitals.md +148 -0
- package/skills/generating-tests-from-code/SKILL.md +142 -0
- package/skills/generating-tests-from-code/reference/auth-analysis.md +220 -0
- package/skills/generating-tests-from-code/reference/framework-patterns.md +242 -0
- package/skills/generating-tests-from-openapi/SKILL.md +234 -0
- package/skills/generating-tests-from-openapi/reference/openapi-auth-mapping.md +247 -0
- package/skills/generating-tests-from-openapi/reference/openapi-parsing.md +194 -0
- package/skills/operating-k6-in-ci-cd/SKILL.md +98 -0
- package/skills/operating-k6-in-ci-cd/reference/ci-cd-pipelines.md +265 -0
- package/skills/operating-k6-in-ci-cd/reference/extensions.md +144 -0
- package/skills/operating-k6-in-ci-cd/reference/k6-operator.md +214 -0
- package/skills/promptfoo/SKILL.md +121 -0
- package/skills/promptfoo/reference/assert-types.md +74 -0
- package/skills/promptfoo/reference/providers.md +70 -0
- package/skills/testing-resilience/SKILL.md +230 -0
- package/skills/testing-resilience/reference/fault-injection.md +153 -0
- package/skills/testing-resilience/reference/resilience-patterns.md +500 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# k6 CI/CD Pipeline Reference
|
|
2
|
+
|
|
3
|
+
## GitHub Actions
|
|
4
|
+
|
|
5
|
+
### Using Official Actions
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
name: k6 Performance Test
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
branches: [main]
|
|
12
|
+
pull_request:
|
|
13
|
+
branches: [main]
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
k6-test:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Setup k6
|
|
22
|
+
uses: grafana/setup-k6-action@v1
|
|
23
|
+
|
|
24
|
+
- name: Run k6 test
|
|
25
|
+
uses: grafana/run-k6-action@v1
|
|
26
|
+
with:
|
|
27
|
+
path: tests/load-test.js
|
|
28
|
+
env:
|
|
29
|
+
BASE_URL: https://staging.example.com
|
|
30
|
+
|
|
31
|
+
- name: Upload results
|
|
32
|
+
if: always()
|
|
33
|
+
uses: actions/upload-artifact@v4
|
|
34
|
+
with:
|
|
35
|
+
name: k6-results
|
|
36
|
+
path: summary.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### With Grafana Cloud k6
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
jobs:
|
|
43
|
+
k6-cloud:
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@v4
|
|
47
|
+
- uses: grafana/setup-k6-action@v1
|
|
48
|
+
- name: Run k6 cloud test
|
|
49
|
+
uses: grafana/run-k6-action@v1
|
|
50
|
+
with:
|
|
51
|
+
path: tests/load-test.js
|
|
52
|
+
cloud-run-locally: true
|
|
53
|
+
env:
|
|
54
|
+
K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Manual Setup (Without Official Actions)
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
jobs:
|
|
61
|
+
k6-test:
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v4
|
|
65
|
+
|
|
66
|
+
- name: Install k6
|
|
67
|
+
run: |
|
|
68
|
+
sudo gpg -k
|
|
69
|
+
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
|
|
70
|
+
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
|
|
71
|
+
sudo apt-get update
|
|
72
|
+
sudo apt-get install k6
|
|
73
|
+
|
|
74
|
+
- name: Run load test
|
|
75
|
+
run: k6 run tests/load-test.js
|
|
76
|
+
env:
|
|
77
|
+
BASE_URL: ${{ vars.STAGING_URL }}
|
|
78
|
+
API_KEY: ${{ secrets.API_KEY }}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Docker-Based
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
jobs:
|
|
85
|
+
k6-docker:
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
container:
|
|
88
|
+
image: grafana/k6:latest
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/checkout@v4
|
|
91
|
+
- name: Run test
|
|
92
|
+
run: k6 run tests/load-test.js
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## GitLab CI
|
|
98
|
+
|
|
99
|
+
### Basic Configuration
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
# .gitlab-ci.yml
|
|
103
|
+
stages:
|
|
104
|
+
- test
|
|
105
|
+
- performance
|
|
106
|
+
|
|
107
|
+
k6-load-test:
|
|
108
|
+
stage: performance
|
|
109
|
+
image:
|
|
110
|
+
name: grafana/k6:latest
|
|
111
|
+
entrypoint: ['']
|
|
112
|
+
script:
|
|
113
|
+
- k6 run tests/load-test.js
|
|
114
|
+
variables:
|
|
115
|
+
BASE_URL: https://staging.example.com
|
|
116
|
+
artifacts:
|
|
117
|
+
when: always
|
|
118
|
+
paths:
|
|
119
|
+
- summary.json
|
|
120
|
+
expire_in: 30 days
|
|
121
|
+
rules:
|
|
122
|
+
- if: $CI_COMMIT_BRANCH == "main"
|
|
123
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### With JSON Output
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
k6-load-test:
|
|
130
|
+
stage: performance
|
|
131
|
+
image:
|
|
132
|
+
name: grafana/k6:latest
|
|
133
|
+
entrypoint: ['']
|
|
134
|
+
script:
|
|
135
|
+
- k6 run --out json=results.json tests/load-test.js
|
|
136
|
+
artifacts:
|
|
137
|
+
when: always
|
|
138
|
+
paths:
|
|
139
|
+
- results.json
|
|
140
|
+
- summary.json
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### With Cloud Results
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
k6-cloud-test:
|
|
147
|
+
stage: performance
|
|
148
|
+
image:
|
|
149
|
+
name: grafana/k6:latest
|
|
150
|
+
entrypoint: ['']
|
|
151
|
+
script:
|
|
152
|
+
- k6 cloud run --local-execution tests/load-test.js
|
|
153
|
+
variables:
|
|
154
|
+
K6_CLOUD_TOKEN: $K6_CLOUD_TOKEN
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Jenkins
|
|
160
|
+
|
|
161
|
+
### Pipeline (Declarative)
|
|
162
|
+
|
|
163
|
+
```groovy
|
|
164
|
+
pipeline {
|
|
165
|
+
agent any
|
|
166
|
+
|
|
167
|
+
environment {
|
|
168
|
+
BASE_URL = 'https://staging.example.com'
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
stages {
|
|
172
|
+
stage('Install k6') {
|
|
173
|
+
steps {
|
|
174
|
+
sh '''
|
|
175
|
+
curl -sL https://github.com/grafana/k6/releases/latest/download/k6-linux-amd64.tar.gz | tar xz
|
|
176
|
+
mv k6-*/k6 /usr/local/bin/
|
|
177
|
+
'''
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
stage('Run Load Test') {
|
|
182
|
+
steps {
|
|
183
|
+
sh 'k6 run tests/load-test.js'
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
post {
|
|
189
|
+
always {
|
|
190
|
+
archiveArtifacts artifacts: 'summary.json', allowEmptyArchive: true
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Docker-Based Pipeline
|
|
197
|
+
|
|
198
|
+
```groovy
|
|
199
|
+
pipeline {
|
|
200
|
+
agent {
|
|
201
|
+
docker {
|
|
202
|
+
image 'grafana/k6:latest'
|
|
203
|
+
args '--entrypoint=""'
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
stages {
|
|
208
|
+
stage('Run Load Test') {
|
|
209
|
+
steps {
|
|
210
|
+
sh 'k6 run tests/load-test.js'
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Best Practices
|
|
220
|
+
|
|
221
|
+
### Separate Test Stages
|
|
222
|
+
|
|
223
|
+
```yaml
|
|
224
|
+
# Run smoke test on every PR
|
|
225
|
+
smoke-test:
|
|
226
|
+
script: k6 run --vus 3 --duration 30s tests/test.js
|
|
227
|
+
|
|
228
|
+
# Run full load test on main branch only
|
|
229
|
+
load-test:
|
|
230
|
+
script: k6 run tests/test.js
|
|
231
|
+
rules:
|
|
232
|
+
- if: $CI_COMMIT_BRANCH == "main"
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Environment Variables
|
|
236
|
+
|
|
237
|
+
Always pass sensitive data via CI/CD secrets:
|
|
238
|
+
```yaml
|
|
239
|
+
env:
|
|
240
|
+
BASE_URL: ${{ vars.STAGING_URL }} # Non-sensitive
|
|
241
|
+
API_KEY: ${{ secrets.API_KEY }} # Sensitive
|
|
242
|
+
K6_CLOUD_TOKEN: ${{ secrets.K6_TOKEN }} # Cloud token
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Artifact Collection
|
|
246
|
+
|
|
247
|
+
Always collect test results regardless of pass/fail:
|
|
248
|
+
```yaml
|
|
249
|
+
- name: Upload results
|
|
250
|
+
if: always() # Runs even if test fails
|
|
251
|
+
uses: actions/upload-artifact@v4
|
|
252
|
+
with:
|
|
253
|
+
name: k6-results
|
|
254
|
+
path: |
|
|
255
|
+
summary.json
|
|
256
|
+
results.json
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Exit Codes
|
|
260
|
+
|
|
261
|
+
| Code | Meaning |
|
|
262
|
+
|------|---------|
|
|
263
|
+
| 0 | Test completed, all thresholds passed |
|
|
264
|
+
| 99 | Test completed, one or more thresholds failed |
|
|
265
|
+
| Other | Test execution error |
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# k6 Extensions (xk6) Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
k6 extensions add capabilities beyond the core k6 feature set. Types:
|
|
6
|
+
- **JavaScript extensions** — New JS APIs and modules
|
|
7
|
+
- **Output extensions** — Send metrics to custom backends
|
|
8
|
+
- **Secret source extensions** — Provide secrets at runtime
|
|
9
|
+
|
|
10
|
+
## Automatic Resolution (k6 v1.2.0+)
|
|
11
|
+
|
|
12
|
+
Official extensions auto-load when imported:
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
import faker from 'k6/x/faker'; // Auto-resolved at runtime
|
|
16
|
+
import sql from 'k6/x/sql'; // Auto-resolved at runtime
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Community extensions require opt-in:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
K6_ENABLE_COMMUNITY_EXTENSIONS=true k6 run script.js
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Building Custom k6 Binary (xk6)
|
|
26
|
+
|
|
27
|
+
### Using Go
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Install xk6
|
|
31
|
+
go install go.k6.io/xk6/cmd/xk6@latest
|
|
32
|
+
|
|
33
|
+
# Build with extensions
|
|
34
|
+
xk6 build \
|
|
35
|
+
--with github.com/grafana/xk6-faker \
|
|
36
|
+
--with github.com/grafana/xk6-sql
|
|
37
|
+
|
|
38
|
+
# Build specific k6 version
|
|
39
|
+
xk6 build v1.2.0 \
|
|
40
|
+
--with github.com/grafana/xk6-faker
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Using Docker
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Build custom binary
|
|
47
|
+
docker run --rm -v $(pwd):/output grafana/xk6 build \
|
|
48
|
+
--with github.com/grafana/xk6-faker \
|
|
49
|
+
--output /output/k6
|
|
50
|
+
|
|
51
|
+
# Run with custom binary
|
|
52
|
+
./k6 run script.js
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Dockerfile for CI/CD
|
|
56
|
+
|
|
57
|
+
```dockerfile
|
|
58
|
+
FROM grafana/xk6 AS builder
|
|
59
|
+
RUN xk6 build \
|
|
60
|
+
--with github.com/grafana/xk6-faker \
|
|
61
|
+
--with github.com/grafana/xk6-sql \
|
|
62
|
+
--output /k6
|
|
63
|
+
|
|
64
|
+
FROM alpine:3
|
|
65
|
+
COPY --from=builder /k6 /usr/local/bin/k6
|
|
66
|
+
ENTRYPOINT ["k6"]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Popular Official Extensions
|
|
70
|
+
|
|
71
|
+
| Extension | Import | Description |
|
|
72
|
+
|-----------|--------|-------------|
|
|
73
|
+
| xk6-faker | `k6/x/faker` | Generate fake/random data |
|
|
74
|
+
| xk6-sql | `k6/x/sql` | Database testing (PostgreSQL, MySQL, SQLite) |
|
|
75
|
+
| xk6-disruptor | `k6/x/disruptor` | Fault injection for Kubernetes |
|
|
76
|
+
|
|
77
|
+
## Popular Community Extensions
|
|
78
|
+
|
|
79
|
+
| Extension | Description |
|
|
80
|
+
|-----------|-------------|
|
|
81
|
+
| xk6-output-influxdb | Send metrics to InfluxDB |
|
|
82
|
+
| xk6-kafka | Apache Kafka testing |
|
|
83
|
+
| xk6-amqp | AMQP/RabbitMQ testing |
|
|
84
|
+
| xk6-redis | Redis testing |
|
|
85
|
+
| xk6-mqtt | MQTT protocol testing |
|
|
86
|
+
| xk6-cable | ActionCable testing |
|
|
87
|
+
| xk6-exec | Execute external commands |
|
|
88
|
+
|
|
89
|
+
## Extension Usage Examples
|
|
90
|
+
|
|
91
|
+
### xk6-faker (Data Generation)
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
import faker from 'k6/x/faker';
|
|
95
|
+
|
|
96
|
+
export default function () {
|
|
97
|
+
const user = {
|
|
98
|
+
name: faker.person.firstName() + ' ' + faker.person.lastName(),
|
|
99
|
+
email: faker.internet.email(),
|
|
100
|
+
phone: faker.phone.number(),
|
|
101
|
+
address: faker.location.streetAddress(),
|
|
102
|
+
company: faker.company.name(),
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
http.post(url, JSON.stringify(user), {
|
|
106
|
+
headers: { 'Content-Type': 'application/json' },
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### xk6-sql (Database Testing)
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
import sql from 'k6/x/sql';
|
|
115
|
+
import driver from 'k6/x/sql/driver/postgres';
|
|
116
|
+
|
|
117
|
+
const db = sql.open(driver, 'postgres://user:pass@localhost:5432/testdb');
|
|
118
|
+
|
|
119
|
+
export function setup() {
|
|
120
|
+
db.exec(`CREATE TABLE IF NOT EXISTS test (id SERIAL PRIMARY KEY, name VARCHAR(50))`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export default function () {
|
|
124
|
+
db.exec(`INSERT INTO test (name) VALUES ('test_${Date.now()}')`);
|
|
125
|
+
const results = sql.query(db, 'SELECT COUNT(*) as count FROM test');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function teardown() {
|
|
129
|
+
db.close();
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Checking Dependencies
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Check what extensions a script needs
|
|
137
|
+
k6 deps script.js
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Extension Discovery
|
|
141
|
+
|
|
142
|
+
Browse available extensions:
|
|
143
|
+
- Official: https://grafana.com/docs/k6/latest/extensions/
|
|
144
|
+
- Community: https://github.com/topics/xk6
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# k6 Operator (Kubernetes Distributed Testing) Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The k6-operator is a Kubernetes operator that enables running distributed k6 load tests across multiple pods. It uses a Custom Resource Definition (CRD) called `TestRun` (previously `K6`).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### Using Helm
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
helm repo add grafana https://grafana.github.io/helm-charts
|
|
13
|
+
helm repo update
|
|
14
|
+
helm install k6-operator grafana/k6-operator \
|
|
15
|
+
--namespace k6-operator-system \
|
|
16
|
+
--create-namespace
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Using kubectl
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Install CRDs and operator
|
|
23
|
+
kubectl apply -f https://github.com/grafana/k6-operator/releases/latest/download/bundle.yaml
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Verify Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
kubectl get pods -n k6-operator-system
|
|
30
|
+
# Should see k6-operator-controller-manager running
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## TestRun CRD
|
|
34
|
+
|
|
35
|
+
### Basic TestRun
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
apiVersion: k6.io/v1alpha1
|
|
39
|
+
kind: TestRun
|
|
40
|
+
metadata:
|
|
41
|
+
name: k6-load-test
|
|
42
|
+
spec:
|
|
43
|
+
parallelism: 4 # Number of k6 pods
|
|
44
|
+
script:
|
|
45
|
+
configMap:
|
|
46
|
+
name: k6-test-script # ConfigMap containing the test script
|
|
47
|
+
file: test.js # Script filename in ConfigMap
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Creating the ConfigMap
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# From file
|
|
54
|
+
kubectl create configmap k6-test-script --from-file=test.js=./tests/load-test.js
|
|
55
|
+
|
|
56
|
+
# Or inline
|
|
57
|
+
kubectl apply -f - <<EOF
|
|
58
|
+
apiVersion: v1
|
|
59
|
+
kind: ConfigMap
|
|
60
|
+
metadata:
|
|
61
|
+
name: k6-test-script
|
|
62
|
+
data:
|
|
63
|
+
test.js: |
|
|
64
|
+
import http from 'k6/http';
|
|
65
|
+
import { check } from 'k6';
|
|
66
|
+
|
|
67
|
+
export const options = {
|
|
68
|
+
vus: 50,
|
|
69
|
+
duration: '5m',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default function () {
|
|
73
|
+
const res = http.get('http://my-service.default.svc.cluster.local:8080/api');
|
|
74
|
+
check(res, { 'status 200': (r) => r.status === 200 });
|
|
75
|
+
}
|
|
76
|
+
EOF
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Running the Test
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
kubectl apply -f testrun.yaml
|
|
83
|
+
|
|
84
|
+
# Monitor progress
|
|
85
|
+
kubectl get testrun k6-load-test -w
|
|
86
|
+
|
|
87
|
+
# Check pod logs
|
|
88
|
+
kubectl logs -l k6_cr=k6-load-test -f
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Cleanup
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
kubectl delete testrun k6-load-test
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Advanced Configuration
|
|
98
|
+
|
|
99
|
+
### With Arguments and Environment Variables
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
apiVersion: k6.io/v1alpha1
|
|
103
|
+
kind: TestRun
|
|
104
|
+
metadata:
|
|
105
|
+
name: k6-load-test
|
|
106
|
+
spec:
|
|
107
|
+
parallelism: 4
|
|
108
|
+
script:
|
|
109
|
+
configMap:
|
|
110
|
+
name: k6-test-script
|
|
111
|
+
file: test.js
|
|
112
|
+
arguments: --out json=/tmp/results.json
|
|
113
|
+
runner:
|
|
114
|
+
env:
|
|
115
|
+
- name: BASE_URL
|
|
116
|
+
value: "http://my-service.default.svc.cluster.local:8080"
|
|
117
|
+
- name: API_KEY
|
|
118
|
+
valueFrom:
|
|
119
|
+
secretKeyRef:
|
|
120
|
+
name: api-secrets
|
|
121
|
+
key: api-key
|
|
122
|
+
resources:
|
|
123
|
+
limits:
|
|
124
|
+
cpu: "500m"
|
|
125
|
+
memory: "512Mi"
|
|
126
|
+
requests:
|
|
127
|
+
cpu: "200m"
|
|
128
|
+
memory: "256Mi"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### With Extensions (Custom Image)
|
|
132
|
+
|
|
133
|
+
```yaml
|
|
134
|
+
spec:
|
|
135
|
+
runner:
|
|
136
|
+
image: custom-k6-image:latest # Custom k6 image with extensions
|
|
137
|
+
imagePullPolicy: Always
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### With Grafana Cloud k6
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
spec:
|
|
144
|
+
parallelism: 4
|
|
145
|
+
script:
|
|
146
|
+
configMap:
|
|
147
|
+
name: k6-test-script
|
|
148
|
+
file: test.js
|
|
149
|
+
arguments: --out cloud
|
|
150
|
+
runner:
|
|
151
|
+
env:
|
|
152
|
+
- name: K6_CLOUD_TOKEN
|
|
153
|
+
valueFrom:
|
|
154
|
+
secretKeyRef:
|
|
155
|
+
name: k6-cloud-secrets
|
|
156
|
+
key: token
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### With Istio Service Mesh
|
|
160
|
+
|
|
161
|
+
When testing services behind Istio:
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
spec:
|
|
165
|
+
runner:
|
|
166
|
+
metadata:
|
|
167
|
+
annotations:
|
|
168
|
+
sidecar.istio.io/inject: "true" # Enable Istio sidecar
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Parallelism and Load Distribution
|
|
172
|
+
|
|
173
|
+
Each pod runs the full test script independently. If your script defines `vus: 100` and `parallelism: 4`, each pod runs 100 VUs (400 total VUs).
|
|
174
|
+
|
|
175
|
+
**To distribute load evenly:** Divide VUs by parallelism in your script or use environment variables:
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
const PARALLELISM = parseInt(__ENV.K6_PARALLELISM) || 1;
|
|
179
|
+
const TOTAL_VUS = 400;
|
|
180
|
+
|
|
181
|
+
export const options = {
|
|
182
|
+
vus: Math.ceil(TOTAL_VUS / PARALLELISM),
|
|
183
|
+
duration: '5m',
|
|
184
|
+
};
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Or use scenarios with `constant-arrival-rate` for more predictable distribution.
|
|
188
|
+
|
|
189
|
+
## TestRun Lifecycle
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
Created → Initialized → Started → Finished
|
|
193
|
+
↓
|
|
194
|
+
(cleanup)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Monitor status:**
|
|
198
|
+
```bash
|
|
199
|
+
kubectl get testrun -w
|
|
200
|
+
# NAME STAGE STATUS AGE
|
|
201
|
+
# k6-load-test started running 2m
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Troubleshooting
|
|
205
|
+
|
|
206
|
+
### Common Issues
|
|
207
|
+
|
|
208
|
+
| Problem | Solution |
|
|
209
|
+
|---------|----------|
|
|
210
|
+
| Pods stuck in Pending | Check resource limits, node capacity |
|
|
211
|
+
| ConfigMap not found | Verify ConfigMap exists in same namespace |
|
|
212
|
+
| Connection refused | Check target service DNS and network policies |
|
|
213
|
+
| Uneven load | Use arrival-rate executors for better distribution |
|
|
214
|
+
| OOMKilled | Increase memory limits in runner.resources |
|