배경
이직한 회사에서 데이터 허브를 적극적으로 활용하여 데이터셋과 컬럼에 대한 메타데이터를 체계적으로 관리하려는 니즈가 있었다. 기존엔 쿠버네티스와 ArgoCD를 통해 배포 자동화를 주로 진행했었는데, 이번에는 EC2에 설치된 데이터 허브 환경에서 YAML 파일로 메타데이터를 관리하고, 이를 파이썬 코드와 GitHub Actions를 이용해 자동 업데이트하는 프로세스를 구축하게 되었다.
초기에는 단순히 PEM 키를 이용한 SSH 접근 방식으로 충분할 것이라 생각했지만, EC2가 위치한 환경이 VPC 환경이어서 불가능했다.
문제 상황
프라이빗 서브넷 환경
•
GitHub Actions에서 직접 SSH로 EC2 인스턴스에 접근해 git pull 명령어를 실행하려 했으나, 프라이빗 서브넷으로 인해 접근이 불가했다.
•
GitHub Actions의 GitHub-hosted runner는 인터넷에서 실행되기 때문에 직접 SSH 접근이 차단됨
해결 방법 고려
•
Bastion host 사용
•
Proxy 서버 설정
•
AWS Systems Manager 사용
별도의 서버 구축(Bastion Host나 Proxy 서버) 시 추가적인 인프라 운영 부담이 생기므로 가장 간편하게 사용할 수 있는 AWS Systems Manager를 선택했다.
AWS Systems Manager(SSM)이란?
AWS Systems Manager는 AWS 리소스를 중앙에서 관리·운영하기 위한 통합 관리 서비스다. EC2 인스턴스를 비롯하여 온프레미스 서버, 가상 머신 같은 다양한 환경을 관리 대상(Managed Instance)으로 등록하여 일괄적으로 설정 적용, 패치, 명령 전달, 인벤토리 수집 등을 수행할 수 있다.
SSM 에이전트
•
역할
◦
관리대상으로 등록된 EC2 인스턴스 내부에서 상시 실행되는 데몬(daemon) 프로세스
◦
AWS Systems Manager 서비스와의 통신 채널을 유지하며, 중앙에서 보내는 명령(Command)이나 정책(State)을 주기적으로 폴링해서 가져와 실행
•
통신 방식
◦
에이전트는 HTTPS(포트 443)로 SSM 엔드포인트에 연결하여, JSON 형태의 Run Command Request나 State Manager Document 등을 내려받음
◦
실행 결과는 암호화된 HTTPS 응답을 통해 다시 S3, CloudWatch나 Systems Manager 콘솔에 업로드
◦
별도의 SSH 포트(22) 개방 없이도 AWS 내부망을 통해 양방향 통신이 이루어지므로, 프라이빗 서브넷처럼 외부에서 SSH 접근이 불가능한 환경에서도 명령을 안전하게 보낼 수 있다
•
Amazon Linux AMI에는 기본으로 SSM Agent가 설치되어 있어 따로 설치해주진 않음
SSM 문서(Document)
•
개념
◦
SSM Documents는 JSON 또는 YAML 형식으로 작성되는 작업 템플릿
◦
Amazon이 제공하는 AWS-RunShellScript, AWS-UpdateLinuxAmi, AWS-ApplyPatchBaseline 같은 사전 정의 문서가 있고, 필요에 따라 Custom Document도 만들 수 있음
•
AWS-RunShellScript:
◦
이번에 사용하는 Run Command 기능에서 가장 많이 쓰이는 기본 문서
◦
Bash 스크립트를 한 번에 여러 인스턴스에 전달해서 실행한다
요약
•
SSM Agent가 설치된 EC2는 별도 SSH 포트 없이 AWS SSM 서비스와 통신해 원격 명령을 수신·실행
•
IAM Role과 SSM 정책만 있으면, SSH 키를 관리할 필요 없이 Run Command 기능으로 안전하게 git pull 같은 쉘 명령을 실행할 수 있음
•
SSM 명령 실행 이력은 CloudTrail에 기록되어 누가 언제 어떤 문서를 어떤 인스턴스에 실행했는지를 전부 추적할 수 있음
명령 실행 이력
SSM 트러블 슈팅
아래는 SSM을 사용하며 발생 했던 이슈 및 해결과정이다.
1. SSM 권한 설정
•
문제: IAM 역할에 SSM 명령을 실행 권한이 없어 권한 부족 에러 발생
•
해결 방법: EC2 인스턴스의 IAM 역할에 필요한 SSM 권한 추가
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2messages:*",
"ssmmessages:*"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "ssm:SendCommand",
"Resource": [
"arn:aws:ssm:리전:*:document/AWS-RunShellScript",
"arn:aws:ec2:리전:계정ID:instance/연결할ec2인스턴스아이디"
]
}
]
}
JSON
복사
•
EC2와 SSM이 서로 메시지 주고 받을 수 있도록 ec2messages:* & ssmmessages:* 설정 필요
•
AWS의 공식 문서인 AWS-RunShellScript를 사용하므로 리전 뒤에 특정 계정 ID 대신 *을 지정
Git ownership (소유권) 문제
•
문제: SSM 명령이 기본적으로 root 사용자로 실행되어 Git 저장소와 소유자가 달라 Git의 보안 경고 발생
fatal: detected dubious ownership in repository at '/home/ec2-user/git-repo'
Plain Text
복사
•
해결 방법:
◦
Git 전역 설정으로 안전한 디렉터리(safe.directory) 추가
sudo git config --system --add safe.directory /home/ec2-user/petfriends-data-catalog
Bash
복사
◦
Git 명령을 소유자(ec2-user) 권한으로 실행
command: |
sudo -u ec2-user <실행 커맨드>
YAML
복사
Host key verification 문제
•
문제: GitHub의 호스트 키 검증 오류 발생
◦
SSH는 최초 연결 시 상대 서버(GitHub)의 공개키를 로컬의 known_hosts에 기록하고 이후 연결 시 이 키로 서버의 신원을 확인
Host key verification failed.
Bash
복사
•
해결 방법: GitHub의 호스트 키를 시스템 전체의 ssh_known_hosts에 추가
sudo mkdir -p /etc/ssh # 없으면 만들것
sudo ssh-keyscan -H github.com | sudo tee -a /etc/ssh/ssh_known_hosts
Bash
복사
◦
명령어 설명:
▪
ssh-keyscan은 지정된 호스트(github.com)에 연결하여 SSH 서버가 제공하는 호스트 공개키를 가져옴
▪
이를 시스템 전체에서 접근 가능한 /etc/ssh/ssh_known_hosts에 저장하여 이후 모든 사용자가 SSH 연결 시 서버 신원을 바로 확인 가능하도록 함
최종 성공한 명령어
GitHub Actions의 최종 실행 명령은 아래와 같다.
- name: SSM - Git Pull on EC2
uses: peterkimzz/aws-ssm-send-command@master
with:
aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
instance-ids: ${{ secrets.EC2_INSTANCE_ID }}
working-directory: /home/ec2-user/git-repo
command: |
sudo -u ec2-user git pull origin master
comment: git pull from ${{ github.actor }} - commit ${{ github.sha }}
YAML
복사
•
GitHub Actions 워크플로우를 통해 EC2 인스턴스에 GitHub에서 최신 코드를 가져오는 환경 구축
