[AWS][API Gateway] API Gateway 유형에 따른 ALB Private Integration 차이 /w VPC Link

컴퓨터공학/서버리스

2022. 09. 08.

API Gateway에서 REST API · HTTP API 모두 VPC Link(AWS Hyperplain의 지원)를 통해 VPC의 사설 자원과 통합될 수 있다. 다만, 게이트웨이 타입에 따라 VPC Link가 제공하는 추상화가 사뭇 다르다는 점을 언급하고자 한다.

참고 글

AWS 블로그

아마존 API Gateway에서 VPC Link를 통한 사설 통합 이해하기

 

AWS 문서

기술 백서 - API Gateway 사설 통합 - REST API

기술 백서 - API Gateway 사설 통합 - HTTP API

공식 문서 - HTTP API vs. REST API

결론

  • REST API Gateway는 VPC Link를 두어 사설 ALB와 통합할 될 수 있다. 다만 직접적이지 않다. 추가적인 NLB를 ALB 앞에 둬야한다. REST API의 VPC Link는 기저가 PrivateLink로 구성되기 때문이다.
  • HTTP API Gateway는 새로운 유형의 VPC Link를 제공한다. 사설 ALB와의 통합이 훨씬 간편하다. 그도 그럴게, 나의 VPC 속 사설 자원들과 API Gateway를 단 하나의 VPC Link가 통합해 준다. 왜냐하면 ENI로 식별 가능한 매지니드 NAT 변환 자원이 가운데서 참여하기 때문이다.

보안 그룹 팁

  • HTTP API Gateway의 VPC Link의 우리 ENI: 우리 ALB로 향하는 Outbound 트래픽을 허용하자.
  • HTTP API Gateway와 사설 통합하는 우리 ALB: 우리 ENI에서 들어오는 Inbound 트래픽을 허용하자.

서론

저번에 AWS 과제의 솔루션을 제시하면서, 서버리스 API Gateway를 MSA의 통합 엔드포인트로 삼을 것을 얘기했다.

운영 부담 감소 · ELB 담당 트래픽의 감소→유닛 감소 · 요청 수 기반 과금 모델이 이유이다.

제안 아키텍처

골자는, 모든 마이크로 서비스의 트래픽을 감내할 자원을, 본인 네트워크 관할에서 운용하겠다는 건 부담이라는 점이다. 부담을 AWS의 서버리스 API Gateway에 위임하고, 삼분할로 작아진 트래픽을 우리 쪽 ELB가 담당하도록 제안하였다.

API Gateway를 말할 때는 REST API의 여러 기능을 언급하지 않으면 섭섭하다. 몇 개 꼽자면, API-Key를 통한 사용량 관리나, 처리율 제한 기능 제공이다.

덕분에 별도 API Gateway 서버(Spring Cloud)나 웹 서버(nginx)를 두지 않고, 또 S3에서 스태틱 파일을 내려주도록 구성하면, 서버리스의 혜택을 누리며 웹 앱(Springboot)에 더욱 노력을 투입할 수 있게 된다. 

 

나는 비즈니스 로직 개발에 집중하고픈 타입이라, 인프라 기능을 AWS에게 많이 많이 책임지우고 싶다. 또 그런 기능은 앞 단에서 구현되는 것이 자명히 좋다. 앞에서 거르지 못한 하나의 트래픽은 뒷 단의 모든 자원을 소모하기 때문이다.

 

https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html 여기서 API Gateway의 내재 기능들을 더 확인할 수 있다.

 

근데 제시한 아키텍처 뷰를 보니 VPC LinkPrivate Link로 오기한 점이 발견됐다. 수정 사항으로 노트하게 되었다.

그러다가 언뜻, 서버리스 서비스로 하여금 우리 사설 자원을 호출하게 만들어 준 뭐시기 링크란 도대체 뭘까? 궁금해진다⋯.

 

AWS 문서와 블로그를 방문하여 VPC Link에 대해 좀 더 파고들었는데

API Gateway 타입이 REST냐, HTTP냐에 따라 그림의 저 위치에 Private Link를 둔게 꼭 틀린 말이 아니군⋯! 하고 깨닫게 되었다.

REST API · HTTP API의 VPC Link는 사뭇 달라요

API Gateway는 서버리스 자원이므로 나의 VPC에 존재하지 않는다. 따라서 사설 서브넷에 있는 자원을 볼 수가 없다.

 

VPC Link란, API Gateway에서 어떤 VPC 내부의 사설 자원하고 통합하기 위해 제공되는 기능이다. 이는 추상화된 네트워킹 자원이다. VPC Link를 생성하는 것으로, 기저에 몇 가지 네트워킹 자원이 투명하게 생성된다는 말이다.

 

알아 둘 점은, REST API냐 HTTP API냐에 따라 생성되는 네트워킹 자원이 다르다는 것이다.

VPC Link for REST API Gateway

이 그림에서 '고객'이란 우리를 말하는 거다.

REST API Gateway의 VPC Link는 PrivateLink를 통해 사적 연결을 구현한다. PrivateLink를 만들어 봤다면 알 거다. 서비스 제공자 측에 NLB 혹은 GWLB를 둬야하고, 사용자 쪽에는 ENI를 둬야 한다는 점. (다만 S3랑 DDB는 GW Typed) 그러니 (ENI, PrivateLink, NLB) 자원 트리플이 필요하겠구나⋯ 생각이 정리될 것이다.

  • VPC Endpoint - Interface Typed용 ENI
  • PrivateLink
  • VPC Endpoint Service로 노출할 NLB

실제로 AWS 콘솔에서 VPC Link를 생성해 볼라카면, 갖고 있는 NLB를 지정하라고 나온다.

VPC Link for HTTP API Gateway

HTTP API Gateway의 VPC Link는 VPC간 주소 변환(NAT)을 이용한다. 이 한 줄을 읽었을 때는 언뜻 그 구조가 직관적으로 상상되지 않았다. 글을 더 읽어보니 (ENI, NAT, ENI) 자원 트리플이 생긴다는 걸 알았다.

  • NAT 작업을 하는 어떤 자원 - AWS Hyperplane Managed이다.
  • 왼쪽 ENI - API Gateway 네트워크 측의 ENI
  • 오른쪽 ENI - 우리 네트워크 측 ENI

애석하게도⋯ 문서의 설명이 최소 권한의 보안 그룹을 생성하는 법까지는 미치지 못 했다. 따라서 그림을 보며 트래픽이 어찌 흘러다닐지 다음과 같이 가정해 보았다.

 

1) 양측 ENI들은 방금 말한 NAT 작업 자원에 붙는 듯하다. 덕분에 얘는 두 네트워크에서 가시적이다.

 

2) API Gateway는, '우리의 사설 서브넷 CIDR에 포함된 주소'를, 목적지로 삼아 트래픽을 쏠 것이다. 라우트 테이블에 의해 이 트래픽이 NAT에 전달될 것이다. 자기네들 ENI가 NAT에 붙었으니 당연히 NAT이 보일 것이다.

 

3) NAT은 패킷의 발신지 주소를, 자기한테 붙은 우리네 ENI 주소로 바꾸고, 우리네 서브넷에 흘려보낼 것이다. 결국 우리 사설 인스턴스가 트래픽을 최종적으로 받을 것이다.

 

4) 요청에 대한 응답 트래픽은, 방금 과정의 역순으로 API Gateway에게 전달되겠지.

 

3번 시나리오가 맞다면, 우리 측 ALB의 보안 그룹은 '우리측 ENI 주소를 발신지로 한 트래픽'을 인바운드에서 허용해야만 한다.

 

가정한 내용을 검증하기 위해 레퍼런스 아키텍처를 그대로 구축하고, VPC Flow Logs를 우리 ALB의 ENI에 달아 로그를 확인해 보았다.

NAT은 우리 쪽 ENI의 임시 포트에서 트래픽을 발사했고, 이것은 우리 ALB의 80번 포트에 들어오셨다.

 

내 가정이 맞았으니, ENI 발신 트래픽을 허용하는 보안 그룹을 ALB에 붙여서 사설 통합을 잘 구축하게 됐다.

ALB에 붙이는 보안 그룹 - 실험을 위해 /32 주소를 허용했다. 귀찮지 않게 ENI의 보안 그룹 허용하시면 됨.

다음으로는 우리 측 ENI에 붙일 보안 그룹 설정이 궁금할 터이다. 사고 실험을 해보면 별 거 없다.

  • NAT이 우리측 ENI를 통해 개시하는 트래픽은 항상 우리 측 ALB를 향하는 Outbound 트래픽이다.
  • 따라서 ENI 보안 그룹은, 우리 ALB 보안 그룹으로 향하는 Outbound 트래픽을 허용하면 된다.
  • Inbound 트래픽은 아무것도 허용하지 않아도 된다. 보안 그룹은 Stateful 하니까.

ENI에 붙이는 보안 그룹

제안 아키텍처 수정

오타 및 정보 표현이 부족한 원래 아키텍처

API Gateway 타입 별 VPC Link가 갖는 차이를 인지했으니, 수정 중이던 아키텍처 뷰로 돌아가 보자. 원래 그림이 위 그림이다.

 

API Gateway 타입이 REST API라고 가정한다면

  • 오기입한 PrivateLink를 VPC Link로 수정해 준다.
  • PrivateLink가 VPC Link에 의해 생성된다는 점은 구두로 언급해야 하겠다.
  • PrivateLink는 NLB로 노출한 Endpoint Service와 통합한다. 그래서 ALB를 NLB로 수정하거나, ALB 앞에 NLB를 둘 필요가 있다.
  • 프록시 자원 표기는 {+proxy}가 아니라 {proxy+}가 맞다. 그렇게 수정한다.

이미 API Gateway를 거쳐 ELB로 들어온 부하는, 서비스 단위로 걸러졌기 때문에 Layer7 정책이 필요하지 않다. ELB는 그저 ECS와 연계된 타깃 그룹의 컨테이너들에게 부하를 뿌려줄 뿐이다.

 

따라서 부가적인 ALB를 추가할 이유가 없으니 첫번째로 언급한 방식으로 NLB를 두겠다. 그림을 수정해 보면⋯

REST API Gateway를 가정하고 제안 아키텍처 수정 (1)

 

여기서 비용을 최적화하기 위해, 다수의 (VPC Link, NLB) 조합을 쓰지 말고, 하나의 NLB에 포트포워딩을 정의해 본다. 그림을 수정해 보면⋯

REST API Gateway를 가정하고 제안 아키텍처 수정 (2)

 

이렇게 바꿔보니, NLB 역시 마이크로서비스를 위한 통합 엔드포인트가 된다. 아이고야⋯ API Gateway의 배치를 뒷 받침하던 Rationale이 퇴색되었다.

 

여기서 REST API Gateway를 유지하려면 API-Key · 처리율 제한 · Cognito 연동 등을 근거로 대서 보강해야 한다. 완전 AD-HOC하게, '품질->전술->솔루션'의 반대 과정으로 논리가 전개되므로, 내 입장에서는 떳떳히 채택할 수 없는 사안이다.. 따라서 최종적으로는 REST API Gateway를 제거해야 하겠다.

 

API Gateway를 HTTP API라 가정한다면

  • 오기입한 PrivateLink를 VPC Link로 수정해 준다.
  • API Gateway가 하나의 VPC Link 덕분에 우리 쪽의 자원들을 훤히 들여다 볼 수 있음을 표현해준다.
  • 이것이 VPC-to-VPC NAT 덕분임을 구두로 언급한다.
  • REST API 타입에만 있는 추가기능 사용을 고려하고 있었다면, 다른 지점에서 기능을 커버해야 한다고 언급한다.
    • 처리율 제한 - 뒷단 ALB에 WAF를 통합하거나, 사이드카 컨테이너를 두거나, nginx를 부활시키거나.
    • API-Key 관리 - 뒷단 ALB에서 헤더 기반 룰을 정의하거나, 스프링 시큐리티를 쓰거나, nginx를 부활시키거나.

마지막 그림을 그려보자면⋯

HTTP API Gateway를 가정하고 제안 아키텍처 수정

 

최종적으로 이 개선안을 선택하고자 한다. HTTP API Gateway + ALB + ECS 컨테이너 조합은 기술 백서에서 언급된 레퍼런스 아키텍처이고 내가 수립한 Rationale에 가장 부합하여 정말 필요에 의한 자원들만 배치한다.