Spring Cloud with Spring Config and Eureka in high availability using docker swarm

Spring Cloud and Netflix stack is awesome, it is easy to setup by using several annotations everything just snaps into place. All of the microservices patterns like auto discovery, centralized configuration, centralized logging , autoscaling are solved and ready to be used.

In this post I will show you how to use this tools and deploy them to your docker swarm in a highly available way. First I will show you how to have Eureka in a high available way using two instances that talk to each other. Then I will show you how to have Spring Remote Config scaled to 3 instances and of course client app that talks with Eureka and Spring config is gong to be scaled to 3 as well. Docker swarm is going to be deployed to 3 virtual machines.

Before we start let me turn your attention to some other posts that you might read before you jump into serious stuff ūüôā

In the previous post I wrote about Spring Remote Config  and shown how to leverage different profiles of spring config like native, git and vault. Then some time ago I wrote about docker swarm that is deployed to 3 machines and have scaled nginx.

Spring Remote Config

In this example I wanted to setup remote config that loads configuration from my GitHub account . You can check the configurations out is is fairly simple.   To set this up I have created one spring boot app using next dependencies :

First is important so that we can have config server and other is so that we can protect it and restrict access in a easy way. ( you should however use better security mechanism for your production system but for a demonstration this is secure enough).

Main Class of the spring boot is really simple, it just has @EnableConfigServce annotation that creates all the magic.

There is one application.properties file with few basic properties like application name, basic auth user name and password, along with profile and url to my GitHub repository.

I will explain all of the files located in this repository latter.

Eureka Server

As you probably know Eureka server acts as a registry and allows all clients to register them selves and be able to find ip address and port of other services if they want to talk to. Eureka server is a client as well. This property is used to setup Eureka in highly available way.

Dependencies for the Eureka Server are:

Config starter is required because Eureka loads all configuration from the remote config, and security is here so that we can restrict access.

Spring Boot main class is simpleit just has @EnableEurekaServer annotation that creates all the magic.

We are going to have Eureka deployed in a highly available way ( using two Eureka instances, we can have more if we want to using same pattern). First instance is going to have name eureka and second is going to be called eureka-backup so that we easily understand who is who in the docker swarm and that two eureka instances can talk to each other. Both instances are going to have their own configurations.

eureka.properties

eureka-backup.properties

Observe that both instances have same username and password, ports are different and both instances know how to talk to each other because serviceUrl points to the other instance with username and password written into the URL. This is all it takes to setup eureka into highly available way.

I have disabled selfPreservation, here is a good explanation of how this works here.

How is eureka going to know where is config server located ?

For this we have bootstrap.properties file with next content:

http://config:8888 is the address of the config service that runs in the docker swarm in the same network.

Spring Boot Client

In this example we are going to have one client, in a real case we can have 100 or even more small microservices that use remote config server to load configuration from, but the principal is the same.

Client is going to be a simple web application with next dependencies:

We need actuator so that we can execute http POST request to /refresh and refresh the configuration.

We need config so that application can load the configuration from remote configuration server.

We need eureka to register the client.

Finally we need web so that app can be web application :).

Spring boot main class is :

There are few annotations

  • @RefreshScope, used to tell spring to refresh the bean instance when we hit /refresh mentioned above so that property response is refreshed
  • @EnableEurekaClient, used to enable eureka client and register the app to eureka server.

You can find all of the code HERE on my git hub account.

In the next section I show you how to

  • dockerize apps
  • prepare docker swarm using 3 virtual machines
  • build docker images
  • spin up images into containers with initial scaling
  • and show you how to manage docker swarm using portainer.io as a client.

App Dockerization

What I want is to deploy this three applications to docker swarm, to make this possible I need to create docker image out of every project.

Creating docker image from a spring boot project is a fairly simple task using a maven plugin that is added into the pom.xml.

Additionally you need to add property docker.image.prefix

Plugin will create an image named springio/eureka for example. Optionally you can push the image into the image repository.

Docker image can not be created without a blueprint. Instructions on how to build an image are located in file Dockerfile located on path /src/main/docker/Dockerfile . Here is the content of the standard Dockerfile.

Observe the third line ADD config-0.0.1-SNAPSHOT.jar app.jar , this line adds the self executable jar file into the docker image. It is important to notice that you need to set jar name properly in order to make it work.

You can alter the command to work with any name of the jar.

Once we have project setuped all that is left is to execute the command and create an image:

If you run this in all of your projects you will have 3 images created for you. Here is a handy script for you to make this work. Go to the root of the project and execute:

Execute docker images ls to verify.

This is the end of the dockerization of the images, in next section I will create docker swarm and start those apps.

Docker Swarm

To get started with docker swarm I advise that you read the post , this will help you get going with docker swarm using docker-machine. There I have used macOS to set all up.

Here I will just list the commands that will

  • create three docker-machines
  • initialize swarm with manager
  • join two workers machines
  • start 4 services and setup scaling for each service
Create docker machines

First I will create 3 docker machines using names manager, worker1 and worker2. Their name will represent their role in the swarm.

To validate that docker machines are created execute next command

Pay attention to the ip of the manager as you will need to know the address in the next section.

Initialize swarm

To initialize swarm properly you should have advertise-addr set as the manager IP address.

Create Network for docker

What we want is to allow containers to reference each other using their names. To make this happen I will create one network using overlay driver using next command:

Docker Services

Creating docker swarm is not enough we need to tell docker what services are going to be executed in the swarm. To create a services we need a number of parameters :

  • number of replicas
  • name of the service
  • reserve-memory
  • published ports
  • update-delay
  • network
  • image

Now lets create all required services.

Config Service

Eureka and Eureka-backup service

Observe that both services are using same image springio/eureka but different application name is being passed to the service. This allows gives us good leverage to use one image and have multiple configurations for each of the Eureka instances.

Client Service

Monitoring docker swarm

We need a way to monitor and manage a docker swarm, for this Portainer is used. To create a portainer service use :

Visit the url http://192.168.99.102:9000/ , setup the initial password and you are ready to go.

What did we do so far?

First we have created a 3 maven projects for

  • Eureka
  • Spring config, with git reporitory
  • Client app

Then we have built all of the apps creating 3 images and have prepared the docker swarm. In docker swarm we have created 4 services , two for eureka so that we have high availability, one for spring config and client.

After we have started all of the containers we opened the portainer to mange the docker swarm. Here we can manage secrets, view nodes and update services among other things.

Where to go next?

There are number of things you can do, first you can use docker secrets to pass the username and password of the config server. You can also use some other authentication mechanism for your apps…

In order to build an application with high number of microservices auto refreshing the configurations is a must. For this you will need to add spring cloud bus and rabbitMQ…

Related GitHub repository :

https://github.com/savicprvoslav/spring-cloud-config-eureka-docker