최근에 AWS의 Landing Zone 구조와 유사하게 사내 AWS 계정 구조를 변경하면서 공유 VPC를 사용하면 여러 혜택을 볼 수 있다는 것을 알게 되었습니다.
- 네트워크 관리 전용 계정의 분리를 통해서 공통 네트워크를 하나만 구성함으로써 다수의 계정에서 네트워크와 관련한 동일한 설정을 반복하지 않도록 합니다.
- 회사 부서마다 계정을 별도로 소유함으로써 부서에 속한 리소스의 관리에 대한 책임을 분할할 수 있으며, 비용 구분도 손쉽게 할 수 있습니다.
그래서 각 부서 별로 AWS 계정을 생성하고 네트워크 전용 계정에서 RAM (Resource Access Manager)을 사용하여 VPC와 서브넷을 사전에 미리 공유하는 등, 여러 준비를 진행해 놓고 때를 기다리고 있었습니다. 그리고 드디어 공유 VPC 위에서 처음으로 서비스를 구축하게 되었습니다.
RabbitMQ 생성의 문제
EC2와 ECS, RDS 등의 많은 서비스들이 아주 무난하게 구축이 진행되었습니다. Route 53의 Private DNS가 네트워크 계정에서 생성해야 하는 약간의 문제가 있었지만 공유 VPC의 사용에는 문제가 없었습니다. 그런데, 큰 문제는 RabbitMQ에서 발생했습니다.
RabbitMQ를 부서 계정에서 생성하려고 하면 VPC를 소유하지 않았기 때문에 MQ를 생성할 수 없다는 경고를 제공하고 있습니다. 그리고 현재 계정이 소유한 VPC를 제공하라고 합니다. 대체 이게 무슨 일일까요?
RabbitMQ를 생성하게 되면 AWS에서는 내부적으로 MQ에 대한 VPC 엔드포인트를 생성하게 됩니다. 실제로 RabbitMQ가 정상 생성되었다면 VPC의 엔드포인트 목록에서 신규 생성된 항목을 확인할 수 있습니다.
그런데, VPC 엔드포인트는 VPC를 소유하지 않은 부서 계정에서는 생성할 수 없고 네트워크 계정에서만 생성이 가능합니다. 이런 상황에서 VPC 엔드포인트가 필요한 RabbitMQ를 부서 계정에서는 절대로 생성할 수 없게 됩니다! 그래서 AWS 문서를 찾아보니 다음과 같은 내용이 적혀있었습니다. [Work with shared VPCs]
Unsupported services for shared subnets
Participants cannot create resources for the following services in a shared subnet:
- AWS CloudHSM
- Amazon MQ
- Amazon Managed Workflows for Apache Airflow (MWAA)
- RDS Proxy
앞서 언급한 것처럼 VPC 엔드포인트를 요구하는 서비스들은 공유 VPC에서 생성이 불가능하다고 합니다. 그럼에도 불구하고 RabbitMQ를 꼭 사용해야 하는 상황에서 이를 어떻게 극복할 수 있을까요?
네트워크 계정에 RabbitMQ를 설치하기
가장 손쉬운 해결 방법은 결국 네트워크 계정에서 RabbitMQ를 설치하는 것입니다. VPC 엔드포인트 생성이 가능하기 때문에 아무런 문제 없이 생성할 수 있습니다. 그렇지만 여기에는 고려해봐야 할 점이 있습니다.
- 애초에 네트워크 관리와 리소스 관리의 분리를 위해서 공유 VPC를 이용하는 상황인데, 목적과 맞지 않는 예외 케이스를 만들게 되어버립니다.
- RabbitMQ를 Managed 서비스로 이용하는 이유 중에 하나는 손쉬운 메트릭 수집입니다. 이러한 메트릭 기반으로 알람을 생성하고 Auto Scaling 정책을 수립하게 되는데, 네트워크 계정의 메트릭으로 부서 계정에서는 알람을 생성할 수 없거나, 공유받은 알람에 대해서 Auto Scaling 정책의 생성이 불가능합니다.
Auto Scaling에 메트릭 연동이 되지 않는 것은 저희 서비스에서 큰 문제로 인식되었습니다. 그래서 다른 방법을 알아봅니다.
부서 계정에 VPC 생성하기
소유한 VPC가 없어서 문제라면, VPC를 만들면 됩니다! 새로운 VPC를 서브넷 정도의 크기로 작게 생성하여 그 위에서 RabbitMQ를 생성합니다. 그리고 VPC를 네트워크 계정의 메인 VPC와 Peering을 맺습니다. 여기에도 물론 문제점은 있습니다.
- 네트워크 계정이 모든 네트워크를 통제하지 못할 수 있습니다.
- 부서 계정에서 네트워크에 대한 관리를 설정해야 할 수 있습니다.
그리고 위와 같은 문제점을 해결하기 위해서 부서 계정의 VPC는 네트워크 계정의 메인 VPC에 대한 Satellite 형태로 동작하도록 해야만 합니다. 즉, 내부 트래픽을 제외한 모든 트래픽을 Peering에 의존하도록 합니다.
네트워크 계정이 부서 계정의 VPC에 대한 모든 트래픽을 통제하려면, 부서 계정의 VPC에서는 0.0.0.0/0
에 대한 트래픽을 메인 VPC로 라우팅합니다. Internal 라우팅과 위에서 설정한 라우팅을 제외하고 그 어떤 라우팅도 설정하지 않습니다. 이렇게 설정하면, 부서 계정에서는 네트워크 설정을 최초 1회만 수행하면 건드릴 일이 없습니다.
저는 이 방법을 선택했습니다.
EC2 또는 ECS에서 RabbitMQ 사용하기
고민은 했지만, 수행하지는 않은 방법입니다. EC2에 직접 RabbitMQ를 설치하거나, 컨테이너 이미지를 기반으로 ECS 등에서도 RabbitMQ를 실행하고 사용할 수 있습니다. 특히, CloudWatch로 메트릭을 전송하는 유저 플러그인이 존재하기 때문에 AWS에서 제공하는 Managed RabbitMQ가 아니더라도 동일한 기능을 구현할 수 있습니다.
이 경우의 장단점은 다음과 같습니다.
- RabbitMQ는 RI (Reserved Inatance)/SP (Savings Plans)가 존재하지 않으면서 Managed 서비스라는 이유로 비용이 온디맨드 EC2 기준 3배 정도로 책정되어 있습니다. EC2에 설치하고 SP 할인을 적용 받는다면 1/5 정도의 비용으로 이용 가능합니다.
- RabbitMQ 설치나 대시보드 연동, 플러그인 설정에 많은 시간을 소모해야 할 수 있습니다. 그리고 이미 Managed 서비스에 맞게 구성된 설정들을 모조리 변경해야 하는 이슈가 있습니다.
- 모든 이슈를 직접 해결해야 하고 인프라에도 관심을 가져야 합니다.
저는 업무 부하를 낮춰야 하는 상황이라서 높은 비용을 선택했습니다.
부서마다 별도의 AWS 계정을 갖춰서 인프라에 대한 책임을 분산하고자 AWS 조직을 구성했고, 여기서 네트워크 관리 부담을 줄이기 위해서 공유 VPC 개념을 적용했는데 이렇게 예측하지 못했던 문제가 발생하게 되었습니다.
다른 분들도 동일한 문제를 겪게 될지도 모르기 때문에 글로 이력을 남기게 되었습니다. 다행히, 약간의 노력으로 해결은 되었으나 AWS에서도 이러한 문제에 대해서 좀 더 근본적인 해결책을 제공해주기를 바라며 글을 마칩니다.