Isotope Mail: How to deploy Isotope+Traefik into Kubernetes


Introduction

Isotope mail client is a free open source webmail application and one of the side projects in which I invested my spare time during the last year. You can read more about Isotope’s features in a previous blog post.

Although there is still no official release, the application is quite stable and usable. In this post, I will show you how to deploy the application to a Kubernetes cluster. For the purpose of the tutorial I’ve used minikube + kubectl, but the same steps should be reproducible in a real K8s cluster.

Traefik v1

Despite it’s not part of the implementation, Traefik (or any other alternative) is one of the main pieces of the deployment as it will act as the API gateway (reverse-proxy) and route the requests to the appropriate Isotope component/service.

The first step is to create an Ingress controller for Traefik (if there isn’t any in the cluster yet). We will follow Traefik’s official documentation to create the new Ingress controller.

Role Based Access Control configuration (Kubernetes 1.6+ only)

Starting from 1.6 Kubernetes has introduced Role Based Access Control (RBAC) to allow more granular access control to resources based on the roles of individual users.

In order to allow Traefik to access global Kubernetes API, it’s necessary to create a ClusterRole and a ClusterRoleBinding.

traefik.rbac.yaml

Kubectl Isotope Traefik RBAC

Deploy Traefik using a DaemonSet

The next step is to deploy Traefik ingress controller using a DaemonSet.

If you follow Traefik’s official documentation, you’ll see you can also achieve this using a Deployment. For the sake of this tutorial and as we are using Minikube, we will use a DaemonSet because it’s easier to configure and to expose with Minikube (Minikube has problems to assign external IPs to ingresses using Traefik ingress controller deployed using a Deployment).

traefik.ds.yaml

Kubectl Isotope Traefik DaemonSet

Traefik UI

We can optionally create a Service and Ingress for the Traefik web UI dashboard in order to monitor the new Traefik DaemonSet deployment.

traefik.ui.yaml

Kubectl Isotope Traefik web UI

It’s important to note that for the Ingress configuration we are using traefik-ui.minikube as the public host. In a production environment, we would add a real hostname. An additional required step is to add the Kubernetes cluster IP (minikube ip / kubectl get ingress) into our local hosts file (/etc/hosts).

Finally, we can point our browser to traefik-ui.minikube to load Traefik’s dashboard.

Traefik Web UI Dashboard

Isotope

The last step is to deploy Isotope.

isotope.yaml

Kubectl Isotope Mail Client

Secret

The first entry in the Yaml configuration is a Kubernetes Base64 encoded secret that will be used to set the encryption symmetric key in Isotope Server component.

Isotope Server Deployment

The next entry is the Deployment configuration for the Isotope Server component. As this deployment is more complex than the Client Deployment, basic common configurations for both components will be described in the next section (Isotope Client Deployment).

In the env section, we’re declaring the ENCRYPTION_PASSWORD environment variable and assigning it the value of the Secret we declared in the previous step. This variable will be available to all Pods created by Kubernetes from this Deployment configuration, thus, all Pods will share the same encryption key and will be compatible.

We’re also defining two different probes so that Traefik and Kubernetes know when the Isotope Server Pods are ready and traffic can be routed to them. Liveness probe will be used to determine if the container is still alive. Otherwise, Kubernetes will restart the Pod as the application state is considered to be broken. We’re also using the initialDelaySeconds because the application takes a couple of seconds to spin up and this way we’ll avoid false positives for the probe. If your Kubernetes version supports it, it’s better to define a startup probe instead of this initialDelaySeconds.

A readiness probe is also defined in this section. This probe is similar to the liveness probe and will be used to indicate if the application is ready to receive traffic. If for some reason the application is temporarily not admitting traffic (max number of connections, etc.) the probe will set the application “down” but Kubernetes will not restart it.

For both probes, we’re using an HTTP request pointing to Spring Actuator’s health check endpoint which is available in Isotope Server component.

Isotope Client Deployment

Same as we did for the Server component, we’re now defining a Deployment for Isotope’s Client component.

In the spec section we’re defining the number of replicas we want for our Pods, in this case, one. The selector property, although optional in previous API versions, is now mandatory and will be used by Kuberentes to determine the number of Pods actually running to spin up more replicas if necessary (they should match the labels in the template section).

The template entry within the spec section is used to define the Pod specifications. For Isotope Client we’re defining a Pod with a single container based on marcnuri/isotope:client-latest Docker image exposing Http port.

As with the Isotope Server deployment, we define a simple liveness probe in case the Pod becomes unstable and reaches a broken state so that Kubernetes will automatically restart it.

Services

The next section in the configuration defines a Service for each of the previous deployments (server/client) in order to expose them to the cluster.

To ease the Ingress definition in further steps, both Services will expose Http port (80).

Ingress

The final section of the configuration defines an Ingress using the Ingress controller deployed in the first steps of the tutorial.

We are going to use isotope.minikube as the public host, although in a production environment we should use a valid and real hostname. We will also need to add an additional entry in our /etc/hosts file.

Traffic reaching http://isotope.minikube/api will be routed by Traefik to isotope-server service, traffic reaching http://isotope.minikube/ will be routed to isotope-client service.

The use of traefik.frontend.rule.type: PathPrefixStrip configuration will remove /api from the requests to isotope-server service, this way, no additional modifications or configurations will be necessary for Isotope Server component to be compatible with our deployment.

Traefik dashboard with Isotope

Once Isotope configuration is deployed, Traefik dashboard will automatically update and display the new routes for Isotope.

Traefik Dashboard with Isotop

Isotope deployment

If everything went OK and Traefik dashboards display healthy Isotope components, we can now point our browser to http://isotope.minikube where Isotope will be ready and accessible.

Isotope in Kuberentes

Isotope + Kuberentes

Leave a comment

Your email address will not be published. Required fields are marked *