※ 이 방법은 EC2 인스턴스에 SSH로 직접 접근하는 방식으로, 빌드를 EC2 인스턴스 상에서 진행하기 때문에 EC2 메모리 등의 자원을 사용하여 서비스에 영향을 줄 수 있습니다. 빌드를 Github Actions에서 진행하여 S3에 업로드하고, S3에 업로드된 파일을 바탕으로 EC2에 배포하는 방식을 사용한다면 AWS CodeDeploy를 사용하시는 것을 추천합니다.
name: Deploy
on:
workflow_dispatch:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Get Github Actions IP
id: ip
uses: haythem/public-ip@v1.2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Add Github Actions IP to Security group
run: |
aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
- name: SSH Commands
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.AWS_SSH_HOST }}
username: ${{ secrets.AWS_SSH_USERNAME }}
key: ${{ secrets.AWS_SSH_KEY }}
port: ${{ secrets.AWS_SSH_PORT }}
script_stop: true
script: |
cd my-project
npm ci
npm run build
- name: Remove Github Actions IP From Security Group
run: |
aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
각 step별로 나누어 설명하겠습니다.
Get Github Actions IP
EC2에 SSH로 접근하려면 보안 그룹의 인바운드 규칙에서 접근을 시도하는 쪽의 IP를 미리 등록해야 합니다.
하지만 Github Actions의 IP를 미리 알 수 없기 때문에 배포시 Github Actions의 IP를 받아서 EC2의 보안 그룹에 해당 IP로의 접근을 허용하는 인바운드 규칙을 추가하여야 SSH로 EC2에 접근할 수 있습니다.
현재 step에서는 "ip"라는 이름으로 Github Actions의 IP를 출력하여 다음 step들에서 접근할 수 있도록 해줍니다.
Configure AWS Credentials
AWS 관련 설정값을 등록합니다. aws-access-key-id, aws-secret-access-key는 AWS IAM에서 사용자를 등록하면 받는 액세스 키 ID와 시크릿 액세스 키에 해당합니다. aws-region에는 현재 EC2가 위치한 리전을 작성하면 됩니다. 저는 서울 리전을 사용하고 있으므로 ap-northeast-2를 작성하였습니다.
이 step에서 등록된 값들은 이후의 step들에서 AWS CLI를 사용할 때 자동으로 설정값으로 들어가게 됩니다.
여기서 aws-access-key-id, aws-secret-access-key는 반드시 EC2에 대한 접근 권한(ex AmazonEC2FullAccess 등)을 가진 사용자의 키를 사용해야 합니다.
Add Github Actions IP to Security Group
AWS CLI로 EC2의 보안 그룹에 현재 Github Actions의 IP를 등록하여 SSH 접근이 가능하도록 해줍니다.
AWS_SG_ID는 EC2의 보안 그룹 ID를 나타냅니다.
SSH Commands
SSH로 EC2 인스턴스에 접근합니다. 접속을 위해 필요한 값으로 host는 EC2 서버 IP주소, username은 EC2 유저 이름(AWS Linux를 사용한다면 기본값은 ec2-user입니다. EC2 인스턴스에서 whoami 명령어로 확인 가능합니다.), key는 EC2 인스턴스를 생성할 때 발급받은 키(.pem 파일 => 메모장으로 열어서 안에 있는 값 전체를 사용하면 됨), port는 인바운드 규칙에서 정의한 포트(AWS에서 인바운드 규칙 유형을 SSH로 하면 자동으로 22로 설정됨. 또한 appleboy/ssh-action 자체에서 port의 기본값이 22이므로 작성하지 않아도 됨)를 나타냅니다.
script_stop은 중간에 하나 실패하면 뒤에 있는 스크립트를 실행하지 않는 옵션입니다.
마지막으로 script에 EC2 인스턴스 상에서 실행할 명령어들을 입력하면 됩니다. 이 방식을 사용한다면 여기서 build를 해야할 것입니다. (build를 Github Actions에서 하지 않기 때문에 checkout 같은 action도 필요 없음)
Remove Github Actions IP From Security Group
앞에서 Github Actions의 임의의 IP에 대해 SSH 접근을 허용했었는데, 이제 필요한 작업이 끝났으니 이 IP로부터의 접근을 허용하는 인바운드 규칙을 삭제합니다.
필자는 EC2에 배포를 직접 수동으로 하다가 배포 자동화를 위해 구글링하면서 위 방법을 사용하게 되었으나, 이 방법은 EC2에 수동으로 배포하는 작업 그대로를 자동화한 것뿐이기에 그다지 효율적이지 않은 것을 알게 되었습니다. 가능하면 AWS에서 제공하는 CodeDeploy를 사용하시고, 이 방법은 부득이하게 Github Actions에서 EC2에 SSH로 접근하고자하는 분께 추천드립니다.
참고자료
https://kaizen8501.tistory.com/m/260
https://www.daleseo.com/github-actions-steps/
https://kamrul.dev/dynamically-add-github-actions-ip-to-aws-security-group/
https://docs.aws.amazon.com/cli/latest/reference/ec2/authorize-security-group-ingress.html