기타/인프라 구축과정

[Infra] 10. 최종 아키텍처 - HelloWorld Project

배발자 2023. 6. 5.
반응형

 

 

 

 

개발자 개인 브랜치에서 Remote 환경의 Develop 브랜치에 Merge를 하게 되면 자동으로 빌드가 진행된다. 

해당 빌드는 깃랩의 WebHook 설정과 젠킨스 설정을 통해 이루어진다. 

 

 

[Back]

 

1. 백엔드 개발자가 Develop-BE로 Merge를 진행한다. 해당 브랜치에는 Back 프로젝트만 존재한다.

 

2. 젠킨스에서 깃랩에 Merge된 Develop-BE 브랜치의 프로젝트 파일들을 빌드한다. 

 

 2-1. MainAPI : 서버에 존재하는 .yml 파일을 통합시켜 빌드를 진행한다. jar 파일이 생성되면 배포 폴더로 이동.

 2-2. Noitfy : 서버에 존재하는 .yml 파일을 통합시켜 빌드를 진행한다. jar 파일이 생성되면 배포 폴더로 이동. 

 2-3. Story : 서버에 존재하는 .yml 파일을 통합시켜 빌드를 진행한다. jar 파일이 생성되면 배포 폴더로 이동.  

 

3. 빌드 작업이 완료되면 자동으로 배포 작업이 진행된다. 

 

 3-1. MainAPI : 배포 폴더에 존재하는 Dockerfile을 기반으로 이미지를 빌드하고 도커 허브에 푸쉬.

 3-2  MainAPI : deploy.sh 쉘 스크립트를 통해 Blue-Green 무중단 배포를 진행한다. 

 3-1. Noitfy : 배포 폴더에 존재하는 Dockerfile을 기반으로 이미지를 빌드하고 도커 허브에 푸쉬.

 3-2  Noitfy : deploy.sh 쉘 스크립트를 통해 Blue-Green 무중단 배포를 진행한다. 

 3-1. Story : 배포 폴더에 존재하는 Dockerfile을 기반으로 이미지를 빌드하고 도커 허브에 푸쉬.

 3-2  Story : deploy.sh 쉘 스크립트를 통해 Blue-Green 무중단 배포를 진행한다. 

 

4. 사용하지 않는 모든 Docker 이미지를 강제로 삭제한다. 

 

[Front]

 

1. 프론트 개발자가 Develop-FE Merge를 진행한다. 이때는 배포환경에서 아무런 변화가 없다. 

 

Develop-BE 브랜치로 Back 코드가 병합될 때마다 EC2 서버에 웹 애플리케이션 서버 컨테이너 3개가 배포된다. 프론트는 로컬에서 배포된 컨테이너로 API 통신이 이루어진다. 즉, 로컬에서 작업을 편리하게 하기 위함이다. 

 

2. Develop-BE와 Develop-FE 브랜치의 내용물들이 Develop 브랜치로 Merge를 진행한다. 

 

3. 젠킨스에서 깃랩에 Merge된 Develop 브랜치의 프로젝트 중 프론트 파일들만 빌드한다.  

 

 3-1. Vue : 서버에 존재하는 env 파일을 통합시켜 빌드를 진행한다. 빌드된 dist 폴더를 배포 폴더로 이동. 

 

4. 빌드 작업이 완료되면 자동으로 배포 작업이 진행된다. 

 

 4-1.  Vue : 배포 폴더에 존재하는 Dockerfile을 기반으로 이미지를 빌드하고 도커 허브에 푸쉬.

 4-2   Vue : deploy.sh 쉘 스크립트를 통해 Blue-Green 무중단 배포를 진행한다. 

 

5. 사용하지 않는 모든 Docker 이미지를 강제로 삭제한다. 

 

 

 

"Zero-Downtime Deployment Enviroment"

 

 

기본적으로 Blue-Green 무중단 배포 서비스를 진행하는데 Java, Vue 모두 동일한 프로세스로 진행된다.

현재 Blue 컨테이너가 존재하지 않으면 Blue 컨테이너를 생성한다. 만약, Blue 컨테이너가 존재하면 Green 컨테이너를 생성한다. 새로운 컨테이너가 제대로 떴는지 확인 후, 이전 컨테이너를 종료한다. 

 

 

사용자 요청

 

1. 사용자가 배포된 도메인으로 URL을 입력한다. 

2. 도메인:80 포트는 기본적으로 생략되어있기 때문에 서버의 Nginx에서 80 포트를 받는다.  

3. HTTP 요청은 HTTPS로 리다이렉션되며 upstream 설정을 통해 가장 적은 연결 수가 있는 서버로 요청을 보낸다. 

 

 

포트포워딩 상세

 

"도메인/" 요청이 오면 Vue 서버로 포트포워딩 한다.

"도메인/api" 요청이 오면 MainAPI 서버로 포트포워딩 한다.

"도메인/notify" 요청이 오면 Notify 서버로 포트포워딩 한다. 

"도메인/story" 요청이 오면 Story서버로 포트포워딩 한다. 

 

Vue Container (Blue-Green)
- 0.0.0.0:3000 -> 80
- 0.0.0.0:3001 -> 80

Back(MainAPI) Container
 (Blue-Green)

- 0.0.0.0:8081 -> 8080
- 0.0.0.0:8082 -> 8080

Notify Container (Blue-Green) 
- 0.0.0.0:8085 -> 8080
- 0.0.0.0:8086 -> 8080

Story Container (Blue-Green) 
- 0.0.0.0:8087 -> 8080
- 0.0.0.0:8088 -> 8080

 


 

Vue Container는 사실상 Vue 파일들이 빌드된 정적 파일이 저장된 Nginx Container이다. 

이해하기 어려울 수 있는데, 예를 들면 "http://도메인명/"의 url로 입력하여 접속하였다고 가정하자. 

현재 "도메인/" 요청이 왔으니 Vue 서버로 포트포워딩될 것이다. 

 

그러면 "도메인:3000 -> 80" (현재 3000:80 컨테이너가 구동 중이라고 가정.)으로 포트 포워딩이 진행되는데, 

컨테이너의 80번 포트에 연결한다. 

 

Vue Container의 /etc/nginx/conf.d/helloworld.conf에 다음과 같이 설정되어있다. 

server {
  listen 80;

  location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
}

 

컨테이너의 80번 포트로 요청이 오면 빌드된 정적 파일의 index.html을 띄워주는 것이다. 

 

1.  "http://도메인:3000" 으로 요청이 들어오면 바로 FrontContainer의 80번 포트에 연결

2. "http://도메인:80 (포트생략가능)" 으로 요청이 들어오면 Nginx에서 https로 변환 후 도메인:3000으로 요청. 1번 과정이 진행.  

 

여기서 Nginx가 존재하는 서버에서 다시 한 번 같은 서버로의 도메인:3000 포트의 요청 흐름이 이해하기 어려울 수 있지만 만약 Nginx가 외부 세상에 존재한다면 조금 이해가 쉬울 것이다. 

 

필자의 프로젝트에서는 서버 한 대를 이용해 배포를 진행하지만, 실제 현업에서는 여러대의 서버를 둔다. Nginx 또한 하나의 서버로 구축되어있다고 한다. 즉, A 서버(Nginx)에서 사용자의 요청을 받으면 A 서버(Nginx)는 리버스 프록시 역할을 통해 B 서버로 전달하게 되는 것이다. 

 

필자의 프로젝트에서는 A 서버(Nginx)에서 사용자의 요청을 받으면 A 서버로 다시 요청하는 것으로 프로세스가 진행된다. 

 

반응형

댓글