Travis CI, AWS, Docker를 이용해서 무중단 배포 환경을 구축한다.
자신의 프로필에서 push할 repository의 토글을 활성화한다.
AWS에서 인스턴스를 생성
보안그룹의 인바운드에서 HTTP 80 포트를 추가한다.
S3로 이동 후 버킷 만들기를 눌러준다.
이름은 ajou-wassub 입력하고 다음을 눌러준다.
실제로 배포하는 게 아닌 실습이기 때문에 다음과 같이 설정하였다.
완료된 모습
권한이나 서브 계정을 관리하는 IAM 로 이동한다.
사용자를 눌러서 사용자 이름을 입력한다.
AWS 액세스 유형은 프로그래밍 방식 액세스를 선택한다.
권한 설정에서 기존 정책 직접 연결을 선택하고
AmazonS3FullAccess, CodeDeployFullAccess를 체크한다.
사용자 만들기를 누르고 csv를 설치해야한다.
IAM 의 역할을 누르고 역할 만들기를 누른다.
서비스로 EC2를 고르고 사용 사례에서 EC2를 클릭한다.
권한 정팩에서 AmazonEC2RoleforAWSCodeDeploy를 클릳한다.
마찬가지로 codeDeploy를 선택한다.
EC2 대시보드에서 인스턴스를 오른쪽 클릭 후 보안에서 IAM 역할 수정을 누른다.
만든 EC2 Deploy Role을 적용한다.
chmod 400 ajou-wassub.pem
ssh -i ajou-wassub.pem ec2-user@(인스턴스 퍼블릭 IP 주소)
터미널에서 인스턴스를 접속한다.
sudo yum install awscli
AWS CodeDeployAgent 설치한다.
sudo aws configure
사용자를 만들때 받은 csv 파일을 열고
Access Key ID와 Secret Acecess Key을 작성한다.
나머지는 enter 키로 default를 주었다.
aws s3 cp s3://aws-codedeploy-ap-northeast-2/latest/install . --region ap-northeast-2
chmod +x ./install
sudo apt-get install ruby
sudo ./install auto
install 파일을 실행할 수 있는 권한을 준다. sudo ./install auto로 AWS CodeDeploy 에이전트를 설치한다.
sudo service codedeploy-agent start
sudo service codedeploy-agent status
AWS CodeDeploy 에이전트를 실행한다.
The AWS CodeDeploy agent is running as PID 3711
sudo yum install docker
sudo usermod -aG docker ec2-user
mkdir docker-image
cd docker-image
vi Dockerfile
Dockerfile
#node 10.14 버전을 사용하겠다는 의미
FROM node:10.14
#해당 이미지를 만든 사용자의 정보
MAINTAINER ajou-wassup <mlsh1112@ajou.ac.kr>
#도커 컨테이너 호스트와 공유할 디렉터리 지정
VOLUME /deploy/node-koa-server
#도커 이미지를 실행할시 실행될 스크립트
COPY ./start-server.sh /usr/local/bin
RUN ln -s /usr/local/bin/start-server.sh /start-server.sh
CMD ["start-server.sh"]
vi start-server.sh
start-server.sh
#!/bin/bash
cd /deploy/node-koa-server
yarn install
yarn prod
chmod +x ./start-server.sh
sudo systemctl start docker
sudo systemctl enable docker
sudo chmod 666 /var/run/docker.sock
docker build -t node-koa-server-docker-image .
docker image를 build하는데 permission denied error가 발생해서
sudo chmod 666 /var/run/docker.sock 로 권한을 바꿔주었다.
docker images
docker image가 생성되었는지 확인한다.
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose version
docker-compose 툴을 만들어줍니다.
vi docker-compose.yml
docker-compose.yml
version: '2'
services:
node-koa-server:
image: node-koa-server-docker-image
volumes:
- /home/ec2-user/deploy/node-koa-server:/deploy/node-koa-server
ports:
- "3000:3000"
docker-compose up -d
docker가 실행하고 있는지 확인한다.
sudo yum update
sudo amazon-linux-extras install nginx1
sudo service nginx start
sudo service nginx status
/etc/nginx/sites-available로 이동한다.
만약 디렉토리가 없으면
https://stackoverflow.com/questions/17413526/nginx-missing-sites-available-directory
node-koa-server 파일을 생성한다.
server {
listen 80;
server_name localhost; # 세미콜론 붙여주셔야 합니다.
location / {
proxy_pass http://127.0.0.1:3000;
}
}
sudo ln -fs /etc/nginx/sites-available/node-koa-server /etc/nginx/sites-enabled/
sudo service nginx restart
인스턴스의 퍼블릭 IP 주소로 접속 가능하면 성공이다.
server 3001이 실행하면 업데이트한 소스코드를 실행한 서버를 3002포트에서 실행한다. 실행이 끝나면 3001 포트를 종료한다. nginx는 3001포트 3002 포트를 로드밸런싱 해야한다.
cd /home/ec2-user/docker-image
vi docker-compose.blue.yml
vi docker-compose.green.yml
docker-compose.blue.yml
version: '2'
services:
node-koa-server:
image: node-koa-server-docker-image
volumes:
- /home/ec2-user/deploy/node-koa-server:/deploy/node-koa-server
ports:
- "3001:3000"
docker-compose.green.yml
version: '2'
services:
node-koa-server:
image: node-koa-server-docker-image
volumes:
- /home/ec2-user/deploy/node-koa-server:/deploy/node-koa-server
ports:
- "3002:3000"
deploy.sh
#!/bin/bash
DOCKER_APP_NAME=node-koa-server
EXIST_BLUE=$(docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml ps | grep Up)
if [ -z "$EXIST_BLUE" ]; then
echo "blue up"
docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml up -d
sleep 10
docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml down
else
echo "green up"
docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml up -d
sleep 10
docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml down
fi
파일 생성 후 실행 권한 부여한다.
chmod +x ./deploy.sh
cd /etc/nginx/sites-available
node-koa-server 파일 변경
# Load Balancing
upstream node-koa-server {
least_conn;
server 127.0.0.1:3001 weight=5 max_fails=3 fail_timeout=10s;
server 127.0.0.1:3002 weight=10 max_fails=3 fail_timeout=10s;
}
server {
listen 80;
server_name localhost; # 세미콜론 붙여주셔야 합니다.
location / {
proxy_pass http://node-koa-server;
}
}
sudo ln -fs /etc/nginx/sites-available/node-koa-server /etc/nginx/sites-enabled/ &&
sudo nginx -t && sudo service nginx restart
/home/ec2-user/docker-image로 이동 후 ./deploy.sh 로 실행한다.
aws codeDeploy로 이동하고 배포에서 애플리케이션을 생성한다.
애플리케이션 이름을 적고 컴퓨터 플랫폼으로 EC2를 선택한다.
애플리케이션이 생성되었으면 배포그룹을 만든다.
이름과 서비스역할을 고르고 키 값을 인스턴스 키 값과 동일하게 해야한다. (중요,, 여기서 오류나서 매우 고생,,,,,)
배포그룹을 생성했으면 travis.yml을 만든다.
travis.yml
language: node_js
node_js:
- "10.14"
before_install:
- npm install -g yarn
branches:
only:
- master
before_deploy: # 배포하기전 하는 작업들
- rm -rf node_modules # travis가 설치한 node_moduels를 삭제
- zip -r node-koa-server * # node-koa-server 라는 이름으로 zip 파일 생성
- mkdir -p deploy # deploy 라는 디렉터리를 만듬
- mv node-koa-server.zip deploy/node-koa-server.zip # deploy 디렉터리로 node-koa-server.zip 파일을 이동
deploy: # 배포
- provider: s3 # AWS S3를 의미
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: ajou-wassub # S3에 생성한 버킷
region: ap-northeast-2
skip_cleanup: true
local_dir: deploy # deploy 디렉터리에 있는 파일을 s3로 업로드 하겠다는 의미
wait-until-deployed: true
on:
repo: ajou-wassub/backend #Github 주소
branch: master
- provider: codedeploy # AWS CodeDeploy를 의미
access_key_id: $AWS_ACCESS_KEY # Travis repo settings에 설정된 값
secret_access_key: $AWS_SECRET_KEY # Travis repo settings에 설정된 값
bucket: ajou-wassub # AWS CodeDeploy가 다운로드 받은 버킷
key: node-koa-server.zip # 해당 버킷에 저장되어 있는 파일 이름
bundle_type: zip # 버킷에 저장되어 있는 파일의 확장자
application: ajou-wassub-code-deploy-service # AWS 배포 애플리케이션
deployment_group: ajou-wassub-deploy-group # AWS 배포 애플리케이션에 만들어져 있는 배포 그룹
region: ap-northeast-2
wait-until-deployed: true
on:
repo: ajou-wassub/backend #Github 주소
branch: master
appspec.yml
(AWS CodeDeploy가 어떤 역할을 해야하는지 알려줌)
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/deploy/node-koa-server/ # S3에서 가지고온 파일을 저장할 디렉터리 지정
overwrite: yes
hooks:
BeforeInstall:
- location: before-deploy.sh
timeout: 180
AfterInstall: # 배포가 끝나면 아래 명령어를 실행
- location: execute-deploy.sh
timeout: 180
execute-deploy.sh
#!/bin/bash
cd /home/ec2-user/docker-image
./deploy.sh > /dev/null 2> /dev/null < /dev/null &
-->travis CI가 commit을 하고 배포하는 과정 중 codeDeploy를 하는 과정 중에서 beforeinstall에서 appspce.yml 파일이 충돌하는 오류가 발생했다. Beforeinstall에서 파일을 삭제하는 명령어가 필요했다.
before-deploy.sh
#!/bin/bash
cd /home/ec2-user/deploy #기존에 있는 build파일을 삭제하고 ....
#sudo rm -rf server-latest #기존에 있는 파일을 삭제한다..!
sudo rm -rf node-koa-server/
해당 repository의 settings에서 환경변수에 각각 AWS_ACCESS_KEY, AWS_SECRET_KEY를 입력한다.
EC2에 접속해서 코드를 git repository에 push한다.
travis CI를 보면 commit이 성공했음을 확인할 수 있다.
AWS CodeDeploy에서 배포 상태를 보면 성공임을 확인할 수 있다.
첨 보는 오류 하나로 며칠을 구글링했는지,,, 배포 성공하고 나니 별게 아니였다...허허ㅓㅎ