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

Learn our four-stage model for executing greenfield projects: discovery, planning, execution, and feedback. This post unveils our strategy for achieving high client satisfaction and making critical decisions efficiently.

Learn from 8 years of experience in upgrading multi-tenanted production Kubernetes clusters. This post details the challenges of keeping clusters up to date, from managing API deprecations to aligning with vendor support schedules, and provides a recommended upgrade timeline to ensure a smooth, business-as-usual process.

Explore how to implement robust Platform Lifecycle Management using FluxCD for GitOps and Concourse for delivery management. This post details an automated, reliable, and continuous approach to deploying platform services across multiple environments.