문제 상황
Spring Cloud Eureka를 사용하는 MSA 구조에서, ECS Fargate 환경에 배포된 서비스들이 잘못된 IP로 Eureka에 등록되는 현상이 발생했습니다.

- 모든 서비스가 Eureka에 등록될 때 IP 주소가 169.254.172.2로 고정됨.
- Gateway로 요청시 다음과 같은 오류 메세지를 받음
finishConnect(..) failed: Connection refused: /169.254.172.2:8082
원인은?
원인은 Fargate의 네트워크 구조와 Eureka의 기본 IP 등록 방식 때문이었습니다.
Eureka는 기본적으로 컨테이너가 실행되는 호스트의 IP 또는 호스트 네임을 가지고 주소를 자동 등록합니다.
하지만 Fargate는 EC2와 달리 호스트 머신 이 없는 서버리스 환경입니다. (like lamda)
각 컨테이너는 고유한 ENI와 IP를 가집니다. 그런데 Eureka는 기본적으로 eth0의 첫번째 IP를 잡기 때문에 문제가 생깁니다.
Fargate에서 각 컨테이너는 169.254.172.2 이라는 주소를 가지고 있습니다. 이는 링크 로컬 IP 주소로 태 컨테이너 내부에서 메타데이터에 접근하기 위한 링크등으로 사용되는 주소입니다.
Eureka는 첫번째 주소로 해당 주소를 발견했기 때문에 실제 사용할 수 없는 IP를 Eureka서비스에 등록해버린 것입니다.
그럼 해결은?
해결하기 위해서는 Eureka가 실제 컨테이너의 Private IP를 사용하도록 설정해야 합니다. 매번 Private IP는 바뀌기 때문에 동적으로 할당해줘야하는데 이를 위해 ECS에서 제공하는 ECS 메타데이터를 활용합니다.
1. ECS 메타데이터 활용
AWS는 Fargate 환경에서 컨테이너 정보를 조회할 수 있도록
ECS_CONTAINER_METADATA_URI 환경 변수를 자동으로 주입합니다.
이 변수를 통해 현재 컨테이너의 네트워크 정보(IP 포함)를 JSON으로 조회할 수 있습니다.
2. Entrypoint에서 IP 추출
저는 컨테이너가 시작될 때, 아래 스크립트를 실행해
현재 컨테이너의 실제 private IP를 추출하고, 환경 변수로 설정하도록 하였습니다.
#!/bin/bash
set -e
echo "[entrypoint] Fetching container metadata..."
ECS_INSTANCE_IP_ADDRESS=$(curl -s "$ECS_CONTAINER_METADATA_URI" | jq -r '.Networks[0].IPv4Addresses[0]')
if [ -z "$ECS_INSTANCE_IP_ADDRESS" ]; then
echo "[entrypoint] Failed to retrieve ECS instance IP address."
exit 1
fi
export ECS_INSTANCE_IP_ADDRESS
echo "[entrypoint] ECS_INSTANCE_IP_ADDRESS resolved as: $ECS_INSTANCE_IP_ADDRESS"
exec java $JAVA_OPTS -jar /app.jar
위 코드를 entrypoinst.sh에 저장하고 Dockerfile에 이를 복사해서 이미지를 실행하면 됩니다.
FROM openjdk:21-jdk-slim
EXPOSE 8080
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
# 필수 도구 설치
RUN apt-get update && apt-get install -y curl jq
# entrypoint 스크립트 복사
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
3. application.yml에서 Eureka 설정
Eureka가 자동으로 호스트 정보를 쓰지 않도록 prefer-ip-address: true로 명시해주고 ip-address는 환경변수를 참조하도록 수정합니다.
eureka:
instance:
prefer-ip-address: true
ip-address: ${ECS_INSTANCE_IP_ADDRESS}
결과
이렇게 하니 각 서비스는 고유한 Private IP로 Eureka에 정상적으로 등록 되었습니다.
마무리
ECS Fargate는 EC2와 네트워크 구조가 다르므로, 서비스 등록 시 자동으로 IP를 잘못 잡을 수 있습니다.
다행히 AWS 메타데이터 서비스를 통해 간단하게 해결할 수 있었습니다.
댓글