[Practice] How to access a private RDS using AWS SSM

Private RDS Access Using AWS Session Manager
Dec 20, 2023
[Practice] How to access a private RDS using AWS SSM

 
 
일반적으로 클라우드 네이티브 환경, 그 중에서도 AWS에서 개발을 한다고 치면 Production Level의 서비스 구성이 필요하다.
 
Production Level, 이른바 prod 스테이지의 서비스 인프라 구성을 고민하다 보면 VPC와 서브넷을 통해 사설망으로 네트워크를 관리하는 것을 쉽게 떠올릴 수 있다.
 
Private Subnet에 EC2와 RDS를 가두고, bastion host를 통해 Private Subnet에 접근하는 이런 방식은 흔하디 흔하게 사용되지만 부수적이며 고질적인 문제가 따라온다.
 
바로 내 로컬 Vscode 개발 환경에서, Private Subnet안에 갇혀 있는 RDS에 접근하여 데이터 쿼리를 돌려본다거나 로컬에서 테스트를 진행할 상황이 흔히들 생기곤 하는데 로컬에서 접근이 불가능하다는 것이다.
 
이번에 회사에서 dev 스테이지 구성을 위에서 언급한 것과 비슷하게 구성하게 됐고, 일반적인 db 연결로는 불가능 하다는 사실을 깨닫고 방법을 찾기 시작했다.
 
AWS VPN이나, 자체 VPN 설정을 통해 접근할까도 고민했지만 복잡하고 많은 설정이 필요하다는 결론이 나와 다른 방안을 찾던 중 SSM을 이용한 Private RDS 접근 방법에 대해 알게 됐다. 그리고 찾아본 결과 SSM을 이용한 방식을 사용하기로 결정했는데
 
그 중 가장 큰 이유는, AWS Client VPN Endpoint이 너무 expensive하다는 것이었다.
 

 
 
notion image

AWS SSM

 
AWS SSM(AWS Session Manager)은 AWS의 수 많은 리소스와 Application 운영을 지원하기 위해 생성된 E2E 관리 솔루션이다. Session Manager는 종합 관리형 AWS Systems Manager 기능입니다.
 
공식문서대로의 설명은 저렇지만, 간단하게 설명하면
 
인프라를 제어하고, 사용자가 SSH 연결 없이도 AWS 리소스에 접근하여 원격으로 명령을 실행할 수 있도록 도와주는 Support tool이라고 볼 수 있다.
 
SSM의 장점은 다음과 같다.
 
  • PEM키가 필요없다.
    • 일반적으로 PEM키는 EC2당 하나를 만들고 모든 사람이 하나의 PEM키를 돌려서 사용할 것이라고 생각한다… 매우 건설적이지 못하지만, FM대로 하면 개인당 하나의 PEM키를 사용해야 하는데 이건 관리 포인트가 너무나 늘어나기 때문에 규모가 작아질수록 어려운 선택이라고 생각한다. 일단 이런 PEM키에서 벗어날 수 있다.
  • Security Group이 필요하지 않다.
    • 보안 그룹의 inbound 설정.. port를 열어주고 이런 귀찮은 행위에서 벗어날 수 있다.
  • Bastion Host가 필요하지 않다.
    • 이런 장점과 무관하게 SSH로 접근할 경우도 필요했기 때문에 크게 체감되진 않았다.
  • SSM을 통해 RDS를 내 로컬에서 forwading하여 연결할 경우, RDS의 host에 크게 구애받지 않고 내 local의 원하는 port에서 데이터베이스에 연결할 수 있다.
 
그렇다면 단점은?
  • 결국 단지 CLI와 엮여 있는 리소스 Supporting이라는 측면에서 분명 한계가 존재한다.
  • 내가 소개할 Private RDS는 위에서 Bastion Host가 필요하지 않다고 했지만, 필요하다.
 
사실 크게 단점을 찾지 못했다.
존재 자체만으로도, 기존의 다른 리소스들의 단점을 어느정도 커버할 수 있는 영역에 있다고 느꼈기 때문에 아주 체계적으로 무언가를 갖춰서 사용하는 것도 아니었고 단점을 크게 찾기 어려웠다.
 

 

실습

  • 여기서 말하는 EC2는 Bastion Host를 의미합니다.
  • 해당 솔루션은 Window / Mac에 AWS CLI가 설치되어 있다는 가정입니다.

1. EC2 Instance Profile 설정

먼저 EC2에 권한을 설정해야 한다. EC2의 Instance Profile은 사용자가 IAM으로 특정 권한만 할당 받아 해야하는 리소스만 사용하는 것 처럼, EC2에도 이와 비슷하게 권한을 부여하고 권한에 따른 수행만 가능하도록 설정하는 것이다.
 
  • AmazonSSMManagedInstanceCore
    • IAM config
      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:StartSession", "ssm:DescribeAssociation", "ssm:GetDeployablePatchSnapshotForInstance", "ssm:GetDocument", "ssm:DescribeDocument", "ssm:GetManifest", "ssm:GetParameter", "ssm:GetParameters", "ssm:ListAssociations", "ssm:ListInstanceAssociations", "ssm:PutInventory", "ssm:PutComplianceItems", "ssm:PutConfigurePackageResult", "ssm:UpdateAssociationStatus", "ssm:UpdateInstanceAssociationStatus", "ssm:UpdateInstanceInformation" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2messages:AcknowledgeMessage", "ec2messages:DeleteMessage", "ec2messages:FailMessage", "ec2messages:GetEndpoint", "ec2messages:GetMessages", "ec2messages:SendReply" ], "Resource": "*" } ] }
 
위 IAM을 검색하여 EC2 Instance Profile에 설정해서 연결까지 시켜줘야 한다.
 
위 권한을 설정해주지 않는다면,
An error occurred (TargetNotConnected) when calling the StartSession operation: i-067274f7d4511ac57 is not connected.
 
라는 에러와 함께 연결이 안될 것이다.
 
그리고 EC2안에 SSM Agent를 설치해야 하는데, 기본적으로 Ubuntu LTS 22.04 버전부터는 EC2안에 설치된다고 하지만 실제 EC2에 들어가
sudo snap start amazon-ssm-agent // ssm agent 실행 sudo snap services amazon-ssm-agent // 상태확인
 
커맨드를 입력하여 실제 Agent가 돌아가고 있는지 확인해 줘야 한다.
Agent까지 정상 작동하고 있는 걸 확인했다면 나의 로컬환경 설정을 해주어야 한다.
 
 

2. Local Vsocde 동작을 위한 설정

일단 나의 Local Window / Mac에 AWS Session Manager Plugin을 설치해야 합니다.
https://s3.amazonaws.com/session-manager-downloads/plugin/latest/windows/SessionManagerPluginSetup.exe
 
위 주소를 입력하면, 다운로드가 실행되고 다운로드된 파일을 실행시키면 설치됩니다.
 
EC2의 Instance Profile에 설정해줬던 것 처럼, 나의 IAM에도 아래와 같은 config 설정을 해주어야 한다. 결국 SSM은 Local AWS CLI에 등록된 나의 AWS IAM을 기반으로 동작하는 것이기 때문에 권한이 빠지면 안된다.
IAM config
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:StartSession", "ssm:DescribeAssociation", "ssm:GetDeployablePatchSnapshotForInstance", "ssm:GetDocument", "ssm:DescribeDocument", "ssm:GetManifest", "ssm:GetParameter", "ssm:GetParameters", "ssm:ListAssociations", "ssm:ListInstanceAssociations", "ssm:PutInventory", "ssm:PutComplianceItems", "ssm:PutConfigurePackageResult", "ssm:UpdateAssociationStatus", "ssm:UpdateInstanceAssociationStatus", "ssm:UpdateInstanceInformation" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2messages:AcknowledgeMessage", "ec2messages:DeleteMessage", "ec2messages:FailMessage", "ec2messages:GetEndpoint", "ec2messages:GetMessages", "ec2messages:SendReply" ], "Resource": "*" } ] }
 
Plugin이 설치되고 나면, powerShell을 열어 다음의 커맨드를 입력하고 accesskey와 secretKey 등을 입력해 줘야 한다.
aws configure
 
입력이 모두 완료 됐다면, 다시 한 번 커맨드 입력을 통해 설정된 CLI config가 올바른지 확인합니다.
aws sts get-caller-identity
 

Port fowarding

configure입력까지 끝났다면, powerShell을 열어 아래 커맨드를 한줄로 입력합니다.
aws ssm start-session --target "EC2 ID" --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters host="RDS HOST END POINT",portNumber="RDS PORT 번호",localPortNumber="로컬에서 사용할 포트번호" aws ssm start-session --target "bastionhost instanceId" --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters host="RDS 호스트 주소",portNumber="rds 접근 port",localPortNumber="원하는 forwarding port" // 이런느낌인데 실행되지 않는다면 --parameter부분에 띄어쓰기가 들어가서 그럴 확률 이높습니다. // 위에 실행 커맨드처럼 딱 붙여서 작성해주세요
 
아마도.. 올바른 값을 넣어 한줄로 입력한다면 실행될 것 입니다. 간단하게 설명을 드리면
  • target
    • 포트 포워딩의 주체가 될 타겟인 Bastion Host EC2 ID입니다.
  • document-name
    • 아마도.. 문서이름을 전부 저렇게 하는 것으로 보아, 국룰인 것 같습니다.
  • parameters
    • host : RDS HOST 엔드포인트입니다.
    • portNumber: RDS의 Port 번호입니다.
    • localPortNumber: 로컬에서 사용할 포트번호 입니다.
 
위와 같은 절차를 모두 따라 했다면, 이제
HOST = "127.0.0.1" PORT = "3307" USER = "root" PWD = "password"
 
이런식의 환경변수로도 위에서 언급했던 커맨드가 실행되면서 자연스럽게 Private RDS에 접근할 수 있게 됩니다.
 
이제 로컬 Vscode에서도 DB에 접근하여 서버가 실행됩니다.
 
Share article

vlogue