Development/Node

nestjs backend beanstalk bitbucket ci/cd 자동배포 구축하기 (eventbridge, lambda 까지..)

Jun Mr 2022. 1. 5. 00:32
728x90
반응형

Backend CI/CD 자동 배포 구축

 

지난번에는 cloudfront를 활용한

frontend 자동배포구축을 해보았습니다.

 

https://developerjun2.tistory.com/170

 

React 프로젝트 Aws cloudfront, bitbucket pipelines 로 자동배포하기

React 프로젝트 자동배포  실제 Front Web 프로젝트를 서비스하기 위해 어떻게 배포하나요~? 관리 중인 git을 통해 commit or push 만으로도 실제 서비스 배포가 적용되면 얼마나 편할까요? AWS Cloudfront와

developerjun2.tistory.com

 

이번에는 backend 프로젝트를 자동 배포해보려고 합니다.

 

자동 배포를 사용할 경우,

 

개발을 집중 할 수 있었고

심신안정에 좋으며(부담감소)

빠르고 편리했습니다.

 

자, 그럼 빨리 바로 실전으로 들어가 볼게요.

 

준비물은

bitbucket 계정,

AWS 계정

입니다.

 

그리고 자동 배포는 아래와 같은 과정으로 진행됩니다.

 

1. Bitbucket Commit & Push

2. Bitbucket PipeLines로 Docker 이미지 빌드 및 생성

3.. Bitbucket PipeLines로 Docker 이미지를 ECR로 전송

4. Amazon EventBridge 규칙을 통해 ECR의 PUSH액션에 의한 Lambda 함수 실행

5. Lambda 함수를 통해 Beanstalk 재실행

6. Beanstalk 재실행되면서 ECR의 Latest 태그의 이미지를 찾아 배포

7. Beanstalk 배포 완료 및 적용 완료

 

우선 테스트로 사용될

beanstalk-cicd-test 

이름으로 Bitbucket Repogitory를

만들어주었습니다.

 

 

그리고 backend temp Project로

사용될 nestjs 프로젝트를 생성해보겠습니다.

 

정말 심플하게,

nest new beanstalk-cicd-test

명령어를 날려

아무 설정 없이

프로젝트를 default로 만들어주었습니다.

 

그리고 bitbucket repository와

연동을 해주었습니다.

 

cd beanstalk-cicd-test

git remote add master https://계정주소~~~~

 

 

그리고 살포시 커밋!~

 

그리고 살포시 푸시까지!

 

여기까지가

자동 배포를 하고자 하는

프로젝트가 존재하는

상태 세팅이라고 보시면 됩니다.

 

 

이제 본격적으로

자동 배포를 위해 AWS로 접속해보겠습니다.

 

ecs를 검색하여 Elastic Container Service로 접속합니다.

 

 

그리고 ECR의

Repositories로 접속합니다.

 

 

그리고 레포지토리 생성!!

 

beanstalk-cicd-test-repo

저희가 만든 프로젝트에 '-repo'를 붙여

만들어주었습니다.

그냥 이유 없음. 구분을 위한?

 

 

그리고 Beanstalk 도 미리 만들어줍시다!!

생성하는데 시간이 걸리니!!

Elastic Beanstalk으로 접속해줍니다.

 

생성 버튼 클릭!!

 

 

기본 세팅으로 웹 서버 환경을 선택해주었습니다.

 

애플리케이션 이름으로 저희가 생성한 프로젝트 이름과 동일하게 입력!

입력하면 아래 환경 이름이 자동으로 기입됩니다.

 

이후 플랫폼을 Docker로 선택해주고

나머지 그대로!!

환경 생성!!!!

 

그리고 뭔가 막 설정을 하며

생성되기 시작합니다.

생각보다 시간이 걸립니다.

 

알아서 생성되도록 놔두고

저흰 다시 Bitbucket pipeline을 위한 세팅을 위해

다시 돌아가 봅시다.

 

저희가 만든 프로젝트에서

bitbucket-pipelines.yml

Dockerfile

두 개의 파일을 만들어줄 겁니다.

 

bitbucket-pipelines.yml

이 파일의 코드는 아래와 같습니다.

image: node:14.17.6-alpine

pipelines:
  branches:
    master:
      - step:
          name: docker build
          script:
            - docker build -t beanstalk-cicd-test-repo .
            - docker save --output image.docker beanstalk-cicd-test-repo
          services:
            - docker
          artifacts:
            - image.docker
      - step:
          name: ecr push (commit tag)
          script:
            - docker load --input ./image.docker
            # use the pipe to push the image to AWS ECR
            - pipe: atlassian/aws-ecr-push-image:1.4.2
              variables:
                AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY
                AWS_SECRET_ACCESS_KEY: $AWS_SECRET_KEY
                AWS_DEFAULT_REGION: 'ap-northeast-2'
                IMAGE_NAME: beanstalk-cicd-test-repo
                TAGS: ${BITBUCKET_COMMIT:0:7}
          services:
            - docker
      - step:
          name: ecr push (latest)
          script:
            - docker load --input ./image.docker
            # use the pipe to push the image to AWS ECR
            - pipe: atlassian/aws-ecr-push-image:1.4.2
              variables:
                AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY
                AWS_SECRET_ACCESS_KEY: $AWS_SECRET_KEY
                AWS_DEFAULT_REGION: 'ap-northeast-2'
                IMAGE_NAME: beanstalk-cicd-test-repo
                TAGS: latest
          services:
            - docker

 

밑줄 친 부분의 master는 branch 이름입니다.

해당 branch의 push에 따라 반응하겠다는 소리!

그리고 나머지 밑줄친 부분은

생성한 ecr이름과 동일하게 해 주었습니다.

나머지는 그대로 사용해도 됩니다.

 

 

FROM node:14.17.6-alpine as builder

WORKDIR /app

COPY . /app

RUN npm ci --only=production \
    && npm i @types/express \
    && npm i -g @nestjs/cli \
    && npm run build

# ---

FROM node:14.17.6-alpine

WORKDIR /app

COPY --from=builder /app/package*.json /app/
COPY --from=builder /app/node_modules/ /app/node_modules/
COPY --from=builder /app/dist/ /app/dist/

CMD ["npm", "run", "start:prod"]

 

도커 파일의 코드는 위와 같습니다.

특별히 신경 쓸 내용은 없네요.

그대로 사용 가능!

 

 

그리고 Bitbucket으로 돌아와

가장 아래 Repository settings 접속!

 

 

그리고 해당 프로젝트의 pipelines기능을 사용하기 위한 설정 On!!

 

단순히 pipelines의 설정에 들어가

라디오 버튼을 클릭해주면 끝입니다.

 

아참!

그리고 실제 AWS에 접속하여

생성한 ECR에 이미지를 떨구기 위해서

접속키를 발급해줄 겁니다.

 

 

iam에 접속합니다.

 

사용자 생성을 위해 사용자로 접속!

 

그리고 사용자 추가 클릭!

 

사용자 이름은 원하는 이름으로 설정합니다.

전 그냥 샘플로 프로젝트 명과 동일하게 해 주었습니다.

 

기존 정책 직접 연결을 클릭하여

그리고 ECR의 전체 권한 설정

 

 

 

ECS의 전체 권한 설정 후

다음을 클릭하였습니다.

 

 

여기는 그냥 바로 다음

 

그리고 사용자를 만들어줍니다.

 

그럼 이 키 2개가 생성이 되었을 겁니다.

 

 

그럼 다시 bitbucket으로 돌아와 실제 키 정보를 입력해줄 겁니다.

 

AWS_ACCESS_KEY - 액세스 키 ID

AWS_SECRET_KEY - 비밀 액세스 키

 

이렇게 각각 입력해주면 됩니다.

 

그리고 이제 Git push를 진행해볼 겁니다.

 

 

아까 입력한 두 개의 파일을 실제로 커밋 후 푸시를 해줄 겁니다.

 

푸시를 바로 누르고

 

원래 Repository로 돌아와 pipelines를 클릭하여 보면

뭔가 갑자기 돌아가기 시작합니다.

 

In Progress를 클릭하여 들어가 보면

bitbucket-pipelines.yml

에 입력한 내용대로

step에 따라 하나씩 실행이 될 겁니다.

 

 

그럼 최종 완료가 된 것을 확인합니다.

다행히 에러 없이 모든 것이 한 번에 착착 되었네요.

 

그럼 다시 ECR로 돌아와서

저희가 생성한 repositories에

파일이 잘 넘어왔나 확인해보니

정말 잘 넘어와있습니다!!

 

우선 해당 파일을 활용하여

beanstalk에 배포를 해봅시다!!

 

빈즈 톡으로 돌아와

저희가 만든 빈즈 톡이 모두 생성되었습니다.

업로드 배포를 해주기 위해

파일을 하나 만들어주어야 합니다.

 

Dockerrun.aws.json

 

파일명으로 파일을 생성할 것이고,

위치 상관없이

코드 작성 후

업로드해줄 겁니다.

 

전 일단 그냥 프로젝트 내부에 파일을 만들어주었고,

코드는 위와 같습니다.

Name에 들어갈 내용은 

 

 

저희가 만든 ECR 레포지토리 경로라고 보시면 됩니다.

 

다시 beanstalk으로 돌아와

업로드 및 배포를 클릭하고

 

 

파일 선택하여

방금 새로 작성한 Dockerrun.aws.json파일을

업로드해주면 됩니다.

그 후 자동으로 생성되는

버전 레이블을 수정하지 않고 그대로 사용하겠습니다.

(이건 추후 lambda함수에서 사용)

 

배포를 클릭하면

막 돌면서 확인하고 

 

최종 확인이 초록색으로 바뀌면

해당 주소를 클릭하여!!

 

저희는 드디어

Hello World!

문구를 확인할 수 있습니다.

 

하지만 하나의 이슈가 존재합니다.

Hello World!

를 수정하여 커밋 후 푸시를 하면

ECR까지는

자동으로 올라갈 텐데,

이 올라간 파일을

Beanstalk이 갱신하기 위해서는

Beanstalk를 재실행시켜주어야 합니다.

 

이마저도 자동으로 하기 위해

EventBridge를 사용하겠습니다.

 

그전에!!! 

미리 lambda 함수를 생성해주겠습니다.

 

lambda를 검색하여 접속해줍니다.

 

 

함수 생성 클릭!!

 

람다 함수 이름을 임의로

beanstalk-cicd-test-beanstalk-restart

로 지어주고 바로 함수 생성!

 

 

 

그리고 코드는 이렇습니다.

밑줄 친 부분이

beanstalk의 환경 이름,

그리고 버전 라벨 이름을 잘 기입해주어야 합니다.

중요!!!!

해당 기입 내용은 밑줄 친 부분을 기입하면 됩니다.

저 같은 경우는 다른 시도로 인해서 -3이 되어버렸네요.

여러분은  'Sample Application-1' 이 상태일 것 같습니다.

 

const AWS = require('aws-sdk');

exports.handler = async (event) => {
    try {
    const beanstalk = new AWS.ElasticBeanstalk();
    const result = await beanstalk.updateEnvironment({ EnvironmentName: 'Beanstalkcicdtest-env', VersionLabel:'Sample Application-1' }).promise();
    console.log('result : ', result)
    
    const response = {
        statusCode: 200,
        body: JSON.stringify('SUCCESS!'),
    };
    return response;
    } catch(error) {
        console.log(error);
        return error;
    }
};

그래서 이 코드가 최종 코드가 되겠네요.

 

그리고 deploy를 클릭해주면 작성 완료!!

 

그리고 람다가 직접 beanstalk을 재실행해줄 수 있는 실질적인

권한을 만들어주어야 합니다.

 

다시 람다로 돌아가 구성을 클릭하면 이런 화면이 나오고,

역할 이름을 클릭해줍니다.

 

위와 같은 화면이 나오면 바로 정책 연결을 클릭해줍니다!!

 

그리고 

'AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy'

이름의 정책을 찾아 정책 연결을 해줍니다.

 

연결된 것이 확인되네요!!

그럼 테스트를 한번 진행해보시죠.

 

저는 테스트 탭으로 들어가

테스트를 바로 클릭해주었습니다.

 

클릭하면 바로 결과가 이렇게 짠!

문제없이 실행이 가능 확인!

이제 eventbridge와 연결해주겠습니다.

 

eventbridge를 검색 후 접속해줍니다.

 

그리고 규칙을 들어가,

규칙 생성 버튼을 클릭합니다.

 

이름은 임의로 

beanstalk-cicd-test-beanstalk-restart

이렇게 지어주었습니다.

 

그리고 ECR의 생성되는 순간을 포착하여

자동 배포를 위한 액션을 취해줄 것이기에

저희가 만든 ECR 내용에 맞춰 선택 및 작성을 해줍니다.

내용은 간략하게

ECR의 특정 리포지토리의 latest파일이

push가 성공하면 뭘 할 것이다.

의 내용을 작성해준 겁니다.

 

이후, 아까 만들어놓은

Lambda 함수를 여기에 연결시켜줍니다.

그리고 생성!!!!!!!!!

 

그럼 이제

자동화 배포를 위해 테스트를 해봅시다!!!!!

 

저는 실제로 heloo world! 를

한글로 헬로 월드로 변경 후

커밋!!!!

 

그리고 바로 푸시를 눌러주었습니다!!!

 

그리고 빠르게 bitbucket으로 들어가

pipelines를 보니 바로 반응을 합니다!!

 

들어가 확인하면 대략 5분 정도 시간이 소요가 되어

최종 ECR까지 업로드가 끝이 납니다.

 

그리고 나면

 

 

Aws beanstalk에 들어가 보면

이렇게 event bridge로 인하여 반응을 하게 되고,

 

최종적으로 확인 상태가 되면!!!

이렇게 자동 배포가 완료가 됩니다.

 

 

그리고 URL을 클릭하여 확인해보면

짠!!!

자동 배포가 최종적으로 완성되었네요!!

 

지금까지 작업들을 순서대로 나열을 하면

 

1. Bitbucket Commit & Push

2. Bitbucket PipeLines로 Docker 이미지 빌드 및 생성

3.. Bitbucket PipeLines로 Docker 이미지를 ECR로 전송

4. Amazon EventBridge 규칙을 통해 ECR의 PUSH액션에 의한 Lambda 함수 실행

5. Lambda 함수를 통해 Beanstalk 재실행

6. Beanstalk 재실행되면서 ECR의 Latest 태그의 이미지를 찾아 배포

7. Beanstalk 배포 완료 및 적용 완료

 

 

반응형