애플리케이션의 전체 또는 대부분을 한 번에 업데이트
실제 서비스가 되고 있는 상태에서 업데이트
과거 광부들이 카나리아를 데리고 일을 했다. 왜? 카나리아가 가스에 민감하기 때문에 경보장치로써 사용함.
전체 사용자 중 일부 사용자만 새 서비스를 사용 가능하다.
점진적으로 사용할 수 있는 사용자의 수가 늘어난다.
실제 사용자의 경험을 얻을 수 있다
애플리케이션 배포를 자동화해주는 서비스
서비스 중인 서버가 있다면 변경된 서비스를 배포
두 개의 블루/그린 시스템을 한 쌍씩 준비
IAM > 역할 > 역할 생성
IAM > 역할 > 역할 생성
생성된 역할 확인하면 권한 정책은 없고 신뢰관계만 있다는 것을 확인할 수 있다.
3.1. 기본 VPC 생성
기본 VPC가 소유한 서브넷은 모두 Public이다.
3.2. 소스 코드를 배포할 웹 서버 인스턴스 생성
애플리케이션 코드 없는 인스턴스 생성 → 해당 인스턴스에 서비스 환경(오토 스케일링, 로드밸런싱) 구성
애플리케이션 코드가 없는 인스턴스를 생성하는 이유? 인스턴스가 실행될 때 CodeDeploy를 통해서 소스코드를 가져오도록 설정할 것이기 때문에
EC2 > 인스턴스 시작
고급 세부 정보 > 사용자 데이터에 내용을 추가한다.
#!/bin/sh
# Amazon Linux Extras 리포지토리에서 LAMP 스택을 설치
amazon-linux-extras install -y lamp-mariadb10.2-php7.2 php7.2
yum -y install httpd php-mbstring
# Apache 웹 서버를 시스템 시작 시 자동으로 시작하도록 설정하고 웹 서버를 즉시 시작
chkconfig httpd on
systemctl start httpd
# 특정 S3 버킷에서 웹 애플리케이션의 tarball을 다운로드하고 압축을 해제
if [ ! -f /var/www/html/immersion-day-app-php7.tar.gz ]; then
cd /var/www/html
wget https://aws-joozero.s3.ap-northeast-2.amazonaws.com/immersion-day-app-php7.tar.gz
tar xvfz immersion-day-app-php7.tar.gz
fi
# PHP 스크립트 생성하여 웹 서버의 메타데이터 표시
cat <<EOF > /var/www/html/get-index-meta-data.php
<?php
\$hostname = gethostname();
\$results = explode(".", \$hostname);
echo "<table style='width:100%'>";
echo "<tr><th style='width:30%'>Meta-Data</th><th style='width:70%'>Value</th></tr>";
echo "<tr><td>Private IP DNS Name</td><td>".\$hostname."</td></tr>";
echo "<tr><td>Private IP</td><td>".getHostByName(\$hostname)."</td></tr>";
echo "<tr><td>Region</td><td>".\$results[1]."</td></tr>";
echo "</table>";
?>
EOF
# AWS SDK for PHP를 다운로드하고 설치
if [ ! -f /var/www/html/aws.zip ]; then
cd /var/www/html
mkdir vendor
cd vendor
wget https://docs.aws.amazon.com/aws-sdk-php/v3/download/aws.zip
unzip aws.zip
fi
# 모든 패키지를 최신 상태로 업데이트
yum -y update
나머지 설정은 그대로 두고, 인스턴스 생성
4.1. 웹 서버 인스턴스의 퍼블릭 IP로 SSH 접속
4.2. 기존에 배포되어 있던 소스코드 모두 삭제
Bitvise SSH Client > New Terminal
삭제하는 이유? /var/www/html 디렉토리에 소스코드를 배포하기 위함
, #_
~\_ ####_ Amazon Linux 2023
~~ \_#####\
~~ \###|
~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
# /var/www/html 디렉토리 확인
$ ls /var/www/html
db-update.php index.php rds-initialize.php rds.php
get-cpu-load.php load.php rds-read-data.php sql
get-index-meta-data.php menu.php rds-write-config.php style.css
immersion-day-app-php7.tar.gz put-cpu-load.php rds.conf.php vendor
# /var/www/html디렉토리에 있는 모든 파일과 디렉토리 삭제
$ sudo rm -rf /var/www/html/*
4.3. CodeDeploy Agent 설치
리전별 리소스 키트 버킷 이름
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/resource-kit.html#resource-kit-bucket-namesCodeDeploy Agent 설치 관리자 다운로드 문서
https://bucket-name.s3.region-identifier.amazonaws.com/latest/install
- bucket-name은 해당 리전의 CodeDeploy 리소스 키트 파일이 포함되어 있는 Amazon S3 버킷의 이름
- region-identifier는 리전의 식별자
ex) 미국(오레건)
https://aws-codedeploy-us-west-2.s3.us-west-2.amazonaws.com/latest/install
# yum 업데이트
$ sudo yum update
# Ruby 설치
$ sudo yum install ruby
#'Web Get'의 약어로 웹 상의 파일을 다운로드 받을 때 사용하는 리눅스 커맨드라인 유틸리티
$ sudo yum install wget
# home/ec2-user 디렉토리로 이동
$ cd /home/ec2-user
# wget를 이용해 AWS CodeDeploy Agent를 리전에 맞게 설치한다.
$ wget https://aws-codedeploy-us-west-2.s3.us-west-2.amazonaws.com/latest/install
# 설치 확인
$ ls
install
# install 파일에 실행할수 있는 권한 부여('+x'는 'executable' 라는 뜻)
$ chmod +x ./install
# install 파일 권한 확인
$ ls -l
total 20
-rwxr-xr-x. 1 ec2-user ec2-user 17892 Apr 3 2023 install
# install 파일을 실행
$ sudo ./install auto
# Codedeploy agent 서비스 상태 확인
$ sudo service codedeploy-agent status
...
The AWS CodeDeploy agent is running as PID 27236
# Codedeploy agent 서비스 상태 확인
$ systemctl status codedeploy-agent
● codedeploy-agent.service - AWS CodeDeploy Host Agent
Loaded: loaded (/usr/lib/systemd/system/codedeploy-agent.service; enabled; preset: disabled)
Active: active (running) since Fri 2023-12-08 01:45:52 UTC; 3min 23s ago
Main PID: 27236 (ruby)
Tasks: 3 (limit: 1114)
Memory: 66.0M
CPU: 1.137s
CGroup: /system.slice/codedeploy-agent.service
├─27236 "codedeploy-agent: master 27236"
└─27238 "codedeploy-agent: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller of >
Dec 08 01:45:51 ip-172-31-25-231.us-west-2.compute.internal systemd[1]: Starting codedeploy-agent.s>
Dec 08 01:45:52 ip-172-31-25-231.us-west-2.compute.internal bash[27203]: /opt/codedeploy-agent/vend>
Dec 08 01:45:52 ip-172-31-25-231.us-west-2.compute.internal bash[27203]: /opt/codedeploy-agent/vend>
Dec 08 01:45:52 ip-172-31-25-231.us-west-2.compute.internal bash[27203]: /opt/codedeploy-agent/vend>
Dec 08 01:45:52 ip-172-31-25-231.us-west-2.compute.internal bash[27203]: /opt/codedeploy-agent/vend>
Dec 08 01:45:52 ip-172-31-25-231.us-west-2.compute.internal systemd[1]: Started codedeploy-agent.se>
AMI(=이미지) 란? EC2 인스턴스를 실행하기 위한 정보 모음(OS, 아키텍쳐 타입, 저장공간 용량 등)
EC2 > 인스턴스 > 이미지를 생성할 인스턴스 체크 > 이미지 및 템플릿 > 이미지 생성
생성된 AMI 확인
기다리다보면 상태가 사용 가능으로 변경된다.
시작 템플릿이란? EC2 인스턴스 시작에 필요한 구성 정보를 모아둔 것. AMI의 ID, 인스턴스 유형, 키 페어, 보안 그룹 및 EC2 인스턴스를 시작하는 데 사용할 기타 파라미터 등이 포함
EC2 > 인스턴스 > 시작 템플릿 > 시작 템플릿 생성
인스턴스 프로파일이란? 역할을 위한 컨테이너로서 인스턴스 시작 시 EC2 인스턴스에 역할 정보를 전달하는데 사용
나머지 설정은 그대로 두고, 시작 템플릿 생성
EC2 > 인스턴스 > MyWebServer-020 인스턴스 종료하여 불필요한 인스턴스 정리
EC2 > 보안 그룹 > 보안 그룹 생성
대상 그룹이란? 리스너가 전달한 요청을 처리하기 위한 부하분산 대상들의 모임. Elastic Load Balancer가 부하를 분산을 할 때 어디로 분산할 것이냐를 모은 그룹들이 대상그룹.
EC2 > 대상 그룹
나머지 설정은 그대로 두고, 다음
버튼 클릭
인스턴스를 대상으로 등록 후 대상 그룹 생성
버튼 클릭
EC2 > 대상 그룹 > 로드 밸런서와 연결한 대상그룹 클릭 > 새 로드 밸런서와 연결
기본 구성
로드 밸런서 이름 : MyWebServerELB-020
체계 : 인터넷 경계
IP 주소 유형 : IPv4
네트워크 매핑
t2.micro 인스턴스 유형을 제공하는 첫번째와 세번째 가용영역에 생성된 서브넷 선택 (리전 별로 상이하므로 확인 필요)
보안 그룹 : 80포트만 허용하는 보안그룹 선택
리스너 및 라우팅
나머지 설정 그대로 두고, 로드 밸런서 생성
버튼 클릭
EC2 > Auto Scaling
다음
버튼 클릭
다음
버튼 클릭
다음
버튼 클릭
나머지 설정은 그대루 두고, 다음
> Auto Scaling 그룹 생성
버튼 클릭
로드밸런서 MyWebServerELB-020
의 DNS 주소로 접근하면 화면이 정상적으로 나타난다.
오토 스케일링 그룹 MyWebServerASG-020
을 통해 추가된 인스턴스 확인 가능
로드밸런서의 동작을 확인할 수 있도록 각 인스턴스의 웹 루트 디렉터리에 IP 주소를 출력하는 index.html 파일을 추가해준다.
# i-0682fc8e15642ce06
$ echo "<h1>54.186.57.226</h1>" > /var/www/html/index.html
# i-0fa96a4ae0b450217
$ echo "<h1>34.215.133.163</h1>" > /var/www/html/index.html
로드밸런서 DNS주소로 접근하여 새로고침해서 확인하면 모든 인스턴스가 동작 중인 것을 확인할 수 있다.
12.1. 리포지터리에 index.html
추가
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<script>
var text = "I told you so!";
</script>
</head>
<body>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<msup><mi>a</mi><mn>2</mn></msup>
<mo>+</mo>
<msup><mi>b</mi><mn>2</mn></msup>
<mo>=</mo>
<msup><mi>c</mi><mn>2</mn></msup>
</mrow>
</math>
<!-- embed svg elements directly in HTML5 -->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="190">
<polygon points="100,10 40,180 190,60 10,60 160,180"
style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;">
</svg>
<script>
document.write("<p>"+text+"</p>");
document.write("<p>"+text+"</p>");
document.write("<p>"+text+"</p>");
</script>
</body>
</html>
12.2. 레포지터리에 appspec.yml
추가
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html
hooks:
AfterInstall:
- location: scripts/set_owner
timeout: 5
runas: root
12.3. scripts/set_owner
추가
echo "Running set_owner"
chown -R ec2-user /var/www/html
12.4. CodeDeploy 어플리케이션 생성
CodeDeploy > 배포 > 어플리케이션 > 애플리케이션 생성
애플리케이션 생성
버튼 클릭
컴퓨팅 플랫폼
- EC2/온프레미스 : 물리적 서버의 인스턴스. 배포에서는 인 플레이스 또는 블루/그린 배포 유형을 사용하여 인스턴스로 트래픽이 전송되는 방식을 관리.
- AWS Lambda : 업데이트 버전의 Lambda 함수로 구성된 애플리케이션을 배포.
- AWS ECS : 컨테이너화된 애플리케이션을 작업 세트로 배포.
12.5. 배포그룹 생성
생성한 애플리케이션에 배포 그룹 생성
배포그룹이란?
배포대상(개발계, 테스트계, 운영계 등)과 배포 방법(한 번에, 반반씩, 단계적으로 등)정의 한 것
배포 방법(=배포 설정)
- AllAtOnce : 한 번에 가급적 많은 수의 인스턴스에 배포.
- OneAtTime : 한 번에 한 인스턴스에만 배포.
- HalfAtTime : 최대 절반의 인스턴스를 한 번에 배포.
배포 그룹 생성
버튼 클릭
12.6. 배포 생성
CodeDeploy > 애플리케이션 > 배포할 애플리케이션 클릭 > 배포를 생성할 배포 그룹 클릭 > 배포 생성
클릭
Github에 연결
버튼 클릭배포 만들기
버튼 클릭
12.7. 배포 확인
로드 밸런서 DNS주소로 접근하면 Github에 있는 코드가 반영된 것을 확인할 수 있다.
새롭게 추가된 인스턴스는 어떤 상태로 실행될까?
CodeDeploy
로 배포 자동화를 설정해놨기 때문에 새롭게 추가된 인스턴스에는CodeDeploy Agent
가 최신 정보를 반영해준다. 요즘 Github 액션과 결합해서 사용하기도 한다는 듯?
✅ codedeploy 애플리케이션 삭제
✅ ASG 용량 모두 0
✅ 로드밸런서 삭제
✅ 대상그룹 삭제
✅ 오토스케일링 그룹 삭제
✅ 시작 템플릿 - 템플릿 버전 삭제 후 템플릿 삭제
✅ AMI 등록 취소
✅ 스냅샷 삭제
✅ 보안그룹 - 만약 보안그룹이 삭제되지 않는다면 인바운드/아웃바운드 규칙 모드 제거 후 삭제(Default는 삭제 불가)
✅ VPC 삭제
✅ 역할 삭제
✅ 정책 삭제
✅ 로그 그룹 삭제