nodejs서버(DockerFile로 배포가능하면 무엇이든 가능)를 gitlab에 커밋 - AWS S3에 코드를 업로드 - AWS elastic beanstalk + docker + pm2 배포
위 과정의 자동화에 대한 포스팅이다.
<사전 준비사항>
- AWS Route53을 통한 도메인 생성
- AWS certificate manager를 통한 ssl 인증서 발급
- AWS IAM계정 파두기
- AWS S3 버킷 생성
- 키페어 하나 준비해두기
- EC2 인스턴스 보안그룹 입맛에 맞게 생성
-> 나중에 필요하면 따로 포스팅할 예정.
<Elastic beanstalk 환경생성>
새 환경 생성 버튼 클릭
웹 서버 환경 -> 선택 클릭
어플리케이션 이름과 환경 이름 설정
관리형 플랫폼 - docker 선택 후 추가옵션 구성 버튼 클릭
로드 밸런서와 오토스케일링 붙일거니까 고가용성 선택
인스턴스, 로드밸런서, 보안에서 편집사항 있음.
인스턴스 보안 그룹 적절히 지정해서 선택
로드밸런서에서 리스너 추가
다음과 같이 추가
가상머신 권한에 EC2 키페어 추가
환경생성
http로 샘플 애플리케이션이 돌아가는 것 확인
<Route53으로 우리 도메인 연결>
사용할 레코드 생성
별칭으로 방금 생성한 elastic beanstalk 환경에 연결
SSL인증이 된 우리 라우터에 연결된 것 확인
<gitlab runner 구동>
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
<Dockerfile 작성>
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"]
<ecosystem.config.js 작성>
pm2의 세부 설정을 작성하는 파일. 기본 스크립트 설정만 했다.
module.exports = {
apps : [{
name: "app1",
script: 'npm run start',
//instances: 0
//exec_mode: 'cluster'
}],
};
21.8.9월 추가
<cluster 모드를 사용한다면?>
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"]
21.8.25추가
빌드후 정적파일을 nginx로 배포
nginx.config
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name www.bobsikgoo.com;
location / {
root /app/build;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass https://api.bobsikgoo.com;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
include servers/*;
}
dockerfile. multi stage build 사용
# Common build stage
FROM node:16.6.0-alpine3.11
WORKDIR /app
COPY . /app
RUN npm install
RUN npm run build
#production stage
FROM nginx:alpine
WORKDIR /app
COPY --from=0 /app/build/ /app/build/
COPY --from=0 /app/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
<참고>
외 공식 문서들..
'웹 > Infra' 카테고리의 다른 글
초보를 위한 쿠버네티스 안내서 - 실습준비 (0) | 2021.09.21 |
---|---|
k8s - Kube arch object (0) | 2021.09.21 |
k8s - Kube Architecture (0) | 2021.09.21 |
k8s - Container Orchestration (0) | 2021.09.21 |
nodejs로 AWS S3 연동 (0) | 2021.07.16 |