Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I configure Spring Cloud with Netflix Zuul and Eureka in a Docker contained in an EC2 instance

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?

like image 702
Rob Avatar asked Aug 03 '15 04:08

Rob


People also ask

How does Zuul work with Eureka?

Each request received by Zuul is forwarded to a different instance in a round robin fashion. If we start another instance and register it in Eureka, Zuul will register it automatically and start forwarding requests to it: Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8083'!

What is Netflix Zuul and Eureka?

Zuul acts as the API gateway, providing a uniform, single point of entry into the set of microservices, while Eureka is essentially used as a “meta data” transport. Each client application instance (read microservice) registers its instance information (location, port, etc.) with the Eureka server.

How configure Zuul API gateway in spring boot?

Creating Zuul Server ApplicationAdd the @EnableZuulProxy annotation on your main Spring Boot application. The @EnableZuulProxy annotation is used to make your Spring Boot application act as a Zuul Proxy server. You will have to add the Spring Cloud Starter Zuul dependency in our build configuration file.


1 Answers

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.

like image 126
Rob Avatar answered Sep 29 '22 20:09

Rob