본문 바로가기
Spring/Spring Boot

Spring에서 생기는 Failed to connect to service endpoint 해결과정

by 졸린개발자 2022. 5. 14.

안녕하세요 졸린개발자입니다.

 

오늘은 Sping Application 개발중 만났던 exception인,

com.amazonaws.SdkClientException: Failed to connect to service endpoint

를 해결했던 과정에 대해 포스팅해보겠습니다.

 

로컬환경에서 개발중, 다음과 같은 문제를 만났습니다. (클릭하면 크게보입니다.)

<그림1 로컬호스트 오류발생>

오류 메시지를 보면,

Unabled to retrieve the requested metadata(/latest/meta-data/instance-id). Failed to connect to service point

라고 되어있네요. (아래 stack trace부분말고, logger가 WARN으로 찍어준 부분입니다.)

 

물론, 이 문제는 WARN수준이라 사실 어플리케이션이 실행이 되긴합니다.

 

하지만, 문제는 어플리케이션을 실행할때 connect가 timeout이 날때까지 기다려야 한다는것입니다.

로컬환경에서 어플리케이션 서버를 띄울때 약간의 delay가 생기네요.

 

 

오류 발생 원인

spring boot cloud AWS에서는 특별한 url로 ec2의 정보를 가져오려고 시도합니다.

 

그러한 정보는 어떤정보일까요?

 

aws ec2공식문서에서 답을 찾았습니다.

https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

 

EC2에서는 EC2내부에서 자신에 대한 정보를 조회할 수 있게 해줍니다.

자신의 id, 어디에서 실행되는지 등등의 자신의 정보를 말이죠.

 

자신의 정보는 2가지의 URL로 나눠서 조회할 수 있습니다.

1.메타데이터조회 2.사용자 정보 조회

 

메타데이터 조회는 Ec2 자신의 메타데이터입니다.

http://169.254.169.254/latest/meta-data/ 로 조회할 수 있고,

ec2의 정보를 조회할 수 있습니다.

 

사용자 정보는 이 Ec2 인스턴스가 실행될때 자동으로 실행되는 스크립트 정보입니다.

http://169.254.169.254/latest/user-data/ 로 조회할 수 있습니다.

 

위의 오류는 결국, EC2의 메타데이터중 instance의 id를 조회하는 과정에서 

url에 접근하지 못하여 발생한 문제네요.

 

이 url은 ec2안에서만 접근가능한 url이기 때문에,

로컬환경에서는 조회가 되지 않아, 이런 오류가 발생하는 것입니다.

 

 

해결방안

결국, 이러한 url에 접근하지 않게 어떻게든 해주어야합니다.

 

제 생각에는, 아마존정도 되는 큰 회사면, 이러한 문제를 분명 알고 있을것이고,

특별한 환경변수같은 값을 넣으면, 이러한 정보가 조회되지 않도록 

소스코드를 작성해 놓았을 것이라고 생각합니다.

 

그럼 소스코드를 하나씩 직접 봐야겠군요.

 

그림1에서 봤던 Stack trace를 자세히 살펴봅시다

<그림2 자세한stacktrace>

 

정보를 조회하는 메소드는 AwsCloudEnvironmentCheckUtils 클래스의 isRunningOnCloudEnvironment 인것 같군요.

메소드 이름으로 봤을때, 실행환경이 cloud에서 돌아가는지 체크하는 메소드 같네요.

 

그럼 저 메소드의 소스를 살펴봅시다.

<그림3 isRunningOnCloudEnvironment>

이 메소드에서 /instance-id에 대해 조회하네요.

 

근데 EC2_METADATA_ROOT는 뭘까요? 자세히 살펴봅시다.

<그림4 EC2_METADATA_ROOT>

 

합쳐보면, 조회할때 /latest/meta-data/instance-id로 조회하네요.

제대로 찾아온것 같습니다.

 

저 url을 어디서 보지 않은것 같지 않나요?

기억이 나지 않으신다면 그림 1에서의 오류코드를 봅시다.

/latest/meta-data/instance-id에서 오류가 났던것 기억나시나요?

 

이제 쭉 따라가다보면, 실제로 조회하는 코드를 만날 수 있겠네요.

 

 

그럼 저 경로로 조회하기 위해 getData에 매개변수를 전달하는 것이군요.

그럼 저 안에있는 getData메소드를 자세히 살펴봅시다.

 

<그림5 getData>

getItems에서 정보를 가져오는것 같군요. 저 메서드를 살펴봅시다

 

 

<그림6 getItems>

InstanceMetadataServiceResourceFetcher.getInstance().readResource()에서 정보를 불러오는군요

자세히 들여다 봅시다.

 

<그림7 readResource>

이 메소드에서 isEc2MetadataDisabled 라는 메소드를 부릅니다.

 

어? 해석해보면 Ec2의 Metadata를 불러오지 않도록 설정할 수 있나 봅니다.

 

저 메소드를 자세히 살펴보죠

 

<그림8 isEc2MedatdataDisabled>

이 메소드가 true이면 메타데이터를 가져오지 않습니다

 

저 메소드에 의하면

1. System property에 특정한 property가 설정되어있으면 메타데이터를 가져오지 않고

2. 특정한 환경변수가 설정되어있으면 메타데이터를 가져오지 않는군요.

 

그럼 어떤 것이 설정되어야 할까요?

1. System property부터 자세히 들여다 봅시다

<그림9 AWS_EC2_METADATA_DISABLED_SYSETM_PROPERTY>

이런 property가 설정되어있으면 메타데이터를 가져오지 않는군요

-Dcom.amazonaws.sdk.disableEc2Metadata=true

이렇게 설정되어있으면 가져오지 않겠군요

 

 

2. 환경변수는 어떻게 설정되어야 할까요?

<그림10 AWS_EC2_METADATA_DISABLED_SYSTEM_PROPERTY>

 

환경변수가 저걸로 세팅된다면 가져오지 않겠군요

OS마다 환경변수 세팅방법은 다르니, 이 부분은 넘어가겠습니다.

 

 

로컬에서는 os의 환경변수를 설정하면, 다른 어플리케이션까지 영향을 미칠 수 있으니,

property를 수정하는 방법으로 해결해야겠군요.

 

<그림11 property변경>

저는 intellij로 개발하기 때문에, 이렇게 설정을 변경하였습니다.

 

<그림12 로컬환경 해결>

Ec2 Instance Metadata Service is disabled라고 뜨면서

더이상 메타데이터를 가져오지 않게 만들었습니다.

 

이제 더이상 딜레이가 생기지 않네요.

 

또 하나 해결했군요.

 

결론

사실, 저번 포스트에서 생긴 문제와 비슷한 원인입니다.

결국 ec2의 정보조회를 하다가 생긴 문제입니다.

2022.04.28 - [Spring/Spring Boot] - Spring Boot, EC2에 배포했을때, The requested metadata is not found 오류 해결과정

 

Spring Boot, EC2에 배포했을때, The requested metadata is not found 오류 해결과정

안녕하세요 졸린개발자입니다. 오늘은 AWS EC2 Instance에 Sping Application을 배포할때 com.amazonaws.SdkClientException: The requested metadata is not found 를 해결했던 과정에 대해 포스팅해보겠습니다...

sleepy-developer.tistory.com

 

그래서 이번에는 문제해결을 위해 많은 시간을 들이지 않고,

해결해서 기분이 좋군요.

 

그럼 긴글 읽어주셔서 감사합니다.