EC2 인스턴스 2개로 서버 구축하기
DevOps

EC2 인스턴스 2개로 서버 구축하기

이번에 백엔드 서버를 구축하면서 Web Server - Web Application Server - DB 와 같은 구조로 구축하게 되었다.

우선, 처음에 페어인 제이온과 함께 배포를 진행할 때에는 한 인스턴스에서 모든 것을 구성해 진행했다.

즉, 한 서버에서 먼저 애플리케이션 서버를 배포한 뒤, nginx를 이용하여 Proxy를 관리하고, mysql 서버를 이용하여 내부 localhost로 db를 연결하였다.

 

이미지 출처: https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html

하지만 이 모든 과정 중 디비와 서버 인스턴스를 분리하는 것이 맞다고 판단하였고, 분리하는 과정을 글로 남겨보려 한다.

따라서 이 글은 한 인스턴스에 Web Server(Https로 바인딩해주는 Reverse Proxy) <-> Web Application Server <-> Database가 배포되어있다는 가정 하에, 데이터베이스를 떼어 내 볼 것이다.

 

Database용 인스턴스 분리하기

 

별도의 EC2(ubuntu 18.04 LTS)를 생성한 뒤, mysql-server를 설치한다. 그리고 MySQL에서 이용할 계정을 생성하면서 동시에 WAS의 Private IP에 대해 모든 권한을 부여한다. 

 

Mysql 기본 설정하기

$ sudo apt update
$ sudo apt install mysql-server

$ sudo mysql -uroot -p

# create user {MySQL 유저명}@'{WAS Server Private IP}' identified by '{MySQL 유저 password}';
# CREATE DATABASE {schema} DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
# grant all privileges on {schema}.* to {MySQL 유저명}@'{WAS Server Private IP}';
# flush privileges;

 

만약 도커를 설치해서 mysql을 실행하는 경우에는 다음과 같이 할 수 있다.

 

1. docker-compose.yml 파일을 만든 뒤 다음을 작성한다.

version: '3'
services:
  local-db:
    image: library/mysql:5.7
    container_name: {사용할 컨테이너 명}
    restart: always
    ports:
      - 13306:3306
    environment:
      MYSQL_ROOT_PASSWORD: {mysql root 사용자에게 설정할 비밀번호}
      TZ: Asia/Seoul
    volumes:
      - ./db/mysql/data:/var/lib/mysql
      - ./db/mysql/init:/docker-entrypoint-initdb.d

2. docker 명령어로 서버를 실행한다.

이 때, 앞선 docker-compose.yml 파일이 위치한 경로에서 아래 //도커 실행하기 명렁어를 수행한다.

//도커 실행하기
docker-compose up -d 

 //도커 정지하기
docker stop $(docker container ls -q)

// 도커 삭제하기
docker-compose rm -v -f
sudo rm -rf db

 

3. mysql을 실행한다.

docker exec -it {container name} bash

 

4. 위의 mysql 기본 설정하기 과정을 수행한다.

 


 

 

다음으로, mysql 설정 파일을 열어, 보안그룹에 허용되어있는 포트를 port로 설정한다. 

그리고 bind-address로 WAS 서버의 private IP를 등록한다. 0.0.0.0을 등록한다.

이 부분에 대해서는 접은글로 작성하겠다.

더보기

bind-address에 WAS의 private IP를 등록하면 mysql server를 restart할 때 에러가 발생한다. 

그 이유를 확인해보기 위해 Mysql error log를 확인해보니, 다음과 같이 나왔다.

 

 이는 WAS와 디비가 동일한 보안그룹을 이용하고 있기 때문에 우리는 디비의 포트도 8080으로 뚫어주어야했는데, 이 때 WAS의 private-ip를 bind-address로 작성하면 이미 WAS의 private IP의 8080 포트에는 바인딩된 것이 존재하기 때문에 예외가 발생하는 것이었다. 🤭

$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

-- 보안 그룹에 허용되어있는 포트로 설정
port		= 8080 [보안 그룹에 맞는 포트번호]
bind-address		= 0.0.0.0
-- 

-- 설정을 모두 완료한 뒤 mysql을 재시작한다.
$ sudo service mysql restart 

 

이제, 애플리케이션 서버의 yml 또는 properties 파일에 우리의 데이터베이스 인스턴스 아이피를 연결한다.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://{DB 인스턴스 private IP}:{mysqlconf.d에 설정한 Port}/{schema}?serverTimezone=UTC&characterEncoding=UTF-8
    username: {MySQL 계정}
    password: {MySQL 계정 비밀번호}
handlebars:
  suffix: .html
  enabled: true
security:
  jwt:
    token:
      secret-key: my_secret_is_secret
      expire-length: 3600000

 

mysql.cnf 파일의 bind-address를 db 인스턴스의 private ip로 설정해도 연결이 허용되는데 그 이유에 대해서는 https://joanne.tistory.com/178 이 글에서 자세히 다루겠다.