Istio, Kubernetes, and WireMock? Yup! It's a powerful combination!
Recap
In my previous blog https://marinow.hashnode.dev/how-to-not-stub-your-toe-in-production, we discussed ideas on how you can combine the power of Istio and WireMock Stub functionality to get you ready for production deployment. Let’s quickly recap both Istio and WireMock’s capabilities and then we'll proceed to deploy and test.
Istio
A powerful and highly customizeable Open Source Service Mesh and Application Networking Layer providing the following capabities:
Highly customizable Traffic Engineering
Encryption, Authentication, Authorization, Policy and Zero Trust
Observability and Telemetry
Application Resiliency
WireMock
A highly tunable and customizable HTTP Stub Response Server that provides a variety of features for API testing:
Request Matching
Response Templating
Baselining and Playback
Simulating Stateful Services
Service Proxying
Injecting Faults
Extensibility
Now, it’s fun to keep digging into theory but, I think it’s WAY MORE FUN to get this up and running.
LET’S GO!!!
Prerequisites
Now, to make WireMock and Istio work together, we’ll need a few immediate pieces:
A Kubernetes cluster
This can be KinD, or your favourite managed cluster (Civo, GKE, EKS)
Make sure you’re using a recent version like 1.25 or 1.26.
Kubectl
Istioctl (Istio v1.17 will suffice), which you can obtain here.
Note, istioctl targets the context your kubectl is currently configured to. You may want to make sure your kubectl is showing you resources for the K8s cluster you created.
We won't be deploying the
sidecar
resource as of yet, but will do in the next blog post.
A WireMock container can be found here: https://hub.docker.com/r/wiremock/wiremock
The documentation https://wiremock.org/docs/docker/ does have v2.3.5 listed but, we can either use:
wiremock/wiremock:2.35.0
wiremock/wiremock:latest
Once you have these ready to go, we can start setting this up.
The Setup
Before I begin walking through setting this up, it's worthwhile visualizing how this all looks.
The diagram above shows that Istio and Kubernetes are running, and WireMock is deployed. Also, notice that additional configurations for Istio and WireMock are deployed, and this is done through Kubectl, as the Kubernetes API understands the resources you're attempting to deploy. Once all is good, a file called stub.json
is created and sent to the WireMock server using curl
and the HTTP POST method.
Finally, using curl
you can call on the stub
and see a response from the WireMock server saying Hello, This is WireMock on K8s with Istio!
In my setup, I’ve decided to use Civo Kubernetes so I can simply expose the service using a load balancer, and test responses from anywhere. If you want your friends to see those stub replies, you might want to consider using a load balancer.
If you've deployed your cluster and you have istioctl download, let's go ahead and deploy Istio to K8s using the demo profile.
istioctl install --set profile=demo -y
Next, let's deploy WireMock as a Deployment in K8s, along with a Service resource to expose it. Note: We use the ClusterIP type to ensure that the Istio Ingress Gateway routes to this resource.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: wiremockstub
spec:
replicas: 1
selector:
matchLabels:
app: wiremock
template:
metadata:
labels:
app: wiremock
spec:
containers:
- name: wiremock
image: wiremock/wiremock:latest
ports:
- containerPort: 8080
args:
- "--port"
- "8080"
EOF
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: wiremock
spec:
selector:
app: wiremock
ports:
- protocol: TCP
port: 8080
targetPort: 8080
EOF
Let's deploy the Istio Gateway resource which listens on any "host" but specifically on port 80 for HTTP protocol. This way, requests targeted towards the WireMock server are directed to the Kubernetes Service.
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: wiremock-gateway
spec:
selector:
istio: ingressgateway # Use the Istio default ingress gateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*" # Allow all hosts for this example; you can specify your domain here if needed
EOF
Next, we can apply the Virtual Service resource in Istio, which simply uses the previous Istio Gateway resource we deployed, and just specifically tells us which K8s service we're routing to and which port (8080 in this case.)
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: wiremock
spec:
hosts:
- "*" # Match all hosts for this example; you can specify your domain here if needed
gateways:
- wiremock-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
host: wiremock # This is the Kubernetes Service you defined for WireMock
port:
number: 8080 # This is the port your WireMock service runs on
EOF
Once, you've applied these commands, you'll need the Public IP or External Address for the Istio Ingress Gateway. You can run the following to capture the external IP:
kubectl get svc -n istio-system
And you'll proceed to see an EXTERNAL-IP
assigned to the Istio Ingress Gateway. (see below)
marino@mwlinux02:~/k8s_examples/4-WireMock-on-K8s$ kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istiod ClusterIP 10.43.173.99 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 175m
istio-egressgateway ClusterIP 10.43.150.118 <none> 80/TCP,443/TCP 175m
istio-ingressgateway LoadBalancer 10.43.5.177 <YOUR-PUBLIC-IP> 15021:31823/TCP,80:31347/TCP,443:31965/TCP,31400:31225/TCP,15443:31137/TCP 175m
Testing WireMock Stub Responses through the Istio Ingress Gateway
Now that you have the EXTERNAL-IP
, create the WireMock stub by saving this as stub.json
{
"request": {
"method": "GET",
"url": "/hello-stub"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "{\"message\": \"Hello, This is WireMock on K8s with Istio!\"}"
}
}
Next, we need to add the stub to WireMock using stub.json w/ curl, and you'll need to replace the <external-ip-from-istio-ingress>
with your IP. By issuing the command below, you'll run the HTTP POST
method to add the stub to WireMock. If all's good, you should get a 200 Success code
stating that the POST
was successful.
curl -X POST -d @stub.json --header "Content-Type: application/json" http://<external-ip-from-istio-ingress>/__admin/mappings
Now! We can test curl
against the WireMock stub to see the response:
curl http://<external-ip-from-istio-ingress>/hello-stub
AND THE RESULT!
marino@mwlinux02:~/k8s_examples/4-WireMock-on-K8s$ curl http://<replace-with-your-external-ip>/hello-stub
{"message": "Hello, This is WireMock on K8s with Istio!"}
Wrapping up
Being able to test your API is a very powerful feature both Developers and Platform Engineers can appreciate, especially before deploying to production. While many organizations have the flexibility to choose (and possibly build) their internal developer platforms, it's undeniable that Kubernetes, Istio, and WireMock are puzzle pieces that complete the story of Platform Operations.
In this blog post, we deployed Istio to a Civo Kubernetes cluster, deployed a WireMock deployment and service manifest for Kubernetes, exposed this through the Istio Ingress Gateway, and loaded in a test stub to test out functionality. We then verified that the WireMock HTTP Server returned our expected response. Quite powerful!
In the next blog post, we will use all of this together to do some chaos testing and prove how WireMock can allow us to profile our APIs and give us a baseline for expected operation, which can then be moved to production!
Ready to take your stubbing to the next level? Head over to WireMock.org for more details. Also, feel free to join the WireMock community in Slack and follow them on Twitter!
Looking for something beyond open source like a hosted solution, and user interface for a quick and easy start? Check out WireMock Cloud!!!
Want to get meshy with Service Mesh, Kubernetes and Istio? Head over to Istio.io!
Thanks for reading :)