Bootstrapping Spring Cloud Netflix Eureka using DNS
Spring Cloud Netflix is a spring wrapper around many of the core components of the Netflix OSS stack.
It makes running some of these components very simple, but the devil is usually in the configuration. Let's take a look at how to configure your Eureka server instances to discover each other via DNS when running in your own datacenter.
Spring Cloud Netflix != Netflix OSS
First a word of warning. Part of the Spring Cloud Netflix wrapper around the Netflix components is a separate configuration system. The configuration options I use in this post do not match exactly to what you will find if you are using the Netflix libraries directly.
Creating a Eureka Server with Spring Cloud Netflix
You only need a tiny piece of java code to bring up a Eureka server using the Spring libraries.
package com.storytel.eureka;
import org.springframework.boot.Banner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
@EnableEurekaClient
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class)
.bannerMode(Banner.Mode.CONSOLE)
.registerShutdownHook(true)
.web(true)
.run(args);
}
}
Configuring a Spring Cloud Netflix Eureka server for DNS
There are two ways to link eureka servers to each other. You can either provide static configuration or you can utilize well defined DNS records. Here I show how to do the latter via application.yml
.
spring:
application:
name: eureka
server:
port: 8761
eureka:
instance:
healthCheckUrlPath: /health
client:
region: global
eurekaServerPort: 8761
useDnsForFetchingServiceUrls: true
eurekaServerDNSName: eureka.storytel
eurekaServerURLContext: eureka
registerWithEureka: true
fetchRegistry: true
endpoints:
enabled: false
health:
enabled: true
Here are the important parts :-
useDnsForFetchingServiceUrls
This must be true for DNS based configurationeurekaServerDNSName
This is the suffix added to the DNS requests, so must match the records you createeurekaServerURLContext
This is the url added to the servers returned from DNS. e.g.eureka01.storytel.local
will becomehttp://eureka01.storytel.local/eureka
eurekaServerPort
This is the port added to the servers returned from DNS. Important if you run a non-standard port.
In addition to these values you bake in to your config, there are some additional properties you should set. We do that via environment variables which can be used to add/override any value in application.yml
EUREKA_INSTANCE_HOSTNAME
The hostname for this instanceEUREKA_INSTANCE_IP_ADDRESS
The ip address for this instanceEUREKA_CLIENT_REGION
The region this instance is running in
What's the deal with regions
A Eureka topology is modeled as Region > Datacenter > Instance
on amazon this might be us-east > us-east-1 > eurkeka01
on digital ocean this may be ams > ams2 > eureka01
This is important to understand as it is used when the Eureka client queries DNS.
DNS TXT records
Eureka will start by querying the TXT records for your region txt.<region>.<eurekaServerDNSName>
eg txt.us-east.eureka.storytel
where it will expect to find one value for each datacenter in the region us-east-1.eureka.storytel
.
It will then make another TXT lookup this time for txt.<datacenter>
e.g. txt.us-east-1.eureka.storytel
where it will expect to find one value for each instance in the datacenter eureka01.us-east-1.eureka.storytel
, eureka02.us-east-1.eureka.storytel
.
How to add the TXT records
This will depend heavily on your environment. We use dnsmasq which you can also read about on my blog here.