Replies: 18 comments 20 replies
-
2️⃣ CD 를 ec2 마다 / 순차적으로 하게 한다.방법) max-parallel기본적으로는 모든 러너를 사용해서 job들을 병렬적으로 수행한다. 하지만 max-parallel 설정을 통해 동시에 실행할 job의 개수를 설정해줄 수 있다. jobs:
test-concurrency:
runs-on: ${{ matrix.os }}
strategy:
max-parallel: 1 # 동시에 1개만 job이 실행되도록 설정
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
concurrency:
group: sequential-test
cancel-in-progress: false # 이전 작업을 취소하지 않는다는 설정 실험 결과 순서대로 하나씩 runs-on을 실행함! |
Beta Was this translation helpful? Give feedback.
-
Code Deploy
|
Beta Was this translation helpful? Give feedback.
-
문제 상황
시도할 방안1.(ec2 삭제 -생성 방식 맞음) 도메인 주소로 prod1,2에 접속할 수 있는 방법 찾아서 모니터링 서버에 도메인 주소로 박음: 블루 그린 방식 가능 |
Beta Was this translation helpful? Give feedback.
-
🧑🏻⚖️ 우리는 왜 [Code Deploy의 블루 그린] 방법을 사용하지 않았는가?Code Deploy의 블루 그린 방식을 고려했던 이유
한계
느낀 점
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
0. env.prod 파일로 환경 변수 설정
이때 설정한 환경변수는 docker-compose 파일에 적용되며, shell script 에도 적용된다. 1/ docker-compose 파일에 적용하는 방법 docker-compose --env-file .env.prod up -d 2/ shell script 에 적용하는 방법 source /.env.prod 1. Docker Compose 파일 수정두 개의 서비스를 정의하고, 포트를 변수로 설정한다. version: '3'
services:
app-green: # 서비스 이름, shell 의 docker-compose up 뒤에 들어가면 하나의 서비스만 up 할 수 있다.
image: reviewme/review-me-app:${DOCKER_TAG}
ports:
- "80:${GREEN_PORT}"
environment:
- SERVER_PORT=${GREEN_PORT}
app-blue:
image: reviewme/review-me-app:${DOCKER_TAG} # release
ports:
- "80:${BLUE_PORT}"
environment:
- SERVER_PORT=${BLUE_PORT} 🤔 두개의 서비스를 정의함으로써 사용되는 추가 리소스는 없을까?cf. 서비스란, 이미지를 기반으로 실제로 실행되는 애플리케이션이다. 두 개의 서비스를 저장해야 하므로 약간의 추가 디스크 공간이 필요하다. 2. application.yml 수정docker-compose 에서 지정한 환경변수로 port 를 설정한다. spring:
profiles:
active: prod
server:
port: ${SERVER_PORT} 3. 배포 스크립트 작성아래 과정에서 #!/bin/bash
# .env.prod 파일의 내용을 환경변수로 저장
source /.env.prod
# 현재 활성화된 포트 확인
CURRENT_PORT=$(docker ps --filter name=app -q | xargs -I {} docker port {} | grep -o '808[01]')
# 새로운 포트 설정
if [ "$CURRENT_PORT" == ${BLUE_PORT} ]; then
NEW_PORT=${GREEN_PORT}
NEW_COLOR=green
else
NEW_PORT=${BLUE_PORT}
NEW_COLOR=blue
fi
# 새 버전 배포
docker-compose --env-file .env.prod up -d app-$NEW_COLOR # e.g. 컨테이너 서비스명: app-green
# 새 컨테이너 상태 확인
MAX_RETRIES=10
RETRY_INTERVAL=5
for i in $(seq 1 $MAX_RETRIES)
do
if nc -z localhost $NEW_PORT; then
echo "New version is up and running on port $NEW_PORT"
break
fi
if [ $i -eq $MAX_RETRIES ]; then
echo "New version failed to start, rolling back"
docker-compose --env-file .env.prod stop app-$NEW_COLOR
exit 1
fi
echo "Waiting for the new version to start... (Attempt $i/$MAX_RETRIES)"
sleep $RETRY_INTERVAL
done
# 이전 버전 종료
docker-compose --env-file .env.prod stop app-$([ "$NEW_COLOR" == "blue" ] && echo "green" || echo "blue")
- name: Deploy new version
run: |
chmod +x ./deploy.sh
sudo ./deploy.sh
working-directory: ${{ env.APPLICATION_DIRECTORY }}/app |
Beta Was this translation helpful? Give feedback.
-
10월 19일어떤 순서로 일을 처리할 것인가?docker compose & shell acript
github actions
실전
어떻게 해야 이 일을 더 효율적으로 처리할 수 있을까?
|
Beta Was this translation helpful? Give feedback.
-
커비 작업 1. 동시에 두개의 서비스가 떠있는 상태가 된다면, 80 포트로 들어온 요청은 두가지 서비스로 둘 다 가나?하고 싶은것 새로운 쪽 어플리케이션이 잘 run되기 전까지는 기존 서비스로 요청이 가고, |
Beta Was this translation helpful? Give feedback.
-
산초 작업 - 컨테이너 포트를 기반으로 지금 8080 이 떠있는지 / 8081이 떠있는지 확인한다.get_current_port() {
local current_port=$(docker ps --format '{{.Names}}:{{.Ports}}' |
grep '^review-me-app' |
grep -E ':::80->(8080|8081)/tcp' |
sed -E 's/.*:::80->([0-9]+)\/tcp.*/\1/')
if [ -z "$current_port" ]; then
echo "No active 'review-me-app' container found running on port 8080 or 8081"
exit 1
fi
echo $current_port
}
CURRENT_PORT=$(get_current_port)
echo "Current active port: $CURRENT_PORT" docker ps --format '{{.Names}}:{{.Ports}}'
grep 'review-me-app'
grep -E ':::80->(8080|8081)/tcp'
sed -E 's/.:::80->([0-9]+)/tcp./\1/'
|
Beta Was this translation helpful? Give feedback.
-
커비 작업 2. 기존 어플리케이션으로 간 요청을, 받은 요청까지는 처리하고 docker-compose down하는 방법graceful shutdown
version: '3'
services:
app-green:
image: reviewme/review-me-app:${DOCKER_TAG}
ports:
- "80:${GREEN_PORT}"
environment:
- SERVER_PORT=${GREEN_PORT}
stop_grace_period: 10s
app-blue:
image: reviewme/review-me-app:${DOCKER_TAG}
ports:
- "80:${BLUE_PORT}"
environment:
- SERVER_PORT=${BLUE_PORT}
stop_grace_period: 10s
docker-compose --env-file .env.prod stop app-$([ "$NEW_COLOR" == "blue" ] && echo "green" || echo "blue") |
Beta Was this translation helpful? Give feedback.
-
산초 작업 - 새로 up 한 서비스가 잘 살아있는지를 체크한다.처음에는 health-check 엔드포인트로 확인하는 방법을 고려했다. 따라서, docker ps + grep 으로 새로 띄운 서비스의 포트가 있는지 확인하는 방법으로 결정했다. # new_port 변수가 설정되어 있다고 가정
check_service() {
local container_info=$(docker ps --format '{{.Names}}:{{.Ports}}' |
grep '^review-me-app' |
grep -E ":::80->$new_port/tcp")
if [ -n "$container_info" ]; then
echo "Service 'review-me-app' is running and mapped from port 80 to $new_port"
return 0
else
echo "Service 'review-me-app' is not running or not mapped correctly"
return 1
fi
} docker ps --format '{{.Names}}:{{.Ports}}'
** grep '^review-me-app'**
grep -E ":::80->$new_port/tcp
if [ -n "$container_info" ]; then
|
Beta Was this translation helpful? Give feedback.
-
현재까지 작업 반영 (10.19 19:35 기준)1. 배포 스크립트#!/bin/bash
# .env.prod 파일의 내용을 환경변수로 저장
source /.env.prod
# 현재 활성화된 포트 확인
get_current_port() {
local current_port=$(docker ps --format '{{.Names}}:{{.Ports}}' |
grep '^app' |
grep -E ':::80->(8080|8081)/tcp' |
sed -E 's/.*:::80->([0-9]+)\/tcp.*/\1/')
if [ -z "$current_port" ]; then
echo "No active app container found running on port 8080 or 8081"
exit 1
fi
echo "$current_port is current port!"
}
CURRENT_PORT=$(get_current_port)
# 새로운 포트 설정
if [ "$CURRENT_PORT" = "8080" ]; then
NEW_PORT=8081
elif [ "$CURRENT_PORT" = "8081" ]; then
NEW_PORT=8080
else
echo "Error: Unexpected CURRENT_PORT value: $CURRENT_PORT"
exit 1
fi
# 기존 활성화된 포트로 포워딩 유지
echo "Forwarding 80 -> $CURRENT_PORT"
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port $CURRENT_PORT
# 새 버전 배포
docker-compose --env-file .env.prod up -d app-$NEW_PORT
# 새 컨테이너 상태 확인
is_new_container_healthy() {
docker ps --format '{{.Names}}:{{.Ports}}' |
grep '^app' |
grep -E ":::80->$NEW_PORT/tcp"
}
# 반복하며 새 컨테이너 상태 확인
MAX_RETRIES=10
RETRY_INTERVAL=5
for i in $(seq 1 $MAX_RETRIES)
do
container_info=$(is_new_container_healthy)
if [ -n "$container_info" ]; then
echo "New version is up and running on port $NEW_PORT"
break
fi
if [ $i -eq $MAX_RETRIES ]; then
echo "New version failed to start, rolling back"
docker-compose --env-file .env.prod �down app-$NEW_PORT
exit 1
fi
echo "Waiting for the new version to start... (Attempt $i/$MAX_RETRIES)"
sleep $RETRY_INTERVAL
done
# 새 버전으로 포워딩 업데이트
echo "Updating forwarding: 80 -> $NEW_PORT"
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port $NEW_PORT
# 이전 버전 종료 (graceful shutdown)
OLD_PORT=$([ "$NEW_PORT" == "8080" ] && echo "8081" || echo "8080")
docker-compose --env-file .env.prod stop app-$OLD_PORT 2. Docker Compose 파일version: '3'
services:
app-8080:
image: reviewme/review-me-app:${DOCKER_TAG}
container_name: review-me-app
ports:
- "80:8080"
- "5959:5959"
volumes:
- ./application-${SPRING_PROFILE}.yml:/application.yml
- /home/ubuntu/logs/:/logs
environment:
- SERVER_PORT=8080
- TZ=Asia/Seoul
stop_grace_period: 10s
app-8081:
image: reviewme/review-me-app:${DOCKER_TAG}
container_name: review-me-app
ports:
- "80:8081"
- "5959:5959"
volumes:
- ./application-${SPRING_PROFILE}.yml:/application.yml
- /home/ubuntu/logs/:/logs
environment:
- SERVER_PORT=8081
- TZ=Asia/Seoul
stop_grace_period: 10s |
Beta Was this translation helpful? Give feedback.
-
bash 파일을 거의 완성해가니 실제 실행할 때를 상상해보며 드는 생각github action을 썼을 때는 어디서 문제가 발생했는지 볼 수 있었는데 bash 파일 내부는 스텝별로 어느 문제가 안에서 생겼는지는 못보겠지? |
Beta Was this translation helpful? Give feedback.
-
롤백 관련 커비 작업1. 헬스 체크에서 unhealthy 하다는게 확정되어 exit 1 로 빠져나간다면, 뒤에 있는 것들이 실행이 아예 안되야하는데 그런가?그렇다. exit 1이 실행되면 스크립트의 실행이 즉시 중단된다. 따라서, 스크립트를 종료하고, 지정한 상태 코드(여기서는 1)를 반환한다. 2. docker up은 성공했는데, 어플리케이션 run이 실패하는 경우 docker는 계속 up 상태인가?맞다. 왜냐면 docker up은 성공했는데, 어플리케이션 run이 실패하는 아래와 같은 경우가 있어서.
그럼 어플리케이션 실패하면 직접 down 해줘야하나?놀랍게도 이미 처리가 되어있다. 5. docker-compose 파일을 지금 dev 와 prod 가 공유를 하고 있는데, 8081 / 8080 의 분리를 dev에도 적용해서 dev도 무중단으로 해야 할 필요가 있을까?1. dev도 똑같은 docker-compose를 적용해서 무중단으로 하자: 해서 나쁠 것 없어서단점이 있는가? dev는 머지가 많이 일어나는데 그 때마다 dev ec2에 어플리케이션이 2개가 뜨는 순간이 짧지만 존재한다. 그 순간에 cpu, mem이 치솟아 오를 수 있다는 점. 2. dev는 무중단 배포가 아닌 docker-compose를 적용하자: 필요없는데 굳이 무중단 할 필요 없어서.그렇다면 dev만을 위한 docker-compose 분기를 해야할텐데 이렇게 파일이 나눠지는 게 괜찮은가? 추후 설정이 추가된다면 dev, prod용 docker-compose 파일 두 곳에 추가해야한다는 점이 번거롭다. 아니면 docker-compose 파일은 하나를 쓰되, 그 안에 태그를 통해 구분해서 dev 인 거는 include??등을 활용해 하나 포트로 하고, |
Beta Was this translation helpful? Give feedback.
-
shell script 의 정상 종료와 비정상 종료를 GitHub action 에서 알 수 있나?
steps:
- name: Step that might fail
run: ./risky_script.sh
continue-on-error: true
- name: Run only on failure
if: ${{ failure() }}
run: echo "The previous step failed" ➡️ 우리에게 적용해보자면... |
Beta Was this translation helpful? Give feedback.
-
도커 이미지 직전 버전 가져오는 방법 찾기
방법 :
name: CD Pipeline
on:
push:
branches: [ main ]
env:
DOCKER_IMAGE: myorganization/myapp
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build new image
# 새로운 도커 이미지를 만들고, 마지막 커밋을 태그로 단다 (식별하기 위해서)
run: docker build -t ${{ env.DOCKER_IMAGE }}:${{ github.sha }} .
- name: Update tags
run: |
# 현재의 latest 이미지를 pull 한다.
docker pull ${{ env.DOCKER_IMAGE }}:latest || true
# latest 를 previous로 태그 한다.
docker tag ${{ env.DOCKER_IMAGE }}:latest ${{ env.DOCKER_IMAGE }}:previous || true
# 새로운 이미지를 latest 로 태그한다.
docker tag ${{ env.DOCKER_IMAGE }}:${{ github.sha }} ${{ env.DOCKER_IMAGE }}:latest
- name: Push images
run: |
docker push ${{ env.DOCKER_IMAGE }}:${{ github.sha }}
docker push ${{ env.DOCKER_IMAGE }}:latest
docker push ${{ env.DOCKER_IMAGE }}:previous
- name: Deploy and test
id: deploy
run: |
# 배포 스크립트
./deploy-and-test.sh
continue-on-error: true
- name: Rollback if deployment failed
if: steps.deploy.outcome == 'failure'
run: |
echo "Deployment failed. Rolling back to previous version."
# previous 이미지를 가져온다.
docker pull ${{ env.DOCKER_IMAGE }}:previous
# previous 이미지를 latest 로 바꾼다.
docker tag ${{ env.DOCKER_IMAGE }}:previous ${{ env.DOCKER_IMAGE }}:latest
# 그리고 푸쉬한다.
docker push ${{ env.DOCKER_IMAGE }}:latest |
Beta Was this translation helpful? Give feedback.
-
우리 서비스에 적용(어플리케이션 a, b는 각 8080, 8081 포트로 스프링 어플리케이션을 실행할 수 있는 상태, 하나의 인스턴스 내에서 실행됨)
|
Beta Was this translation helpful? Give feedback.
-
.
Beta Was this translation helpful? Give feedback.
All reactions