Using an Istio gateway to access a Spring Boot application in minikube

Posted on Oct 11, 2022
Note: This article was written a while ago and may contain outdated information. Please verify the details before relying on it. If I express opinions or recommendations, they might not reflect my current views. For this reason, I recommend checking for more recent articles on the same topic.

In the last days I was trying to run and experiment with Istio. I followed the getting started guide by Istio itself, but I couldn’t make it run with kind. I followed some guides, but I didn’t want to install explicitly an nginx ingress, because I like it when things are as lightweight as possible when I’m learning new stuff.

So here’s a guide how to run a Spring Boot application and access it through an Istio Gateway.

Setting up the environment

To follow this guide, you need an installation of kubectl. The other needed tools will be installed in the following steps.

Install and set up minikube

Install minikube:

  1. Download the latest release.
  2. Copy the release to a directory (like C:\minikube).
  3. Execute the minikube command to assure that it runs.
  4. Start a minikube cluster: minikube start
  5. Execute kubectl get pods --all-namespaces to assure that the command runs against your cluster.
  6. Allow the invocation of the docker command: minikube -p minikube docker-env --shell powershell | Invoke-Expression. From now on, every docker command in this window will be executed against your minikube.
  7. In a new CLI window execute the following command to open up access to your ingress in the minikube instance: minikube tunnel

Install istioctl

  1. Download the latest istioctl release.
  2. Install the istioctl CLI tool.

Install istio in Kubernetes cluster

Now you are ready to bring Istio into your Kubernetes cluster!

  1. Install istioctl with profile demo in the cluster:
istioctl install --set profile=demo -y
  1. Verify it via the following command:
kubectl get pods --all-namespaces

The output should be something like the following:

NAMESPACE            NAME                                           READY   STATUS    RESTARTS      AGE
istio-system         istio-egressgateway-7984f88c64-9hrmx           1/1     Running   0             4m47s
istio-system         istio-ingressgateway-57988c96c4-g9d7m          1/1     Running   0             4m47s
istio-system         istiod-7d5c56bcbf-v9dpb                        1/1     Running   0             5m3s
  1. For our experiment we’ll use the namespace sidecar-test.

Create the namespace:

kubectl create namespace sidecar-test
  1. Add a label to allow Istio to auto-inject an Envoy sidecar proxy to your Pods in the sidecar-test namespace:
kubectl label namespace sidecar-test istio-injection=enabled

Set up the application

Now it’s time to set up the application. I’ll not make stuff with 2 or more services, as I want a basic setup as a starting point for further experiments.

So, create a basic Spring Boot application with a RestController and /books route. You can also use any other application with this route. Just make sure, that the following steps are granted:

  1. Initialize your Spring Boot application
  2. Create the controller:
package de.dkwr.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@org.springframework.web.bind.annotation.RestController
@RequestMapping("books")
public class RestController {
    @GetMapping()
    public String getBook() {
        return "Hello world!";
    }
}
  1. Configure the application to run on Port 8080 (this is the default port for a Spring Boot application)
  2. Build a Docker image with the following Dockerfile:
FROM openjdk:17

COPY ./build/libs/demo-0.0.1-SNAPSHOT.jar ./src/

WORKDIR /src

CMD ["java", "-jar", "./demo-0.0.1-SNAPSHOT.jar"]

And the following command:

docker build . -t demo-v1:latest

Run the application in the cluster

Now you have a cluster, a running istio daemon and a docker image of an application, waiting to be deployed in your cluster. Let’s do this!

Create the Kubernetes resource files:

service.yml:

apiVersion: v1
kind: Service
metadata:
  name: demo
  namespace: sidecar-test
spec:
  ports:
    - port: 8080
      name: http
  selector:
    app: demo

deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
  namespace: sidecar-test
spec:
  revisionHistoryLimit: 3
  replicas: 1
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
        - name: demo
          image: demo-v1:latest
          imagePullPolicy: Never
          ports:
            - containerPort: 8080

Apply the files:

kubectl apply -f service.yml
kubectl apply -f deployment.yml

Check that the pod is running:

kubectl get pods -n sidecar-test

And that the route is available:

kubectl exec "$(kubectl get pod -l app=demo -n sidecar-test -o jsonpath='{.items[0].metadata.name}')" -c demo -n sidecar-test -- curl -sS demo:8080/books

This should output Hello world!

But we want to make it available through the Istio ingress gateway. So let’s define it:

gw.yml:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: demo-gateway
  namespace: sidecar-test
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: demo
  namespace: sidecar-test
spec:
  hosts:
    - "*"
  gateways:
    - demo-gateway
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: demo
            port:
              number: 8080

The gateway is called demo-gateway. We apply a VirtualService resource to which can be accessed through any host. Every route will be routed to the demo application.

Access the application

Now you can access http://localhost/books in your browser.

Conclusion

Here I showed you how to do a very basic setup of Istio on your local machine with minikube. If you want to try it out, you can also use kind, but I don’t recommend it, as you don’t have an external LoadBalancer.

I hope that one day I can make a post with advanced topics on this. There are also some other challenges, like using it with different services, mesh them up, setup security sidecars and use different hosts.

But that’s it, so far!

Want to know more?

Keep on reading and choose one of the related articles. You can also check the home page for my latest thoughts, notes and articles.