목표

GCP의 Compute Engine과 Cloud SQL을 이용해서 SpringBoot 프로젝트 서버 구축하기

 

준비

1. 빌드된 SpringBoot 프로젝트 (*.jar 파일)

 

방법

1. Google Cloud Platform의 새로운 계정을 만들어서 프리티어 이용하기

 

2. 사용할 Project 선택하기

링크 => https://console.cloud.google.com/

 

3. Cloud SQL로 데이터베이스 만들기

3-1. 메뉴에서 SQL 메뉴로 이동

 

3-2. Cloud SQL 인스턴스 만들기

 

Create a PostgreSQL instance
Create a PostgreSQL instance

CREATE INSTANCE 버튼을 누르면 완료

(이후 인스턴스 생성되는 시간이 꽤 걸리므로 4. Compute Engine에서 VM 인스턴스 만들기를 먼저해도 됨)

 

3-3. 유저 만들기

SpringBoot 프로젝트에서 데이터베이스 연결할 username과 password 생성

 

3-4. 데이터베이스 만들기

 

3-5. 외부에서 데이터베이스 접속가능하게 하기

모든 네트워크에서 접속가능하게 하려면 0.0.0.0/0을 입력한다

특정 네트워크만 허용해도 된다

Save 누르면 완료

 

4. Compute Engine에서 VM 인스턴스 만들기

4-1. 인스턴스 생성하기

Create Instance
Create Instance
Create Instance
Create Instance

CREATE 버튼을 누르면 완료

 

4-2. VM 인스턴스의 고정 IP 주소 만들기

현재는 외부/내부 임시 IP로 구성되어 있으므로 외부 고정 IP를 만든다 

 

Reserve 버튼을 누르면 완료

 

4-3. 포트(Port) 열어주기

SpringBoot의 기본 포트인 8080을 열어준다

Create a Firewall Rule
Create a Firewall Rule

Create 버튼 누르면 완료

 

5. SSH Key 발급하고 VM Instance에 등록하기

1. SSH KEY 발급하는 방법 => https://cloud.google.com/compute/docs/connect/create-ssh-keys?hl=ko#linux-and-macos

2. SSH Key 중에 .pub으로 끝나는 파일의 내용을 복사한다

3. 다음으로

Save 누르면 완료

 

6. VSCode에서 SSH로 VM 인스턴스에 연결하기

 

7. VM 인스턴스에서 SpringBoot 실행하기

1. api 폴더(아무 이름의 폴더)를 만듭니다.

2. SpringBoot를 빌드한 파일과 application.properties 또는 application.yml을 옮깁니다.

(이 환경 설정 파일에서 database 관련 설정을 Cloud SQL에서 만들었던 정보들로 수정)

spring.datasource.url=jdbc:postgresql://[Cloud Sql Instance의 Public IP]/[만든 데이터베이스 이름]?useSSL=false&characterEncoding=UTF-8
spring.datasource.username=[만든 유저 이름]
spring.datasource.password=[만든 유저 비밀번호]

3. 터미널에서 api 폴더로 이동한 합니다.

4. SpringBoot를 백그라운드에서 중단 없이 실행하는 명령어를 입력합니다.

nohup java -jar [빌드파일이름].jar &

 

문제

로컬에서는 bean이 내가 생각한 대로 실행된다. 그래서 firebase 초기화를 한 부분이 실행 되고 firebase를 사용하는 service 부분이 다음으로 실행되기 때문에 에러가 나지 않는다.

 

그런데 App Engine에 배포를 하니 @PostConstructor 어노테이션을 붙인 firebase 초기화 코드가 먼저 실행되지 않고 service 부분이 먼저 실행돼서 계속 에러가 난다는 것을 알게 됐다.

 

해결

1. FirebaseConfig 클래스에 @Order(1) 어노테이션을 붙인다.

2. 그리고 그 다음으로 실행되는 클래스인 FirebaseStorageService 클래스에 @DependsOn("firebaseConfig")를 붙여서 FirebaseConfig에 의존한 클래스라는 것을 명시한다.

3. 그리고 그 다음으로 실행되는 클래스인 BoardService 클래스에 @DependsOn("firebaseStorageService")를 붙여서 FirebaseStorageService에 의존한 클래스라는 것을 명시한다.

 

*주의점은 @DependsOn(" ") 이곳에 들어가는 값이 클래스 명이 아니라 빈의 이름을 쓴다고 한다. 그렇기에 파스칼 케이스가 아닌 카멜 케이스로 쓴다.

 

위 처럼 작성하면 App Engine에서도 문제 없이 순서대로 실행되는 것 같다.

참고

 

https://stackoverflow.com/questions/40762475/what-is-the-difference-between-google-compute-engine-app-engine-and-container-e


Cloud Functions (FaaS) 응용 계층을 추상화하고 원자력 서비스 호출을 위한 제어 표면을 제공합니다.

App Engine (PaaS) 인프라스트럭처를 추상화하고 애플리케이션 계층에서 제어 표면을 제공합니다.

Kubernetes Engine (CaaS) VM을 추상화하고 kubernetes 클러스터 및 호스트된 컨테이너를 관리하기 위한 제어 영역을 제공합니다.

Compute Engine (IaaS) 기본 하드웨어를 추상화하고 인프라 구성 요소에 대한 제어 영역을 제공합니다.

  • App Engine 표준: 제한된 런타임(Python, Java, PHP, Go), 매우 간단한 시작 및 실행, 자동 확장 등. App Engine용으로 특별히 설계된 집중 API입니다.
  • App Engine 유연성: 컨테이너에 넣을 수 있는 모든 것, 자동 확장 등
  • 컨테이너 엔진: 마이크로 서비스 측면에서 애플리케이션을 설계하고 확장 방법 등을 지정하지만 컨테이너 엔진( Kubernetes 의 Google Cloud Platform 구현 )이 확장을 수행하도록 합니다.
  • Compute Engine: 기본적으로 이점이 있는 호스팅된 VM입니다. 실시간 마이그레이션, 관리형 인스턴스 그룹 내 자동 크기 조정과 같은 일부 기능은 위의 기능보다 훨씬 "베어메탈"에 가깝습니다.

'베어메탈(Bare Metal)'이란 용어는 원래 하드웨어 상에 어떤 소프트웨어도 설치되어 있지 않은 상태를 뜻합니다. 즉, 베어메탈 서버는 가상화를 위한 하이퍼바이저 OS 없이 물리 서버를 그대로 제공하는 것을 말합니다. 따라서 하드웨어에 대한 직접 제어 및 OS 설정까지 가능합니다.

 

App Engine Standard는 '0으로 확장'을 지원합니다. 즉, 앱에 트래픽이 발생하지 않으면 완전히 휴면 상태가 될 수 있습니다. 따라서 취미 프로젝트를 위한 훌륭한 환경이 됩니다.

1. [App Engine에서 Node.js 앱 빌드] 를 따라서 설치와 설정 등을 해준다.

https://cloud.google.com/appengine/docs/standard/nodejs/building-app?hl=ko 

 

App Engine에서 Node.js 앱 빌드  |  Google App Engine 표준 환경 문서  |  Google Cloud

의견 보내기 App Engine에서 Node.js 앱 빌드 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 가이드를 활용하면 App Engine을 시작하고 앱 배포 및 관리에 익숙해

cloud.google.com

2. 공개 IP Cloud SQL 인스턴스 만들기

https://cloud.google.com/sql/docs/postgres/connect-instance-app-engine?hl=ko#expandable-1 

 

App Engine 표준 환경에서 PostgreSQL용 Cloud SQL에 연결  |  Google Cloud

Google Cloud 콘솔을 사용하여 PostgreSQL 인스턴스에 연결된 App Engine 표준 환경에 샘플 앱을 배포하는 방법을 알아봅니다.

cloud.google.com

3. Cloud SQL Node.js Connector로 PostgreSQL 정의하기.

https://github.com/GoogleCloudPlatform/cloud-sql-nodejs-connector#using-with-postgresql

 

GitHub - GoogleCloudPlatform/cloud-sql-nodejs-connector: A JavaScript library for connecting securely to your Cloud SQL instance

A JavaScript library for connecting securely to your Cloud SQL instances - GitHub - GoogleCloudPlatform/cloud-sql-nodejs-connector: A JavaScript library for connecting securely to your Cloud SQL in...

github.com


3번 설명)

GCP의 Cloud SQL 문서에서 보면 [App Engine 표준 환경에서 연결]

이렇게 두가지 방법을 소개한다.

먼저 Unix 소켓 예제를 보면 knex를 사용하여 postgresql을 연결하는 코드가 설명되어 있다.

이것의 단점은

1. 원래 postgresql 연결에 사용했던 pg 모듈이 아니기 때문에 코드를 바꿔야하고

2. 무엇보다 local에서는 쉽게 작동이 되는데 gcp에 배포했을 때는 안됐다. 데이터베이스 설정 부분이 문제가 있을 것 같다.

 

그래서 두번째 방법인 Cloud SQL Connector로 결국 연결에 성공하였다.

3번의 링크에 들어가면 예제가 있다. 아래는 데이터베이스 연결부분만 따로 파일을 만든 것이다.(db.js)

또, Connector 부분만 추가되어서 pg 문법을 그대로 사용하면 된다. 바꿀 것이 없다.

import pg from "pg";
import { Connector } from '@google-cloud/cloud-sql-connector';
const { Pool } = pg;

const connector = new Connector();
const clientOpts = await connector.getOptions({
  instanceConnectionName: process.env.INSTANCE_UNIX_SOCKET,
  ipType: 'PUBLIC', 
});

const dbConfig = {
  ...clientOpts,
  user: process.env.PG_USER,
  password: process.env.PG_PASSWORD,
  database: process.env.PG_DATABASE,
};

const client = new Pool(dbConfig);

export default client;

그리고 process.env.~는 dotenv에 정의하지 않고 1번에서 만들었던 app.yaml 파일에 정의한다.

runtime: nodejs16

env_variables:
  INSTANCE_UNIX_SOCKET: 
  PG_USER: 
  PG_PASSWORD: 
  PG_DATABASE:

SQL > 개요

INSTANCE_UNIX_SOCKET 위 이미지의 연결이름 부분을 복사해서 그대로 적으면 된다.

user와 database name을 잘 모르겠다면 각각의 탭에 들어가서 확인할 수 있는데 기본적으로 postgres로 설정이 되어있었다.

 

출처

https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html 


가상 머신 → 리눅스 컨테이너 → 도커

가상 머신 Virtual Machine

  • 기존의 가상화 방식인 OS 가상화 (호스트 OS위에 게스트 OS전체를 가상화하여 사용하는 방식)
  • 예를들어 리눅스에서 윈도우를 쓸 수 있다
  • 무겁고 느려서 운영환경에선 사용할 수 없다
  • OS가상화를 개선하기 위해 CPU 가상화 기술인 HVM을 이용한 Kernel-Based virtual Machine과 반가상화 Paravirtualization 방식의 Xen이 등장
  • 이 기술들은 OpenStack이나 AWS, Rackspace 같은 클라우드 서비스에서 가상 컴퓨팅 기술의 기반이 되었다.

리눅스 컨테이너

  • 전가상화든 반가상화든 성능문제가 있어서 이를 개선한 프로세스를 격리하는 방식이 등장
  • CPU나 메모리 사용량을 제한할 수 있고 호스트의 특정 포트와 연결하거나 호스트의 특정 디렉토리를 내부 디렉토리인 것처럼 사용할 수도 있다.
  • 도커는 리눅스 컨테이너(LXC)를 기반으로 시작해서 0.9버전에서는 자체적인 libcontainer 기술을 사용하였고 추후 runC기술에 합쳐졌습니다.

도커 Docker: 컨테이너 기반의 오픈소스 가상화 플랫폼

이미지

  • 도커에서 가장 중요한 개념은 컨테이너와 이미지
  • 컨테이너 실행에 필요한 파일과 설정값 등을 포함하고 있는 것
  • 상태값을 가지지 않고 변하지 않는다 Immutable
  • 추가되거나 변하는 값은 컨테이너에 저장된다
  • 같은 이미지에서 여러개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 변하거나 삭제되어도 이미지는 그대로이다.
  • 새로운 서버가 추가되면 미리 만들어 놓은 이미지를 다운받고 컨테이너를 생성하면 된다 (한 서버에 여러개의 컨테이너 가능)

컨테이너 Container

  • 다양한 프로그램, 실행환경을 컨테이너로 추상화하고 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 한다.
  • 백엔드 프로그램, 데이터 베이스 서버, 메세지 큐 등 어떤 프로그램도 컨테이너로 추상화 될 수 있다.
  • 시스템의 나머지 부분과 격리된 프로세스 세트
  • 소프트웨어 서비스를 실행하는 데 필요한 특정 버전의 프로그래밍 언어 런타임 및 라이브러리와 같은 종속 항목과 애플리케이션 코드를 함께 포함하는 경량 패키지
  • 컨테이너는 Linux, Windows, Mac 등의 운영체제를 가리지 않고, 가상 머신, 물리적 서버, 개발자 컴퓨터, 데이터 센터, 온프레미스 환경, 퍼블릭 클라우드 등 사실상 어느 환경에서나 구동되므로 개발 및 배포가 크게 쉬워집니다.
  • 컨테이너는 OS 수준에서 가상화되고 VM은 하드웨어 수준에서 가상화됩니다.
  • 이미지Image를 실행한 상태로 응용프로그램의 중속성과 함께 응용프로그램 자체를 패키지이 or 캡슐화하여 격리된 공간에서 프로세스를 동작시키는 기술이다.
  • 조립PC, AWS, Azure, Google cloud 등 모두 실행할 수 있다.

레이어

  • 도커는 유니온 파일 시스템을 이용하여 여러개의 레이어를 하나의 파일 시스템으로 사용할 수 있게 한다.
  • 이미지는 여러개의 읽기 전용read only 레이어로 구성되고 파일이 추가나 수정되면 새로운 레이어가 생성된다.
  • 컨테이너를 생성할 때도 기본의 이미지 레이어 위에 읽기-쓰기read-write 레이어를 추가한다. 컨테이너가 샐행중에 생성하는 파일이나 변경된 내용은 읽기-쓰기 레이어에 저장되므로 여러개의 컨텐이너를 생성해도 최소한의 용량만 사용한다

+ Recent posts