A DeepDive Into Testing WireMock On K8s With Istio

A DeepDive Into Testing WireMock On K8s With Istio

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

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 :)