Netflix Eureka Server and Client instance registration issue with Docker swarm - spring

We are trying to deploy Netflix Eureka Server on Docker container which is a Spring Boot application. We are deploying it as a docker service with Docker swarm for container orchestration.
Everything works fine when we directly create the container and run the application.
Eureka server registers all the client application with correct IP addresses.
But when we create and deploy it as docker service it registers the application with the wrong IP address.
We have tried below solution as per spring documentation, updated property values in our configuration files.
spring:
cloud:
inetutils:
ignoredInterfaces:
- docker0
- veth.*
eureka:
instance:
preferIpAddress: true
Tried these solutions as well:
https://github.com/spring-cloud/spring-cloud-netflix/issues/1820
https://github.com/spring-cloud/spring-cloud-netflix/issues/2084
While we run the docker service, the container gets assigned one IP address lets say 172.16.1.3 and service started inside docker gets assigned new IP address 172.16.1.4, because of this issue client application registers its self with container's IP into Eureka server. But it is accessible with 172.16.1.4.
So why running docker as service assigns two IP addresses?
Here Eureka server is running on 10.255.53.172 IP address but as we can see in the second image it shows different IP in Instance Info
Eureka instance is registered with containers IP but it's accessible with its service IP in the network

We use this configuration on production using docker swarm mode:
Eureka server configuration
# Defines the Eureka server that is used by the Netflix OSS components to use as the registry
# for server discovery
eureka:
instance:
hostname: ${HOST_NAME:localhost}
appname: eureka-cluster
# enable to register multiple app instances with a random server port
instance-id: ${spring.application.name}:${random.uuid}
leaseRenewalIntervalInSeconds: 10
leaseExpirationDurationInSeconds: 20
Eureka client configuration
eureka:
client:
registerWithEureka: ${REGISTER_WITH_EUREKA:true}
fetchRegistry: ${FETCH_REGISTRY:false}
serviceUrl:
defaultZone: ${EUREKA_DEFAULT_ZONE:http://localhost:8761/eureka/}
instance:
hostname: ${HOST_NAME:${spring.application.name}} # work on swarm
preferIpAddress: ${PREFER_IP_ADDRESS:false}
# enable to register multiple app instances with a random server port
instance-id: ${spring.application.name}:${random.uuid}
leaseRenewalIntervalInSeconds: ${LEASE_RENEWAL_INTERVAl_IN_SECONDS:10}
leaseExpirationDurationInSeconds: ${LEASE_EXPIRATION_DURATIONIN_SECONDS:20}
ON swarm service definition
rd-service:
image: my-eureka-server-microservice-image
ports:
- "8763:8763"
networks:
- backend
client-service:
image: my-eureka-client-microservice-image
networks:
- backend
networks:
environment:
- "EUREKA_DEFAULT_ZONE=http://rd-service:8763/eureka"
- "REGISTER_WITH_EUREKA=true"
- "FETCH_REGISTRY=true"
networks:
backend:
external: true
Important: Services must be in the same docker overlay network used on eureka server docker service.

Related

Api Gateway adding "localhost" to address on docker-compose

I'm trying to deploy SpringBoot microservices using docker-compose but I'm having a problem with API Gateway.
If I run the project locally it works ok, even if I deploy project using docker-compose but API Gateway locally, it works ok, so problem has to be "dockerizing" the API Gateway service.
Doing docker logs <container> it shows:
io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: localhost/127.0.0.1:8083
Is obvious there is a problem on host localhost/127.0.0.1. Why Gateway is trying to point a "repeated" address?.
docker-compose.yml looks like this:
version: '3.8'
services:
# more services
api-gateway:
build: ./path_to_dockerfile
depends_on:
- eureka-server
environment:
- eureka.client.serviceUrl.defaultZone=http://eureka-server:8761/eureka/
restart: always
container_name: gateway
ports:
- '9000:9000'
Dockerfile is as simple as this
FROM openjdk:8-jdk-alpine
ADD target/apigateway-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
And application.yml:
server:
port: 9000
spring:
application:
name: Api-Gateway-Service
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_UNIQUE
globalcors:
# cors config
routes:
- id: <name>-microservice
uri: http://localhost:8083
predicates:
- Path=/<path>/**
- Method=GET,POST,DELETE,PUT,OPTIONS
# more routes on different ports
eureka:
# eureka config
So, why is adding "localhost" or "127.0.0.1" and calling twice?
Thanks in advance.
I don't think Connection refused: localhost/127.0.0.1:8083 means that it was trying to add or call localhost twice. It is just the way it shows the error.
In your application.yml, try changing uri to the name you used for your microservice inside docker-compose file.
routes:
- id: <name>-microservice
uri: <YOUR_SERVICE_NAME>
I guess the problem is that docker doesn't support network communication between containers by default. You can connect to the 8083 port from your host but not another container. If so, you should create a network and contact the container and network.

Consul share network from docker

There is consul server in docker.
vote-consul-server:
image: consul:1.7.2
environment:
CONSUL_BIND_INTERFACE: eth0
ports:
- "${CONSUL_PORT}:8500"
It generates hosts for registred applications.
The main problem is that anothers applications can't communicate between each other if they are not in docker.
For example: I have config-service (docker with consul), user-service(IDE).
When user-service starts, it asks for configurations from config-server, but consul gives not correct link (available only in docker network).
c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://83a6c7ab12d0:8888/
How to publish all links from consul(docker)?
Since every container has own IP and may have own network, you can try to use host networking:
docker run --rm -d --network host --name vote-consul-server
For more details, see host networking tutorial.
Also, you can learn about networking from the container’s point of view
First of all - need to define IP address configuration in bootstrap.yaml
spring:
...
cloud:
consul:
host: ${CONSUL_HOST}
port: ${CONSUL_PORT}
discovery:
ip-address: ${CONSUL_HOST}
prefer-ip-address: true
The main properties are: ip-address and prefer-ip-address.
If all aplications work in one network - problem doesn't exist.
For example: all services work in docker.

Dockerized Spring boot and Zuul

I got troubles get Zuul working with a dockerized Spring boot app.
It seems Zuul is not able to proxy requests to the target application (gis_import_export) even if it is up and running.
My Zuul based Spring app configuration:
spring:
banner:
location: classpath:banner.txt
zuul:
debug:
request: true
routes:
ie:
url: http://gis_import_export:8080
geoserver:
url: http://geoserver:8080
geonetwork:
url: http://geonetwork:8080
ribbon:
eureka:
enabled: false
and my docker-compose.yml file:
version: "3"
services:
geoserver:
image: kartoza/geoserver
geonetwork:
image: geonetwork
postgres:
image: postgres
environment:
- POSTGRES_DB=xxx
- POSTGRES_PASSWORD=xxx
- POSTGRES_USER=xxx
gis_import_export:
image: gis_import_export:develop
ports:
- 8888:8080
zuul:
image: gis_api_gateway:develop
ports:
- 8080:8080
I'm able to have geonetwork/geoserver proxied correctly via Zuul service exposed port but I'm stuck with getting with Spring boot app seems not get proxied.
By the way, the dockerized Spring boot apps works as expected if accessed via the 8888 port and via Zuul if zuul itself is not deployed via Docker.
Running a ping/telnet to dockerized spring boot app inside the Zuul docker container works as expected, so names are being resolved correctly.
Ideas?
Thanks, FB
Your services running in different docker networkds.
You have to specify same network in two files network.
And of course it will be good if you specify hostname parameter for each container

Spring Cloud Netflix and Docker Compose - cannot register services with eureka

I'm trying to use docker-compose to run 2 simple services locally (Ubuntu): a eureka server, and config server (which is also a eureka client). Both of these have simple dockerfiles that run java -jar, expose their ports, and individually work fine. I also tried to add eureka.client.service-url.defaultZone=http://company-service-discovery:8761/eureka to see if it would register itself, and it worked.
My config server cannot successfully register to the eureka server, and I've googled it and nothing I've seen helped me solve this.
According to docker-compose documentation at https://docs.docker.com/compose/networking/ :
By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
With the following example web should be able to use postgres://db:5432 to communicate with the database.
version: "3"
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
ports:
- "8001:5432"
I have used the same method to configure my services, but my config server gets connection refused when trying to register:
docker-compose.yml
version: '3.3'
services:
company-service-discovery:
build: company-service-discovery/
ports:
- "8761:8761"
company-config-server:
build: company-config-server/
ports:
- "8888:8888"
links:
- company-service-discovery
config server bootstrap.yml
server:
port: 8888
management:
security:
enabled: false
spring:
application:
name: company-config-server
cloud:
config:
server:
native:
search-locations: classpath:/shared
profiles:
include: native
eureka:
client:
service-url:
defaultZone: http://company-service-discovery:8761/eureka
eureka server bootstrap.yml
spring:
application:
name: company-service-discovery
server:
port: 8761
management:
security:
enabled: false
exception
2017-07-26 14:25:05.738 WARN 1 --- [nfoReplicator-0] c.n.d.s.t.d.RetryableEurekaHttpClient : Request execution failed with message: java.net.ConnectException: Connection refused (Connection refused)
2017-07-26 14:25:05.739 WARN 1 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_COMPANY-CONFIG-SERVER/365d20275ab0:company-config-server:8888 - registration failed Cannot execute request on any known server
question
Is there anything wrong with my configuration ? How can I make it work ?
Let me know if there's any info missing, I'll gladly give any info I can.
Add the defaultZone configuration to the Eureka server's properties too (and change the service-url to serviceUrl in your config server bootstrap.yml).
eureka server bootstrap.yml
spring:
application:
name: company-service-discovery
eureka:
client:
serviceUrl:
defaultZone: http://company-service-discovery:8761/eureka
server:
port: 8761
management:
security:
enabled: false
Thank you sooo much. this post resolved my problem - connecting eureka client to eureka server with docker. After 2 days of searching it work. I am in tears.
So basically -
you should use following in eureka client's application.properties/.yml
eureka.client.service-url.defaultZone=http://eureka-server:8761/eureka
and in docker-compose.yml your eureka service name should match with - the url host name, in my case it is - eureka-server

How to config spring cloud oauth2 in docker container

I met some problems with micro-spring-docker , i think maybe the sso token-url is not correct.
The demo https://github.com/keryhu/micro-oauth2-docker
In local computer , sso service and auth-service works fine .
But not in docker container ,
the problem is that redirecting to auth-server Timeout .
SSO(pc-gateway service) application.yml:
security:
user:
password: none
oauth2:
client:
accessTokenUri: http://${AUTHSERVER_PORT_9999_TCP_ADDR:localhost}:9999/uaa/oauth/token
userAuthorizationUri: http://${AUTHSERVER_PORT_9999_TCP_ADDR:localhost}:9999/uaa/oauth/authorize
docker-compose.yml
eureka:
image: eureka:0.0.1-SNAPSHOT
container_name: eureka
hostname: eureka
ports:
- "8761:8761"
configserver:
image: config-server:0.0.1-SNAPSHOT
container_name: configserver
hostname: configserver
links:
- eureka
ports:
- "8888:8888"
authserver:
image: auth-server:0.0.1-SNAPSHOT
container_name: authserver
hostname: authserver
links:
- eureka
- configserver
ports:
- "9999:9999"
pcgateway:
image: pc-gateway:0.0.1-SNAPSHOT
container_name: pcgateway
hostname: pcgateway
links:
- eureka
- configserver
- authserver
ports:
- "8080:8080"
After starting in docker container :
http://192.168.99.100:8761/ showing :
Instances currently registered with Eureka
Application AMIs Availability Zones Status
AUTHSERVER n/a(1) (1) UP (1) - authserver:authserver:9999
CONFIGSERVER n/a(1) (1) UP (1) - configserver:configserver:8888
PCGATEWAY n/a(1) (1) UP (1) - pcgateway:pcgateway:8080
But when open the auth page: http://192.168.99.100:8080
It should be redirected to auth-server login page , but it opened Timeout , the Address Bar is:
http://172.17.0.4:9999/uaa/oauth/authorize?client_id=clientapp&redirect_uri=http://192.168.99.100:8080/login&response_type=code&state=cdXhfg
I don't know why , maybe the above sso tokenurl is not correct . How to resolve ?
The 172.17.0.4 IP-address is the IP-address of the authserver container on the internal (container-container) network, which is not reachable from outside the docker host (Virtual Machine).
This may be tricky, because (in this case) you need to provide the IP-address of the Virtual Machine that docker runs on, which may change, and definitely will be different in production.
If you change ${AUTHSERVER_PORT_9999_TCP_ADDR:localhost} to 192.168.99.100, it should work.
I suggest to make the IP-address (or domain) configurable using an environment-variable that you provide in the docker-compose.yml, so something like:
${DOMAIN_NAME:192.168.99.100}
Which defaults to the "standard" IP-address of the Virtual Machine. In production you can then pass the actual domain-name, or IP-address of the server your project runs on.
Note that the "link" environment variables are marked deprecated, and only will
be used on the default (bridge) network. The new linking feature won't create
these variables, but you can simply link to other containers by name. See
https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks

Resources