Our solution to microservices

After researching and reading on Microservices I reached the conclusion that everyone does it differently. There’s still no standard for this. There are some best practices but not enough that we can just implement everything without spending time researching. And like I was saying, after loads of research this is what we came up with.

Our first step was to decide where to start. We chose 3 very simple endpoints of our API to split into a microservice. This service needs to be able to self deploy to our kubernetes cluster into the UAT and production environments.

Setting this up is simple. We make the service work and then create a Deployment and a Service objects in Kubernetes, like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: microservice-1
name: microservice-1
spec:
template:
metadata:
labels:
app: microservice-1
spec:
containers:
- image: attentive/microservice-1
name: microservice-1
ports:
- containerPort: 8001
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
labels:
app: microservice-1
name: microservice-1
spec:
externalTrafficPolicy: Cluster
selector:
app: microservice-1
ports:
- name: http
port: 8001

This is the easy part. Now comes the hard one. We’re using Digital Ocean so we don’t have access to the LoadBalancer service type in Kubernetes. This means we can either use DigitalOcean’s Load Balancers or we can try to run our own load balancer inside Kubernetes. After checking out the possibilities we started using Traefik. Traefik uses Kubernete’s Ingress object and integrates with Let’s Encrypt. So after configuring Traefik (which was a small challenge on its own) we have the following Ingress configuration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: attentive
spec:
rules:
- host: api.attentive.us
http:
paths:
- backend:
serviceName: microservice-1
servicePort: 8002
path: /users/
- backend:
serviceName: microservice-2
servicePort: 8001
path: /deals/
- backend:
serviceName: microservice-3
servicePort: 8003
path: /pipelines/
- host: app.attentive.us
http:
paths:
- backend:
serviceName: frontend-service
servicePort: 80
path: /

All of our traffic now gets routed to the correct service without us needing to have an nginx filled with proxy passes. All of this with the added bonus of getting automagic valid SSL certs for every domain we add to the YAML.

It took some time to reach this setup but at this point I’m very confortable with it.

If you want to know more or have any questions on any of this email me. I’ll be more than happy to help.