nodejs, gitlab, elastic beanstalk CICD구축

nodejs, gitlab, elastic beanstalk CICD구축

728x90

nodejs서버(DockerFile로 배포가능하면 무엇이든 가능)를 gitlab에 커밋 - AWS S3에 코드를 업로드 - AWS elastic beanstalk + docker + pm2 배포

위 과정의 자동화에 대한 포스팅이다.

<사전 준비사항>

- AWS Route53을 통한 도메인 생성

- AWS certificate manager를 통한 ssl 인증서 발급

- AWS IAM계정 파두기

- AWS S3 버킷 생성

- 키페어 하나 준비해두기

- EC2 인스턴스 보안그룹 입맛에 맞게 생성

-> 나중에 필요하면 따로 포스팅할 예정.

새 환경 생성 버튼 클릭

웹 서버 환경 -> 선택 클릭

어플리케이션 이름과 환경 이름 설정

관리형 플랫폼 - docker 선택 후 추가옵션 구성 버튼 클릭

로드 밸런서와 오토스케일링 붙일거니까 고가용성 선택

인스턴스, 로드밸런서, 보안에서 편집사항 있음.

인스턴스 보안 그룹 적절히 지정해서 선택

로드밸런서에서 리스너 추가

다음과 같이 추가

가상머신 권한에 EC2 키페어 추가

환경생성

http로 샘플 애플리케이션이 돌아가는 것 확인

사용할 레코드 생성

별칭으로 방금 생성한 elastic beanstalk 환경에 연결

SSL인증이 된 우리 라우터에 연결된 것 확인

gitlab runner를 로컬에서 돌려도 되지만, ec2 인스턴스에서 도커로 상시 구동되도록 했다. 돈이 아깝다면 그냥 로컬에서 돌리는게 좋다.

ubuntu18로 ec2 인스턴스 만들고 ssh 연결 해서 gitlab-runner와 docker를 cli로 설치해준다.

gitlab-runner 설치:

https://docs.gitlab.com/runner/install/linux-manually.html

docker 설치:

https://docs.docker.com/engine/install/ubuntu/

깃랩 러너를 등록해준다.

sudo gitlab-runner register

여기에 깃랩프로젝트 - settings - cicd - runners expand 에서 나오는 정보와 러너의 태그를 정해준다.

여러 개의 러너를 등록할 수도 있다.

혹시 gitlab-runner 데몬이 종료됐다면 다음과 같이 다시 켜주면 된다.

sudo gitlab-runner start

<.gitlab-ci.yml 작성>

프로젝트의 루트 폴더에 작성한다.

runner가 등록된 gitlab 프로젝트의 정해둔 branch가 원격 저장소에 push되면 이 yml파일을 기반으로 runner가 동작한다.

gitlab 프로젝트 - settings - cicd - variables에 변수들을 등록할 수 있다.

AWS 키페어를 등록할 때의 예시다. END RSA PRIVATE KEY 줄 뒤에 개행(enter)가 반드시 필요하다. 없으면 에러난다..ㅠ

.gitlab-ci.yml 예시.

깃랩에 올라가는 소스코드 전체를 zip으로 묶어서 S3에 업로드 S3에 올린 소스코드를 기반으로한 어플리케이션 생성 애플리케이션을 beanstalk 환경 위에서 배포

#여러 단계로 ci/cd를 수행할 수 있음 stages: - run #gitlab cicd variables에 등록한 변수들을 $와 함께 사용할 수 있움 variables: AWS_EB_APP_NAME: ${MY_AWS_EB_APP_NAME} AWS_EB_ENV_NAME: ${MY_AWS_EB_ENV_NAME} APP_VERSION: "1.0.0" S3_BUCKET: ${AWS_S3_EB_BUCKET} AWS_ID: ${MY_AWS_ID} AWS_ACCESS_KEY_ID: ${MY_AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${MY_AWS_SECRET_ACCESS_KEY} AWS_REGION: ${AWS_REGION} AWS_PLATFORM: Docker deploy_eb: stage: run image: python:latest allow_failure: false before_script: ## ## AWS에서 발급받은 키페어를 .ssh밑에 저장해둔다 ## - mkdir ~/.ssh - echo "$SSH_PRIVATE_KEY" >> ~/.ssh/yourKeyName - chmod 700 ~/.ssh/yourKeyName script: | echo "#######################################################" echo "#####create elastic beanstalk application(version)#####" echo "#######################################################" apt-get update apt-get install zip pip install awscli echo "setting environmnet variable" export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} export AWS_DEFAULT_REGION=${AWS_REGION} echo "Creating zip file" zip -r ${AWS_EB_APP_NAME}.zip . echo "Creating AWS Version Label" AWS_VERSION_LABEL=${AWS_EB_APP_NAME}-${APP_VERSION}-${CI_PIPELINE_ID} S3_KEY="front/src/$AWS_VERSION_LABEL.zip" echo "Uploading to S3" aws s3 cp ${AWS_EB_APP_NAME}.zip s3://${S3_BUCKET}/${S3_KEY} --region ${AWS_REGION} echo "Creating new app version" aws elasticbeanstalk create-application-version \ --application-name ${AWS_EB_APP_NAME} \ --version-label $AWS_VERSION_LABEL \ --region ${AWS_REGION} \ --source-bundle S3Bucket=${S3_BUCKET},S3Key=${S3_KEY} \ --description "${CI_COMMIT_DESCRIPTION}" \ --auto-create-application \ echo "#######################################################" echo "#####deploy elastic beanstalk application(version)#####" echo "#######################################################" pip install awsebcli --upgrade --user AWS_VERSION_LABEL=${AWS_EB_APP_NAME}-${APP_VERSION}-${CI_PIPELINE_ID} export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} export PATH=~/.local/bin:$PATH echo "eb init start" eb init -i ${AWS_EB_APP_NAME} -p ${AWS_PLATFORM} -k bobsikgoo_key.cer --region ${AWS_REGION} echo "eb deploy start" eb deploy ${AWS_EB_ENV_NAME} --version ${AWS_VERSION_LABEL} only: refs: - yourBranch tags: #runner's tag - yourRunnerzTag

beanstalk은 도커를 배포한다. 이 때, Dockerfile로 도커 컨테이너를 설정해줄 수 있다. 깃랩 원격 저장소에 올라가지 않는 중요한 파일을 beanstalk이 만들어준 S3컨테이너(외부에서 접근 불가)에 넣고, 배포하면서 꺼내 쓰는 방식을 선택했다.

도커로 배포할 땐 pm2대신 pm2-runtime을 쓰라는 글을 봐서 그렇게 했다.

# Common build stage FROM ubuntu:18.04 RUN apt-get update RUN apt-get install sudo -y RUN sudo apt-get install zip -y RUN sudo apt-get install curl -y #aws cli 다운로드 RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" RUN unzip awscliv2.zip RUN sudo ./aws/install #node 다운로드 RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - RUN sudo apt-get install nodejs -y COPY . ./app WORKDIR /app #.env 가져오기 RUN aws s3 cp yourSecretFilezS3URI ./.env RUN npm install RUN npm install pm2 -g EXPOSE 3000 #ecosystem.config에 반영 가능한 걸로 보임 ENV NODE_ENV development CMD ["pm2-runtime", "start", "ecosystem.config.js"]

private repository써서 중요파일까지 한번에 올린다면 이렇게 간단하게 해도 될듯하다.

# Common build stage FROM node:14.14.0-alpine3.12 COPY . ./app WORKDIR /app RUN npm install RUN npm install pm2 -g EXPOSE 3000 #ecosystem.config에 반영 가능한 걸로 보임 ENV NODE_ENV development CMD ["pm2-runtime", "start", "ecosystem.config.js"]

pm2의 세부 설정을 작성하는 파일. 기본 스크립트 설정만 했다.

module.exports = { apps : [{ name: "app1", script: 'npm run start', //instances: 0 //exec_mode: 'cluster' }], };

21.8.9월 추가

ecosystem.config.js의 스크립트를 말그대로 메인 자바스크립트 파일 경로를 써줘야 한다.

module.exports = { apps: [ { name: 'app1', script: 'dist/server.js', instances: 0, exec_mode: 'cluster', //merge_logs: true, }, ], };

package.js에 등록해둔 npm run start를 쓰지 못하므로 Dockerfile에 npm run build를 추가했음.

# Common build stage FROM node:14.14.0-alpine3.12 COPY . ./app WORKDIR /app RUN npm install RUN npm install pm2 -g RUN npm run build EXPOSE 3000 #ecosystem.config에 반영 가능한 걸로 보임 ENV NODE_ENV development CMD ["pm2-runtime", "start", "ecosystem.config.js"]

<참고>

외 공식 문서들..

728x90

from http://suuntree.tistory.com/331 by ccl(A) rewrite - 2021-08-11 23:00:28