November 24, 2021
2021년 3월 초기에 작성했던 문서라 현재 AWS 콘솔과는 달라질 수 있다는점 꼭 확인해주세요!

EC2 → Auto Scaling → Launch Configurations 에서 시작 구성 생성


#! /bin/bash
cd /home/ubuntu
./start.sh
# codeDeploy 실행
# 확인 결과 AMI에서 codeDeploy-agent가 설치되었다면 실행하지 않아도 자동으로 실행합니다.
sudo ./install auto원본 인스턴스에서 필요한 환경

IP 주소 유형


그룹 생성하기







해당 그룹에서 새로운 인스턴스를 확인할 수 있습니다.

AWS CodeDeploy에서 생성합니다.




배포 설정
여기까지 왔으면 AWS Console로 생성은 모두 마쳤습니다. 마지막으로 해당 프로젝트 루트에서 쉘스크립트, appspec.yml을 설정합니다.

- name: Code Deploy
run: aws deploy create-deployment --application-name cicdtest --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name cicd-bluegreen --s3-location bucket=cicdtestsunny,bundleType=zip,key=build.zip--application-name : AWS CodeDeploy 애플리케이션 이름--deployment-config-name : 배포 구성(CodeDeploy의 배포구성)--deployment-group-name : 배포 그룹 이름--s3-location : s3 버킷 이름, 빌드 타입, 빌드 파일이름 지정version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/myapp # 파일 배포 경로
permissions:
- object: /home/ubuntu/
owner: ubuntu
group: ubuntu
mode: 755
hooks:
BeforeInstall:
- location: beforeInstall.sh # 배포 이전
timeout: 60
runas: root
AfterInstall:
- location: deploy.sh
timeout: 60
runas: root
AWS CodeDeploy는 이전 파일이 존재일 경우 에러가 발생합니다.
The deployment failed because a specified file already exists at this locationCodeDeploy는 파일 덮어쓰기가 불가능하기 때문에 다음 레퍼런스처럼 삭제하고 다시 배포하는 형식을 취하면 됩니다.
#!/usr/bin/env bash
REPOSITORY=/home/ubuntu/
if [ -d $REPOSITORY/myapp ]; then
rm -rf $REPOSITORY/myapp
fi
mkdir -vp $REPOSITORY/myapp#!/usr/bin/env bash
REPOSITORY=/home/ubuntu/myapp
APP_NAME=demo
echo "> pid 확인"
CURRENT_PID=$(pgrep -fl $APP_NAME | grep java | awk '{print $1}')
echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
echo "> 현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> 새 애플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)
echo "> Jar name: JAR_NAME"
echo "> $JAR_NAME에 실행 권한 추가"
chmod +x $JAR_NAME
echo "> $JAR_NAME 배포"
nohup java -jar $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &배포스크립트는 해당 프로젝트마다 다르니 꼭 쉘스크립트는 프로젝트 환경 확인하시고 작성해주세요.
여기까지 작성하느라 고생하셨습니다. 이제 테스트를 해보겠습니다.
우선 간단한 Spring 컨트롤러를 만듭니다.
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.net.InetAddress;
import java.net.UnknownHostException;
@RestController
public class HelloController {
@GetMapping("/hello")
public String getUser() {
String hostName, ipaddress;
try {
hostName = InetAddress.getLocalHost().getHostName();
ipaddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostName = new StringBuilder("Error : ").append(e.getLocalizedMessage()).toString();
ipaddress = "";
}
return "hostName : " + hostName + " ipaddress : " + ipaddress + " pland가 조아";
}
@GetMapping("/hi")
public String hi() {
String hostName;
String ipaddress;
try {
hostName = InetAddress.getLocalHost().getHostName();
ipaddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostName = new StringBuilder("Error : ").append(e.getLocalizedMessage()).toString();
ipaddress = "";
}
return "Hi" + hostName + " :: " + ipaddress;
}
}hostname, piaddress를 생성하여 auto scaling과 load balancer가 제대로 작동하는지 확인할 수 있는 컨트롤러 입니다.
커밋하고 실행!

다음과 같이 인스턴스 생성 삭제를 확인할 수 있습니다.

ELB Round Robin 방식으로 새로고침할 때마다 ip가 달라지는 모습을 확인할 수 있습니다.
기존의 Classic Load Balancer는 스프링에서 처리할 때 HTTP로 요청을 받아 처리하는 바람에 OAuth2 로그인 적용시 HTTPS로 요청보냈다가 HTTP로 받을 수도 있었습니다. 그래서 스프링부트의 내부톰캣 설정으로 다음과 같은 처리가 필요합니다.
server.tomcat.remoteip.protocol-header=x-forwarded-proto그러나 현재 사용하고 있는 Application Load Balancer는 전부 HTTPS로 처리하기 때문에 스프링 톰캣 설정을 추가할 필요가 없습니다.

여기까지 따라오시느라 고생많으셨습니다!!
ELB로 무중단 배포를 성공적으로 이뤄지길 바랍니다!!😆
Nginx와는 다르게 AWS 인프라 하나로 다 처리할 수 있어 관리할 때는 편합니다.
다만, 시간이 Nginx 배포보다 훨씬 느리고 비용도 더 많이 들어 스타트업이나 작은 규모의 회사에서는 사용할 가치가 있는지 고려를 해야할 듯 합니다.
특히 배포 테스트할 때 너무 오래 걸려 힘들었네요😭
DOWNLOAD_SOURCE 실패할 때
CLIENT_ERROR: Get "[<https://github.com/pland-sunny/cicdtest/info/refs?service=git-upload-pack>](<https://github.com/pland-sunny/cicdtest/info/refs?service=git-upload-pack>)": dial tcp 52.78.231.108:443: i/o timeout for primary source→ NAT Gateway 필요합니다.
→ IAM을 권한 받기전에 AWS CodeDeploy를 실행했기 때문입니다.
→ sudo service codedeploy-agent restart 를 시도해볼것!
codedeploy The specified key does not exist해당 파일이 없다는 뜻으로 S3에서 파일이름, 확장자 확인해야합니다.
The deployment failed because no instances were found in your blue fleet.blue 인스턴스가 생성하지 못함 → 확인 결과 2b의 서브넷은 t2.micro 생성하도록 설정했기 때문에 auto-scaling에서 생성하지 못하여 에러 발생합니다.
The deployment failed because a specified file already exists at this location