VPC Endpoint를 통해 ECR에서 이미지를 가져와 ECS에서 구동하기

728x90

서론 


지난 포스팅에서 AWS ECR까지 생성하는 것을 진행해보았다. 이번 글에서는 내용을 이어서 VPC Endpoint를 생성하여 AWS ECR과 AWS ECS를 연결하고, 컨테이너 인스턴스를 구동하여 동작이 되는 것까지 확인해보도록 하겠다.

VPC Endpoint 생성


VPC Endpoint를 통해 Private subnet 상에 있는 ECS와 ECR을 서로 연결해주면 ECR에 있는 이미지를 ECS가 가져와 쓸 수 있다.

인터페이스 엔드포인트 생성


앞서 VPC 엔드포인트는 크게 인터페이스 엔드포인트와 게이트웨이 엔드포인트가 있다고 하였다. 우리는 Private link를 사용하여 AWS ECR 과 ECS를 연결해야 하므로 인터페이스 엔드포인트를 생성하겠다.



이름은 임의로 입력한다. ECR은 AWS의 서비스 일종이므로 서비스 범주는 AWS 서비스를 선택하면 된다.

아래 서비스에서 ecr을 검색하면 ecr.api 그리고 ecr.dkr 두 가지 서비스가 나온다. 





ecr.dkr과 ecr.api 중 어떤 걸 생성해야 하지?


aws 공문서에 따르면 ecr.dkr과 ecr.api의 역할은 다음과 같다.

 



ecr.dkr은 docker push pull 등 docker 클라이언트 명령어를 수행할 수 있게 해주는 반면, ecr.api는 'CreateRepository'등 ECR만의 API 명령어롤 수행할 수 있게 하는 서비스다. 우리는 docker 이미지를 ECS에 pull하는 기능만 필요하므로 ecr.dkr 서비스만으로도 충분하다고 생각할수도 있다. 하지만 ecs.dkr만 인터페이스 엔드포인트로 생성하면 ECS Task가 정상적으로 생성되지 않을 수 있다. 그 이유는 아래 공문서를 확인하자.

 


즉, Task 배포에 사용하는 컴퓨팅 서비스가 Fargate 1.3.0 이하면  ecr.dkr 인터페이스 엔드포인트와 S3 게이트웨이 엔드포인트 이렇게 2개만 있으면 되지만, 배포에 Fargate 1.4.0 이상 버전을 사용한다면 ecr.dkr, ecr.api, S3 게이트웨이 엔드포인트 이렇게 3개의 엔드포인트가 필요하다는 것이다. 

현재 프로젝트에 사용하는 컴퓨팅 서비스 종류를 확인해보자.

 



플랫폼 버전을 LATEST로 지정하여 사용하고 있다. 이런 경우에는 Endpoint를 ecr.dkr과 ecr.api 둘 다 생성해줘야 한다. (물론 1.3.0이하로 배포한다면 그냥 dkr만 있어도 된다.) 

S3 게이트웨이 엔드포인트는 필수


S3 게이트웨이 엔드포인트는 1.3.0버전이든 1.4.0버전이든 어느 경우에서도 필요하다. S3 게이트웨이 엔드포인트가 필요한 이유는 아래와 같이 AWS 공문서에 나와있다.


기존에 서브넷을 생성할 때 생성할 리소스를 "서브넷 등" 을 선택했다면 아래와 같이 자동으로 생성되어있을 것이다.

 

 




그러므로 VPC s3 gateway endpoint가 이미 있다면 따로 신경쓰지 않아도 된다. 만약 VPC를 생성할 때 함께 생성하지 않았다면 별도로  S3 엔드포인트를 현재 사용할 VPC에 생성해주도록 하자.

S3 게이트웨이 엔드포인트 관련 주의사항



여기서 추가적으로 주의해야할 사항은 ECR 기능을 사용할 사용자가 S3에 다음과 같은 접근 권한을 가지고 있어야 한다는 것이다. AWS 공문서에 나와있는 권한을 참고하여 IAM에서 권한을 추가하도록하자. 만약 S3FullAccess 권한이 있는 사용자라면 해당 내용은 신경쓰지 않아도 된다.

 

 

ECR 연결을 위한 인터페이스 엔드포인트 생성하기



우선 엔드포인트에 사용할 이름을 임의로 입력하고, 서비스 범주는 AWS 서비스를 선택한다 (ECR은 AWS 서비스니까)

 

 


앞서 언급한 대로 ECR 관련 엔드포인트는 ecr.dkr과 ecr.api 두 개 존재한다. 둘 다 생성해야 1.4.0이상 버전에서 사용할 수 있다. 

 



엔드포인트를 연결할 VPC를 지정하고 서브넷까지 선택해준다. VPC 엔드포인트는 가용영역 별로 요금이 부과된다. VPC 엔드포인트를 사용할 가용영역을 지정하여 서브넷을 연결한다.


그런 다음 미리 만들어둔  VPC의 보안그룹까지 선택하고 엔드포인트 생성을 누르면 엔드포인트가 생성된다. dkr과 api 엔드포인트 둘 다 생성해주도록 한다.



ECS를 위한 VPC 엔드포인트 생성하기



이렇게 ECR 엔드포인트를 생성했어도 ECS Task는 private Link를 사용하여 컨테이너를 구동하지 못한다. 왜냐하면 ECR에 대한 VPC Endpoint는 생성되었지만, ECS에 대한 VPC Endpoint는 생성되지 않았기 때문에 ECS 서비스가 정상적으로 ECR 이미지를 가져오지 못하기 때문이다.

지난 시간 프로젝트 다이어그램을 아래와 같이 보인 바 있다.

 


하지만 위 다이어그램은 엄연히 말해서 잘못된 다이어그램이다. ECS와 ECR의 실제 동작은 아래와 같다. 

 

 


ECS도 AWS 서비스의 일종으므로 subnet의 외부에 존재한다. 우리의 subnet에는 ECS에서 생성한 컴퓨팅 인스턴스가 존재하는 것이지, ECS 서비스 자체가 존재하는 것은 아니다. 그러므로 ECS 서비스에 접근하기 위해서 ECS를 위한 VPC 엔드포인트도 생성해줘야 한다.

어떤 VPC endpoint를 생성할지는 아래처럼 AWS 공문서에 잘 나와있다.

 


차례대로 3가지 ECS VPC endpoint를 생성한다.

 

정리: 필요한 VPC 엔드포인트는 크게 3 종류



정리하자면, ECR에서 ECS로 private link를 통해 이미지를 가져오기 위해서는 아래 공문서에 언급된대로 크게 3종류의 VPC endpoint가 필요하다.


S3 게이트웨이 엔드포인트와 ECS 인터페이스 엔드포인트 3가지는 어느 경우에서나 필요하고, ECR 인터페이스 엔드포인트는 ecr.dkr은 항상 필요하며 Fargate 1.4.0 이상 버전을 사용할 경우 ecr.api 엔드포인트도 필요하다.

20230422 업데이트: NAT gateway도 있어야 한다.


상기한 VPC 엔드포인트를 전부 생성했어도 ECS TASK가 정상적으로 구동되지 않을 수도 있다. 그 원인은 NAT gateway를 생성하지 않아서 그럴 수도 있다. 아래 AWS 공문서 내용을 확인해보자. 


즉, ECR에서 private link를 통해 이미지를 가져오려면 NAT gateway도 있어야 한다는 말이다. 후속 이미지 pull에는 NAT gateway가 필요없지만, Image를 업데이트하여 push를 한다면 NAT gatway 설정이 필요한 것이다. (이럴거면 그냥 차라리 Docker Hub에 이미지 쌓아두고 NAT gateway만 쓰는게 낫지 않나 싶다.)


NAT gateway를 생성하고 Private subnet에서 오는 요청을 모두 해당 NAT gateway에 보낼 수 있도록 라우팅 테이블을 설정하는 작업까지 모두 완료해야 프라이빗 리포지토리에서 정상적으로 이미지를 가져올 수 있다. 


AWS ECS TASK 구동하기

Private subnet에 ECS 생성하여 구동하기


AWS ECS 서비스로 넘어와 클러스터를 선택하여 서비스를 생성한다. 컴퓨팅 구성은 시작유형의 FARGATE를 선택하고 버전은 LATEST로 지정하고, 배포 구성은 서비스를 선택하여 미리 작성해둔 태스크 정의를 선택하고, 이름은 임의로 지정한다. 태스크 수는 테스트 용도이므로 하나만 생성한다.




네트워킹 탭에서는 아까 엔드포인트를 생성할 때 선택한 동일한 VPC와 서브넷을 선택하고 보안그룹도 동일하게 지정해줘야 한다. 서브넷은 private subnet만 선택하는 것을 유념해야한다. 퍼블릭 IP는 꺼줘야 한다.



미리 생성해둔 로드밸런서를 연결한다. 로드밸런서는 내부 로드밸런서를 사용해야하며 프라이빗 IP 주소를 통해 ECS Task와 연결되어야 한다. 당연히 로드밸런서의 서브넷은 private이어야 한다.

이렇게 서비스 또는 태스크를 생성하면된다. 엔드포인트를 생성하여 ECR과 ECS를 연결해줬기 때문에 정상적으로 이미지를 불러와 태스크를 생성한 것을 확인할 수 있다.


private subnet에 생성했기 때문에 퍼블릭 IP가 존재하지 않는다. 따라서 직접 IP 주소로 접근할 수는 없다. 



하지만 이 Task는 로드밸런서에 연결되어 있으므로 API gateway 프라이빗 리소스를 통해 로드밸런서에 요청을 날리면 로드밸런서가 해당 Task에 요청을 보내고 응답을 불러올 것이다.


어플리케이션 동작 확인

 

API gateway 를 통해 private subnet에서 동작하는 ECS Task 동작 확인 하기


미리 생성해둔 HTTP API gateway에서 NLB와의 통합을 실행해준다. 프라이빗 리소스를 통한 통합을 진행하려면 VPC link가 존재해야한다. 별도로 미리 생성해둔 VPC link를 사용하거나, 통합을 하면서 동시에 VPC link를 생성하면 된다. 통합이 완료되면 아래와 같이 리소스의 메서드 옆에 통합 유형이 뜨게 된다.

주의사항


현재 글쓴이는 API gateway 유형으로 HTTP API gateway를 사용했다. HTTP API gateway를 사용할 때 주의해야 하는 사항은 API gateway에 있는 리소스에 등록된 주소와 실제 docker image에 작성된 라우팅의 주소가 서로 일치해야 해당 주소로 라우팅이 된다는 것이다.

예를 들면 현재 글쓴이의 Controller 매핑은 다음과 같이 되어있는데, GetMapping 주소가 "/"로 되어있으면 HTTP API gateway에서도 "/"로 설정해줘야 한다.  

 



만약 HTTP API gateway에서 주소를 "/"가 아닌 다른 주소를 사용하여 통합을 진행하게 되면 라우팅이 적절하게 되지 못해 에러가 발생하게 된다. 더 자세한 사항은 별도의 포스팅을 참고하길 바란다.


동작 확인


통합에 사용한 API gateway 이름을 클릭하여 세부 정보를 살펴본다. api gateway URL을 클릭하여 동작을 확인할 수 있다.

 



정상적으로 서버가 동작하는 것을 확인할 수 있다. 

서버 동작 구조 정리

 


현재 서버 동작을 위한 인프라 구조를 간략하게 다이어그램으로 정리하면 아래와 같다.


결론



현재 소규모 프로젝트에서는 AWS ECR을 사용할 이점이 없다.  어쨌든 NAT gateway도 사용해야하므로 NAT gatway + AWS ECR + VPC endpoint 등 삼중으로 비용이 발생하기 때문이다. 그냥  개인 프로젝트 작업자는 Docker Hub + NAT gateway를 사용하는 것이 더 경제적일 것이다.