WiseN

AWS 업데이트 읽어주기 - S3용 AWS Privatelink(Interface Endpoints)가 출시되었습니다

Mar 25, 2021   |   AWS

작성자_최준승

페이스북 공유하기 트위터 공유하기
Blog thumbnail

안녕하세요. 오늘은 S3용 PrivateLink 출시소식을 전해드리려고 합니다. 이번 업데이트는 단위 기능이 새로 출시되었다기 보다는, 기존 기능에 대상이 확대된 것이라서요. 막 새로운 내용은 아니지만, 부분적으로 알아둬야 할 차이점들이 제법 있어서 관심 있으신 분들은 주의깊게 읽어보셔야 합니다.

 

AWS를 포함한 대부분의 클라우드 벤더에서는 VPC라는 가상네트워크 서비스를 제공합니다. VPC 서비스의 가장 큰 목적은 내가 갖고 있는 가상 서버들을 묶어 일정한 사설주소 공간에 격리하는 것입니다. 내부적으로는 어떻게 구현이 되어 있을지 몰라도, 사용자는 일정한 주소대역을 갖고 있는 가시적인 네트워크 공간을 만든 후에 그 내부에 서브넷과 서버를 배치하게 됩니다. 그리고 이 범위 안에서 일정한 방화벽 규칙을 거쳐 서버간 통신을 하게 됩니다.


통신은 VPC 내의 서버간에만 하는 것이 아니고, 동일 벤더 내의 타 서비스(예를 들어 AWS S3)와 통신해야 하는 상황도 빈번합니다. 예를 들어 EC2라고 하면 내부에서 생성되는 로그를 S3라는 객체 스토리지에 밀어넣는 상황이 있을수 있습니다. 이때 문제는 S3 주소의 끝점이 VPC 내부에 있는것이 아니라 VPC 외부(Public)에 있다는 것입니다. 그렇다고 EC2 인스턴스를 Public Subnet 위치에 배치하기도 좀 그렇기 때문에, 보통은 NAT G/W같은 Proxy 계층을 Outbound 전용으로 만들어 "Public 구간에 있는 타 서비스"를 제어하거나 상호 데이터를 주고 받게 됩니다.


NAT G/W를 통해 인터넷 구간과 통신을 하면 편하기는 한데, 문제는 별도의 제어 계층이 없는 경우​ AWS 서비스 外의 끝점과도 자유롭게 통신을 할 수 있게 됩니다. 예를 들어 임의의 주소값을 통해서 외부에서 악성코드를 당겨올수도 있구요. 보안상 아무래도 단위 서버와 외부간 접점이 커지기 때문에 사용자는 "VPC 내부의 객체"와 오직 "AWS 서비스 끝점"과만 따로 통신할 수는 없을지 고민을 하게 됩니다. 그래서 만들어진 기능이 VPC Endpoint입니다. 비슷한 개념의 연장선에서 GCP에는 Private Google Access라는 기능이 있고, 네이버 클라우드에는 서비스 별로 별도의 사설 도메인을 제공하기도 합니다.

 

참고로 AWS에서는 2가지 유형의 VPC Endpoint를 제공합니다. 하나는 Gateway 방식, 다른 하나는 Interface 방식입니다. 각 서비스별로 제공하는 VPC Endpoint의 유형이 다르구요. 참고로 대부분의 AWS 서비스는 Interface 방식의 유형을 제공합니다. 초창기에 S3와 DynamoDB 등의 서비스만 Gateway 유형의 VPC Endpoint를 제공해 왔는데요. 이번 업데이트로 S3 서비스의 경우 (기존 Gateway 방식에 덧붙여) 아래처럼 Interface 방식을 추가적으로 지원하게 되었습니다.

 


 

자, 그럼 이제 VPC 내의 객체(EC2, Lambda 등)가 S3와 은밀히(?) 통신할때 사용할 수 있는 기법이 2가지가 생긴 셈인데요. 각 유형의 동작 방식은 어떻고, 어떤 상황에서 어떤 유형의 VPC Endpoint를 활용해야 하는지 간단한 테스트를 통해 살펴보도록 하겠습니다.


먼저 기존 Gateway 유형이 어떤식으로 동작하는지부터 짚고 넘어가겠습니다. 예시 그림을 보시죠.




V1은 그야말로 Public Subnet에 위치한 인스턴스입니다. S3를 포함하여 인터넷 구간에 있는 끝점과 양방향으로 자유롭게 통신할 수 있습니다. V1 인스턴스 내부에서 한번 특정 S3 버킷을 대상으로 객체 Listing 요청을 해보겠습니다.


$ nslookup s3.ap-northeast-2.amazonaws.com

Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   s3.ap-northeast-2.amazonaws.com
Address: 52.219.60.145

$ aws s3 ls s3://jschoi.acl
                           PRE private1/
                           PRE public1/
2017-09-26 05:03:18      29606 jschoi.acl_test.csv

2018-06-21 07:44:25      25184 what-is-eks.png​

 

​역시 잘됩니다. Seoul Region의 S3 서비스 끝점 주소을 조회하면 52. 대역의 IP값을 반환합니다. 이 주소는 공인IP 대역이구요. V1은 Public Subnet에 위치하기 때문에 S3 서비스 끝점에 요청을 전달하고 응답을 받아오는데 전혀 문제가 없습니다.


이번에는 (그림에는 없지만) 임의의 Private Subnet에 V3라는 인스턴스가 있다고 가정해보겠습니다. 어떤 VPC Endpoint도 설정되어 있지 않은 Private Subnet입니다. 여기서 동일한 요청을 해보도록 하겠습니다.


$ nslookup s3.ap-northeast-2.amazonaws.com

Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   s3.ap-northeast-2.amazonaws.com
Address: 52.219.56.89

$ aws s3 ls s3://jschoi.acl --debug
[중략]
2021-04-13 04:43:47,423 - MainThread - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): s3.ap-northeast-2.amazonaws.com:443
2021-04-13 04:48:56,413 - MainThread - awscli.clidriver - DEBUG - Exiting with rc 255

Connect timeout on endpoint URL: "https://s3.ap-northeast-2.amazonaws.com/jschoi.acl?list-type=2&delimiter=%2F&prefix=&encoding-type=url"


우선 dns 조회에는 문제가 없습니다. 동일하게 52.대역의 A레코드가 반환됩니다. 그리고 이어 s3 ls 요청을 하게 되면, Private Subnet에 위치한 V3라는 인스턴스는 저 공인IP 대역의 주소와 통신할 수 있는 라우팅값이 없기 때문에 Connection Timeout이 발생하게 됩니다. (에러 로그를 위해 debug모드로 요청함)


다음으로는 그림에서 보이는 V2의 경우를 살펴보겠습니다. V2가 위치한 Subnet의 경우 Gateway 유형의 VPC Endpoint를 설정한 상태입니다. (Gateway 유형의) VPC Endpoint를 구성하고, 그 Endpoint를 사용할 Subnet을 지정하게 되면 아래와 같이 일부 라우팅값이 추가됩니다.




V2 인스턴스에서 동일한 요청을 해보겠습니다.


$ nslookup s3.ap-northeast-2.amazonaws.com

Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   s3.ap-northeast-2.amazonaws.com
Address: 52.219.148.40

$ aws s3 ls s3://jschoi.acl
                           PRE private1/
                           PRE public1/
2017-09-26 05:03:18      29606 jschoi.acl_test.csv

2018-06-21 07:44:25      25184 what-is-eks.png

 

결론은 잘됩니다. S3 끝점은 52.대역의 주소값이 반환되었지만, Gateway 유형의 VPC Endpoint를 통해 vpce-xxxxxx라고 하는 별도의 라우팅을 따라서 S3 끝점에 Access하게 됩니다. 글머리에서 말씀드렸던 "오직 AWS 서비스와의 통신만 가능"한 구성이 완료되었네요. 단, 여기서 VPC Endpoint를 통해 접근할 수 있는 AWS 서비스 끝점은 동일 리전의 끝점에 한정된다는 것을 유의하셔야 합니다.


자, 다음 순서는 Interface 유형의 VPC Endpoint를 살펴볼 차례입니다. 이번에 출시된 S3용 Interface 유형 VPC Endpoint(PrivateLink)를 살펴보기 전에, 다른 Interface 유형의 VPC Endpoint가 어떤 메커니즘으로 동작하는지부터 보도록 하겠습니다. 이것을 살펴보는 이유는 기존의 것들과 S3의 그것이 좀 다른 부분이 있기 때문입니다.




Kinesis용 VPC Endpoint(Interface)를 한번 볼까요. 사용자가 Interface 유형의 VPC Endpoint를 만들면 VPC안에 사설 주소를 가진 끝점이 하나 생성됩니다. 그리고 VPC 내부의 객체로부터 이 ENI의 주소값을 매개로 하여, 각 AWS 서비스 끝점과 통신할 수 있습니다. Gateway 유형 VPC Endpoint처럼 라우팅을 따로 정의할 필요가 없이, 마치 내부 통신처럼 동작하게 됩니다. 대신 어플리케이션 등에서 각 서비스 끝점을 지칭하는 주소값을 기존것이 아닌 vpce-*로 시작하는 별도의 주소값을 사용해야 합니다. 그래야 앞에서 생성한 ENI의 주소값이 반환되고, 해당 끝점을 통해 통신하게 됩니다.


그런데 어플리케이션에 별도의 주소값을 따로 지정해줘야 한다면 불편하지 않을까요? 그냥 기존의 주소값(각 리전별 서비스 끝점)을 사용할 수는 없을까요? 네, 가능합니다. 단, VPC Endpoint(Interface)를 만들때 아래 옵션을 활성화해야 합니다.




위 옵션을 켜게 되면 별도의 vpce-* 주소값을 사용할 필요 없이, 기존과 동일한 리전별 서비스 끝점 주소를 사용하면 됩니다. 그럼 VPC 내부의 DNS가 알아서 내부에 생성한 ENI의 끝점 주소를 반환하고, 해당 VPC Endpoint를 통해 통신할 수 있습니다. 아래 그림처럼 되는 셈이죠.




이해를 돕기 위해 EC2용 VPC Endpoint(Interface)를 하나 만들어서 테스트를 해보도록 하겠습니다. 위에서 말씀드린 "Enable DNS name" 옵션을 활성화한 상태입니다.


$ nslookup ec2.ap-northeast-2.amazonaws.com

Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   ec2.ap-northeast-2.amazonaws.com
Address: 10.0.12.153
Name:   ec2.ap-northeast-2.amazonaws.com

Address: 10.0.11.233

 

​보이시나요? "ec2.ap-northeast-2.amazonaws.com"라고 하는 기존의 서비스 끝점 주소를 질의했을때, VPC 내부의 사설 IP주소가 반환되는것을 볼 수 있습니다. ​이런 구성이 완료되면 어플리케이션에서 따로 주소값을 지정해줄 필요없이, VPC 구성만으로 원하는 라우팅이 구현되도록 만들 수 있습니다. 개인적으로 봤을때 가장 이상적인 구성입니다.

 

자, 드디어 이번에 출시된 S3용 VPC Endpoint(Interface)를 살펴보도록 하겠습니다. 결론부터 말씀드리면, S3용 VPC Endpoint(Interface)는 다른 서비스의 VPC Endpoint(Interface)와 달리 Private DNS 기능을 지원하지 않습니다.

 


 

따라서 S3용 VPC Endpoint(Interface)를 구성(Gateway 유형은 설정X)하고 테스트를 해보면 아래와 같이 동작합니다. 왜 저런 결과값이 나왔는지를 이해하시면 됩니다.


$ nslookup s3.ap-northeast-2.amazonaws.com

Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   s3.ap-northeast-2.amazonaws.com
Address: 52.219.56.117

$ aws s3 ls s3://jschoi.acl
[Connection Timeout]

$ nslookup bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com
Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com
Address: 10.0.12.133
Name:   bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com
Address: 10.0.11.80​

$ aws s3 --endpoint-url https://bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com ls s3://jschoi.acl
                           PRE private1/
                           PRE public1/
2017-09-26 05:03:18      29606 jschoi.acl_test.csv

2018-06-21 07:44:25      25184 what-is-eks.png


충분히 이해가 가셨을테니, 이번 결과는 따로 해설을 달지 않도록 하겠습니다.

 

자, 그럼 다시 원점으로 돌아와서 AWS에서 이번 기능을 출시한 이유가 무엇일까요? 아래 그림이 힌트입니다.





Direct Connect나 VPN을 통해 VPC와 연동되는 On-Premise 구간이 특정 IDC에 있다고 가정해보겠습니다. 이때 On Premise 내부의 서버에서도, VPC 내부의 서버와 마찬가지로 "Public 구간에 있는 S3같은 서비스"에 Access가 필요한 상황이 있을 수 있겠죠. IDC에서 바로 인터넷 구간으로 나가서 S3와 직접 통신하는 것이 아닌 연동구간(Direct Connect/VPN)을 통해 Access하는 것이 보안상 더 바람직한 구성입니다. 이때 기존처럼 Gateway 유형의 VPC Endpoint만 지원했던 S3의 경우, On Premise의 객체가 S3와 통신하려면 부득이하게 VPC 내부에 Proxy 서버를 구성해야 하는 요구사항이 있었습니다. Gateway 유형의 Endpoint 라우팅을 탈 수 있는 대상이 오직 VPC 내부의 객체만 가능하다는 제약사항 때문이었는데요. Proxy야 구성하면 그만이지만, 해당 계층은 사용자 영역이기 때문에 가용성을 관리하거나 해당 EC2 인스턴스의 성능(네트워크등)이 병목으로 작용하는 등의 이슈가 있었습니다.


이번에 S3용 Interface 유형의 VPC Endpoint가 출시된 이유는 위와 같은 연동구간에서 좀 더 쉽게 S3에 Access할 수 있도록 하기 위함입니다. Proxy 서버를 거쳐 Gateway 유형의 Endpoint 라우팅을 탈 필요 없이, VPC 내부에 구성된 VPC Endpoint(Interface) ENI 끝점의 주소값만 정확하게 찍어주면, 원하는 Private한 통신을 할 수 있게 됩니다.


이제 S3로 Private하게 Access하기 위한 2가지 선택지가 생겼습니다. 그럼 이 두가지 유형중에 무엇을 골라 사용해야 할까요? 아래 그림에 힌트가 있습니다.

 



​참고로 Gateway 유형과 Interface 유형 2가지를 모두 설정하고 테스트하면 아래와 같은 결과가 나옵니다.

 

$ nslookup s3.ap-northeast-2.amazonaws.com

Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   s3.ap-northeast-2.amazonaws.com
Address: 52.219.58.25

$ aws s3 ls s3://jschoi.acl
                           PRE private1/
                           PRE public1/
2017-09-26 05:03:18      29606 jschoi.acl_test.csv
2018-06-21 07:44:25      25184 what-is-eks.png

$ nslookup bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com
Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com
Address: 10.0.12.133
Name:   bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com
Address: 10.0.11.80

$ aws s3 --endpoint-url https://bucket.vpce-0916e80803286e2d6-s14qjhy6.s3.ap-northeast-2.vpce.amazonaws.com ls s3://jschoi.acl
                           PRE private1/
                           PRE public1/
2017-09-26 05:03:18      29606 jschoi.acl_test.csv

2018-06-21 07:44:25      25184 what-is-eks.png​ 


결론입니다. Gateway 유형의 VPC Endpoint의 경우, 가장 큰 장점은 오고가는 트래픽이 무료라는 것입니다. 따라서 VPC 내부의 객체(EC2 인스턴스, Lambda 등)는 Gateway 유형의 VPC Endpoint를 활용하는 것이 좋습니다. 그리고 On Premise의 연동 구간에서 S3에 접근이 필요할때는 Gateway 유형은 활용할 수 없으므로, 이번에 새로 나온 Interface 유형의 VPC Endpoint를 활용(대신 별도의 끝점 주소를 사용)하면 됩니다. 간단하죠?


​오늘 소개드린 내용이 좀 많았는데요. 이런 VPC 구성들은 처음에 잘 셋팅해 놓으면, 나중에 어플리케이션에서 신경쓸 것들이 많이 줄어듭니다. 관련 지식이 필요하신 분들께 도움이 되시길 바랍니다. 마칩니다. 끝.