Eureka Client Registered with Container IP in ECS Fargate - spring

We deployed Spring Boot services in the ECS Fargate with Eureka Registry Service, Gateway Service and a few business services. In the Eureka registry page all the client services registered were showing same IP (could be container IP).
Please share what configuration should be provided to register with ECS task private ip instead of container IP. Thanks in advance.
Eureka Service Application Properties:
server.port=8080
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
Eureka Client Service Application Properties
server.port=8766
spring.application.name= client-service
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.prefer-ip-address= true
eureka.client.service-url.defaultZone= <eureka-ecs-ip>:8080
eureka.instance.lease-renewal-interval-in-seconds=30

Problem solved by adding the below code to SpringBootApplication source. This block picks update host IP address (not container) and overrides the config property/yaml settings.
#Bean
public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils){
EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils);
String ip = null;
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
config.setIpAddress(ip);
config.setPreferIpAddress(true);
return config;
}

To anyone that still can't fix it with the accepted answer:
I also had to set secure/non-secure port in config (and enable it).

Related

Does KPL support proxy configurations?

I have Spring beans configured in a microservice as follows that I'm using to connect to Kinesis:
#Bean
// ClientConfiguration has proxy protocol, proxy host, and proxy port set
public AmazonKinesisAsync amazonKinesisAsync(ClientConfiguration clientConfiguration, AppProperties properties) {
return AmazonKinesisAsyncClientBuilder.standard().
withClientConfiguration(clientConfiguration).withRegion(properties.getRegion()).build();
}
#Bean
public KinesisProducerConfiguration kinesisProducerConfiguration(AppProperties properties) {
return new KinesisProducerConfiguration()
.setRegion(properties.getRegion());
}
This GH issue states that the KPL doesn't support proxy configuration, but I'm hoping there is a way to utilize KPL behind a firewall. So, my main question is whether or not KPL supports proxy configuration, and if not, how can I use KPL/KCL behind a corporate firewall? I've read about AWS Kinesis VPC Endpoints here, so would this be the only alternative we would have if we can't use KPL with a proxy configuration?

How to find IPs of Eureka registered service on the clients

I have the following services:
EurekaServer - hosts the eureka discovery server
Client-service - registers to EurekaServer
Finder-service - registers to EurekaServer
Is there a way to get Client-service's ip so I can make requests to it from the Finder-service.
I know there is a way to find InstanceInfo from EurekaServer and I was thinking of making a controller in eureka server where you pass service id and get service's instance ip. This way Finder-service would only need to know service id and eureka ip which it knows because it is registered there.
Is there another solution which is cleaner than this?
To use client discovery you first need to enable by adding either #EnableEurekaClient or #EnableDiscoveryClient to your #SpringBootApplication annotated class (or your specialized #Configuration).
Next to make use of the resolution of the actual service instance to use you need to create a RestTemplate which is load-balanced. This will add an interceptor which translates the service name into the ip-address / DNS name to send the request to (if multiple instances are found it will distribute the load between those instances).
To create a load balanced RestTemplate add the #LoadBalanced annotation to the configured RestTemplate.
#Bean
#LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder rtb) {
return rtb.build();
}
Now when doing a request through the RestTemplate it will resolve the service name client-service to the actual service instance to use. Without you having to do anything.

spring consul services are all healthy but can't reach each other when on different hosts

Running Consul and spring-cloud-consul I have five micro services all registered and showing as healthy. Each of these services is running on a different EC2 instance.
Using the name of the micro service that is registered in consul I can't get a connection through to any of them using a RestTemplate
If Service A was to call Service B with the following code
private final static String SERVICE = "http://instance-service";
#LoadBalanced
#Autowired
private RestTemplate restTemplate;
#GetMapping("/instances")
public ResponseEntity<String> instances() {
ParameterizedTypeReference<String> reference = new ParameterizedTypeReference<String>() {
};
return restTemplate.exchange(SERVICE, HttpMethod.GET, null, reference);
}
Service A throws
2017-12-19 17:30:36.000 ERROR 1 --- [nio-8443-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://instance-service": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)] with root cause
and even with debugging set to TRACE I can see nothing coming in at all on Service B.
However if I take my identical setup and run it on a single EC2 instance everything works as expected.
All services are running in docker, but the consul agent is running on the host of each EC2 instance.
Each micro service has the following bootstrap.yml set
spring:
cloud:
consul:
config:
enabled: true
discovery:
instance-id: ${spring.application.name}
prefer-ip-address: true
If I give the RestTemplate a random endpoint it returns Unknown host so it knows the micro service is there, it's just being blocked somewhere before it hits the codebase.
How can I debug this further to find the real reason the services are getting rejected when running on different hosts?
I have tried opening all ports on the security config just to rule that out but it made no difference.
Edit: Looking at the Consul UI - I see my services are registered under the a private IP (172.18.0.2).
Should this be a public facing address?
172.18.0.2 is an ip in a a docker bridged network, you definitely want the ip address that is registered in consul to be accessible by clients that use the service discovery..
I don't know your network setup or needs but you can (some ideas, there are many) -
if you expose ports to the docker host (-p), make sure the ip of the docker host is registered for each service instance (I'm not familiar with bootstrap.yml or spring cloud)
run docker containers with --net=host
register the services in consul in different methods and outside of spring cloud's scope (API call to the consul agent, service definition file, https://github.com/gliderlabs/registrator, ...)

Register Hazelcast Cluster instances on Eureka

I have a Spring Boot service in which I've started an HazelCast instance.
#Bean
public Config config(){
return new Config();
}
#Bean
public HazelcastInstance hazelcastInstance(Config config){
return Hazelcast.newHazelcastInstance();
}
Now, I want to register my HazelCast instances in Eureka so that my HC clients can retrieve HC cluster instances dynamically.
HazelCast plugin page point me to the eureka plugin but this one is from 2015 and contains a lot of deprecated code recommending me to use EurekaModule and DI.
Does someone have an example?
Have a look at https://github.com/hazelcast/hazelcast-code-samples/tree/master/hazelcast-integration/springboot-eureka-partition-groups
Should do what you need

Eureka on spring-cloud-netflix with DNS based config, all instances showing up as unavailable

I'm trying to setup a eureka cluster on aws with DNS-based EIP configuration as described at https://github.com/Netflix/eureka/wiki/Configuring-Eureka-in-AWS-Cloud
Everything seems to work, but the eureka dashboard insists that the eureka instances are unavailable. I'm now wondering if this is only an ui problem (i think so) or if i'm missing something.
As i understand the "unavailable-replicas" logic in the dashboard this is because eureka is comparing the registration hostname and the replica hostname. The instances register with their internal VPC ip at the discovery client but with their EIP when looking for replica peers (strange enough, in the eureka log i can see internaly they are also using the internal VPC ip).
The question is: Is that only some cosmetic ui problem that i shouldn't worry about or are bigger problems waiting to step in because of some misconfiguration? If it's only an ui thing: can i "repair" that somehow?
Edit:
Maybe related https://github.com/spring-cloud/spring-cloud-netflix/issues/102#issuecomment-74446709
With the help of #rozhok in the related github issue i now have a working solution. If anyone is facing the same problem, here's what i've done:
application.yml
eureka:
datacenter: cloud
client:
eurekaServerDNSName: your.dns.name
eurekaServerPort: 8761
eurekaServerURLContext: eureka
region: eu-west-1
registerWithEureka: true
fetchRegistry: true
useDnsForFetchingServiceUrls: true
server:
waitTimeInMsWhenSyncEmpty: 0
enableSelfPreservation: true
EurekaServer
#SpringBootApplication
#EnableEurekaServer
#EnableDiscoveryClient
public class EurekaServer {
#Value("${server.port:8761}")
private int port;
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class, args);
}
#Bean
#Autowired
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils) {
EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils);
AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka");
// Don't use spring cloud's hostname here.
// See comment below by Michal
config.setHostname(
info.get(AmazonInfo.MetaDataKey.publicHostname));
config.setIpAddress(info.get(AmazonInfo.MetaDataKey.publicIpv4));
config.setNonSecurePort(port);
config.setDataCenterInfo(info);
return config;
}
}
With that configuration each eureka server sees only the other servers as available replicas:

Resources