An extension for the k6 load testing tool that resolves a gRPC balanced host to its individual replicas, detecting updates in the available replicas while the test is running.
Considering a scenario where we have a gRPC service with N replicas, and a hostname that resolves to these replicas: when using the k6 gRPC client (k6/net/grpc), it internally resolves the IPs for all the replicas just when calling the client.connect method.
However, if new replicas are deployed while the test is running, these new replicas will not be used by the test. The xk6-grpcresolver extension solves this issue by detecting updates in the available replicas while the test is running, and using the new replicas in the test. This includes new replicas and replicas that are removed.
To build a k6 binary with this extension, first ensure you have the prerequisites:
- Go toolchain
- Git
Then:
- Download xk6:
go install go.k6.io/xk6/cmd/xk6@latest- Build the k6 binary:
xk6 build --with github.com/InditexTech/xk6-grpcresolver@latestThe default target in the Makefile will download the dependencies, format your code, run the tests, and create a k6 binary with the extension built from the local code rather than from GitHub.
git clone git@github.com:InditexTech/xk6-grpcresolver.git
cd xk6-grpcresolver
makeThis extension is always enabled when running a k6 binary compiled with this extension, and specifying the URL of the gRPC service prefixed by k8s:/// (this can be changed with the GRPC_RESOLVER_PROTOCOL environment variable). See the examples for more details.
There are some attributes that can be configured with the following environment variables:
| Key | Description | Default |
|---|---|---|
GRPC_RESOLVER_PROTOCOL |
Set the protocol name that will trigger the extension to work for a connection, if its URL has this protocol name. | k8s |
GRCP_UPDATE_EVERY |
Periodicity at which query the list of IPs for the hostnames. Value must comply with Go time.ParseDuration format. | 3s |
GRPC_SYNC_EVERY |
Periodicity at which synchronize the resolved IPs with the gRPC clients per VU. Value must comply with Go time.ParseDuration format. | 3s |
GRPC_DEBUG_LOGS |
If true, show debug logs. |
Disabled |
The following example requires Docker & Docker Compose to be installed in your system:
make runThis will deploy two clusters of gRPC servers (each cluster with multiple replicas) from the Docker Compose file. Then, it will run the k6 example that will request both replicas, making use of the xk6-grpcresolver functionality.
Then a k6 gRPC client connects, the Builder is executed. The xk6-grpcresolver extension overrides the default Builder with a custom one, which uses a custom Resolver.
The Resolver resolves the client's hostname to a list of IPs, which is retrieved periodically. This is performed by two tasks in the extension, which run periodically in background:
- The Lookup Task resolves the hostname to the IP/s using the net.LookupIP from Go. This task is unique for each hostname, and shared between all the clients. The periodicity at which this task runs is determined by the
GRCP_UPDATE_EVERYenvironment variable. - The Sync Task synchronizes the IP/s resolved for the hostname by the Lookup Task. This task is attached to each
Resolver, thus each client and hostname has its own Sync Task. The periodicity at which this task runs is determined by theGRPC_SYNC_EVERYenvironment variable.
flowchart TB
grpcClient["GRPC Client"]
hostIPs{{"IPs resolved"}}
lookupTask(("Lookup Task"))
settingUpdateEvery>"GRCP_UPDATE_EVERY"]
settingSyncEvery>"GRPC_SYNC_EVERY"]
settingUpdateEvery --> lookupTask
settingSyncEvery --> syncTask
subgraph "per host"
grpcClient --> builder --> resolver
syncTask -- "update IPs in" --> resolver
hostIPs --> syncTask
lookupTask -- "net.LookupIP" --> hostIPs
subgraph "per GRPC Client"
builder["Builder"]
resolver["Resolver"]
syncTask(("Sync Task"))
end
end
Contributions are welcome! Please see the CONTRIBUTING.md file for guidelines on how to contribute to this project.
This project is licensed under the terms of the AGPL-3.0-only license.
© 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)