24시간 작동하는 서버 만드는 방법
- 집에 PC를 24시간 구동시킨다
- 호스팅 서비스(cafe 24 등)를 이용
- 클라우드 서비스(AWS, AZURE, GCP 등) 이용
- 비용은 호스팅 서비스나 집 pc를 이용하는 것이 저렴
- 특정 시간에만 트래픽이 몰린다면 유동적으로 사양을 늘릴 수 있는 클라우드가 유리함
📙 1. 클라우드 서비스
인터넷(클라우드)을 통해 서버, 스토리지(파일 저장소), 데이터베이스, 네트워크, 소프트웨어, 모니터링 등 컴퓨팅 서비스를 제공하는 것
- AWS의 EC2는 서버 장비를 대여하는 것이지만, 실제로는 그 안의 로그 관리, 모니터링, 하드웨어 교체, 네트워크 관리 등을 기본적으로 지원하고 있음
- IaaS
Infrastructure as a Service
- 기존 물리 장비를 미들웨어와 함께 묶어둔 추상화 서비스
- 가상머신, 스토리지, 네트워크, 운영체제 등의 IT인프라를 대여해 주는 서비스라고 보면 된다.
- AWS의 EC2, S3 등
- PaaS
Platform as a Service
- IaaS에서 한 번 더 추상화한 서비스
- 한 번 더 추상화했기 때문에 많은 기능이 자동화되어있다.
- AWSd의 Beanstalk, Heroku 등
- SaaS
Software as a Service
- 소프트웨어 서비스
- 구글 드라이브, 드롭박스 등
IaaS를 사용하는 이유
PaaS인 Beanstalk이용시 대부분 작업이 간소화되지만, 프리티어로 무중단 배포가 불가능하다.
아마존 EC2 사용해 리눅스1 서버 생성시 해야 할 설정
- Java 8 설치(맞는 자바 버전 설치)
- 타임존 변경 : 기본 서버의 시간은 미국 시간대
- 호스트 네임 변경 : 현재 접속한 서버의 별칭 등록. 실무에서는 한 대의 서버가 아닌 수십대의 서버가 작동 → IP만으로 어떤 서버가 어떤 역할을 하는지 알 수 없음. 이를 구분하기 위해 보통 호스트 네임을 필수로 등록.
📙 2. AWS RDS : AWS에 데이터베이스 환경을 만들기
- RDS : 직접 데이터베이스를 설치하지 않고, 클라우드 기반 관계형 데이터베이스
- 하드웨어 프로비저닝, 데이터베이스 설정, 패치 및 백업과 같이 잦은 운영 작업을 자동화하여 개발자가 개발에 집중할 수 있게 지원하느 서비스
- 조정가능한 용량을 지원하여 예상치 못한 양의 데이터가 쌓여도 비용만 추가로 내면 정상적으로 서비스가 가능한 장점도 있음
MySQL, MariaDB, PostgreSQL을 사용하는 이유
- Oracle, MSSQL보다 MySQL, MariaDB, PostgreSQL이 동일한 사양대비 가격이 저렴하다.
- Amazon Aurora로 교체하기 쉽다.
- Amazon Aurora 는 AWS에서 MySQL과 PostgreSQL을 클라우드 기반에 맞게 재구성한 데이터베이스인데, AWS에서 직접 엔지니어링하고 있기 때문에 계속해서 발전하고 있다. 성능이 기존 RDS MySQL대비 5배, RDS PostgreSQL보다 3배로 제공된다. 하지만, 프리티어 대상이 아니고 최저 비용이 월 10만원 이상이다.
MariaDB
- 단순 쿼리 처리 성능이 압도적이다.
- MySQL을 기반으로 만들어졌기 때문에 쿼리를 비롯한 전반적인 사용법은 MySQL과 유사하다.
- MySQL보다 MariaDB가 가진 장점
- 동일 하드웨어 사양으로 MySQL보다 향상된 성능
- 좀 더 활성화된 커뮤니티
- 다양한 기능
- 다양한 스토리지 엔진
💁♂️ 3. EC2 서버에 프로젝트 배포
(1) EC2 프로젝트에 깃을 설치하고, 내 레포를 clone받기
(2) 배포 스크립트 만들기 (vim)
git clone
또는git pull
을 통해 새 버전의 프로젝트를 받음- Gradle이나 Maven을 통해 프로젝트 테스트와 빌드
- EC2 서버에서 해당 프로젝트 실행 및 재실행
(3) 외부 Security 파일 등록
- 외부 Security파일은 .gitignore로 git 제외대상이라 깃허브에 올라가 있지 않기 때문에 서버가 그 설정들을 직접 가지고 있게 만듦.
(4) 스프링 부트 프로젝트로 RDS 접근하기
- 테이블 생성
- 프로젝트 설정 : 자바 프로젝트가 MariaDB에 접근하려면 데이터베이스 드라이버가 필요하다. MariaDB에서 사용 가능한 드라이버를 프로젝트에 추가
- EC2 (리눅스 서버) 설정 : 데이터베이스 접속 정보는 중요하게 보호해야 할 정보. 공개되면 외부에서 데이터를 모두 가져갈 수 있기 때문. EC2 서버 내에서 접속 정보를 관리하도록 설정해야 함.
💁♂️ 4. Travis CI 배포 자동화: 코드가 푸시되면 자동으로 배포하기
테스팅 자동화까지 가능한, 배포 자동화 방법
CI/CD
- CI
Continuous Integration
: 지속적 통합. 코드버전 관리를 하는 VCS시스템(git, svn 등)에 Push가 되면 자동으로 테스트와 빌드가 수행되어 안정적인 배포 파일을 만드는 과정 - CD
Continuous Deployment
: 지속적 배포. 비륻 결과를 자동으로 운영 서버에 무중단 배포까지 진행하는 과정
CI/CD가 등장한 배경
- 여러 개발자가 작성한 코드를 합칠 때마다 병합일(code merge 하는 날)을 정하여 개발한 코드를 합치는 일을 진행했다.
- 수작업은 생산성이 좋지 않았고, 개발자들은 개발에만 집중하지 못했다
- CI/CD의 필요성이 대두되었다.
CI의 4가지 규칙 (마틴 파울러)
- 모든 소스 코드가 살아 있고, 누구든 현재의 소스에 접근할 수 있는 단일 지점을 유지할 것
- 빌드 프로세스를 자동화해서 누구든 소스로부터 시스템을 빌드하는 단일 명령어를 사용할 수 있게 할 것
- 테스팅을 자동화해서 단일 명령어로 언제든지 시스템에 대한 건전한 테스트 수트를 실행할 수 있게 할 것
- 누구나 현재 실행 파일을 얻으면 지금까지 가장 완전한 실행 파일을 얻었다는 확신을 하게 할 것
Travis CI
- 깃허브에서 제공하는 무료 CI 시스템
- 젠킨스도 CI도구지만, 설치형이기 때문에 이를 위한 EC2인스턴스가 하나 더 필요하다.
💁♂️ 5. Travis CI와 AWS S3 연동하기
S3: AWS에서 제공하는 일종의 파일 서버
- 이미지 파일을 비롯한 정적 파일을 관리하거나, 배포 파일들을 관리하는 등의 기능 지원
- 보통 이미지 업로드를 구현하면 S3를 이용하여 구현하는 경우가 많음.
- 실제 배포는 AWS CodeDeploy 서비스를 이용하지만, S3 연동을 해서 Jar파일을 전달해야 한다.
CodeDeploy
- 저장 기능이 없다.
- Travis CI가 빌드한 결과물을 받아서 CodeDeploy가 가져갈 수 있도록 보관할 수 있는 공간이 필요하다 → AWS S3이용
- 빌드도 하고 배포도 할 수 있다. 깃허브 코드를 가져오는 기능을 지원하기 때문.
- 하지만 이렇게 할 때는 빌드 없이 배포만 필요할 때 대응하기 어렵다.
- 빌드와 배포가 분리되어 있으면 예전에 빌드되어 만들어진 Jar를 재사용하면 되지만, CodeDeploy가 모든 것을 하게 될 때는 항상 빌드를 하게 되니 확장성이 많이 떨어진다.
구조
Github
→
Travis CI
→ 1. jar 전달 AWS S3
→ 3. jar 전달 AWS CodeDeploy
→ 2. 배포 요청 AWS CodeDeploy
→ 4. 배포 AWS EC2
→ Spring Boot
(EC2 인스턴스 내부) ⬅️ 사용자
24365 중단 없는 서비스 만들기
Travis CI활용시 배포하는 동안 애플리케이션이 종료된다.
새로운 Jar가 실행되기 전까진 기존 Jar를 종료시켜 놓기 때문에 서비스가 중단된다.
- 무중단 배포 방식
- AWS에서 Blue-Green 무중단 배포
- 도커를 이용한 웹서비스 무중단 배포
- L4 스위치 (고가의 장비)
💁♂️ 6. Nginx를 이용하기
- Nginx: 웹 서버, 리버스 프록시, 캐싱, 로드 밸런싱, 미디어 스트리밍 등을 위한 오픈소스 소프트웨어
- 아파치가 대세였던 자리를 빼앗은 가장 유명한 웹 서버이자 오픈소스
- 가장 저렴하고 쉽다. 고성능 웹서버다.
- 리버스 프록시: 엔진엑스가 외부의 요청을 받아 백앤드 서버로 요청을 전달하는 행위
- 요청을 전달하면 실제 요청에 대한 처리는 뒷단의 웹 애플리케이션 서버들이 처리한다.
구조
- 하나의 EC2혹은 리눅스 서버에 Nginx 1대와 스프링부트 Jar 2대를 사용한다.
- Nginx는 80
http
, 443https
포트 할당 - 스프링 부트1은 8081 포트로 실행
- 스프링 부트2는 8082 포트로 실행
Github
→
Travis CI
→ 1. jar 전달 AWS S3
→ 3. jar 전달 AWS CodeDeploy
→ 2. 배포 요청 AWS CodeDeploy
→ 4. 배포
AWS EC2
→ Spring Boot
8081 (EC2 인스턴스 내부) ⬅️ Nginx
80, 443 (EC2 인스턴스 내부) ⬅️ 사용자
AWS EC2
→ Spring Boot
8082 (EC2 인스턴스 내부) ⬅️ Nginx
80, 443 (EC2 인스턴스 내부) ⬅️ 사용자
운영과정
- 사용자는 서비스 주소로 접속 (80혹은 443포트)
- 엔진엑스는 사용자의 요청을 받아 현재 연결된 스프링 부트로 요청 전달 (부트1이 있는 8081포트로 요청한다고 가정)
- 스프링 부트2는 엔진엑스와 연결된 상태가 아니니 요청받지 못함.
- 스프링 부트2(8082포트)로 새로운 버전 배포
- 배포하는 동안에도 서비스는 중단되지 않는다. 엔진엑스는 스프링 부트1을 바라보기 때문
- 배포가 끝나고 스프링 부트2가 정상적으로 구동 중인지 확인
- 스프링 부트2가 정상 구동 중이면 nginx reload 명령어를 통해 8081대신 8082를 바라보도록 함
- nginx reload는 0.1초 내에 완료됨
- 스프링 부트1의 배포가 끝났다면 엔진엑스가 스프링부트 1을 바라보도록 변경하고 nginx reload실행
- 이후 요청부터는 엔진엑스가 스트링 부트 1로 요청을 전달