Last active
May 25, 2022 13:39
-
-
Save mljohns89/e1f8881620292329b408465a982dc7b8 to your computer and use it in GitHub Desktop.
Example Config for Making Eureka work with AWS ECS Fargate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
@Slf4j | |
public class AwsEcsFargateConfig { | |
private static final String AWS_API_VERSION = "v2"; | |
private static final String AWS_METADATA_URL = "http://169.254.170.2/" + AWS_API_VERSION + "/metadata"; | |
@Value("${server.port}") | |
private int port; | |
@Value("${spring.application.name}") | |
private String appName; | |
private static final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); | |
@Bean | |
public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) throws JsonProcessingException { | |
EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils); | |
config.setNonSecurePort(port); | |
config.setAppname(appName); | |
config.setVirtualHostName(appName); | |
config.setSecureVirtualHostName(appName); | |
try { | |
String ecsFargateMetadata = readEcsMetadata(); | |
EcsTaskMetadata ecsTaskMetadata = mapper.readValue(ecsFargateMetadata, EcsTaskMetadata.class); | |
String ipAddress = findContainerPrivateIP(ecsTaskMetadata); | |
log.info("OVERRIDE IP ADDRESS TO: {}", ipAddress); | |
config.setIpAddress(ipAddress); | |
config.setHostname(ipAddress); | |
config.setInstanceId(ipAddress+":"+config.getSecureVirtualHostName()+":"+config.getNonSecurePort()); | |
log.info("ECS FARGATE METADATA: {}", ecsFargateMetadata); | |
} catch (Exception e) { | |
log.error("Something went wrong when reading ECS metadata: {}", e.getMessage()); | |
} | |
log.info("EurekaInstanceConfigBean: {}", mapper.writeValueAsString(config)); | |
log.info("EurekaInstanceConfigBean.getVirtualHostName(): {}", mapper.writeValueAsString(config.getVirtualHostName())); | |
return config; | |
} | |
private String readEcsMetadata() throws Exception { | |
URL obj = new URL(AWS_METADATA_URL); | |
HttpURLConnection con = (HttpURLConnection) obj.openConnection(); | |
StringBuilder response = new StringBuilder(); | |
try{ | |
con.setRequestMethod("GET"); | |
try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) { | |
String inputLine; | |
while ((inputLine = in.readLine()) != null) { | |
response.append(inputLine); | |
} | |
} | |
} finally { | |
con.disconnect(); | |
} | |
return response.toString(); | |
} | |
private String findContainerPrivateIP(EcsTaskMetadata metadata) { | |
if (null != metadata){ | |
for (Container container: metadata.getContainers()){ | |
boolean found = container.getName().toLowerCase().contains(appName); | |
if (found){ | |
Network network = container.getNetworks()[0]; | |
return network.getIPv4Addresses()[0]; | |
} | |
} | |
} | |
return ""; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Data | |
public class Container { | |
@JsonProperty("DockerId") | |
private String dockerID; | |
@JsonProperty("Name") | |
private String name; | |
@JsonProperty("DockerName") | |
private String dockerName; | |
@JsonProperty("Image") | |
private String image; | |
@JsonProperty("ImageID") | |
private String imageID; | |
@JsonProperty("Labels") | |
private Labels labels; | |
@JsonProperty("DesiredStatus") | |
private String desiredStatus; | |
@JsonProperty("KnownStatus") | |
private String knownStatus; | |
@JsonProperty("Limits") | |
private Limits limits; | |
@JsonProperty("CreatedAt") | |
private String createdAt; | |
@JsonProperty("StartedAt") | |
private String startedAt; | |
@JsonProperty("Type") | |
private String type; | |
@JsonProperty("Networks") | |
private Network[] networks; | |
@JsonProperty("Health") | |
private Health health; | |
@JsonProperty("Volumes") | |
private Volumes[] volumes; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Data | |
public class EcsTaskMetadata { | |
@JsonProperty("Cluster") | |
private String cluster; | |
@JsonProperty("TaskARN") | |
private String taskARN; | |
@JsonProperty("Family") | |
private String family; | |
@JsonProperty("Revision") | |
private String revision; | |
@JsonProperty("DesiredStatus") | |
private String desiredStatus; | |
@JsonProperty("KnownStatus") | |
private String knownStatus; | |
@JsonProperty("Containers") | |
private Container[] containers; | |
@JsonProperty("Limits") | |
private Limits limits; | |
@JsonProperty("PullStartedAt") | |
private String pullStartedAt; | |
@JsonProperty("PullStoppedAt") | |
private String pullStoppedAt; | |
@JsonProperty("AvailabilityZone") | |
private String availabilityZone; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Data | |
public class Health { | |
private String status; | |
private String statusSince; | |
private String output; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Data | |
public class Labels { | |
@JsonProperty("com.amazonaws.ecs.cluster") | |
private String comAmazonawsEcsCluster; | |
@JsonProperty("com.amazonaws.ecs.container-name") | |
private String comAmazonawsEcsContainerName; | |
@JsonProperty("com.amazonaws.ecs.task-arn") | |
private String comAmazonawsEcsTaskArn; | |
@JsonProperty("com.amazonaws.ecs.task-definition-family") | |
private String comAmazonawsEcsTaskDefinitionFamily; | |
@JsonProperty("com.amazonaws.ecs.task-definition-version") | |
private String comAmazonawsEcsTaskDefinitionVersion; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Data | |
public class Limits { | |
@JsonProperty("CPU") | |
private double cpu; | |
@JsonProperty("Memory") | |
private long memory; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Data | |
public class Network { | |
@JsonProperty("NetworkMode") | |
private String networkMode; | |
@JsonProperty("IPv4Addresses") | |
private String[] iPv4Addresses; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Data | |
public class Volumes { | |
@JsonProperty("DockerName") | |
private String dockerName; | |
@JsonProperty("Source") | |
private String source; | |
@JsonProperty("Destination") | |
private String destination; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example of how to use Eureka Service Discovery in ECS Fargate Instances with a Spring Boot/Spring Cloud Application. The tricky part is you essentially need to grab the private IP Address from the ECS Task Metadata and then override the destination IP Address with that private IP Address. You'll only know what that IP address is though at runtime since it is Fargate (EC2 instances don't have this issue because their IP address are static and can be configured in advance)