- 마이크로 서비스 → Eureka Server
- 마이크로 서비스에서 유레카 서버로 본인의 서비스를 등록할 때, 컨테이너 이름을 사용한 DNS 연결이 잘 되지 않는 문제 식별
- 같은 서브넷 안에 관리되고 있기 때문에 private IP를 직접 지정하여 연결
- 마이크로 서비스 → Eureka Server 등록 성공
- 마이크로 서비스 → Config Server
- Config 서버는 타 마이크로 서비스에서 접근할 때 Eureka 서버에 등록된 DNS 이름으로 접근할 수 있음
- Eureka 서버에 Config 서버 등록은 됐지만, 타 마이크로 서비스에서 Config 서비스에 접근하지 못하는 문제 발견
- Image 생성 시 /src/main/resources/config-repo의 하위 *.yml 파일들이 복사되지 않는 것 발견
- → Image 생성 시 config-repo를 copy하는 과정에서 오타가 있었음을 발견, 수정 후 해결
- 마이크로 서비스 → Eureka Server → 마이크로 서비스
- 각 마이크로 서비스가 유레카 서버에 본인의 IP와 서비스 이름을 등록할 때, 각 서버의 내부 네트워크 IP를 전달하고 있는 문제 식별
- EurekaServer에서 각 마이크로 서비스의 IP를 찾지 못할 때 라우팅하는 167.~ IPv4가 각 서버의 IP라고 제공하고 있었으나, 이는 틀린 정보
- 각 마이크로 서비스가 본인의 외부 IP를 알아내어 EurekaServer에 등록하게 해 문제를 해결
- AWS에서 제공하는 컨테이너 메타 데이터 식별 주소가 담긴 ECS_CONTAINER_METADATA_URI_V4 환경 변수에서 값을 꺼내와 Get 요청을 보낸 뒤 외부 IP를 알아내 Eureka Server에게 전달한 후 배포 성공
package on.ssgdeal.common.eureka.configuration;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestTemplate;
@Configuration
public class EurekaFargateConfig {
private static final String META_V4 = "ECS_CONTAINER_METADATA_URI_V4";
private final RestTemplate rest;
@Autowired
public EurekaFargateConfig(RestTemplateBuilder builder) {
this.rest = builder
.connectTimeout(Duration.ofSeconds(2))
.readTimeout(Duration.ofSeconds(2))
.build();
}
@Bean
public EurekaInstanceConfigBean eurekaInstanceConfigBean(
InetUtils inetUtils,
Environment env) throws Exception {
String uri = System.getenv(META_V4);
if (uri == null) {
throw new IllegalStateException("ECS_CONTAINER_METADATA_URI_V4 환경변수 미설정");
}
String taskJson = rest.getForObject(uri + "/task", String.class);
JsonNode root = new ObjectMapper().readTree(taskJson);
JsonNode containers = root.path("Containers");
JsonNode appContainer = null;
for (JsonNode c : containers) {
String name = c.path("Name").asText("");
if (!name.contains("~internal~")) {
appContainer = c;
break;
}
}
if (appContainer == null && !containers.isEmpty()) {
appContainer = containers.get(0);
}
String ip = appContainer
.path("Networks")
.get(0)
.path("IPv4Addresses")
.get(0)
.asText();
int port = env.getProperty("server.port", Integer.class, 8080);
JsonNode pm = appContainer.path("PortMappings");
if (pm.isArray() && !pm.isEmpty()) {
port = pm.get(0).path("HostPort").asInt(port);
}
EurekaInstanceConfigBean cfg = new EurekaInstanceConfigBean(inetUtils);
String appName = env.getProperty("spring.application.name");
cfg.setAppname(appName);
cfg.setPreferIpAddress(true);
cfg.setIpAddress(ip);
cfg.setHostname(ip);
cfg.setNonSecurePort(port);
cfg.setNonSecurePortEnabled(true);
cfg.setInstanceId(String.format("%s:%s:%d",
ip, appName, port));
return cfg;
}
}