Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IDLE-518] 인프라 재구축 및 CI/CD 재가동 #258

Merged
merged 38 commits into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
de249a6
[IDLE-518] bastion서버를 통해 production 서버로 접근 후, 배포하도록 설정
mjj111 Jan 16, 2025
886cdba
[IDLE-518] ECR 레파지토리 변경
mjj111 Jan 16, 2025
60e0e78
[IDLE-518] docker-compose 파일 경로 변경
mjj111 Jan 17, 2025
0f2c9b7
[IDLE-518] 소스파일 경로 변경
mjj111 Jan 17, 2025
3dd06e0
[IDLE-518] target 경로 변경
mjj111 Jan 17, 2025
97b739b
[IDLE-518] 소스파일 경로 변경
mjj111 Jan 17, 2025
7ba7847
[IDLE-518] 타겟파일 경로 원상복구
mjj111 Jan 17, 2025
05cb8f5
[IDLE-518] 타겟파일 경로 수정
mjj111 Jan 17, 2025
e7cf75a
[IDLE-518] compose 파일 실행 경로 수정
mjj111 Jan 17, 2025
12e3603
[IDLE-518] 하드코딩된 변수를 secrets로 변경
mjj111 Jan 17, 2025
618c08d
[IDLE-518] 하드코딩된 변수를 secrets로 변경
mjj111 Jan 17, 2025
0289f8f
[IDLE-518] 하드코딩된 변수를 secrets로 변경
mjj111 Jan 17, 2025
6da3d85
[IDLE-518] Configuration Env file 스탭 추가
mjj111 Jan 17, 2025
2a3598b
[IDLE-518] secrets로 변경
mjj111 Jan 17, 2025
63733f3
[IDLE-518] CI/CD 재가동 전 수동으로 수정
mjj111 Jan 17, 2025
7626d08
[IDLE-518] CI/CD 재가동 전 수동으로 수정
mjj111 Jan 17, 2025
acf5bec
[IDLE-518] ECR 레파지토리 작성
mjj111 Jan 17, 2025
d217dd3
[IDLE-518] .env 파일 경로 변경
mjj111 Jan 17, 2025
4743a98
[IDLE-518] 레지스트리 내용 변경
mjj111 Jan 17, 2025
290628f
[IDLE-518] DB 이름을 caremeet으로 변경
mjj111 Jan 17, 2025
35a2c16
[IDLE-518] 서비스 간 통신을 위한 컨테이너간 네트워크 설정 추가
mjj111 Jan 18, 2025
a112a29
[IDLE-518] ddl create 적용
mjj111 Jan 18, 2025
008d8f5
[IDLE-518] private_key.pem 파일을 통해 접근하도록 수정
mjj111 Jan 18, 2025
5665589
[IDLE-518] 호스트키 체크 우회 수정
mjj111 Jan 18, 2025
89916cb
[IDLE-518] SSH 세션에 터미널을 할당하도록 옵션 추가
mjj111 Jan 18, 2025
9ed7445
[IDLE-518] 터널링 방법을 수정
mjj111 Jan 18, 2025
9b166a4
[IDLE-518] Private Subnet에 존재하는 서버의 22번 포트를 로컬 2222 포트로 연결
mjj111 Jan 18, 2025
ad53897
[IDLE-518] .env파일 생성하는 명령어 수정
mjj111 Jan 18, 2025
4bb9094
[IDLE-518] 들여쓰기 수정
mjj111 Jan 18, 2025
49224d1
[IDLE-518] INPUT_으로 시작하는 항목, .env 파일에 제외
mjj111 Jan 18, 2025
278b350
[IDLE-518] null 값을 제외하는 처리를 추가
mjj111 Jan 18, 2025
ffe5e36
[IDLE-518] 병합 전에 null 값을 제외하는 처리를 추가
mjj111 Jan 18, 2025
e868544
[IDLE-518] context 출력문 추가
mjj111 Jan 18, 2025
4092ae1
[IDLE-518] JSON 형식으로 변환한 후, SSH 스크립트 내부에서 이를 파일로 저장
mjj111 Jan 19, 2025
edb175e
[IDLE-518] .env 파일에 INSTANCE_PEM_KEY가 들어가지 않도록 수정
mjj111 Jan 19, 2025
d6b15d4
[IDLE-518] ddl을 validate으로 수정
mjj111 Jan 19, 2025
1d5eff6
[IDLE-518] 브랜치 push시에 동작하도록 수정
mjj111 Jan 19, 2025
76742f2
Merge branch 'develop' into chore/IDLE-518
mjj111 Jan 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/dev-server-deployer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ jobs:
key: ${{ secrets.INSTANCE_PEM_KEY }}
envs: VARS_CONTEXT,SECRETS_CONTEXT
script: |
cd ~/app/docker
cd ~/app/docker/idle-presentation
jq -s '.[0] * .[1]' <(echo "$VARS_CONTEXT") <(echo "$SECRETS_CONTEXT") \
| jq -r 'to_entries | map("\(.key)=\(.value)") | .[]' > .env
| jq -r 'to_entries | map(select(.key != "INSTANCE_PEM_KEY")) | map("\(.key)=\(.value)") | .[]' > .env

- name: Run Docker Compose up
uses: appleboy/ssh-action@master
Expand Down
74 changes: 55 additions & 19 deletions .github/workflows/prod-server-deployer.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: Production Server Deployer (CD)

on: workflow_dispatch
on:
push:
branches:
- main
Comment on lines +3 to +6
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

자동 배포 트리거에 대한 보호 장치가 필요합니다.

main 브랜치 푸시 시 자동 배포되는 설정은 위험할 수 있습니다.

다음과 같은 보호 장치 추가를 권장드립니다:

on:
  push:
    branches:
      - main
+    paths-ignore:
+      - '**.md'
+      - 'docs/**'
+  workflow_dispatch:  # 수동 트리거 옵션 유지
+    inputs:
+      confirmation:
+        description: '프로덕션 배포를 진행하시겠습니까? (yes/no)'
+        required: true
+        default: 'no'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
push:
branches:
- main
on:
push:
branches:
- main
paths-ignore:
- '**.md'
- 'docs/**'
workflow_dispatch:
inputs:
confirmation:
description: '프로덕션 배포를 진행하시겠습니까? (yes/no)'
required: true
default: 'no'

jobs:
deploy:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -50,7 +53,13 @@ jobs:
username: ${{ vars.BASTION_USERNAME }}
key: ${{ secrets.INSTANCE_PEM_KEY }}
script: |
ssh -o "ProxyJump=${{ vars.BASTION_HOST }}" -i ${{ secrets.INSTANCE_PEM_KEY }} ${{ vars.INSTANCE_USERNAME }}@${{ vars.INSTANCE_HOST }} << 'EOF'
if [ ! -f private_key.pem ]; then
echo "${{ secrets.INSTANCE_PEM_KEY }}" > private_key.pem
chmod 600 private_key.pem
fi
Comment on lines +56 to +59
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

PEM 키 파일 관리 방식 개선이 필요합니다.

여러 단계에서 PEM 키 파일이 반복적으로 생성되고 있으며, 보안 위험이 있습니다.

다음과 같이 PEM 키 관리를 개선하는 것을 권장드립니다:

  1. 공통 스크립트로 추출:
- name: Setup SSH Key
  id: ssh-key
  run: |
    SSH_KEY_PATH="${RUNNER_TEMP}/private_key.pem"
    echo "${{ secrets.INSTANCE_PEM_KEY }}" > "${SSH_KEY_PATH}"
    chmod 600 "${SSH_KEY_PATH}"
    echo "key_path=${SSH_KEY_PATH}" >> $GITHUB_OUTPUT
  1. 키 경로를 환경 변수로 참조:
- if [ ! -f private_key.pem ]; then
-   echo "${{ secrets.INSTANCE_PEM_KEY }}" > private_key.pem
-   chmod 600 private_key.pem
- fi
+ SSH_KEY_PATH="${{ steps.ssh-key.outputs.key_path }}"
  1. 작업 완료 후 키 파일 정리:
- name: Cleanup SSH Key
  if: always()
  run: rm -f ${{ steps.ssh-key.outputs.key_path }}

Also applies to: 88-91, 122-124

ssh -f -N -M -S my-cicd-socket -o StrictHostKeyChecking=no -i private_key.pem -L 2222:${{ vars.INSTANCE_HOST }}:22 ec2-user@${{ vars.BASTION_HOST }}
ssh -o StrictHostKeyChecking=no -i private_key.pem -p 2222 ubuntu@localhost << 'EOF'
echo "Connected to Private Subnet productionServer via SSH Tunneling"
if ! command -v docker >/dev/null 2>&1; then
echo "Installing Docker..."
sudo apt-get update
Expand All @@ -66,23 +75,42 @@ jobs:
echo "Docker Compose already installed."
fi
EOF
ssh -S my-cicd-socket -O exit ec2-user@${{ vars.BASTION_HOST }}
rm -f private_key.pem

- name: Configuration Env file
uses: appleboy/ssh-action@master
env:
VARS_CONTEXT: ${{ toJson(vars) }}
SECRETS_CONTEXT: ${{ toJson(secrets) }}
with:
host: ${{ vars.BASTION_HOST }}
username: ${{ vars.BASTION_USERNAME }}
key: ${{ secrets.INSTANCE_PEM_KEY }}
envs: VARS_CONTEXT,SECRETS_CONTEXT
script: |
ssh -o "ProxyJump=${{ vars.BASTION_HOST }}" -i ${{ secrets.INSTANCE_PEM_KEY }} ${{ vars.INSTANCE_USERNAME }}@${{ vars.INSTANCE_HOST }} << 'EOF'
cd ~/app/docker
jq -s '.[0] * .[1] | del(.INSTANCE_PEM_KEY)' <(echo "$VARS_CONTEXT") <(echo "$SECRETS_CONTEXT") \
| jq -r 'to_entries | map("\(.key)=\(.value)") | .[]' > .env
if [ ! -f private_key.pem ]; then
echo "${{ secrets.INSTANCE_PEM_KEY }}" > private_key.pem
chmod 600 private_key.pem
fi
ssh -f -N -M -S my-cicd-socket -o StrictHostKeyChecking=no -i private_key.pem -L 2222:${{ vars.INSTANCE_HOST }}:22 ec2-user@${{ vars.BASTION_HOST }}
ssh -o StrictHostKeyChecking=no -i private_key.pem -p 2222 ubuntu@localhost << 'EOF'
echo "Connected to Private Subnet productionServer via SSH Tunneling"
cd ~/app/docker

echo "VARS_CONTEXT: ${{ toJson(vars) }}"
echo "SECRETS_CONTEXT: ${{ toJson(secrets) }}"

VARS_CONTEXT_JSON='${{ toJson(vars) }}'
SECRETS_CONTEXT_JSON='${{ toJson(secrets) }}'

echo "$VARS_CONTEXT_JSON" > vars_context.json
echo "$SECRETS_CONTEXT_JSON" > secrets_context.json

jq -s '.[0] * .[1]' vars_context.json secrets_context.json \
| jq -r 'to_entries | map(select(.key != "INSTANCE_PEM_KEY")) | map("\(.key)=\(.value)") | .[]' > .env

echo ".env file generated:"
cat .env
Comment on lines +97 to +110
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

환경 변수 로깅 보안 위험이 있습니다.

환경 변수 컨텍스트를 echo로 출력하는 것은 보안상 위험합니다.

다음과 같이 디버그 로깅을 제거하고 안전한 방식으로 변경하는 것을 권장드립니다:

- echo "VARS_CONTEXT: ${{ toJson(vars) }}"
- echo "SECRETS_CONTEXT: ${{ toJson(secrets) }}"
- echo ".env file generated:"
- cat .env
+ echo "환경 파일이 성공적으로 생성되었습니다."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "VARS_CONTEXT: ${{ toJson(vars) }}"
echo "SECRETS_CONTEXT: ${{ toJson(secrets) }}"
VARS_CONTEXT_JSON='${{ toJson(vars) }}'
SECRETS_CONTEXT_JSON='${{ toJson(secrets) }}'
echo "$VARS_CONTEXT_JSON" > vars_context.json
echo "$SECRETS_CONTEXT_JSON" > secrets_context.json
jq -s '.[0] * .[1]' vars_context.json secrets_context.json \
| jq -r 'to_entries | map(select(.key != "INSTANCE_PEM_KEY")) | map("\(.key)=\(.value)") | .[]' > .env
echo ".env file generated:"
cat .env
VARS_CONTEXT_JSON='${{ toJson(vars) }}'
SECRETS_CONTEXT_JSON='${{ toJson(secrets) }}'
echo "$VARS_CONTEXT_JSON" > vars_context.json
echo "$SECRETS_CONTEXT_JSON" > secrets_context.json
jq -s '.[0] * .[1]' vars_context.json secrets_context.json \
| jq -r 'to_entries | map(select(.key != "INSTANCE_PEM_KEY")) | map("\(.key)=\(.value)") | .[]' > .env
echo "환경 파일이 성공적으로 생성되었습니다."

EOF
ssh -S my-cicd-socket -O exit ec2-user@${{ vars.BASTION_HOST }}
rm -f private_key.pem

- name: SSH to Bastion and deploy to Production server
uses: appleboy/ssh-action@master
Expand All @@ -91,17 +119,25 @@ jobs:
username: ${{ vars.BASTION_USERNAME }}
key: ${{ secrets.INSTANCE_PEM_KEY }}
script: |
ssh -o "ProxyJump=${{ vars.BASTION_HOST }}" -i ${{ secrets.INSTANCE_PEM_KEY }} ${{ vars.INSTANCE_USERNAME }}@${{ vars.INSTANCE_HOST }} << 'EOF'
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo docker pull public.ecr.aws/f5q3r6m5/caremeet:latest
if [ $(sudo docker ps -q -f name=caremeet_server_prod) ]; then
sudo docker stop caremeet_server_prod
sudo docker rm caremeet_server_prod
if [ ! -f private_key.pem ]; then
echo "${{ secrets.INSTANCE_PEM_KEY }}" > private_key.pem
chmod 600 private_key.pem
fi
sudo docker run --name caremeet_server_prod --env-file ./app/docker/.env \
-e SPRING_PROFILES_ACTIVE=prod \
-d -p 8080:8080 public.ecr.aws/f5q3r6m5/caremeet:latest
ssh -f -N -M -S my-cicd-socket -o StrictHostKeyChecking=no -i private_key.pem -L 2222:${{ vars.INSTANCE_HOST }}:22 ec2-user@${{ vars.BASTION_HOST }}
ssh -o StrictHostKeyChecking=no -i private_key.pem -p 2222 ubuntu@localhost << 'EOF'
echo "Connected to Private Subnet productionServer via SSH Tunneling"
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo docker pull public.ecr.aws/e4z1s9l7/caremeet:latest
if [ $(sudo docker ps -q -f name=caremeet_server_prod) ]; then
sudo docker stop caremeet_server_prod
sudo docker rm caremeet_server_prod
fi
sudo docker run --name caremeet_server_prod --env-file ./app/docker/.env \
-e SPRING_PROFILES_ACTIVE=prod \
-d -p 8080:8080 public.ecr.aws/e4z1s9l7/caremeet:latest
Comment on lines +129 to +137
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

배포 프로세스 개선이 필요합니다.

현재 배포 프로세스에는 몇 가지 개선이 필요한 부분이 있습니다.

다음과 같은 개선사항을 제안드립니다:

  1. Docker 로그인 보안 강화:
- sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
+ echo "${{ secrets.DOCKER_CONFIG_JSON }}" > ${HOME}/.docker/config.json
+ sudo docker login
  1. 헬스체크 추가:
  sudo docker run --name caremeet_server_prod --env-file ./app/docker/.env \
  -e SPRING_PROFILES_ACTIVE=prod \
  -d -p 8080:8080 public.ecr.aws/e4z1s9l7/caremeet:latest
+ echo "서버 헬스체크 시작..."
+ for i in {1..30}; do
+   if curl -s http://localhost:8080/actuator/health | grep -q "UP"; then
+     echo "서버가 정상적으로 시작되었습니다."
+     exit 0
+   fi
+   echo "헬스체크 재시도 중... ($i/30)"
+   sleep 10
+ done
+ echo "서버 시작 실패"
+ exit 1
  1. 롤백 메커니즘 추가:
+ # 이전 이미지 태그 저장
+ PREVIOUS_IMAGE=$(sudo docker inspect caremeet_server_prod --format='{{.Config.Image}}')
+ 
+ # 배포 실패시 롤백
+ if [ $? -ne 0 ]; then
+   echo "배포 실패. 이전 버전으로 롤백 중..."
+   sudo docker run --name caremeet_server_prod --env-file ./app/docker/.env \
+   -e SPRING_PROFILES_ACTIVE=prod \
+   -d -p 8080:8080 ${PREVIOUS_IMAGE}
+ fi

Committable suggestion skipped: line range outside the PR's diff.

EOF
ssh -S my-cicd-socket -O exit ec2-user@${{ vars.BASTION_HOST }}
rm -f private_key.pem

- name: Remove GitHub Actions IP
run: |
Expand Down
5 changes: 4 additions & 1 deletion idle-domain/src/main/resources/application-domain.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${DB_URL:jdbc:mysql://localhost:3306/idle?serverTimezone=Asia/Seoul&characterEncoding=UTF-8}
url: ${DB_URL:jdbc:mysql://localhost:3306/caremeet?serverTimezone=Asia/Seoul&characterEncoding=UTF-8}
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:mysql}
jpa:
Comment on lines +5 to 8
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

데이터베이스 자격 증명 보안 강화 필요

민감한 데이터베이스 접속 정보가 기본값으로 설정되어 있습니다. 보안 강화를 위해 다음 사항을 고려해주세요:

  • AWS Secrets Manager나 Vault를 사용하여 자격 증명 관리
  • 기본 사용자 이름과 비밀번호 제거
  • 로컬 개발 환경에서만 기본값 사용

open-in-view: false
properties:
hibernate.format_sql: true
dialect: org.hibernate.dialect.MySQLDialect
hibernate:
ddl-auto: validate
data:
redis:
host: ${REDIS_HOST:localhost}
Expand Down
21 changes: 18 additions & 3 deletions idle-presentation/compose-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,26 @@ services:
pull_policy: always
env_file:
- .env
depends_on:
- mysql
ports:
- "8080:8080"
depends_on:
- mysql
- redis
networks:
- redis-caremeet-net
- mysql-caremeet-net

mysql:
image: mysql:8.0.33
container_name: mysql_dev
environment:
MYSQL_DATABASE: idle
MYSQL_DATABASE: caremeet
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
TZ: Asia/Seoul
ports:
- "3306:3306"
networks:
- mysql-caremeet-net
Comment on lines +24 to +32
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

MySQL 컨테이너 보안 강화 필요

MySQL 설정에 대한 보안 개선사항:

  • 볼륨 권한 설정 추가
  • 루트 사용자 대신 제한된 권한의 사용자 생성
  • MYSQL_ROOT_PASSWORD 환경 변수 대신 시크릿 사용

다음과 같이 수정을 제안합니다:

  mysql:
    image: mysql:8.0.33
    container_name: mysql_dev
+   user: "999:999"
    environment:
-     MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
+     MYSQL_RANDOM_ROOT_PASSWORD: "yes"
+     MYSQL_USER: ${DB_USER}
+     MYSQL_PASSWORD_FILE: /run/secrets/db_password
    volumes:
+     - type: volume
+       source: mysql-volume
+       target: /var/lib/mysql
+       volume:
+         nocopy: true

Committable suggestion skipped: line range outside the PR's diff.


redis:
image: redis:7.2.5
Expand All @@ -35,6 +42,14 @@ services:
volumes:
- redis-volume:/data
restart: unless-stopped
networks:
- redis-caremeet-net

networks:
mysql-caremeet-net:
driver: bridge
redis-caremeet-net:
driver: bridge

volumes:
mysql-volume:
Expand Down
Loading