오늘은 GCP 무료 요금제를 이용해서 간단하게 배포를 해 보고, 후에 CI/CD 및 container 개념을 배우면서 실습을 진행할 간단한 프로젝트를 준비해보자.
리전은 간단하게 해볼 것 이기 때문에 가장 저렴한 아이오와로 선택하였다. 꽤나 느리지만 그래도 공부용이기 때문에..선택
ssh 접속을 위한 key를 생성.. 아래는 샘플 이미지 이다..
cloud 에 ssh key 등록 하자.
private key로 저장해서.. putty 로그인 할 때 마다 사용하도록 하자.
나는 2개의 클라우드를 이용할거고
A 클라우드 에서는 spring boot server 를 돌리고
B 클라우드 에서는 react 프로젝트와 DB를 올려놓을 것 이다.
서버 배포를 위해서 일단 필요한 모듈먼저 다운 받도록 하자.
sudo apt-get install git
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
nvm install 18.18.0
source ~/.bashrc
sudo apt-get install openjdk-17-jdk
그 후 간단히 post 와 get을 하는 서버 프로젝트를 하나 만들고.. git 프로젝트를 올린 후 서버배포용 클라우드에서 clone을 받고 jar로 패키징을 하였다.
서버를 키는 script 작성
sudo java -jar -Dspring.profiles.active=prod demo-0.0.1-SNAPSHOT.jar > ../logs/app.out 2> ../logs/app.err &
서버 프로세스를 종료하는 script 작성
sudo kill -9 $(ps -ef | grep 'java -jar' | grep -v grep | awk '{print $2}')
이후 이 클라우드에선 서버를 계속 돌리고 있을 것 임..
프로젝트는 /api/v1/demo 의 entry로 get 과 post 만 만들어놓았음.
CrossOrigin 은 test 할 때만 * 로 해놓고 나중에 접근하는쪽만 걸어놓을 것임.
설치는 이 링크를 보고 하였음.
wget https://dev.mysql.com/get/mysql-apt-config_0.8.26-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.26-1_all.deb
sudo apt-get update
첫번째 옵션선택 에서 OK를 눌러주고 비밀번호 설정 후 설치 마침.
-- 유저 생성
CREATE USER 'test'@'%' identified by '1234';
-- 권한 주기
grant all privileges on *.* to 'test'@'%';
-- 권한 적용
flush privileges;
axios.defaults.baseURL = process.env.NODE_ENV === 'development' && 'http://localhost:8001'; 를 이용해서..
npm start를 켯을 땐 development 이고 build 를 치면 production 으로 돌아가기 때문에..
build 를 하면 production 으로 되면서 위의 조건에 부합하지 않기 때문에 현재 url이 axios default주소에 꽂히게 된다.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
axios.defaults.baseURL = process.env.NODE_ENV === 'development' && 'http://localhost:8001';
const FormList = (props) => {
const [demos, setDemos] = useState([]);
useEffect(() => {
axios.get('/api/v1/demo')
.then(response => {
setDemos(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
}, [props.observer]);
return (
<div className="form-list">
<h2>Form List</h2>
<ul>
{demos.length != 0 ? demos.map(demo => (
<li key={demo.id}>
<strong>{demo.name}</strong>: {demo.description}
</li>
)) : <p>데이터 없음</p>}
</ul>
</div>
);
};
export default FormList;
이 프로젝트도 마찬가지로 git 으로 B클라우드 쪽으로 옮겨놓고 build 를 하고.. was로 사용 할 nginx를 먼저 설치하였다.
nginx 에 대한 자세한 내용은 추후에 공부하면서 포스팅 하도록 하고 오늘은 nginx를 이용해서 내 외부 ip주소로 접근했을 때 보여줄 index.html 과 proxy_pass 와 load_balancer 정도만 접근해보자..
설치 - sudo apt install nginx
nginx 작업상태 확인 - sudo systemctl status nginx
사용중인 포트확인 - netstat -napt
80포트가 이미 사용중이었음 확인해보니 apache2 http가 포트를 먹고 있었음
apache2 종료 - sudo systemctl stop apache2
nginx 다시 실행 - sudo systemctl start nginx
여기까지 완료되면 원래 예전에는 nginx 기본 페이지가 떳는데
나는 Apache2 Debian Default Page가 나옴
/etc/nginx/sites-available/default 에 default 설정들이 되어있고 안에 무슨 내용이 있는지 둘러보자
node-java-mysql-git-1@node-java-mysql-git-1:/etc/nginx/sites-available$
node-java-mysql-git-1@node-java-mysql-git-1:/etc/nginx/sites-available$ cat default
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
- 내 외부 ip 접속 시 보여주는 index.html 이 들어있음.
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
크게 엄청난 설정은 없는 것 같다..
따라서 내 nginx.conf 를 조금 custom 해주자..
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
// 이 부분이 default 설정을 쓴다는 import 인데 주석하고
밑에 server 블록을 추가해 overide 하자..
#include /etc/nginx/conf.d/*.conf;
#include /etc/nginx/sites-enabled/*;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location / {
// front 패키지 build 추출물을 이 경로로 보낼거임.
root /etc/shere/html;
index index.html index.htm index.nginx-debian.html;
}
location /api/v1/demo {
// 밑의 그림에서 설명
proxy_pass http://10.128.0.4:8001;
}
}
}
원래는 밑의 그림처럼 data 가 받고 싶다면 A cloud 에 직접적으로 데이터를 요청하면 되지만..
아래처럼 데이터를 주고 받는다면 A cloud 쪽에서 돌리고 있는 쪽의 방화벽규칙을 허용해줘야 한다..
하지만 방화벽규칙을 수정하지 않고 proxy_pass를 이용한다면 ..?
axios.defaults.baseURL = process.env.NODE_ENV === 'development' && 'http://localhost:8001'
front 에서 build 를 하면 production 으로 들어간다. 따라서 클라우드에서 axios default 는 cloud B 의 url로 들어가게 된다.
useEffect(() => {
axios.get('/api/v1/demo')
.then(response => {
setDemos(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
}, []);
고로 컴포넌트가 시작 될 때 'cloud_B_url/api/v1/demo' 로 요청을 하게 될 것이다.
nginx.conf 에서 server block을 아래처럼 추가 했었다.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location / {
root /etc/shere/html;
index index.html index.htm index.nginx-debian.html;
}
location /api/v1/demo {
proxy_pass http://10.128.0.4:8001;
}
}
location /api/v1/demo 랴고 적어놓은 블록에서 proxy_pass가 cloud A의 내부주소를 가리키고 있다.
즉 'cloud_B_url/api/v1/demo' 로 트래픽이 들어올 시 cloud A의 내부주소로 proxy 를 쏴주겠다는 것 이다.
그렇게 되면 axois default config 로 인해 'cloud_A_url/api/v1/demo' 로 요청을 해서 data를 받아올 것 이다.
그렇다면 방화벽규칙을 설정하지 않아도 proxy_pass를 사용해서 통신이 가능하다.
내 server block 설정에서 보도록 하겠다.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location / {
root /etc/shere/html;
index index.html index.htm index.nginx-debian.html;
}
location /api/v1/demo {
proxy_pass http://10.128.0.4:8001;
// 로드 밸런싱할 url..
proxy_pass http://backend;
}
}
// 로드 밸런싱할 url..
upstream backend{
server 10.128.0.20:8090;
server 34.31.28.179:8080;
server 34.170.217.245:8080;
}
위 처럼 설정해주면 nginx가 로드밸런싱을 해준다.