저번 포스팅에서는 Github Actions Workflow 내에서 빌드 결과물을 zip 파일로 만드는 것까지 진행했습니다. 이번 포스팅에서 다룰 부분은 아래 파란 부분입니다.
보안 상의 이유로 Workflow에서 바로 Code Deploy, S3에 접근할 수 없습니다. 그래서 Github Actions에서 AWS 서비스에 접근할 수 있는 권한을 얻기 위해 AWS IAM 사용자를 생성해주도록하겠습니다.
먼저 AWS IAM 대쉬보드에 접속 후 사용자를 선택해주세요.
사용자 추가 버튼을 누른 후 AWS 자격 증명 유형을 액세스 키로 선택한 다음, 다음: 권한
을 눌러주세요.
기존 정책 직접 연결
을 누르고, AmazonS3FullAccess
와 AWSCodeDeployFullAccess
를 선택해주세요. 태그 설정은 자유이므로 생략하겠습니다.
사용자를 생성하기 전에 권한 요약에 아래와 같이 되어있어야합니다.
사용자를 만든 후 액세스 ID와 액세스 키를 복사하거나, .csv를 다운받아서 저장해주세요.
EC2에 배포를 하는 것이기 때문에 CodeDeploy는 EC2에 대한 접근 권한이 있어야합니다. 그래서 CodeDeploy를 위한 IAM 역할을 만들어주겠습니다.
AWS 서비스
> 다른 AWS 서비스의 사용 사례 - CodeDeploy
를 선택해주세요.
정책은 AWSCodeDeployRole
밖에 없으니 이것을 선택해주고, 역할을 생성하시면 됩니다.
EC2에서는 S3에 올린 zip을 다운받기 위해서 S3에 대한 접근 권한이 있어야합니다. 그래서 EC2를 위한 IAM 역할을 만들어주겠습니다.
AWS 서비스
> EC2
를 선택해주세요.
그 다음 AmazonS3ReadOnlyAccess
정책을 추가하고, 역할을 생성해주세요.
IAM 사용자 : 말 그대로 특정 권한을 가진 사용자를 만드는 것입니다. (회원가입이라고도 할 수 있죠. 근데 이제 아이디와 비밀번호를 정해주는..) 그래서 사용자를 만들면 액세스 키 ID와 비밀 액세스 키가 발급되며 해당 정보를 가지고 로그인을 할 수 있습니다.
IAM 역할 : AWS 서비스가 다른 AWS 서비스에 접근할 수 있는 권한을 주는 것입니다. 그래서 IAM 사용자와 달리 액세스 키 ID와 비밀 액세스 키가 발급되지 않으며, 특정 서비스의 대시보드에서 역할을 수정합니다. 예를 들어서 EC2에게 역할을 부여하기 위해서는 EC2 대시보드에 들어가야합니다. 이 과정은 아래에서 다룹니다.
✅ IAM 역할은 AWS 서비스가 다른 AWS 서비스에 접근할 수 있는 권한을 주는 것이기 때문에 Github Actions에게는 IAM 역할이 아니라 IAM 사용자를 만들어 준 것입니다.
EC2를 생성합니다. 여기서 중요한 것은 스토리지 볼륨을 넉넉하게 설정해주어야합니다. 왜냐하면 docker container를 여러 개 띄워서 블루-그린 배포를 구현하고, 배포를 할 때마다 이미지를 생성하기 때문에 스토리지를 8기가로 설정하면 EC2에서 'No space left on device' 에러가 자주 발생합니다.
이 글은 Ubuntu 20.04 환경에 맞춰서 진행됩니다.
TMI이지만 저는 아래처럼 DefaultSecurityGroup
을 만들어둬서 실수로 22, 80, 443 포트를 안 여는 일은 없도록 방지를 합니다.
그리고 나중을 위해서 3001, 3002번 포트를 열어둔 보안 그룹을 따로 만들어 연결해두겠습니다.
위에서 생성한 IAM 역할을 연결해주겠습니다.
인스턴스 상태
> 보안
> IAM 역할 수정
을 선택해주세요.
IAM 역할을 업데이트 해주세요.
S3를 생성합니다. 저는 포스팅을 위해 생성하는 것이라 모든 퍼블릭 액세스 차단
만 풀어주고, 다른 세팅은 기본값으로 하였습니다. 독자분들은 상황에 맞게 설정해주시면 될 것 같습니다.
CodeDeploy 애플리케이션을 생성해줍니다. EC2에서 사용할 것이기 때문에 EC2를 선택해줍니다.
애플리케이션 생성 후 배포 그룹을 생성해줍니다. 배포 그룹은 개발 환경, 운영 환경 등 환경별로 분리해서 사용합니다. 서비스 역할은 위에서 CodeDeploy를 위해 생성한 IAM 역할을 추가해주시면 됩니다. 배포 유형은 현재 위치
로 설정해줍니다. 하나의 EC2 안에서 배포를 진행하기 때문입니다.
특정 태그가 달린 EC2 인스턴스를 선택해주세요. 키가 Name인 태그는 EC2 인스턴스의 이름을 의미합니다.
배포 구성은 CodeDeployDefault.AllAtOnce
로 설정해줍니다. 그 다음 로드밸런서는 사용하지 않기 때문에 체크표시를 꺼줍니다.
다른 배포 구성에 대한 설명은 CodeDeploy에서 배포 구성 작업을 참조해주세요.
위에서 IAM 사용자를 생성하여 얻은 액세스 키 ID와 비밀 액세스 키를 Github Actions에서 사용해보겠습니다.
⚠️ 액세스 키 ID와 비밀 액세스 키를
main.yml
에 절대 하드코딩하지마세요!
레포지토리의 Settings
> Secrets
> Actions
로 들어가서 New Repository secret
을 눌러서 AWS Access ID와 AWS Access Key를 추가해주시면됩니다.
저는 혹시 몰라서 aws region까지 시크릿에 추가해주었습니다.
이제 Github Actions에서 사용하겠습니다.
먼저 Github Actions 내 환경변수를 추가해줍시다.
name: Deploy NestJS Application
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
# ^^^^^^^^ 1편에 있던 내용 ^^^^^^^^
# vvvvvvvvv 추가할 내용 vvvvvvvvv
env:
S3_BUCKET_NAME: my-nest-app-deploy-bucket # S3 버킷 이름입니다.
PROJECT_NAME: my-nest-pp # S3 버킷 내 폴더 이름입니다. 임의로 정하면 알아서 생성해줍니다.
AWS_CODEDEPLOY_APPLICATION_NAME: my-nest-app-codedeploy # CodeDeploy 애플리케이션 이름입니다.
AWS_CODEDEPLOY_DEPLOYMENT_GROUP_NAME: my-nest-app-dev-group # CodeDeploy 배포 그룹 이름입니다.
시크릿에 저장한 값을 Github Actions에서 사용할 때는 ${{ secrets.SECRET_NAME }}
이렇게 사용합니다. 1편에서 작성한 워크플로우 파일 (main.yml
)에 아래 내용을 추가해줍니다.
- name: Make a zip file
run: zip -r ./$GITHUB_SHA.zip . -x "node_modules/*" "coverage/*" "src/*" "test/*" "README.md" "*.git*"
shell: bash
# ^^^^^^^^ 1편에 있던 내용 ^^^^^^^^
# vvvvvvvvv 추가할 내용 vvvvvvvvv
# 위에서 생성한 IAM 사용자 정보를 넣어 자격 증명을 수행합니다.
- 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: ${{ secrets.AWS_REGION }}
# 위에서 만든 zip 파일을 S3에 업로드 합니다.
- name: Upload to S3
run: aws s3 cp --region ${{ secrets.AWS_REGION }} ./$GITHUB_SHA.zip s3://$S3_BUCKET_NAME/$PROJECT_NAME/$GITHUB_SHA.zip
# CodeDeploy에게 deployment를 생성하도록 요청합니다.
- name: Request Deployment
run: aws deploy create-deployment --application-name $AWS_CODEDEPLOY_APPLICATION_NAME --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name $AWS_CODEDEPLOY_DEPLOYMENT_GROUP_NAME --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$PROJECT_NAME/$GITHUB_SHA.zip
위의 워크플로우 내용을 추가한 후, main 브랜치에 푸쉬 혹은 PR을 날리면 Github Actions가 잘 작동할 것입니다. 그리고 Workflow가 끝날 때까지 기다렸다가 S3에 들어가시면 PROJECT_NAME
값을 이름으로 가진 폴더가 하나 생성되고, 그 안에 zip 파일이 생성된 것을 확인할 수 있습니다.