Learn how to scale an HTTP stub for high-performance load testing using WireMock in Kubernetes. This post covers strategies for horizontal scaling, handling dynamic mappings with StatefulSets, and configuring a load generator for effective non-functional testing.


---
apiVersion: v1
kind: ConfigMap
metadata:
name: wiremock-mappings
data:
static.json: |-
{
"request": {
"method": "GET",
"url": "/static"
},
"response": {
"status": 200,
"jsonBody": {
"data": "static"
},
"headers": {
"Content-Type": "application/json"
}
}
}
volumeMounts:
- name: wiremock-mappings-volume
mountPath: /home/wiremock/mappings
http://wiremock
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wiremock
labels:
app.kubernetes.io/name: wiremock
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: wiremock
template:
metadata:
labels:
app.kubernetes.io/name: wiremock
spec:
containers:
- name: wiremock
image: wiremock/wiremock:3.4.2
args:
- "--no-request-journal"
- "--disable-request-logging"
- "--async-response-enabled"
- "true"
volumeMounts:
- name: wiremock-mappings
mountPath: /home/wiremock/mappings
livenessProbe:
httpGet:
port: 8080
path: /static
readinessProbe:
httpGet:
port: 8080
path: /static
ports:
- containerPort: 8080
volumes:
- name: wiremock-mappings
configMap:
name: wiremock-mappings
---
apiVersion: v1
kind: Service
metadata:
name: wiremock
spec:
selector:
app.kubernetes.io/name: wiremock
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: wiremock
labels:
app.kubernetes.io/name: wiremock
spec:
serviceName: wiremocks
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: wiremock
---
apiVersion: v1
kind: Service
metadata:
name: wiremocks
spec:
clusterIP: None # headless
selector:
app.kubernetes.io/name: wiremock
ports:
- protocol: TCP
port: 8080
targetPort: 8080
+ kubectl get pods -l app.kubernetes.io/name=wiremock
NAME READY STATUS RESTARTS AGE
wiremock-0 1/1 Running 0 2h
wiremock-1 1/1 Running 0 2h
wiremock-2 1/1 Running 0 2h
http://wiremock-{index}.wiremocks:8080
import { check } from "k6";
import http from "k6/http";
export function registerStubMapping(replicas, stubMappingDefinition) {
for (let i = 0; i < replicas; i++) {
const replicaEndpoint = `http://wiremock-${i}.wiremocks:8080`;
callWiremock(replicaEndpoint, stubMappingDefinition);
}
}
function callWiremock(endpoint, stubMappingDefinition) {
const url = `${endpoint}/__admin/mappings`;
const params = {
headers: {
"Content-Type": "application/json",
},
};
const res = http.post(url, JSON.stringify(stubMappingDefinition), params);
check(res, {
"stub mapping created": (r) => r.status === 201,
});
}
import { check } from "k6";
import http from "k6/http";
import { registerStubMapping } from "./wiremock.js";
const wiremockReplicas = 3;
const testData = "testing-data-string";
export const options = {
scenarios: {
loadTest: {
executor: "constant-arrival-rate",
rate: 1000,
timeUnit: "1s",
duration: "3m",
preAllocatedVUs: 200,
},
},
thresholds: {
checks: ["rate>0.99"],
http_reqs: ["rate>999"],
http_req_failed: ["rate<0.01"],
http_req_duration: ["p(99)<500"],
},
};
export function setup() {
registerStubMapping(wiremockReplicas, {
request: {
method: "GET",
url: "/api/test",
},
response: {
status: 200,
jsonBody: {
data: testData,
},
headers: {
"Content-Type": "application/json",
},
},
});
}
export default function () {
const res = http.get("http://reference-service/downstream/api/test");
check(res, {
"status is 200": (r) => r.status === 200,
"response body contains stubbed data": (r) => r.body.includes(testData),
});
}
This article is provided as a general guide for general information purposes only. It does not constitute advice. CECG disclaims liability for actions taken based on the materials.
Discover more insights from our blog collection

A deep dive into mise and nix-shell, two modern tools for managing development environments. This post compares their philosophies, features, and practical applications to help you choose the right solution for ensuring consistency and reproducibility in your projects.

How would you test a Kubernetes operator? We figured we would never be truly confident unless we ran the tests against a Kubernetes cluster using kind.

A comprehensive review of Crossplane after one year of intensive professional use, exploring its strengths in infrastructure automation and Kubernetes integration, alongside its challenges and limitations.

Want To Talk This Through?
Design Realistic Load-testing Infrastructure That Scales Safely. We Can Help You Avoid Brittle Test Setups.