과정은 위와 같습니다.
배포용 Jenkins
서버와 실제 애플리케이션 서버를 분리하는 걸 권장하지만, 프리 티어로 사용하기 위해 하나의 인스턴스를 사용했습니다.
스프링 부트 프로젝트부터 생성하도록 하겠습니다.
단순히 배포가 잘 되었는지 확인하는 용도로만 사용할 것이기 때문에 Spring web
만 의존하도록 하겠습니다.
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello World";
}
}
애플리케이션의 health
체크 용 api
를 하나 만들었습니다.
EC2
와 CodeDeploy
에서 필요한 역할을 생성합니다.
역할 만들기를 선택합니다.
먼저 EC2
부터 처리하도록 하겠습니다.
다음 권한을 추가해줍니다.
AWSCodeDeployFullAccess
AmazonS3FullAccess
이름을 구분할 수 있도록 임의로 작성했습니다.
선택한 정책을 확인한 뒤, 역할을 생성했습니다.
다음으로 CodeDeploy
관련 역할을 생성합니다.
다른 AWS 서비스의 사용 사례
에서 CodeDeploy
를 선택하고, EC2
에서 사용할 것이기 때문에 첫 번째 항목인 CodeDeploy
를 선택해줍니다.
정책이 AWSCodeDeployRole
단 하나만 존재하고, 이미 선택되어 있기 때문에 딱히 정책을 선택할 필요는 없습니다.
이름을 구분할 수 있도록 임의로 작성하고 역할을 생성했습니다.
JenKins
를 통해 압축된 빌드 파일을 저장할 버켓을 생성해줍니다.
이름을 구분할 수 있도록 임의로 작성했습니다.
앞서 AmazonS3FullAccess
를 부여한 역할을 만들었기 때문에 버켓의 모든 퍼블릭 액세스를 차단합니다.
인스턴스를 생성해줍니다.
이름을 구분할 수 있도록 임의로 작성하고 역할을 생성했습니다.
프리 티어를 사용합니다.
키 페어를 선택해줍니다.
보안 그룹은 새롭게 생성해주도록 하겠습니다.
SSH
: 로컬에서 접근하기 위해 내 IP
로 허용했습니다.스토리지는 프리 티어에서 사용할 수 있는 최대 범위로 설정했습니다.
이후 인스턴스를 생성합니다.
그 다음 EC2
의 IAM 역할
을 이전에 만들어둔 역할로 수정합니다.
IAM 역할
을 수정했다면 반드시 인스턴스를 재부팅해줍니다.
IAM
을 codedeploy-agent
가 인식할 수 있기 때문입니다.이후 인바운드 규칙을 추가해줍니다.
9000
: Jenkins
포트로 사용할 값입니다.8080
: 그냥 스프링 부트 애플리케이션 포트로 사용할 값입니다.애플리케이션을 생성합니다.
이름을 구분할 수 있도록 임의로 작성했습니다.
컴퓨팅 플랫폼은 EC2
를 사용할 것이므로 EC2/온프레미스
를 선택했습니다.
애플리케이션의 배포 그룹을 생성합니다.
이름을 구분할 수 있도록 임의로 작성했습니다.
기존에 미리 생성해놨던, AWSCodeDeployRole
정책을 가진 역할을 선택합니다.
배포 유형의 경우 현재 위치를 선택합니다.
블루/그린의 경우 다중 서버를 활용해야 하다 보니 프리 티어로는 불가능합니다.
환경 구성의 경우 Amazone EC2 인스턴스
를 선택하고, EC2
를 구분할 수 있도록 key - value
를 지정합니다.
구분할 수 있는 값이라면 어느 값이든 상관 없지만, 개인적으로는 Name
키가 가장 입력하기 편했습니다.
codedeploy-agent
는 직접 설치하도록 하겠습니다.
배포 구성의 경우 단순 테스트 용도이기 때문에 최소한으로 설정하도록 하겠습니다.
로드 밸런서의 경우 단일 서버만 사용하기 때문에 비활성화를 했습니다.
EC2
에서 필요한 작업들을 진행하도록 하겠습니다.
EC2
의 시간을 Chrony
방식으로 동기화합니다.
169.254.169.123
는 Amazon Time Sync Service IP
의 로컬 IP
이며 별도 설정 없이 Private Subnet
에서도 안전하게 접근할 수 있습니다.
# ec2 시간 확인
date
2022. 06. 03. (금) 11:31:04 UTC
# 해당 ec2가 실행될 때마다 chrony 방식으로 시간을 동기화하도록 요청
sudo chkconfig chronyd on
알림: 'systemctl enable chronyd.service'에 요청을 전송하고 있습니다.
# chrony가 169.254.169.123 IP 주소를 사용하여 시간 동기화를 하고 있는지 확인
chronyc sources -v
.-- Source mode '^' = server, '=' = peer, '#' = local clock.
/ .- Source state '*' = current best, '+' = combined, '-' = not combined,
| / 'x' = may be in error, '~' = too variable, '?' = unusable.
|| .- xxxx [ yyyy ] +/- zzzz
|| Reachability register (octal) -. | xxxx = adjusted offset,
|| Log2(Polling interval) --. | | yyyy = measured offset,
|| \ | | zzzz = estimated error.
|| | | \
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* 169.254.169.123 3 4 377 1 +41us[ +46us] +/- 527us
^- ec2-13-209-84-50.ap-nort> 2 6 37 39 -9135us[-9131us] +/- 13ms
^- send.mx.cdnetworks.com 2 6 37 39 -1061us[-1057us] +/- 38ms
^- ec2 ip 2 6 37 37 +9309us[+9313us] +/- 187ms
^- sshhub.dynamigs.net 2 6 37 37 -11ms[ -11ms] +/- 181ms
# 시간 동기화 지표 확인
chronyc tracking
Reference ID : A9FEA97B (169.254.169.123)
Stratum : 4
Ref time (UTC) : Fri Jun 03 11:33:19 2022
System time : 0.000015335 seconds fast of NTP time
Last offset : +0.000015248 seconds
RMS offset : 0.000024212 seconds
Frequency : 20.226 ppm fast
Residual freq : +0.023 ppm
Skew : 0.870 ppm
Root delay : 0.000463618 seconds
Root dispersion : 0.000334083 seconds
Update interval : 16.2 seconds
Leap status : Normal
# 타임존 설정
sudo vim /etc/sysconfig/clock
# 다음과 같이 /etc/sysconfig/clock 값 변경
ZONE="Asia/Seoul"
KST=True
# 현재 타임존 설정 확인
cat /etc/localtime
# UTC로 설정되어 있음
TZif2UTCTZif2�UTC
UTC0
# 기존 설정 삭제
sudo rm /etc/localtime
# 대한민국 표준 시간대 정보를 심볼릭 링크로 설정
sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime
# ec2 시간 확인
date
2022. 06. 03. (금) 20:35:35 KST
자동으로 배포된 스프링 부트 프로젝트를 실행하기 위해 자바를 설치하도록 하겠습니다.
# aws coreetto 다운로드
sudo curl -L https://corretto.aws/downloads/latest/amazon-corretto-11-x64-linux-jdk.rpm -o jdk11.rpm
# java 11 설치
sudo yum localinstall jdk11.rpm -y
# java version 선택
sudo /usr/sbin/alternatives --config java
# java version 확인
java --version
openjdk 11.0.15 2022-04-19 LTS
OpenJDK Runtime Environment Corretto-11.0.15.9.1 (build 11.0.15+9-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.15.9.1 (build 11.0.15+9-LTS, mixed mode)
# 설치 파일 삭제
rm -rf jdk11.rpm
java version 선택
의 경우 위와 같이 여러 자바 버전 중 하나를 선택할 수 있습니다.
EC2 프리티어
인 t2.micro
의 메모리는 1GB
입니다.
이 정도 메모리로는 Jenkins
를 사용할 수 없습니다.
이 문제는 SWAP 메모리
를 통해 (임시로) 해결할 수 있습니다.
최선은 Jenkins
용 배포 서버와 실제 애플리케이션 운영 서버를 분리하는 것이지만, 단순 테스트 용이기 때문에 다음과 같은 방법을 사용하도록 하겠습니다.
권장하는 SWAP 메모리
의 크기는 다음과 같습니다.
# dd 명령어를 통해 swap 메모리 할당
# 시간이 1분 ~ 5분정도 걸릴 수 있음
# 크기는 2GB(128MB x 16)
sudo dd if=/dev/zero of=/swapfile bs=128M count=16
16+0 records in
16+0 records out
2147483648 bytes (2.1 GB) copied, 15.8767 s, 135 MB/s
# swap 파일의 읽기 및 쓰기 권한 업데이트
sudo chmod 600 /swapfile
# Linux swap 영역 설정
sudo mkswap /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=22c80ff2-8555-48cd-91ce-921d45237086
# swap 공간에 swap file을 추가해 즉시 사용할 수 있도록 설정
sudo swapon /swapfile
# 정상적으로 설정되었는지 확인
sudo swapon -s
Filename Type Size Used Priority
/swapfile file 2097148 0 -2
# fstab에 /swapfile 설정 추가
sudo vi /etc/fstab
/swapfile swap swap defaults 0 0
# 정상적으로 적용되었는지 확인
free
total used free shared buff/cache available
Mem: 987700 419664 242604 500 325432 425528
Swap: 2097148 0 2097148
fstab에 /swapfile 설정 추가
의 경우 다음과 같이 마지막 줄에 추가하면 됩니다.
CodeDeploy
가 EC2
에서 작동할 수 있도록 codedeploy-agent
를 설정해줍니다.
# aws-cli 설치 확인
aws --version
aws-cli/1.18.147 Python/2.7.18 Linux/5.10.109-104.500.amzn2.x86_64 botocore/1.18.6
# aws 설정
sudo aws configure
AWS Access Key ID [None]: Access Key
AWS Secret Access Key [None]: Secret Access Key
Default region name [None]: ap-northeast-2
Default output format [None]: json
# codedeploy-agent 설치 파일 다운로드
# 자신의 region에 맞는 설치 파일을 다운로드 받아야 함(ap-northeast-2)
wget https://aws-codedeploy-ap-northeast-2.s3.amazonaws.com/latest/install
# codedeploy-agent를 설치하기 위한 의존성 설정
sudo yum install ruby -y
# 설치파일 권한 부여
chmod +x ./install
# codedeploy-agent 설치
sudo ./install auto
# codedeploy-agent 동작 확인
sudo service codedeploy-agent status
스프링 부트 애플리케이션 기본 포트와 Jenkins
의 기본 포트가 중복되기도 하고, Jenkins
설치를 조금 더 간편히 처리하기 위해 도커를 통해 Jenkins
를 사용하도록 하겠습니다.
# yum 업데이트
sudo yum update -y
# 도커 설치
sudo amazon-linux-extras install -y docker
# 도커 실행
sudo service docker start
Redirecting to /bin/systemctl start docker.service
# 도커에 jenkins 실행
# -p : jenkins의 기본 포트 8080을 외부 포트 9000으로 바인딩
# -e : 도커 컨테이너에 타임존 설정
sudo docker run -d --name jenkins -p 9000:8080 -e TZ=Asia/Seoul jenkins/jenkins:jdk11
# jenkins가 정상적으로 실행되고 있는지 확인
sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
21bb19920e6e jenkins/jenkins:jdk11 "/usr/bin/tini -- /u…" 7 minutes ago Up 7 minutes 50000/tcp, 0.0.0.0:9000->8080/tcp, :::9000->8080/tcp jenkins
http://ec2-ip:9000
으로 접속합니다.
다음과 같이 Jenkins
를 사용할 수 있습니다.
# 도커에 실행중인 jenkins 컨테이너에 bash를 통해 접속
sudo docker exec -it jenkins bash
# 비밀번호 출력
cat /var/jenkins_home/secrets/initialAdminPassword
<기본 비밀번호>
비밀번호를 입력해줍니다.
Install suggested plugins
를 선택합니다.
설치가 진행됩니다.
설치가 끝나면 관리자 계정을 생성할 수 있습니다.
Jenkins
의 접속 URL
를 추가합니다.
Dashboard -> Jankins 관리 -> 플러그인 관리
에서 설치 가능으로 탭을 변경한 뒤 codedeploy
를 선택해 AWS CodeDeploy
플러그인을 설치합니다.
만약 플러그인이 다음과 같은 이유로 설치되지 않았다면 하단의 주의
탭에서 해결방법을 확인해주세요.
플러그인을 설치했다면 Dashboard -> new Item -> Freestyle project
를 생성합니다.
이름은 임의로 작성했습니다.
해당 프로젝트의 정보를 입력합니다.
설명은 임의로 작성했습니다.
Jenkins
와 연동할 깃허브 리포지토리를 등록해야 합니다.
그 전에 깃허브 Credentials
를 선택합니다.
kind
로 어떤 방식으로 Credentials
를 입력할지 선택할 수 있습니다.
깃허브 Repository URL
과 Credentials
를 선택해줍니다.
어떤 브랜치를 기준으로 Jenkins
가 빌드를 진행할지 선택합니다.
적용하고자 하는 브랜치명을 입력해주면 됩니다.
기본값은 */master
로 되어있으며, 제 경우 */main
으로 변경했습니다.
빌드 유발의 경우 Github hook trigger for GITScm polling
을 선택해줍니다.
Build -> Add build step
에서 Execute shell
을 선택해줍니다.
따로 gradle
을 설치하지 않고 스프링 부트 프로젝트 내의 gradlew
를 통해 빌드해주도록 하겠습니다.
빌드 후 조치 -> 빌드 후 조치 추가
에서 Deploy an application to AWS CodeDeploy
를 선택해줍니다.
AWS CodeDeploy Application Name
의 경우 애플리케이션 이름을, AWS CodeDeploy Deployment Group
의 경우 애플리케이션 배포 그룹 이름을 입력합니다.
AWS Region
의 경우 서울, AP_NORTHEAST_2
를 선택해줍니다.
S3 Bucket
이름을 입력합니다.
Include Files
에는 CodeDeploy
를 통해 S3 Bucket
에 업로드 된 파일 중 EC2
로 복사할 파일을 지정합니다.
**/*.jar, **/appspec.yml, **/scripts/*
배포할 애플리케이션 .jar
, CodeDeploy
가 참조할appspec.yml
, appspec.yml
을 통해 실행할 스크립트 디렉토리 scripts
를 입력했습니다.
키를 입력해주고 프로젝트를 생성해줍니다.
Github hook trigger for GITScm polling
을 선택했으므로 관련 설정을 해주도록 하겠습니다.
Jenkins와 연동한 깃허브 리포지토리 -> Settings -> Code and automation -> Webhooks
으로 이동합니다.
Add webhook
을 선택합니다.
Jenkins URL/github-webhook/
를 입력합니다.
반드시 마지막에 /
를 추가해야하며, 추가하지 않을 시 302 Redirect
가 발생해 실패합니다.
이렇게 좌측에 녹색 체크표시가 있어야 정상적으로 설정된 것입니다.
# build.gradle
jar {
enabled = false
}
스프링 부트 gradle 플러그인 2.5 버전부터 빌드 시 프로젝트 관련 의존성을 가지고 있지 않은 plain
버전과 모든 의존성을 가지고 있는 executable
버전 두 개를 빌드하게 됩니다.
여기서는 Jenkins
로 배포 자동화를 진행하기 때문에 plain
버전을 필요 없으므로, 위와 같이 작성해줍니다.
이제 스프링 부트 프로젝트의 루트 디렉토리에 appspec.yml
과 scripts/deploy.sh
를 작성하도록 하겠습니다.
# appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/cicd-test
overwrite: yes
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
hooks:
ApplicationStart:
- location: scripts/deploy.sh
timeout: 60
runas: ec2-user
CodeDeploy
가 의존하는 appspec.yml
을 작성해줍니다.
각 섹션을 확인해보도록 하겠습니다.
version: 0.0
os: linux
version: 0.0
AppSpec
의 버전을 지정합니다.0.0
은 유일하게 허용된 버전입니다.os: linux
EC2
의 os
가 window
가 아니라면 linux
를 입력합니다.files:
- source: /
destination: /home/ec2-user/cicd-test
overwrite: yes
files
CodeDeploy
가 작업하는 파일을 지정합니다.source
appspec.yml
과 scripts
를 작성했으므로 기준을 루트 디렉토리로 설정합니다.destination
CodeDeploy
가 빌드된 파일을 복사할 때, 어느 디렉토리에 복사할지를 지정합니다./home/ec2-user/cicd-test
로 설정했습니다.overwrite
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
permissions
EC2/온프레미스
에서만 작성합니다.ECS
에는 resources
섹션을 작성합니다.files
에서 설정한 내용대로 CodeDeploy
가 복사한 파일에 대한 권한을 지정합니다.object
parrtern
**
를 사용해 지정하면 모든 파일에 적용됩니다.owner
object
의 소유자 이름입니다.group
object
의 그룹 이름입니다.hooks:
ApplicationStart:
- location: scripts/deploy.sh
timeout: 60
runas: ec2-user
in-place
) 배포 기준의 생명주기입니다.hooks
EC2/온프레미스
의 경우 위 사진처럼 CodeDeploy
의 생명 주기에 hook
을 걸어 실행할 스크립트를 설정할 수 있습니다.hook
을 설정할 수 없습니다.ApplicationStart
CodeDeploy
가 배포 파일을 EC2
에 모두 복사한 뒤 실행되는 이벤트입니다.location
hook
에서 실행할 스크립트를 지정합니다.timeout
runas
codedeploy-agent
입니다.이제 CodeDeploy
생명 주기 중 ApplicationStart
에서 실행할 스크립트를 작성하도록 하겠습니다.
#!/bin/bash
BUILD_JAR=$(ls /home/ec2-user/cicd-test/build/libs/*.jar)
JAR_NAME=$(basename $BUILD_JAR)
echo "> build : $JAR_NAME" >> /home/ec2-user/deploy.log
echo "> build 파일 복사" >> /home/ec2-user/deploy.log
DEPLOY_PATH=/home/ec2-user/
cp $BUILD_JAR $DEPLOY_PATH
echo "> 실행중인 애플리케이션 pid 확인" >> /home/ec2-user/deploy.log
CURRENT_PID=$(pgrep -f $JAR_NAME)
if [ -z $CURRENT_PID ]
then
echo "> 실행중인 애플리케이션이 없으므로 종료하지 않음" >> /home/ec2-user/deploy.log
else
echo "> kill -15 $CURRENT_PID" >> /home/ec2-user/deploy.log
kill -15 $CURRENT_PID
sleep 10
fi
DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR 배포" >> /home/ec2-user/deploy.log
nohup java -jar $DEPLOY_JAR >> /home/ec2-user/deploy.log 2>/home/ec2-user/deploy_err.log &
ApplicationStart
의 경우 CodeDeploy
가 빌드 파일을 EC2
에 복사한 이후에 실행되는 hook
이기 때문에, 이를 가정하고 스크립트를 작성하면 됩니다.
BUILD_JAR=$(ls /home/ec2-user/cicd-test/build/libs/*.jar)
JAR_NAME=$(basename $BUILD_JAR)
echo "> build : $JAR_NAME" >> /home/ec2-user/deploy.log
echo "> build 파일 복사" >> /home/ec2-user/deploy.log
DEPLOY_PATH=/home/ec2-user/
cp $BUILD_JAR $DEPLOY_PATH
제 경우 /home/ec2-user/cicd-test
에 빌드 파일을 복사하라고 했기 때문에 이를 경로로 잡아서 처리해주었습니다.
CURRENT_PID=$(pgrep -f $JAR_NAME)
if [ -z $CURRENT_PID ]
then
echo "> 실행중인 애플리케이션이 없으므로 종료하지 않음" >> /home/ec2-user/deploy.log
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 10
fi
$JAR_NAME
으로 실행중인 애플리케이션이 있는지 확인하고 실행중인 애플리케이션이 있다면 kill -15
를 통해 정상적으로 애플리케이션이 종료되도록 요청하고, sleep 10
를 통해 정상적으로 종료될 때 까지 대기합니다.
DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME
echo "> DEPLOY_JAR 배포" >> /home/ec2-user/deploy.log
nohup java -jar $DEPLOY_JAR >> /home/ec2-user/deploy.log 2>/home/ec2-user/deploy_err.log &
이후 nohup
을 통해 백그라운드로 애플리케이션을 실행합니다.
이제 모든 설정을 끝냈기 때문에, 깃허브 리포지토리 main
브랜치에 push
를 하면 Jenkins
가 github webhook
을 통해 자동으로 처리해줍니다.
git push main
Jenkins
가 git push
를 감지했습니다.
빌드 실행 상태를 통해 빌드 진행 상황을 알 수 있습니다.
Jenkins
의 역할은 CI
, 코드 통합입니다.
S3
에 빌드 파일을 위치시키라고 했기 때문에, 빌드 순서와 랜덤 문자열로 빌드 파일이 생성된 것을 확인할 수 있습니다.
CD
, 지속적으로 배포가 가능한 상태로 유지해주는 CodeDeploy
를 확인하면, 배포가 성공한 것을 확인할 수 있습니다.
nohup
을 통해 백그라운드로 실행한 스프링 부트 애플리케이션이 8080 포트
로 실행되고 있음을 확인할 수 있습니다.
로그용으로 만들었던 deploy.log
를 확인하면 정상적으로 동작하고 있음을 확인할 수 있습니다.
ec2 ip/hello
로 요청하면 정상적으로 호출되는 것을 확인할 수 있습니다.
제가 경험했던 오류 및 개선사항과 관련된 주의사항을 적어보고자 합니다.
EC2 IAM
역할 변경 시 재부팅을 해 주어야 codedeploy-agent
가 정상적으로 동작합니다.
github webhook
의 경우 Jenkins url
로 요청을 하다 보니 보안그룹을 잘 설정해주어야 합니다.
모두 허용으로 처리하거나, 링크를 통해 위 사진처럼 github webhook ip
를 확인해 등록해주면 됩니다.
다음과 같이 aws-java-sdk-elasticbeanstalk
관련 오류가 발생할 수 있습니다.
이 경우 Jenkins
에서 aws-java-sdk-elasticbeanstalk
플러그인을 설치하면 해결할 수도 있습니다.
다만, 이 경우 다음과 같은 오류가 발생할 수도 있습니다.
Update required: Amazon Web Services SDK :: Elastic Beanstalk (aws-java-sdk-elasticbeanstalk 1.12.89-292.v2712528e879c) to be updated to 1.12.246-349.v96b_b_f7eb_a_c3c or higher
최신 버전이 아니라서 문제가 발생했다는 의미입니다.
이렇게 된 경우 기존의 플러그인을 모두 삭제한 뒤, Amazon Web Services SDK :: All
플러그인을 직접 설치하는 것을 권장합니다.
Jenkins plugin - Amazon Web Services SDK :: All으로 이동합니다.
최신 버전의 Installation options
에 Download
를 통해 플러그인을 다운로드 받습니다.
Jenkins 관리 -> 플러그인 관리 -> 고급
탭으로 이동합니다.
Deploy Plugin
탭으로 가서 파일을 선택한 뒤, Deploy
버튼을 클릭합니다.
확장자가 .hpi
여야 합니다.
정상적으로 설치된 것을 확인할 수 있습니다.
다시 플러그인 관리
를 확인해보면 위와 같이 업데이트가 필요하다고 하는데, 이 때 업데이트 할 경우 문제가 발생합니다.
위 사진과 같이 최신 버전의 Amazon Web Services SDK :: All
플러그인을 설치했음에도 불구하고 다시 aws-java-sdk-elasticbeanstalk
버전 관련 오류가 발생합니다.
그러므로 업데이트 하지 않고 바로 설치 가능 -> AWS CodeDeploy
를 설치해주면 됩니다.
AWS CodeDeploy
플러그인이 정상적으로 설치되었음을 확인할 수 있습니다.
CodeDeploy
의 경우 발생하는 오류를 다음과 같이 크게 두 가지로 나눌 수 있습니다.
codedeploy-agent
오류CodeDeploy
오류codedeploy-agent
오류의 경우 CodeDeploy
실행 전 EC2
와 접속하는 과정에서 발생하는 문제입니다.
CodeDeploy
오류는 CodeDeploy
가 EC2
에서 배포하는 과정에서 발생하는 문제입니다.
주로 appspec.yml
이나 hook
관련 스크립트에서 발생합니다.
CodeDeploy
오류의 경우 배포 수명 주기 이벤트 -> 이벤트 -> View events
에서 확인할 수 있습니다.
codedeploy-agent
오류의 경우 다음과 같이 건너뜀
상태가 됩니다.
CodeDeploy
실행 전에 EC2
와의 연결조차 되지 않았다는 의미라고 볼 수 있습니다.
그러므로 콘솔에서도 문제를 확인할 수 없습니다.
이럴 때에는 EC2
에서 codedeploy-agent
관련 로그를 살펴보면 해결할 수 있습니다.
cat /var/log/aws/codedeploy-agent/codedeploy-agent.log
기본 로그 경로는 위와 같으며, codedeploy-agent
관련 설정 파일은 /etc/codedeploy-agent/conf/codedeployagent.yml
에 있으므로 적절히 수정해서 사용하시면 되겠습니다.
Region
이 맞지 않다거나 EC2
의 권한이 부족해 S3
이나 CodeDeploy
에서 접근할 수 없는 등 CodeDeploy
콘솔에서 확인할 수 없는 문제들을 확인할 수 있습니다.
CodeDeploy
의 경우 배포에 실패하면 해당 배포를 계속 반복하게 됩니다.
이 상태에서 추가적으로 Jenkins
를 통해 재배포를 요청한다면, Jenkins
의 CI
요청을 성공해 S3
에 배포 파일은 업로드되지만 CodeDeploy
의 경우 배포하자마자 실패하게 됩니다.
이 경우 CodeDeploy
에도 문제를 확인할 수 없고, 다음과 같이 codedeploy-agent
에서도 요청을 무한히 반복할 뿐 에러를 확인할 수 없습니다.
제 경우 깜빡하고 EC2
정책을 변경하지 않아 정책을 변경한 뒤 인스턴스 재부팅 후 Jenkins
를 통해 다시 배포를 요청한 상태였는데, 이전에 EC2
정책을 변경하지 않아 발생한 CodeDeploy
실패를 처리하지 않아 발생했었습니다.
이 경우 CodeDeploy
에서 실패한 배포를 정상적으로 처리해준 뒤 다시 빌드하면 해결할 수 있습니다.
참고
Github - About webhooks
Linux 인스턴스의 시간 설정
스왑 파일을 사용하여 EC2에서 스왑 공간으로 사용할 메모리를 할당하는 방법
AppSpec 파일 구조
AppSpec 'permissions' 섹션(EC2/온프레미스 배포만 해당)
AppSpec 'hooks' 섹션
CodeDeploy 에이전트 구성 참조