배포 자동화, 무중단 배포 환경

이서현·2021년 1월 12일
0

wassub

목록 보기
1/1

Travis CI, AWS, Docker를 이용해서 무중단 배포 환경을 구축한다.

  1. github에 push
  2. github -> travis CI 코드 전달
  3. Travis CI 코드 테스트, 빌드
  4. Travis CI => AWS s3에 업로드
  5. Travis CI => CodeDeploy로 명령 후 배포
  6. CodeDeploy => s3에서 파일을 가져오고 배포
  7. CodeDeploy => s3에서 받은 파일을 인스턴스에 넣고 EC2 배포 스크립트 실행
  8. CodeDeploy => 배포스크립트를 실행 후 내부적으로 배포

Travis CI 연동

자신의 프로필에서 push할 repository의 토글을 활성화한다.

AWS 설정

EC2 생성

AWS에서 인스턴스를 생성
보안그룹의 인바운드에서 HTTP 80 포트를 추가한다.

AWS S3 버킷 생성

S3로 이동 후 버킷 만들기를 눌러준다.
이름은 ajou-wassub 입력하고 다음을 눌러준다.

실제로 배포하는 게 아닌 실습이기 때문에 다음과 같이 설정하였다.

완료된 모습

Travis CI 배포 전용 계정

권한이나 서브 계정을 관리하는 IAM 로 이동한다.
사용자를 눌러서 사용자 이름을 입력한다.
AWS 액세스 유형은 프로그래밍 방식 액세스를 선택한다.

권한 설정에서 기존 정책 직접 연결을 선택하고
AmazonS3FullAccess, CodeDeployFullAccess를 체크한다.
사용자 만들기를 누르고 csv를 설치해야한다.

AWS 역할 생성

IAM 의 역할을 누르고 역할 만들기를 누른다.

aws ec2

서비스로 EC2를 고르고 사용 사례에서 EC2를 클릭한다.
권한 정팩에서 AmazonEC2RoleforAWSCodeDeploy를 클릳한다.

aws codeDeploy

마찬가지로 codeDeploy를 선택한다.

AWS 역할 EC2에 적용


EC2 대시보드에서 인스턴스를 오른쪽 클릭 후 보안에서 IAM 역할 수정을 누른다.

만든 EC2 Deploy Role을 적용한다.

EC2에 AWS CodeDeployAgent 설치

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

Docker 설치

sudo yum install docker
sudo usermod -aG docker ec2-user

Docker image

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가 생성되었는지 확인한다.

Docker-compose 생성

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가 실행하고 있는지 확인한다.

Nginx 설치, 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 로 실행한다.

Travis CI 배포

aws codeDeploy 배포 그룹

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/

Travis CI 에 환경변수 추가하기

해당 repository의 settings에서 환경변수에 각각 AWS_ACCESS_KEY, AWS_SECRET_KEY를 입력한다.

마지막 배포

EC2에 접속해서 코드를 git repository에 push한다.
travis CI를 보면 commit이 성공했음을 확인할 수 있다.

AWS CodeDeploy에서 배포 상태를 보면 성공임을 확인할 수 있다.

노력의 흔적들,,,,,


첨 보는 오류 하나로 며칠을 구글링했는지,,, 배포 성공하고 나니 별게 아니였다...허허ㅓㅎ

reference

https://velog.io/@jeff0720/Travis-CI-AWS-CodeDeploy-Docker-%EB%A1%9C-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94-%EB%B0%8F-%EB%AC%B4%EC%A4%91%EB%8B%A8-%EB%B0%B0%ED%8F%AC-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-2#%EB%AC%B4%EC%A4%91%EB%8B%A8-%EB%B0%B0%ED%8F%AC-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0

profile
안녕하세요. 이서현입니다( ღ'ᴗ'ღ )

0개의 댓글