시작하며
인터넷상의 CodePipeline
사용법에 대한 정보를 찾아보면 죄다 CodePipeline
에 CodeBuild
와 CodeDeploy
를 묶어서 이용하는 방법을 알려준다. 하지만, 이제 막 배포 자동화 접하는 사람의 경우 사실 Build 과정은 필요가 없는 경우가 많을 것 같다. 예를 들어 test case가 완전하게 작성되지 않은 토이프로젝트라거나, 매번 test 할 필요는 없는. 즉 build 보다는 잦은 deploy에 초점을 맞추어 빠르게 deploy 하고싶은 경우들말이다.
CodePipeline
을 처음 이용해보면 은근 CodeBuild
의 build 과정에서 많은 시간을 잡아먹는다. 이 중 대부분의 시간이 CI 서버를 Provisioning 하는 동안 소모된다. 즉 굳이 CI가 필요없는 단계이거나, CI 서버에서 테스트 할 필요 없이 로컬에서 테스트한 뒤 repository에 push 하는 프로젝트라면 쓸 데 없이 많은 시간을 CodeBuild
에서 잡아먹힌다는 것이다.
그래서 이번엔 간단하게 CodeBuild 없이 CodePipeline과 CodeDeploy만으로 배포 자동화를 시켜보는 핸즈온을 적어본다.
작업 과정 요약
세세한 내용들은 이미 앞선 CodePipeline
과 CodeDeploy
에 대한 글들에서 작성하였기에 어느정도 생략한다.
CodeDeploy
가 배포하는 환경은 EC2/On-premise
이다.
Express 앱을 배포할 것이다. - 아주 간단하게 Express 앱의 페이지 내용이 변경되는 Deploy
프로세스를 kill 하기 귀찮으니까 그냥 Docker
을 이용하겠습니다.
( 의도치않게 글의 취지와 맞지않을 수 있을만한 진입장벽으로 느껴지실지도 모르겠군요...)
- github repository를 만든다.
- github repository를 clone따고
express-generator
을 이용해 express application 생성 후 서버를 돌리고, 작동하는지 확인한다. appspec.yml
을 작성한다.Dockerfile
,.gitignore
을 작성- EC2 Instance에
codedeploy-agent
와docker
을 설치한다. Security group에서Inbound
를 설정한다. - CodeDeploy에서
Application
,배포그룹
을 생성한다. - CodePipeline에서 방금 생성한 CodeDeploy Application을 설정한다.
- github repository에 push 한다.
세부 작업과정
Github Repository 생성
배포에 사용할 빈 github repository를 생성한다.
express-generator을 이용해 Express Application 생성
git clone {REPOSIOTRY_URL}
npm install -g express-generator
express tutorial-codepipeline
cd tutorial-codepipeline
npm install
npm start
express-generator
을 설치하면 express
라는 명령어로 express application을 만들 수 있다.
이때 application 이름을 자신의 github repository 디렉토리랑 똑같이 하는 것이 편하다. 그래야 .git
디렉토리가 express application 디렉토리에 함께 위치할 수 있기 때문이다.
(Directory가 이미 존재하고 empty가 아니라는 문구가 떠도 괜찮다고 y를 눌러주자.)
npm start 를 했으면 [http://localhost:3000
으로](http://localhost:3000으로) 접속해서 express app이 잘 돌아가고 있는 지 확인한다.
appspec.yml 작성
맨날 CodeDeploy만 달고사는 사람이 아니라면 appspec.yml
을 모두 암기할 순 없다.... Reference를 보고 찾아 쓰는 능력을 기르자.
How to write appspec.yml
⇒ AWS 의 레퍼런스 => EC2 파트
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/tutorial-codepipeline
hooks:
BeforeInstall:
# 프로젝트 디렉토리 기준으로의 경로를 적어줍니다.
# local이나 server 인스턴스의 기준이 아닙니다!
- location: /scripts/initialize.sh
AfterInstall:
- location: /scripts/buildImage.sh
runas: root
ApplicationStart:
- location: /scripts/start.sh
# ValidateService:
# - location: Scripts/MonitorService.sh
# timeout: 3600
# runas: codedeployuser
initialize.sh 로 실행중이던 원래 컨테이너를 종료시키고 삭제시킬 것이고
rm -rf /home/ubuntu/tutorial-codepipeline
docker stop rabbitmq || true && docker rm rabbitmq || true
buildImage.sh 로 변경사항을 적용한 container를 volume을 이용해 실행시킬 것이고
docker build -f /home/ubuntu/tutorial-codepipeline/Dockerfile . -t tutorial:latest
start.sh 로 docker run 시킬 것이다.
docker run -d --rm --name tutorial -p 3000:3000 -v /home/ubuntu/tutorial-codepipeline:/app tutorial:latest
EC2 Instance 생성 및 IAM Role 생성
EC2 에 CodeDeploy와 Docker를 설치하는 과정은 몇 번을 이 블로그 포스트에 작성하였으므로 필요하신 분은 참고하시길 바랍니다.
간단하게만 정리합니다.
- express 앱은
0.0.0.0:3000
에 서버를 띄운다. 따라서 외부에서 이 포트에 접속이 가능하도록 EC2 Instance 의 Security group에서 Inbound로3000 번 포트
를 허용해준다. codedeploy-agent
설치,docker
설치 (node는 docker hub의 이미지를 이용하므로 필요가 없다~!)- EC2 Instance에서 codedeploy 작업을 수행할
IAM Role
생성 - CodeDeploy에서 작업을 수행할
IAM Role
생성
CodeDeploy 애플리케이션과 그것의 배포 그룹 생성
CodeDeploy 애플리케이션(express 애플리케이션과 혼동할 것 없다. 쉽게 말해 그냥 CodeDeploy 설정 하 나 하나를 의미)을 생성하기에 앞서 CodeDeploy에서 이용할 IAM Role
을 생성해줘야한다.
즉 CodeDeploy가 어떤 작업을 수행할 수 있는지 정의해주는 것이다.
CodeDeploy-CodeDeploy를 선택해준다.
CodeDeploy 애플리케이션을 만들고 (실수로 tutorial-codepipeline이 아니라 tutorial-codedeploy로 만들었는데, 이따가 CodeDeploy 애플리케이션 만들 때에만 제대로 선택하면 된다.)
배포그룹까지 만들어준다. 방금 만든 IAM Role 을 부여해주자.
경험상 굳이 CodePipeline의 Role을 직접 만들 필요는 없었다. 웬만하면 새 서비스 역할을 설정하는 게 골치아플 일 없었고, 어떤 경우에 따라 필요한 IAM Role 을 다르게 설정하는 식의 커스터마이징이 필요없었기 때문이다.
하부의 고급설정은 안 건드려도 된다. S3 에 빌드 후 빌드된 아티팩트를 업로드 한다는 것인데, 이번 글에선 CodeBuild를 안 쓰고 간단하게 배포하는 게 목표이기 때문에 어차피 S3 에 업로드 되지 않는다. (아마도)
소스 공급자로 아까 생성한 나의 github repository를 설정해준다.
여기가 중요. 빌드 스테이지를 건너 뛰는 게 우리의 이번 글의 목표!
아까 설정한 CodeDeploy의 배포그룹까지 설정해준다.
이후 CodePipeline 생성을 완료하면 가장 최근 커밋을 기준으로 배포가 진행된다.~!
배포가 성공적으로 진행된 모습.
배포가 잘 이루어지나 다시 확인
배포가 잘 되나 다시 한 번 확인하기 위해 NEW VERSION이라는 문구를 추가해본다.
배포가 잘된 모습. 아주 편리하다. 흐뭇.
How to fix errors
한 번에 배포가 성공될 리는 없다... 수 많은 착오가 기다리는 법.. 너무 낙담하기 말고 아래의 꿀팁들을 명심하자.
내 블로그의 방향은 단순히 단계 설명만 하기 보단 최대한 실제로 발생할 수 있는 에러들을 잡아나가는 방법을 적는 것이다!
계속되는 "보류 중"
Deploy 과정은 그리 빠르진 않지만 또 그리 오래걸리지 않는다. 1분이상 시작조차 안 되고 있다면 다음의 몇 가지 사항들을 의심해보자.
-
EC2 Instance가 꺼져있거나 CodeDeploy 배포그룹에서 EC2 Instance를 잘 못 골랐다.
-
EC2 Instance의
codedeploy-agent
가 제대로 작동하지 않는다.⇒
sudo service codedeploy-agent status
로 확인 가능 -
EC2 의 IAM Role이 제대로 설정되어있지 않다
⇒ EC2의 CodeDeploy Role을 추가한 뒤 EC2 에 붙여준다.
Script failed 에러
스크립트가 stderr, 즉 에러 스트림을 이용해 출력할 경우 deploy가 중단된다.
redirect stderr to stdout
이라는 키워드를 통해 구글링해보자. 참고
0은 stdin
1은 stdout
2는 stderr
이므로 docker stop tutorial 2>&1
이런 식으로 stderr을 stdout으로 redirect 시킬 수 있다.
에러가 나든 안 나든 한 번 수행하고 싶은 작업을 수행할 때 유용하다.
환경 변수 에러 혹은 그로 인한 no such file or directory
CodeDeploy의 hooks의 commands 를 수행할 때에는 환경변수를 최대한 사용하지 않는 것이 정신건강에 이롭다. /etc/environment
파일에 환경변수를 작성해야지 잘 알아듣고 .profile, .bash_profile 등의 환경변수는 인식하지 않는 듯 하다.
따라서 $HOME/tutorial-codepipeline 이런 식의 경로를 이용하는 script가 있을 경우 제대로 작동하지 않을 수 있고, 에러가 날 수 있다. 따라서 script 상에서의 환경변수의 사용은 자제해야한다.(.env
등을 통한 프로젝트의 환경변수는 문제 없음!)
마치며
CodePipeline을 이용해 AWS 에서 가장 간단한 방법으로 Deploy하는 방법을 알아보았다. 그 동안은 CodeBuild가 꼭 필요한 줄 알고 사실상 빌드 과정이 없는 프로젝트에서도 CodeBuild를 이용했는데, 그럴 필요가 없어졌고, 작업이 훨씬 빨라져서 좋았다.
'AWS' 카테고리의 다른 글
AWS CodePipeLine, CodeBuild, CodeDeploy를 통해 EC2에 배포하기, AWS CI/CD 구축하기 - 2 (0) | 2020.01.21 |
---|---|
AWS CodePipeLine, CodeBuild, CodeDeploy를 통해 EC2에 배포하기, AWS CI/CD 구축하기 - 1 (0) | 2020.01.21 |
AWS CodeDeploy와 S3 이용해서 배포하기 (0) | 2020.01.16 |
AWS CodeDeploy와 Gtithub 이용해 배포하기 (0) | 2020.01.14 |
CloudWatch, Lambda 를 이용한 SlackBot 만들기 (0) | 2019.10.29 |