์์ ์ค์ต ๋ ํฌ์งํ ๋ฆฌ์ ํ๊ฒฝ ์ ํ ์ ์งํํ์ต๋๋ค.
๊ธฐ๋ณธ ์ ํ ์ ๋ํด ๊ถ๊ธํ์ ๋ถ์ด๋, ์์ธํ ๋ด์ฉ์ ์๋ ํฌ์คํ ์ ์ฐธ๊ณ ํด์ฃผ์ธ์.
https://programmer-may.tistory.com/213
๋ฌด์ค๋จ ๋ฐฐํฌ ์ค์ต ๊ธฐ๋ณธ ์ ํ (Github Actions, Nginx ํ์ฉ)
๋ฌด์ค๋จ ๋ฐฐํฌ ์ด๋ก ์ ๋ํด์ ํ์ต์ ํ์๊ณ , ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์ด์ ์ค์ตํด๋ณด๊ฒ ์ต๋๋ค. ์ด๋ก ์ ๊ดํด์๋ ์๋ ํฌ์คํ ์ ์ฐธ๊ณ ํด์ฃผ์ธ์.https://programmer-may.tistory.com/209 ๋ฌด์ค๋จ ๋ฐฐํฌ(Zero-downtime Deployment
programmer-may.tistory.com
๋กค๋ง ์ ๋ต
๋กค๋ง ์ ๋ต(Rolling Deployment)์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฒ์ ์ ์ ์ง์ ์ผ๋ก ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๊ธฐ์กด ์ธ์คํด์ค๋ฅผ ํ๋์ฉ ์๋ก์ด ๋ฒ์ ์ผ๋ก ๊ต์ฒดํ๋ฉฐ, ๋ฐฐํฌ ๊ณผ์ ์์ ์ผ๋ถ ์ธ์คํด์ค๋ ์ด์ ๋ฒ์ , ๋๋จธ์ง ์ธ์คํด์ค๋ ์ ๋ฒ์ ์ด ์คํ๋ฉ๋๋ค.
๋ก๋ ๋ฐธ๋ฐ์์ ์ฐ๊ฒฐ๋์ด ์๋ ์๋ฒ๋ฅผ ํ๋ ์ถ๊ฐ ํ๊ฑฐ๋ ์ฐ๊ฒฐ์ ๋์ด์ ์๋ก์ด ๋ฒ์ ์ผ๋ก ๊ต์ฒดํ๊ณ ๋ก๋๋ฐธ๋ฐ์์ ๋ค์ ์ฐ๊ฒฐํฉ๋๋ค. ์ด ๊ณผ์ ์ ์ ์ง์ ์ผ๋ก ์งํํ์ฌ ์ต์ข ์ ์ผ๋ก๋ ๋ชจ๋ ํธ๋ํฝ์ด ์ ๋ฒ์ ์ ๋๋ฌํ ์ ์๊ฒ ํฉ๋๋ค. ์ด๋ฌํ ๊ณผ์ ์ ํตํด ์๋น์ค ์ค๋จ ์์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค.
rolling_before ๋ธ๋์น
Rolling ๋ฌด์ค๋จ ๋ฐฐํฌ ์ ๋ต ๋์ ์ ํ๊ฒฝ์ ๊ตฌ์ถํฉ๋๋ค. cd-rolling.yml ํ์ผ์ ํตํด JAR ํ์ผ์ ์ ๋ก๋ํ๊ณ , ์ด์ ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์ด๊ณ JAR ํ์ผ์ 8081ํฌํธ, 8082ํฌํธ์์ ์คํํฉ๋๋ค. ์ด ๊ณผ์ ์์ ๋ค์ด ํ์์ด ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
rolling_after ๋ธ๋์น
๋กค๋ง ์ ๋ต ๋์ ํ์ฌ ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์คํํฉ๋๋ค. cd-rolling.yml ํ์ผ์ ํตํด deploy.sh ํ์ผ์ ์คํํฉ๋๋ค.
deploy.sh ํ์ผ์์ฑ
#!/bin/bash
# ์ ํ๋ฆฌ์ผ์ด์
ํฌํธ ์ค์
PORT1=8081
PORT2=8082
DEPLOY_PORT=0
# ํฌ์ค ์ฒดํฌ ํจ์
health_check() {
local port=$1
local CHECK_URL="http://localhost:$port/actuator/health"
local RETRY_COUNT=0
local MAX_RETRY=10
echo "Checking health on port $port..."
until $(curl --output /dev/null --silent --head --fail $CHECK_URL); do
sleep 5
RETRY_COUNT=$((RETRY_COUNT+1))
if [ $RETRY_COUNT -eq $MAX_RETRY ]; then
echo "Health check failed on port $port"
return 1
fi
done
echo "Health check passed on port $port"
return 0
}
timestamp=$(date +"%Y%m%d%H%M%S")
# ๋กค๋ฐฑ ํจ์
rollback() {
local port=$1
local backup_jar="/home/ubuntu/cicd/old_build/app-${port}-${timestamp}.jar"
local current_version_jar="/home/ubuntu/cicd/app-${port}.jar"
echo "Rolling back on port $port..."
# ์ ๋ฒ์ ํ๋ก์ธ์ค ์ข
๋ฃ
sudo fuser -k -TERM $port/tcp
# ๋ฐฑ์
๋ ๊ธฐ์กด ๋ฒ์ ๋ณต์
mv $backup_jar $current_version_jar
# ์ด์ ๋ฒ์ ์คํ
sudo nohup java -jar -Dserver.port=$port $current_version_jar > /home/ubuntu/console-$port.log 2>&1 &
# Nginx ์ค์ ํ์ผ ์๋ ์ํ๋ก ๋ณต๊ตฌ
sudo sed -i '/upstream backend {/,/}/ s/server 127.0.0.1:'"$port"' down;/server 127.0.0.1:'"$port"';/' /etc/nginx/sites-available/default
sudo service nginx reload
}
# ๋ฐฐํฌ ํจ์
deploy() {
local port=$1
local current_version_jar="/home/ubuntu/cicd/app-${port}.jar"
local new_version_jar=$(ls /home/ubuntu/cicd/ZeroDownTimeDeployment-*.jar | head -n 1)
echo "Deploying new version to port $port..."
# ๊ธฐ์กด ๋ฒ์ ๋ฐฑ์
mv $current_version_jar /home/ubuntu/cicd/old_build/app-${port}-${timestamp}.jar
# ์ ๋ฒ์ ๋ฐฐํฌ
cp $new_version_jar $current_version_jar
sudo chmod +x $current_version_jar
sudo nohup java -jar -Dserver.port=$port $current_version_jar > /home/ubuntu/console-$port.log 2>&1 &
sleep 20
# ํฌ์ค ์ฒดํฌ
health_check $port
if [ $? -ne 0 ]; then
rollback $port
return 1
fi
echo "Deployment successful on port $port"
return 0
}
# 8081์ ๋ํ ๋ฐฐํฌ
echo "Routing traffic away from port $PORT1..."
sudo sed -i '/upstream backend {/,/}/ s/server 127.0.0.1:'"$PORT1"';/server 127.0.0.1:'"$PORT1"' down;/' /etc/nginx/sites-available/default
sudo service nginx reload
# 8081 ํฌํธ์์ ์คํ ์ค์ธ ํ๋ก์ธ์ค ์ข
๋ฃ
echo "Stopping process on port $PORT1..."
sudo fuser -k -TERM $PORT1/tcp
if [ $? -ne 0 ]; then
echo "Failed to stop the process on port $PORT1. Aborting..."
exit 1
fi
echo "Process on port $PORT1 stopped."
deploy $PORT1
if [ $? -ne 0 ]; then
echo "Deployment failed on port $PORT1. Aborting..."
exit 1
fi
echo "Re-routing traffic to port $PORT1..."
sudo sed -i '/upstream backend {/,/}/ s/server 127.0.0.1:'"$PORT1"' down;/server 127.0.0.1:'"$PORT1"';/' /etc/nginx/sites-available/default
sudo service nginx reload
# 8082์ ๋ํ ๋ฐฐํฌ
echo "Routing traffic away from port $PORT2..."
sudo sed -i '/upstream backend {/,/}/ s/server 127.0.0.1:'"$PORT2"';/server 127.0.0.1:'"$PORT2"' down;/' /etc/nginx/sites-available/default
sudo service nginx reload
# 8082 ํฌํธ์์ ์คํ ์ค์ธ ํ๋ก์ธ์ค ์ข
๋ฃ
echo "Stopping process on port $PORT2..."
sudo fuser -k -TERM $PORT2/tcp
if [ $? -ne 0 ]; then
echo "Failed to stop the process on port $PORT2. Aborting..."
exit 1
fi
echo "Process on port $PORT2 stopped."
deploy $PORT2
if [ $? -ne 0 ]; then
echo "Deployment failed on port $PORT2. Aborting..."
exit 1
fi
echo "Re-routing traffic to port $PORT2..."
sudo sed -i '/upstream backend {/,/}/ s/server 127.0.0.1:'"$PORT2"' down;/server 127.0.0.1:'"$PORT2"';/' /etc/nginx/sites-available/default
sudo service nginx reload
sudo rm /home/ubuntu/cicd/no_downtime-*.jar
echo "Rolling deployment complete. Both ports are now running the new version."
- ํฌํธ ์ค์ ๋ฐ ํฌ์ค ์ฒดํฌ ํจ์ ์ ์
- PORT1=8081๊ณผ PORT2=8082๋ก ๋ ๊ฐ์ ํฌํธ๋ฅผ ์ค์ ํฉ๋๋ค. health_check ํจ์๋ /actuator/health ์๋ํฌ์ธํธ๋ฅผ ์ฌ์ฉํ์ฌ ์๋ก ๋ฐฐํฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ์์ ์ผ๋ก ์๋ํ๋์ง ํ์ธํฉ๋๋ค.
- ํ์์คํฌํ ์์ฑ
- timestamp=$(date +"%Y%m%d%H%M%S")๋ฅผ ํตํด ํ์ฌ ์๊ฐ์ ํ์์คํฌํ ํ์์ผ๋ก ์ ์ฅํฉ๋๋ค. ์ด ๊ฐ์ JAR ํ์ผ์ ๋ฐฑ์ ํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- ๋กค๋ฐฑ ํจ์ ์ ์
- rollback() ํจ์๋ ๋ฐฐํฌ๊ฐ ์คํจํ์ ๋, ์ด์ ์ ๋ฐฑ์ ๋ JAR ํ์ผ์ ๋ณต์ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ ์คํํฉ๋๋ค.
- ์ ๋ฒ์ ์ ์ข ๋ฃํ๊ณ , ์ด์ ๋ฒ์ ์ ๋ฐฑ์ ํด๋์์ ์๋ ์์น๋ก ๋ณต์ํ ํ ๋ค์ ์คํํฉ๋๋ค.
- ๋ฐฐํฌ ํจ์ ์ ์:
- deploy() ํจ์๋ ์ ๋ฒ์ ์ ํฌํธ์ ๋ฐฐํฌํฉ๋๋ค. ๋จผ์ ๊ธฐ์กด ๋ฒ์ ์ JAR ํ์ผ์ ๋ฐฑ์ ํ๊ณ , ์๋ก ๋ฐฐํฌ๋ ๋ฒ์ ์ผ๋ก ๊ต์ฒดํ ๋ค ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํฉ๋๋ค.
- ๋ฐฐํฌ ํ health_check ํจ์๋ฅผ ํตํด ํฌ์ค ์ฒดํฌ๋ฅผ ์ํํ๋ฉฐ, ์คํจ ์ ๋กค๋ฐฑํฉ๋๋ค.
- ํฌํธ๋ณ ๋ฐฐํฌ ์ ์ฐจ
- PORT1=8081, PORT2=8082๋ฅผ ๋์์ผ๋ก ์์ฐจ์ ์ผ๋ก ๋ฐฐํฌ๋ฅผ ์งํํฉ๋๋ค. ๊ฐ๊ฐ์ ํฌํธ์ ๋ํด ์คํ ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ข ๋ฃํ๊ณ , ์ ๋ฒ์ ์ ๋ฐฐํฌํ ํ ํฌ์ค ์ฒดํฌ๋ฅผ ์ํํฉ๋๋ค.
- Nginx ์ค์ ์
๋ฐ์ดํธ
- Nginx ์ค์ ์ ์ ๋ฐ์ดํธํ์ฌ ์๋ก์ด ํฌํธ๋ก ํธ๋ํฝ์ ๋ผ์ฐํ ํฉ๋๋ค. sed ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ proxy_pass ์ค์ ์ ๋ณ๊ฒฝํ๊ณ , Nginx๋ฅผ reloadํฉ๋๋ค.
- ๋กค๋ง ๋ฐฐํฌ ์๋ฃ
- ๋ ํฌํธ ๋ชจ๋ ์ฑ๊ณต์ ์ผ๋ก ๋ฐฐํฌ๋๋ฉด, Nginx ์ค์ ํ์ผ์ ๋ค์ ๋ก๋ํฉ๋๋ค.
Nginx ์ค์
upstream backend {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 80;
server_name _;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
ํ ์คํธ ๊ฒฐ๊ณผ ํ์ธ
rolling_before ๋ธ๋์น๋ฅผ rolling ๋ธ๋์น์ ํธ์ ํ๊ณ , rolling_after ๋ธ๋์น๋ฅผ ํธ์ํ์ฌ ๋กค๋ง์ ๋ต ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ๋์ ํฉ๋๋ค.
1์ด์ 1๋ฒ ์ฉ simple HTTP Request ๋ฅผ ๋ณด๋ด์ด ๋ค์ด ํ์์ด ์๋์ง ํ์ธํ์์ต๋๋ค.
Apache JMeter
'DevOps > CI&CD' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ฌด์ค๋จ ๋ฐฐํฌ ์ค์ต - ์นด๋๋ฆฌ ์ ๋ต (0) | 2024.09.07 |
---|---|
๋ฌด์ค๋จ ๋ฐฐํฌ ์ค์ต - ๋ธ๋ฃจ๊ทธ๋ฆฐ ์ ๋ต (0) | 2024.08.18 |
๋ฌด์ค๋จ ๋ฐฐํฌ ์ค์ต ๊ธฐ๋ณธ ์ ํ (Github Actions, Nginx ํ์ฉ) (0) | 2024.08.13 |
๋ฌด์ค๋จ ๋ฐฐํฌ(Zero-downtime Deployment) ์ ๋ต (0) | 2024.07.23 |
CI/CD ๋ ๋ฌด์์ธ๊ฐ? (0) | 2024.07.17 |
๋๊ธ