16

I am evaluating building microservices using Spring Boot and Spring Cloud (Zuul and Eureka) running in separate docker containers, deployed in separate Amazon EC2 instances.

I have a simple REST service that registers with Eureka, and have configured Zuul to route requests to this service by looking it up in Eureka. enter image description here

I can get this to work running locally (i.e. not in Amazon/EC2) on my Mac using boot2docker, but when deployed on EC2, Zuul cannot find the service, and reports a 'Forwarding error' (status 500).

In EC2, everything is configured to run on port 80 (just while evaluating so I can easily access through our firewall). I can see both Zuul and my service in the Eureka system status page (although none of the links work!).

The clients are configured to find Eureka with a full AWS domain name, so I can see how they find Eureka OK. e.g.

  client:
    serviceUrl:
      defaultZone: http://ec2-XX-XX-XX-XX.ap-southeast-2.compute.amazonaws.com:80/eureka/,http://ec2-YY-YY-YY-YY.ap-southeast-2.compute.amazonaws.com:80/eureka/

But, the clients seem to be registering themselves with their internal docker IP address (based on the Eureka system status links).

enter image description here

The edgeserver link points to http://172.17.0.2/info The trialservice link points to http://172.17.0.3/info

I'm guessing this is incorrect and that other EC2 instances don't know to get to this address.

I've read this page https://github.com/Netflix/eureka/wiki/Configuring-Eureka-in-AWS-Cloud which suggests using AWS EC2 Elastic IP addresses, but I was hoping I wouldn't have to do this.

I've also seen there is a current discussion around this subject here, https://github.com/spring-cloud/spring-cloud-netflix/issues/432

Has anyone managed to get this type of setup working, and if so, how did they configure the Eureka properties?

Rob
  • 1,037
  • 1
  • 13
  • 20
  • I am working on exactly the same problem now. Not sure of the answer or workaround at the moment. If you find something please update here. I will do the same. – code Aug 05 '15 at 07:08

1 Answers1

19

OK, to answer my own question, I've found a solution. It basically involves configuring eureka to use the hostname and docker to use the net=host option.

Here is my setup (just showing setup for one availability zone):

application.yml:

Zuul:   
    spring:
      profiles: aws         
    server:
      port: 80          
    eureka:
      datacenter: cloud
      instance:
        preferIpAddress: false
      client:
        serviceUrl:
          defaultZone: http://ec2-XX-XX-XX-XX.ap-southeast-2.compute.amazonaws.com:80/eureka/

Eureka:
    spring:
      profiles: aws-discoA          
    server:
      port: 80          
    eureka:
      instance:
        preferIpAddress: false
      datacenter: cloud
      enableSelfPreservation: false
      client:
        name: eureka
        preferSameZone: false
        shouldOnDemandUpdateStatusChange: false
        region: default
        serviceUrl:
          defaultZone: http://ec2-YY-YY-YY-YY.ap-southeast-2.compute.amazonaws.com:80/eureka/

Service:
    spring:
      profiles: aws
    server:
      port: 0 # or 80 if there is only 1 service/docker in this EC2
    eureka:
      datacenter: cloud
      instance:
        preferIpAddress: false
      client:
        serviceUrl:
          defaultZone: http://ec2-XX-XX-XX-XX.ap-southeast-2.compute.amazonaws.com:80/eureka/

I'm not sure if "datacenter: cloud" is needed?

Then to launch each:

Zuul

    sudo docker run -d --name edge -e JAVA_TOOL_OPTIONS="-Dspring.profiles.active=aws -Deureka.instance.hostname=$HOSTNAME" --net="host" edge

Eureka

    sudo docker run -d --name discovery -e JAVA_TOOL_OPTIONS="-Dspring.profiles.active=aws-discoA -Deureka.instance.hostname=$HOSTNAME" --net="host" discovery

Service

    sudo docker run -d --name service -e JAVA_TOOL_OPTIONS="-Dspring.profiles.active=aws -Deureka.instance.hostname=$HOSTNAME" --net="host" service

Just to ensure this works in a more complex setup, I configured more servers, some with multiple dockers per EC2 and now have the following setup.

enter image description here

This setup is duplicated in two availability zones with a load balancer in front of the Zuul servers. Each service has an endpoint that just returns its name, hostname, port and the number of times it has been called.

I can then hit the load balancer and see each service being called as the AWS load balancer and Ribbon load balancers cycle through the services.

Rob
  • 1,037
  • 1
  • 13
  • 20
  • Hi, I'm looking into Zuul for Microservice authentication and authorization. How did, if at all, did you secure your services? – Abhijit Sarkar Dec 24 '15 at 02:37
  • This should probably be a separate question, but this link is a great tutorial on the subject: https://spring.io/guides/tutorials/spring-security-and-angular-js/ – odedia Mar 07 '16 at 18:14
  • Hi Rob, I tried this approach and it works fine the way you have described it. But when I try to implement it in Docker swarm I am facing issue. I am running zuul and service container as docker service. My zuul service is giving error of unknown host exception. Any suggestions? – sanjaykumar81 Sep 11 '17 at 05:27