AWS를 이용한 간략 지속적 통합 예제, 무중단 배포 자동화 CI & CD, CodeBuild, CodeDeploy, CodePipeline
최종수정일자 : 2020-02-14
글의 목적과 뱡향은 다음과 같습니다.
1. 제자 또는 초보자를 위한 참고문서
2. CI & CD의 개념을 알아보자
3. 글의 길이 보다, 핵심 내용을 추리고 압축한다.
4. 예제를 해보려면 최소한 Git 이나 클라우드에 대한 개념 자체는 알고 있어야 한다.
5. 예제를 따라하여 '무중단 배포 자동화'를 실현해보자.
CI & CD 란 무엇일까?
인터넷에 올라와 있는 문서들을 정리 후, 정리하면 다음과 같습니다.
지속적 통합(CI: Continuous Integration)은, 작은 단위의 코드를 짧고 빈번하게 통합 하는 방식
- 코드 퀄리티를 유지
- 여러명이 동시 개발시, 코드 충돌 문제를 줄임
- 작은단위를 빈번하게 통합하므로, 큰 방향으로는 배포시간을 줄이는 것에 목적을 둠
- 코드 단위 테스트 자동화
지속적 전달(CD: Continuous Delivery)는, 테스팅을 위해, 결과물을 짧고 빈번하게 전달 하는 방식
- 운영팀과 개발팀의 Bridge
- 짧고 빈번한 테스팅 환경 구축
- 짧은 시간 내에 결과물 피드백을 받음
- Staging-Area (Production-Area 이전)
지속적 배포(CD: Continuous Deployment)는, 프로덕션 환경까지 빠르게(배포주기), 자동으로 배포 하는 방식
- 애자일, DevOps와 연관됨
- 배포를 하는 과정에서 들어가는 비용을 자동화로 줄임
- 지속적 통합, 지속적 전달과 더불어 고객에게 퀄리티 높은 결과물을 빠르게 제공한다는 관점
- Production-Area (실제 운영 환경)
- 개발자는 변경된 코드를 소스 코드관리 시스템에 올린다.
- 소스 코드관리 시스템은 코드 변경 이벤트를 받을 시 빌드 서버로 전달한다.
- 지속적 통합 서버는, 빌드 후 테스트의 결과를 성공과 실패로 알려준다.
- 개발자 또는 매니저는 상황을 파악한다.
- 문제가 생기면 코드를 재 조정후 1번 부터 시작한다.
왜?
왜는 항상 중요합니다. 왜 필요할까요?
근본적인 이유는 급변하는 경영환경에 대응하기 위함이라고 볼 수 있습니다.
- 고객 트렌드의 급격한 변화로 인해 빠른 출시 및 배포 필요
- 이전의 소프트웨어 개발 방법론으로는 '닭 쫒던 개 지붕 쳐다보듯'
- 효율 극대화
사실 개인적으로 생각하는 큰 이유는 이게 아닐까 쉽습니다.
- 정형화되고 반복적인 귀찮음은 자동화로 해결하자.
- 인간은 실수하기 쉽다.
CI & CD 과정은 어떻게 이루어지는가?
CI & CD 는 기업의 정책과 운영환경에 따라 달라집니다. 또한 각 팀의 규모와 구성에 따라 달라집니다.
다만 공통적인 흐름은 크게 변하지 않습니다.
개념적인 방법으로 요약해보면 다음과 같습니다.
- 코드를 올린다.
- 빌드하고 테스팅한다.
- 문제 없으면 배포한다.
좀 더 상세히 풀어보면 다음과 같습니다.
1. 코드를 원격저장소에 저장한다.(master)
1) 병합할 수 없는 코드는 충돌로 체크하고 피드백 한다.
2. 원격저장소는 코드 변경 이벤트를 받아, 빌드와 테스팅이 가능한 서버로 코드를 전달한다.
3. 빌드한다
1) 빌드 실패시 개발자에게 알려준다.
2) 성공 시 다음단계로 넘어간다.
4. 테스트한다.
1) 테스트 실패시 개발자에게 알려준다.
2) 성공 시 다음단계로 넘어간다.
5. QA 또는 운영팀이 테스팅이 가능한 테스트 서버 (개념적 staging-area)로 빌드된 프로덕트를 전달한다.
6. QA 또는 운영팀이 테스트 서버에서 테스트를 진행한다.
1) 반려 시 개발자에게 알려준다.
2) 통과 시 다음단계로 넘어간다.
7. 프로덕션 환경으로 배포 한다.
1) 배포방식에 따라 배포한다.
2) 배포실패 시 배포실패에 대한 전략에 따라 처리한다.
CI & CD를 가볍게 맛보기 위한 방법
CI & CD 라고 하기에는 엄밀하게 많이 부족하지만 '맛보기 CI & CD 중에서 무중단 배포 자동화'를 중심으로 시작합니다.
최초 흐름을 파악하는 것에 중점을 두고, 나중에 살을 붙이는 것이 좋습니다.
잘 모르는 상태에서, 처음부터 모든 Process를 구성하면 머리가 복잡해집니다..^^;;
AWS의 인프라와 saas를 이용하여 가벼운 CI & CD 를 적용해 볼 겁니다.
예제를 구현함으로써 얻게되는 결과물에 대한 목표
- 변경된 코드를 소스 코드 관리소에 저장한다.
- 소스 코드가 올라가면 빌드를 한다.
- 빌드가 성공하면 무중단 Blue/Grean배포를 진행한다.
(개념적인 것을 알게 되면 모든 프로세스를 직접 설계하고 만들 수도 있습니다. ;옛날에 만들었던 것을 지금보니 좀 난잡하네요;; 부족한 것도 많고..)
(옛날 Naver Cloud Platform 이용 시, 사용할려고 만들었던 엄청 오래된 legacy 프로젝트도 있습니다.)
https://github.com/roka88/NcpCodeDeploy
준비물
- 작은 프로덕트
- EC2
- AMI
- ELB
- CodeCommit
- CodeBuild
- CodeDeploy
- CodePipeline
- CloudWatch
- S3
밑에서 부터는 하나도 빠짐없이 천천히 따라가셔야 합니다.^^
1. 작은프로젝트 다운로드
node.js로 만들어진 작은 프로젝트 입니다.
node.js가 사전에 설치되어 있어야 합니다. 또한 git도 설치되어 있어야 합니다.
koa framework로 만들어졌고 루트 패스로 접속하면 'version 0.0.0' 라고 뜨는 것이 정상입니다.
1) 프로젝트 다운로드
https://github.com/roka88/MinimumNode
# git clone https://github.com/roka88/MinimumNode.git
2) yarn 설치(NPM 설치 시, Global)
# npm install -g yarn
3) 프로젝트 폴더에 node_module 설치
# yarn install
4) 정상 실행 되는 지 실행해보기
# yarn start
2. AWS 계정을 준비한다.
aws 계정이 없으면 조금 난감하다.
aws 계정을 만들고 준비한다.
절차에 대해서는 굳이 설명하지 않겠다.
3. 작은프로젝트를 CodeCommit이나 Github으로 올린다.
1) 리포지토리 생성
2) 리포지토리 URL 복제
4) CodeCommit에 접속할 수 있도록 AWS 자격증명 발급후 세팅하기
해당 내용은 운영체제마다 또는 상황에 따른 대응 방법이 다르므로, 잘 작성되어있는 AWS 문서를 링크합니다.
https://docs.aws.amazon.com/ko_kr/codecommit/latest/userguide/setting-up.html#setting-up-compat
5) Clone 했던 프로젝트 폴더에 가서 원격저장소에서 remote 주소 추가
# git remote add aws https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/Minimum
6) 해당 프로젝트를 CodeCommit에 Push
# git add .
# git commit -m 'release 2020-01-01'
# git remote add aws https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/Minimum
# git push aws master
앞으로 소스 코드를 변경할 때 마다 CodeCommit(소스 코드 관리 원격저장소)에 저장을 할 것이다.
4. AMI를 만들기 위한 EC2 생성 및 준비
Nginx 웹서버 설치, Node설치와 EC2 인스턴스가 Load된 후 실행할 행동들을 정의 할 겁니다.
1) EC2 생성
Caution! : 프리티어로 생성하더라도 인스턴스 운영 무료 시간이 끝나면 과금 될 수 있으므로 테스트 후에는 꼭 인스턴스를 반납해야 합니다.
인스턴스 시작을 클릭한다.
Amazon Linux 2 AMI를 선택한다.
테스트만 진행할 것이므로 프리티어로 선택한다.
간략히 테스트 구축만 할 예정이므로, 나머지는 건들지 않고 CloudWatch 세부 모니터링 활성화만 체크한다.
스토리지 추가도 건들지 않고 패스한다.
일단 태그도 패스한다. 태그는 인스턴스에다가 태그를 달아서 필터링하기 쉽게 만든다.
(인스턴스 그룹 식별자로도 요긴하게 쓰임)
쉽게 포트 방화벽이라고 생각하면 된다. 22번 포트와 80번 포트를 열어둔다. 보안 그룹 이름도 알아서 정한다.
여기 스크린샷에는 22번 포트에 모든 IP를 허용했으나, 직접 따라할 때는 자신의 IP만 접속가능하게 해야한다.
시작하기를 선택한다.
인스턴스 생성시에는 인스턴스에 SSH를 통해 접근하기 위한 키페어가 있어야 한다.
기존의 키 페어가 없으면 새로 만들고 다운로드하여 잘 보관한다.
잃어버리면 다시는 인스턴스를 터미널을 통해 접근 못한다고 볼 수 있다.
생성완료!
2) EC2 접속
Windows 유저라면 putty를 이용하고, mac 또는 리눅서라면 터미널을 통해 생성한 EC2 인스턴스에 접근한다.
생성된 EC2의 IPv4 퍼블릭 IP는 각자 다르다. 스샷 찍던 시점에는 13.125.171.228이다.
EC2를 생성할 때 다운로드 받았던 키를 이용하여 터미널을 통해 EC2에 접속한다.
# ssh -i /Users/roka/test.pem ec2-user@13.125.171.228
3) EC2 커널 업데이트 및 Git과 Node.js 설치
아래의 명령어들은 EC2를 접속하여 EC2 내부에서 실행 해야 하는 명령어입니다. (혹시나 착각할까봐 ^^;;;)
커널을 업데이트 해주자.
# sudo yum update -y
시간설정을 한국으로 해주자. (변경 후 재부팅 하긴 해야하나 지금 할 필요는 없다.)
# sudo vi /etc/sysconfig/clock
ZONE="Asia/Seoul"
로 변경후 저장
sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
Git을 설치해주자.
# sudo yum install git -y
Node 설치를 위한 NVM(Node Version Manager 설치)
# curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
NVM은 별도의 설명을 하지 않습니다.
NVM 활성화
# . ~/.nvm/nvm.sh
최신버전 Node.js 설치
# nvm install node
Node.js 및 설치 버전 확인
# node -v
Yarn 설치
# npm install -g yarn
4) 작은프로젝트 Clone 및 프로젝트 실행 테스트
최초 로컬 컴퓨터에서 CodeCommit에 접근하기 위한 설정을 EC2 내부에서도 유사하게 해야 합니다.
설정되어 있지 않으면 CodeCommit의 리포지토리를 복사할 수 없습니다.
해당 관련 문서는 상단의 CodeCommit의 자격증명 헬퍼를 확인하면 됩니다.
실제 운영시에는 보안을 위해 IAM이나, 임시자격증명을 이용합니다.
AWS Configure
# aws configure
AWS Access Key ID [None]: (access key)
AWS Secret Access Key [None]: (secret key)
Default region name [None]: ap-northeast-2
Default output format [None]:
자격 증명 헬퍼 등록
# git config --global credential.helper '!aws codecommit credential-helper $@'
# git config --global credential.useHttpPath true
작은프로젝트 Clone
# git clone https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/Minimum
해당 작은프로젝트 폴더에서 Node Module 설치
# yarn install
작은프로젝트를 데몬방식(백그라운드)로 실행하기 위한 Systemd Service 등록 (파일명 뒤에 .service 가 꼭 붙어야 한다.)
등록하는 이유는, 추후 프로젝트 배포 때 스크립트 실행 과정에서 서버를 실행하기 위한 서비스 등록입니다.
# sudo vi /etc/systemd/system/node_server.service
node_server 문서에 아래의 해당 내용을 작성후 저장한다.
혹시나 NVM으로 설치된 node의 버전이 13.5.0이 아니거나 Node server가 실행되지 않는 경우
which nvm 명령어를 통해 node 실제 실행경로를 파악 후 변경해주면 된다.
[Unit]
Description=Test Node Server
After=syslog.target
[Service]
WorkingDirectory=/home/ec2-user/Minimum
SyslogIdentifier=test_node_server
ExecStart=/bin/bash -c "/home/ec2-user/.nvm/versions/node/v13.5.0/bin/node /home/ec2-user/Minimum/app.js >> /home/ec2-user/app.log"
User=root
Type=simple
[Install]
WantedBy=multi-user.target
작은프로젝트 서버인 Service를 실행한다.
# sudo service node_server start
실행중인 것을 확인하고 싶으면, EC2 생성시 설정했던 보안그룹에 3000 port를 열어주고 해당 아이피와 포트번호를 브라우저에 작성하면 정상 실행되는 것을 확인 할 수 있습니다. 다만 확인 후 다시 3000 port를 닫아주세요..^^;;
후... 길다..
이젠 Nginx 서버를 설치하고 리버스 프록시 방식으로 Node.js를 연결할 것이다.
Nginx 웹서버 설치
Nginx라는 웹서버와 웹서버가 무엇을 하는지에 대해서는 설명을 하지 않습니다.
# sudo amazon-linux-extras install nginx1.12
Nginx 관련 Directory
# cd /etc/nginx
Nginx Configuration File 수정
# sudo vi /etc/nginx/nginx.conf
기존의 nginx.conf 파일의 내용을 지우고 아래의 내용으로 덮어 씌웁니다.
(작은프로젝트가 3000번 포트로 실행하기 때문에 웹 서버에서 리슨하는 80번 포트를 3000번 포트로 리버스 프록시 설정한 것 뿐입니다.)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
underscores_in_headers on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
Nginx 웹 서버 시작
# sudo service nginx start
후 ...드디어...
5) CloudWatch Log와 CodeDeploy Agent 설치
CloudWatch는 해당 인스턴스의 상태를 체크하며, 모니터링을 도와주고, 로그를 남기기 위한 서비스 입니다.
CodeDeploy는 AWS CodeDeploy는 Amazon EC2, AWS Fargate, AWS Lambda 및 온프레미스 서버와 같은 다양한 컴퓨팅 서비스에 대한 소프트웨어 배포를 자동화하는 완전관리형 배포 서비스 입니다.
AMI(Amazon Machine Image)를 만들기 이전에 앞서 배포 자동화에 필요한 것들을 설치 후, 인스턴스를 이미지로 만들 예정이기 때문에, 미리 준비해야 합니다.
CodeDeploy Agent 설치를 하기 위한 Ruby 설치
# sudo yum install ruby -y
CodeDeploy Agent 설치
# wget https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install
# chmod +x ./install
# sudo ./install auto
CodeDeploy Agent 설치 및 실행 확인
# sudo service codedeploy-agent status
CloudWatch Log 설치
CloudWatch Log 설치 후, 실행하고 인스턴스가 재부팅시에도 자동으로 실행할 수 있도록 설정합니다.
# sudo yum install -y awslogs
# sudo systemctl start awslogsd
# sudo systemctl enable awslogsd.service
CloudWatch Log Configuration
# sudo vi /etc/awslogs/awslogs.conf
Configuration 파일의 맨 밑 하단에서 로그 그룹 및 형식을 설정할 수 있습니다.
Rolling Log 방식이 아니므로 간단하게만 설정합니다. Configuration에 대해 더 자세히 알고 싶은 경우는 이 곳을 클릭
[/var/log/messages]
datetime_format = %b %d %H:%M:%S
file = /var/log/messages
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/messages
# 로그 모니터링을 추가해보자.
[/home/ec2-user/app.log]
datetime_format = %Y-%m%-%d %H:%M:%S
file = /home/ec2-user/app.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /home/ec2-user/app.log
AwsLog AwsCli Plugin Region 변경
깜빡하면 안되는 중요합니다..^^;;
# sudo vi /etc/awslogs/awscli.conf
# 설정파일 아래 내용 변경
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-2
CloudWatch Log 재 실행
환경설정도 바꿔줬으니, 에이전트를 다시 재 실행해 봅시다.
# sudo systemctl restart awslogsd
6) EC2, CodeDeploy와 CloudWatch, 배포를 위한 IAM 설정
iAM은 개념자체가 어렵습니다..^^;; 일단 Hello world를 찍어야겠습니다.
EC2의 IAM에 적용 시킬 정책을 만들겁니다. 먼저 서비스 중 IAM 설정할 수 있는 곳으로 갑니다.
우리는 인스턴스인 EC2 권한에 대한 정책을 만들려고 하므로, AWS 서비스를 체크, EC2를 체크 합니다.
중간 화면에서 정책들을 검색해서 찾아 체크박스로 체크합니다.
AmazonS3FullAccess : CodePipeLine을 통해 프로젝트 압축 파일 배포 권한
AWSCodeDeployFullAccess : CodeDeploy 권한
AWSCodeDeployRole : CodeDeploy 권한
CloudWatchLogsFullAccess : CloudWatch Log 권한
역할이 만들어진 것을 확인합니다.
다시 인스턴스 관리 화면으로 돌아와서, 생성했던 EC2의 IAM 역할을 변경할 겁니다.
다시 인스턴스 관리 화면으로 돌아와서, 생성했던 EC2의 IAM 역할을 변경할 겁니다.
만들었던 IAM 역할을 EC2에게 부여합니다.
해당 인스턴스에 IAM 역할이 부여된 것을 확인할 수 있습니다.
후 ...드디어...
CloudWatch에서도 로그 그룹에 로그가 찍히기 시작합니다.
7) AMI 만들기 전 MinimumTemp 디렉토리 생성
중요한 부분 입니다. MinimumTemp 라는 폴더를 생성 해야 합니다. (빈 폴더로 남겨야 함)
이유는 나중에 CodeDeploy를 통해서 프로젝트 압축 파일을 받을 때 MinimumTemp 라는 폴더로 받아서 압축을 풀 예정입니다.
나중에 쓰이게 됩니다.
AMI 만들기 전 최종 작업으로 해야합니다.
폴더 권한은 ec2-user로 되어있으면 됩니다.
# mkdir /home/ec2-user/MinimumTemp
8) AMI 만들기
인스턴스의 AMI를 만들기 위해 긴 여정을 달려왔습니다. 아직 한참 멀었지만 더 가봅시다.
이미지 이름을 작성하고 이미지를 생성합니다.
이미지가 생성되기 까지 좀 시간이 걸립니다. 이미지가 생성되면 이젠 다음단계입니다.
5. 이중화를 위한 ELB 준비
ELB를 생성하고, 다음단계로 나아갈 예정입니다.
1) 시작구성과 로드밸런서를 한번에
Application Load Balancer를 생성합니다.
리스너 같은 경우는, 로드 밸런서로 443 포트를 사용하지 않기 때문에 일단 80번으로 설정합니다.
443 포트로 연결하지 않는 경우 뜨는 주의사항입니다.
실 운영시에는 항상 보안 프로토콜로 ^^;;
로드밸런서의 보안그룹을 새롭게 생성해 봅니다. 로드밸런서의 방화벽 포트입니다.
우리는 http 80번 포트를 통해, 라우팅 받는 모든 인스턴스와 통신을 할 예정입니다.
(우리는 신성한 칼라를 통해, 모든 생각과 모든 감정을 함께 나누기 때문이다!!)
대상그룹을 설정합니다. 상태검사도 같이 설정하게 됩니다.
(현재는 default로 갑시다. 갈 길 멉니다.)
대상그룹을 생성후 로드밸런서를 연결하는 방법도 있습니다.
아직은 로드밸런서를 통해 인스턴스로 라우팅 하지 않은 예정입니다.
이제 곧 AutoScaling Group 단위로 라우팅을 할 것입니다.
마지막으로 검토 후 Application LoadBalancer를 생성합니다.
6. AutoScalingGroup 만들기
AWS AutoScaling은 애플리케이션을 모니터링하고 용량을 자동으로 조정하여, 최대한 저렴한 비용으로 안정적이고 예측 가능한 성능을 유지합니다.
1) AutoScaling Group 시작구성 생성
하단 탭의 AutoScaling 시작구성을 클릭하고, 시작 구성 생성을 합니다.
기존에 만들었던 AMI를 선택합니다.
AutoScaling 시 어떤 인스턴스 유형을 할지 선택합니다. 테스트때는 프리티어로 합니다.
IAM 역할도, 기존에 만들었던 IAM 역할로 선택합니다.
CloudWatch 세부 모니터링도 활성화 합니다.
Auto Scaling Group도 새로운 보안그룹을 생성해줍시다.
확인 후 시작 구성을 생성합니다.
EC2 생성 때와 같이 키 페어를 선택해 줍니다.
2) AutoScaling Group 생성
시작구성을 기반으로 실제 Auto Scaling Group을 만들 겁니다.
기존의 Auto Scaling 시작 구성을 선택합니다.
그룹 이름을 생성 후, 고급 세부 정보에서 CloudWatch 세부 모니터링 활성화를 체크합니다.
그리고 이전에 만들어둔 LoadBalancer를 연결해줍니다.
상태 검사 유형은 ELB로 합니다.
상태 검사 유예 기간은, 서버 소프트웨어 특성에 따라 조정하긴 하지만 여기선 Default로 갑니다.
일단은 이 그룹을 초기 크기로 유지를 체크 합니다.
인스턴스 상태에 따른 트리거를 설정하는 부분입니다. 지금은 패스^^;;
(예시로 CPU usage가 70% 5분이상 지속시 인스턴스를 추가 시킨다. 등. )
패스
패스
확인 후 생성합니다.
생성 후 인스턴스 관리화면으로 가봅시다. AMI에 의해 새롭게 복사된 인스턴스가 생성됩니다.
그러나, AMI를 만들 때 인스턴스가 부팅 시, NginX나 Node.js가 실행되도록 설정하진 않았기 때문에
80번 포트로 통신이 되진 않습니다..^^
이제 Auto Scaling Group을 조정하여, 목표 용량 0, 최소 0, 최대 2로 조정하여 인스턴스를 종료합니다.
7. CodePipeLine을 통한 CI & CD 구성
CI & CD를 구성하기 위한 밑작업이 꽤 길었습니다.
이제 파이프라인을 본격적으로 구성해봅니다.
1) CodePipeLine 생성
배포 파이프라인 명을 이름을 적고 새 서비스 역할로 설정한다.
역할이 자동으로 만들어지며,
고급설정에서는 default로 냅둔다.
작은프로젝트 소스 코드를 관리하는 CodeCommit Repository를 설정하고 branch는 Mater로 한다.
AWS CodeBuild를 별도로 생성한 적이 없으므로 프로젝트 생성 버튼을 눌러서, CodeBuild를 생성한다.
CodeBuild의 역할 이름을 정해주고 새 서비스로 만든다.
Build Rule을 만든다.
CodeBuild가 어떤 순서와 어떤 명령어를 실행할지 작성하는 스크립트이다.
작은프로젝트는 딱히 빌드할게 없지만(단순히 node_module 설치)
빌드해야 하는 프로젝트들은 이 단계에서
빌드를 하거나 단위 테스트를 실행 하면 된다.
예시로 java는 gradlew 또는 mvn을 이용하여 빌드와 단위 테스트를 실행 할 수 있다.
자세한 내용은 buildspec.yml 사양 에서 확인가능하다
Build Rule Code. (복사 붙여 넣기 하세요.)
version: 0.2
phases:
install:
runtime-versions:
nodejs: 10
commands:
- npm install -g yarn
- yarn install
build:
commands:
- echo Build Starting on `date` Build GOGOGOG~
post_build:
commands:
- echo 'Build Complete'
- ls -l
artifacts:
files:
- '**/*'
CloudWatch 로그를 체크한다.
기존의 CodeDeploy를 만든적이 없기 때문에 배포 스테이지를 건너뛰기 한 후
CodePipeLine을 생성한다.
CodePipeLine을 생성하면 이벤트가 바로 발생하여 빌드를 시작한다.
다만 빌드 후 PipeLine이 없기 때문에 성공이나 실패시 종료된다.
2) CodeDeploy 생성
CodeDeploy를 생성하기 전에 CodeDeploy에게 역할을 부여해야 합니다..^^;;
자동으로 부여되는건 아닙니다.
이전에 IAM 역할은 EC2를 위한 역할이었지만, 이번엔 CodeDeploy를 위한 역할을 부여합니다.
'이 역할을 사용할 서비스 선택' 에서 CodeDeploy를 선택 후 '사용 사례 선택' 에서 CodeDeploy를 선택합니다.
패스합니다. 자동으로 AWSCodeDeployRole 정책이 선택되어있습니다.
패스
IAM 역할 이름을 작성하고 역할을 만듭니다.
다시 CodeDeploy를 생성하기 위해 콘솔창으로 옵니다.
애플리케이션 이름을 정한 후 생성합니다.
애플리케이션을 생성 후 배포 그룹을 생성해야 합니다.
배포그룹은 배포 정책이라고 생각하시면 그나마 이해하기 낫습니다.
배포그룹 이름을 작성후, 방금 전에 만든 IAM을 선택해 줍니다.
우리는 블루/그린 배포를 할 예정입니다.
작은프로젝트(Node.js)는 '현재 위치(in-place)' 배포도 괜찮습니다.
In-place 배포는 나중에 다룰 예정입니다.^^!
(때에 따라 병행해서 씁니다.^^)
환경구성으로는 Amazon EC2 AutoScaling 그룹 자동 복사를 선택 후
이전에 만들어둔 Auto Scaling Group을 지정합니다.
배포 설정에서는 성공 시 인스턴스 종료 시간을 30분으로 했습니다.
배포 구성 부분이 중요하긴 한데 설명하려면 좀 길고 링크를 달아두겠습니다.
배포 구성은 성공 또는 실패시 어떻게 처리할 것인지 정책에 대한 부분입니다.
로드 밸런서는 이전에 만들어둔 로드밸런서를 선택합니다.
배포 그룹이 만들어졌습니다.
3) CodePipeline과 CodeDeploy를 연결
이전에 만들어 둔 CodePipeline으로 다시 돌아옵니다.
상단의 편집버튼을 누르면 스테이지를 추가할 수 있도록 화면이 변경됩니다.
스테이지 이름을 추가합니다. Production 이나 Staging-Area 등 상황에 맞는 이름을 작성합니다.
Production 단계가 생성되었습니다.
Production에서 '작업 그룹 추가'를 선택합니다.
CodePipeLine에 작업 공급자로 AWS CodeDeploy로 선택 후,
이미 만들어둔 CodeDeploy 어플리케이션과, 배포그룹을 선택합니다.
입력 아티팩트가 있는데, 이부분은 이전 단계에서 출력되는 아티팩트 이름을 선택하시면 됩니다.
쉽게 이해가 안된다면 PipeLine이라는 아키텍처를 알아야 하는데 조금 있다가 보충설명하겠습니다.
Production 스테이지에서 작업그룹을 추가했습니다.
완료버튼을 클릭 후 저장버튼을 클릭합니다.
드디어 CodePipeLine에 Deploy Stage가 추가 되었습니다.
그러나 끝은 아닙니다. 중요한 과정이 남아있거든요..^^;;
4) AutoScaling 설정 재 변경
이전에 만들었던 AutoScaling 그룹의 목표용량을 1로 다시 변경합니다.^^;
두 번 일하는 것 같지만 실제 들어가는 비용을 줄여야 합니까요.
블루/그린 배포를 하기 이전에 인스턴스가 최소1개한 이상 운영되고 있어야 합니다.
In-place배포도 마찬가지입니다.
목표용량을 1로 바꾸면 인스턴스가 하나 생성됩니다.
8. 대망의 Deploy 테스트
결과물을 볼 수 있는 마지막 단계까지 왔습니다.
여기까지 따라오느라 고생이 참 많으셨습니다.
Hello world 같이 찍는 것은 참 힘들군요.
다시 로컬 컴퓨터의 작은프로젝트로 돌아가서 코드를 한번 변경해봅시다.
src/routes/BasicRoute.js 에서 version을 0.0.0 -> 0.0.1로 텍스트를 바꿔봅시다.
const Router = require('koa-router');
const router = new Router();
module.exports = router;
router.get('/', (ctx) => {
const {path, status} = ctx;
const {request:{method}} = ctx;
const {request} = ctx;
const userAgent = request.headers['user-agent'];
console.log(userAgent);
ctx.set("Content-Type", "text/plain");
ctx.status = 200;
ctx.body = "version 0.0.1"
});
CodeCommit 원격 소스 코드 저장소로 변경된 코드를 Push 합니다.
# git add .
# git commit -m 'release version 0.0.1'
# git push aws master
CodePipline은 CodeCommit Hook 이벤트를 받으면 Pipeline이 작동하기 시작합니다.
CodeDeploy가 블루/그린 방식으로 배포를 진행합니다.
배포 시간이 생각보다 걸리니 차분히 기달려보세요^^;;
배포 시간이 생각보다 걸리니 차분히 기달려보세요^^;;
이런 화면을 보면 정상적으로 배포가 된 것입니다.^^
'종료' 버튼을 누르면 이전의 인스턴스와 Auto scaling 그룹을 삭제합니다.
아까 전 종료 설정 시 30분으로 했으므로,
종료버튼을 안눌러도 30분 후면 자동으로 이전의 인스턴스와 AutoScaling 그룹을 삭제합니다.
2개의 Auto Scaling Group에서 각각의 인스턴스가 실행됩니다.
다만 착각하면 안되는 것은 로드밸런서가 새롭게 생성된 Auto Scaling Group에 트래픽을 라우팅 합니다.
로드밸런서는 새로운 인스턴스에 라우팅을 합니다.
CodeDeploy에서 종료 버튼을 누르면 바로 이전의 AutoScaling 그룹과, 연결된 인스턴스 삭제 절차를 진행합니다.
로드밸런서를 실행하면, 드디어 ! 변경된 프로젝트를 확인할 수 있습니다.^^!!
9. 작은프로젝트 파일의 appspec.yml과 start.sh?
CodeDeploy를 정상적으로 실행하기 위해서는 사실 appspec.yml로 buildspec.yml 처럼 정책을 설정해야 합니다.
하지만 위에서 언급하지 않고 맨 마지막에 언급하는 이유는, 결과물을 보기위한 진행하는 과정이 길기도 하고 미리 프로젝트에 첨부하여 빠르게 진행하고 싶었기 때문입니다.
CodeDeploy가 CodePipeline을 통해 압축된 아티팩트를 받게 되는데, 압축된 아티팩트를 풀었을 때 루트경로에 appspec.yml이 존재해야 합니다.
작은프로젝트에 동봉된 appspec.yml 파일
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/MinimumTemp
permissions:
- object: start.sh
owner: ec2-user
group: ec2-user
mode: 755
hooks:
ApplicationStart:
- location: start.sh
timeout: 60
runas: ec2-user
작은프로젝트에 동봉된 start.sh 파일
#!/bin/bash
echo 'start ./start.sh'
sudo rm -rf /home/ec2-user/Minimum/*
cp -rf /home/ec2-user/MinimumTemp/* /home/ec2-user/Minimum
sudo service nginx start
sudo service node_server start
appspec.yml이 무엇인지는 여기서 확인해보세요.
10. 정리와 결론
길고 긴 대장정이었습니다.
별 구축을 하지 않고 간단한 것만 했는데도 과정자체가 좀 복잡합니다.
1) CodePipeline을 통해 배포되는 과정을 풀어보면 이렇습니다.
1. 소스코드를 CodeCommit에 올리면 CodePipeline은 감지한다.
2. 변경된 소스코드를 압축 후, S3에 아티팩트로 임시저장한다.
3. CodeBuild는 S3에 저장된 아티팩트를 압축 해제하고, buildspec.yml에 작성된 정책에 따라 빌드 또는 테스트 절차를 거친다.
4. 빌드 또는 테스트 절차가 완료되면 다시 빌드된 결과물을 압축 후, S3에 아티팩트로 임시저장한다.
5. CodeDeploy는 S3에 저장된 아티팩트를 압축 해제하여, 배포절차를 진행한다.
1) 미리 만들어진 AMI와 Auto Scaling Group 시작구성을 통해, 새로운 Auto Scaling Group을 만든다.
2) 새로운 Auto Scaling Group을 만들고 인스턴스가 초기화되면, 인스턴스에 미리 설치된 CodeDeploy Agent를 통해 S3의 아티팩트를
압축을 풀어 appspec.yml의 정책에 따라 액션을 취한다.
3) appspec.yml의 정책 실행이 완료되고 이벤트가 완료되면 기존의 Auto Scaling Group에서 새로운 Auto Scaling Group으로 트래픽 라우팅 할준비 한다.
4) ELB에 새로운 Auto Scaling Group 인스턴스로 트래픽을 라우팅 후, 상태 검사에 성공하면, 기존의 Auto Scaling Group 인스턴스 라우팅 연결을 해제한다.
5) 일단은 배포가 완료된 것으로 판정된다.
6. 종료 트리거 발생 시 기존의 Auto Scaling Group과 인스턴스를 삭제 절차를 진행한다.
2) 맛보기 이후에 더 챙겨야 하는 것들이 있습니다.
너무 많은 내용이라 이번에 다루지 못했습니다.
(양이많고, 정리하기 귀찮 ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ 다음편에 ㅠ)
1) AutoScalingGroup? 왜? 이벤트 트리거?
2) In-place 배포
3) AutoScalingGroup 없이 블루/그린 배포
4) 배포 성공 및 배포 실패시 정책은 어떻게?
5) Staging-Area 구성은 어떻게 할 것인가?
6) 운영팀에게 어떻게 테스트 환경에 대해 알릴 것인가?
7) 배포 허가는?
8) 통합 테스트는?
9) Docker를 통한 배포는?
10) 오케스트레이션?
11) 모니터링은?
12) Node.js 뿐만 아니라 다른 언어와 관련된 프로젝트는?
13) 인스턴스가 문제 생길 경우, 인스턴스 내부의 소프트웨어가 문제가 생겼을 경우
14) CodeCommit 말고 다른 소스코드 저장소는?
15) 배포의 종류
16) 등....^^;;
일단은 쉬고 다음에 더 작성해 볼께요^^!
쨋든 여기까지 따라와줘서 고맙습니다!
혹시나 틀린 것있으면! 댓글 남겨주세요.
참고
내 머리속과 삽질과 연구결과 ^^;;
AMI에서 Node.js 설치 자습서
https://docs.aws.amazon.com/ko_kr/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html
CI/CD란 무엇일까요?
https://www.redhat.com/ko/topics/devops/what-is-ci-cd
Automated software testing in Continuous Integration (CI) and Continuous Delivery (CD)
https://pepgotesting.com/continuous-integration/