공개 노트 검색

github actions, aws codedeploy, lightsail 로 배포 자동화하기

glevel

깃허브 main branch 에 push 하면 빌드 후 서버에 자동으로 배포해주는 시스템을 만들고 있다. 이렇게 하면 개발이 좀 더 빨라질 것 같아서 도입하기 시작했는데 생각보다 시간이 많이 들어가서 고민 중이다. 그래도 지식 공유에 있어 중간 패킷을 만들어서 공유하면 좋다는 조언을 들어서 배움을 공유해본다. 소규모 서버의 경우 배포 자동화까지 필요가 없고 중간 규모 이상부터 배포 자동화 + 무중단 배포 시스템을 만들면 좋을 것 같다.

일단 구조를 이해해야 한다.

github 메인 브랜치에 push가 일어나면 github actions 가 github 내의 우분투 가상 머신에서 실행이 된다. 여기서 빌드 등 필요한 작업을 한 후 aws의 s3에 파일을 압축해서 올리고 코드디플로이를 작동시킨다. codedeploy가 작동되면 서버에 있는 codedeploy-agent가 이를 캐치하여 배포를 하고 후속 작업을 sh 파일을 통해서 할 수 있다. 구조가 좀 복잡하다.

github actions를 사용하지 않아도 된다. aws의 code pipeline을 통해 github를 연결하고 code build를 통해 빌드 작업을 한 후 배포 작업을 진행해도 된다. amazon linux를 사용할 수 있으므로 서버가 amazon linux인 경우 이 루트를 타는게 빌드가 필요한 애플리케이션일 경우 호환성에 좋을 것 같다. 나는 나중에 이 루트로 마무리 할 것 같다.

말이 좀 길어졌는데 이런 것들을 생각해 보고 진행을 하면 좋을 것 같아서 남겨 봤다.

하지만 이번에는 github actions를 통해 진행해 보자!

s3 버켓 만들기

코드디플로이에서 가져올 s3를 만들어야 한다. codedeploy-agent가 바로 github에서 가져올 수 없고 s3에 올려서 받아와야 한다.

s3 console로 가서 버킷 만들기를 선택한다. 이 때 중요한 것은 버킷의 리전을 aws light sail과 같은 지역으로 설정해야 한다. 나는 서울 지역인 ap-northeast-2를 선택했다.

이름을 입력한다. 이름은 s3 전체를 통틀어 유일해야 한다.

모든 퍼블릭 엑세스를 차단한다. 어차피 codedeploy에서만 접근이 가능하면 된다.

버킷 만들기 버튼을 클릭한다.

codedeploy service 역할 만들기

IAM console에 로그인한 후 역할 -> 역할 만들기를 선택한다.

그 후 AWS 서비스를 선택하고 사용 사례에 codedeploy를 입력하여 선택한다. 다음을 누르고 다음을 누른다. 그리고 역할의 이름을 입력하고 역할 생성을 누른다.

여기서 이름의 규칙을 정해두면 좋다. 왜냐하면 이런 방식으로 여러가지 이름을 만들어야 하기 때문이다. 나는 tilnote-codedeploy-이름과 같은 방식으로 하기로 결정했다.

이 역할은 나중에 codedeploy에서 사용된다.

사용자 정책 만들기

codedeploy에 s3 full access를 줄 수 도 있지만 권한은 최소화하고 싶어서 직접 정책을 만들고 IAM User에 붙여주자.

IAM에서 정책을 누르고 정책 생성을 눌러주자. JSON을 누른 후 다음 내용을 입력하자.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:Get*", "s3:List*", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::[아까만든s3버킷이름]/*" ] } ] }

아까 만든 s3 버킷 이름을 입력하는 걸 잊지 말자. 다음 : 태그 -> 다음 : 검토를 눌러 이름을 입력하자. 나는 CodeDeployS3BucketPolicy를 입력했다.

IAM User 만들기

EC2 인스턴스에서는 IAM 역할을 만들고 바로 인스턴스에 부여할 수 있다. 하지만 lightsail 에서는 그렇게 할 수 없다. 그래서 IAM 유저를 만들어서 라이트세일을 등록하고 태그를 다는 작업을 하면 된다.

IAM 콘솔에서 사용자 탭을 선택하자. 사용자 추가를 누르고 사용자 이름을 정해 준다. tilnote-codedeploy-user라는 이름을 사용했다.

다음을 누른 후 직접 정책 연결을 누르고 아까 만든 CodeDeployS3BucketPolicy 와 AWSCodeDeployFullAccess를 선택하고 다음을 누른다. 사용자 생성을 누른다.

그 다음 프로그래밍 방식 액세스를 활성화 해줘야 한다. IAM -> 사용자에서 방금 만든 유저를 선택하고 보안 자격 증명 탭을 선택한다.

원래는 사용자를 만들 때 프로그래밍 방식 액세스를 설정할 수 있었는데 바뀐것 같다. 만들고 설정해 줘야 한다. 아마 액세스 키가 유출되는 사고들이 많이 있어 aws에서 보안 정책을 강화한 것 같다. 절대 git 같은데 포함해서 공개된 장소에 올리면 안된다. 요금 폭탄 맞았다는 이야기를 많이 들었다.

밑으로 내리면 액세스 키가 있다. 액세스 키 만들기를 선택한다.

AWS 외부에서 실행되는 애플리케이션를 선택하고 액세스키 만들기를 선택한다. 액세스키와 비밀 엑세스키를 안전한 곳에 복사해서 저장하자. 비밀키는 이 페이지를 닫으면 나중에 다시 볼 수 없다.

완료를 누른다.

라이트세일 서버에 codedeploy 설치하기

Amazon Linux 또는 RHEL용 CodeDeploy 에이전트 설치 - AWS CodeDeployAmazon Linux 또는 RHEL용 CodeDeploy 에이전트 설치 - AWS CodeDeploy

ruby나 wget이 설치되어 있지 않은 경우

sudo yum update

sudo yum install ruby

sudo yum install wget

codedeploy 설치

cd /home/ec2-user

wget https://bucket-name.s3.region-identifier.amazonaws.com/latest/install

bucket-name은 이전에 만들었던 bucket-name 이름 region은 한국 서버의 경우 ap-northeast-2를 입력한다.

chmod +x ./install

sudo ./install auto

서비스가 실행 중인지 확인하려면 다음 명령을 실행합니다.

sudo service codedeploy-agent status

CodeDeploy 에이전트가 설치되어 실행 중이면 "The AWS CodeDeploy agent is running"와 같은 메시지가 표시되어야 합니다.

그런데 생각보다 codedeploy의 경우 생각보다 메모리를 많이 쓰는것 같다. 참고하자.

lightsail 등록하고 배포 태그 등록하기

이 부분이 중요하다. 나는 이걸 이해 못해서 한참 해맸다 ㅠㅠ

지금 현재 내가 개발하고 있는 로컬 머신에 aws cli를 설치하고 aws 명령어를 활용해서 현재 라이트세일을 등록해줘야 한다. 그리고 배포할 때 이를 구분할 수 있는 태그를 등록해야 한다.

Installing or updating the latest version of the AWS CLI - AWS Command Line InterfaceInstalling or updating the latest version of the AWS CLI - AWS Command Line Interface

이 링크에서 보면 윈도우, 리눅스, 맥의 환경에 맞는 cli 를 설치할 수 있다.

설치 후 $ aws configure 명령어를 입력해서 아까 적어놨던 액세스키와 비밀키를 입력하자.

그리고 작업을 해주기 전에 lightsail에 태그를 달아주자.

라이트세일에서 인스턴스 명을 누른 후 미리보기 점에서 태그를 선택해서 입력하면 된다.

주의할 점은 키 값은 Name 으로 입력해야 한다. 대문자 유의하자. 태그를 인식하는 고유 방식인것 같다. 값은 원하는 값으로 정하면 된다. 나중에 사용됨으로 메모해 두자.

  • 라이트세일 인스턴스를 aws 의 온프레미스 인스턴스로 등록 (나중에 codedeploy에서 사용됨)

aws deploy register-on-premises-instance --instance-name <InstanceName> --iam-user-arn <IAM User ARN> --region <Region>

  • 라이트세일의 태그를 온프레미스 인스턴스에 등록

aws deploy add-tags-to-on-premises-instances --instance-names <InstanceName> --tags Key=Name,Value=<InstanceName> --region <Region>

InstanceName은 라이트세일의 인스턴스 이름을 이야기한다.

IAM 사용자 ARN은 IAM -> 사용자에서 볼 수 있다. arn:aws:iam 와 같은 방식으로 시작한다.

태그는 라이트세일의 태그를 의미한다.

이렇게 등록한건 codedeploy -> on-premise instances에서 확인이 가능하다. 지역은 seoul을 잘 확인하자.

codedeploy 앱 생성하기

codedeploy로 가자. 애플리케이션 탭을 선택한 후 애플리케이션 생성을 누른다.

이름을 입력하고 컴퓨팅 플랫폼은 EC2/온프레미스를 선택한다.

그리고 해당 애플리케이션을 선택하고 배포그룹 생성 버튼을 누른다.

배포 그룹의 이름을 입력한다.

서비스 역할에서 아까 우리가 만들었던 IAM 역할을 선택한다.

배포 유형은 현재 위치를 입력한다.

환경 구성에서 온프레미스 인스턴스를 입력한다.

그러면 태그가 나오는데 여기서 라이트세일에 달아놨던 태그 이름을 입력한다. (이걸 통해서 어느 인스턴스로 배포하는지 구별한다. 중요함.)

나머지는 그대로 놔두고 로드밸런서를 체크해제 한다. 배포그룹 생성을 누른다.

github actions 세팅하기

aws 키값 세팅하기

배포를 원하는 git 저장소에서 Setting을 누르고 Secrets and variables -> Actions를 선택한다.

이곳에 AWS_ACCESS_KEY와 AWS_SECRET_KEY를 만들고 아까 적어놨던 액세스키와 비밀키를 입력한다. 이 키들은 깃허브에서 비밀로 보관하고 actions 에서 사용할 수 있게 한다.

그 다음 Actions탭을 선택하고 New workflow를 누른다. 여기서 set up a workflow yourself (직접 만들기)를 누른다.

이렇게 되면 main.yml 파일이 나오는데 여기서 main으로 푸쉬됐을 때 하는 작업들을 입력해 주면 된다. 다음은 내가 만든 예시이다.

# This is a basic workflow to help you get started with Actions name: CI on: push: branches: [main] workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: checkout release uses: actions/checkout@v3 - name: compress run: tar cvfz ./$GITHUB_SHA.tar.gz * shell: bash - name: AWS configure credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} aws-region: ap-northeast-2 - name: upload to S3 run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.tar.gz s3://[본인의버킷이름] - name: deploy with AWS codeDeploy run: aws deploy create-deployment --application-name [본인의 코드디플로이 앱 이름] --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name [본인의 코드디플로이 배포그룹 이름] --s3-location bucket=본인의버킷이름,bundleType=tgz,key=$GITHUB_SHA.tar.gz

파일을 압축한 후 s3에 올리고 코드디플로이를 작동시킨다. 이러면 라이트세일 인스턴스에 있는 코드디플로이 에이전트가 배포한 파일을 가져오게 된다.

appspec.yml

마지막으로 앱의 루트 폴더에 appspec.yml 파일을 만들어 준다. 확장자 명은 yaml 이 아니라 yml 이다.

version: 0.0 os: linux files: - source: / destination: /home/ec2-user/build/ permissions: - object: / owner: ec2-user group: ec2-user mode: 755 hooks: BeforeInstall: - location: deploy-before.sh runas: ec2-user // ApplicationStart: // - location: deploy.sh // runas: ec2-user

이 파일은 codedeploy가 파일을 가져올 때 수행을 하는 작업을 기술한 파일이다. 가져온 코드를 build 폴더 내에 위치 시키고 적절한 퍼미션을 준다.

그 이후 beforeInstall 이나 ApplicationStart와 같은 훅을 주어 sh 파일로 필요한 작업들을 수행할 수 있다.

앱의 루트 폴더에 다음 파일을 만들고 입력해 보자. (gitignore 등이 있는 최상위 폴더)

deploy-before.sh

if [ -d /home/ec2-user/build ]; then sudo rm -rf /home/ec2-user/build/ fi sudo mkdir -vp /home/ec2-user/build/

이제 메인에 푸쉬하면 것허브 액션과 배포 프로세스가 돌아간다. 각각 깃허브 액션 탭과 aws의 codedeploy 에서 프로그레스 확인이 가능하다.

이렇게 빌드 폴더에 잘 담겨져 있는게 확인 가능하다.

에러가 날 수 도 있는데 코드디플로이 로그는 tail -f /var/log/aws/codedeploy-agent/codedeploy-agent.log 에서 볼 수 있다.

나는 next 를 사용하고 있는데 yarn install 하고 빌드하는 부분은 나중에 기회가 되면 작성해봐야 겠다.

이번에 하면서 고생 많이 해서 혹시 헤멜 수 도 있는 분들을 위해 남긴다. =.=

참고

codedeploy 재시작 명령어

sudo service codedeploy-agent restart

glevel 님의 글을 구독해 보세요. 뉴스레터 글을 공유할 때 전달해드립니다.
구독은 언제든지 취소가 가능하며 수집된 이메일은 보호되고 어디에도 공유되지 않습니다.