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

Explore emerging trends in CI/CD pipelines that challenge conventional processes, advocating for script-based approaches, local execution capabilities, and tools like Dagger for more dynamic and adaptable workflows.

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.

Explore four common mechanisms for integrating Kubernetes with HashiCorp Vault for secret management. This post compares the External Secrets Operator, Kubernetes Secrets Store CSI Driver, Vault Secrets Operator, and Vault Agent, weighing their pros and cons to help you choose the right solution for your platform.