이전 페이지: swagger 설정
다음 페이지:
1. NCP 사용하는 이유
- NCP를 처음 가입해서 사용하는 상황이라서 무료 크레딧 10만원을 받게 됨.
- 2개월 이상 사용하고 후기를 쓰면 20만원 더 받음.
- 현재 개발하면서 조금씩 리펙토링 해갈 생각이므로 오래 유지할 필요가 있어서 위 혜택을 모두 받을 수 있는 NCP를 사용하기로 결졍
- 추가로 처음 가입한 사람들은 1년간 Micro Server(램 1GB, vCPU 1개) 를 무료로 사용할 수 있다. (근데 성능이 매우 구림)
2. NCP 배포 준비
사용할 서비스 선택
현재 계획은 docker-compose 에다가 mysql, redis 정보를 넣어서 image 생성한 다음 사용할 예정임.
이런 상황에서 굳이 NCP에서 제공하는 mysql, redis 서버를 돈내고 사용하기에는 너무 비싸다고 판단함.
하지만 그렇다고 1년간 무료로 사용할 수 있는 Micro Server를 사용하기에는 성능이 너무 구리다고 생각했다.
사실은 이미 이걸로 한번 써봤다가 6개의 서비스중에 몇개가 성능 이슈로 실행이 안되버림. 게다가 docker hub에서 image를 pull 해오는거나 docker 실행하는 것도 농담아니고 30분은 걸린듯함.
그래서 시원하게 한달에 8만원하는 서버 사용하기로 결정함.
서버 스펙은 아래와 같음.
서버 만드는 과정
NCP 첫 가입 하고 크레딧 받는 과정은 캡처한 것도 없고 가입만 하면 받는거니까 생략함.
1. https://www.ncloud.com/ 가서 콘솔 클릭
2. service 클릭
3. server 클릭
- classic 에는 마음에 드는게 서버가 없어서 VPC 선택함
4. 서버 생성
5. 새로 뜨는 팝업창에서 다음과 같이 선택
- 기존 콘솔 화면이 다른 블로그 글과 같을 거 같아서 기존 콘솔선택
- 게다가 새로운 기능은 필요 없음
- 그래도 혹시몰라서 콘솔 선택 모달을 매번 새로 볼 수 있게 선택함
6. 서버 생성
- linux OS는 무료임 그래서 Ubuntu 선택
- VPC 카테고리에 있는 서버중에 Standard가 제일 저렴함
- vpc 생성 먼저 해줘야함
- vpc에 대한 자세한 설명 https://www.ncloud.com/product/networking/vpc
- 10.0.0.0/20 으로 4096개의 IP 주소를 제공
- 아직 대규모 네트워크 경험이 없어서 큰 이유는 없고 적절하게 많이 해두는게 좋을 것 같아서 했음
- 유형은 NORMAL 선택
- VPC를 독립적으로 사용하려면 그냥 NORMAL 선택
- 다른 VPC를 두고 서로 통신하는 상황이라면 TRANSIT 선택
- IP 주소 범위는 적당히 설정 해준다
- Network ACL은 VPC를 만들었다면 아마 자동으로 생겨있을 것임
- Internet Gateway 이거는 Y 눌러야 gateway 통해서 외부랑 통신가능
- 용도는 일반 서버로 사용할거라서 일반 선택
- 원하는 서버 선택하면 월요금제가 나온다. 실습할 용도로 할 거면 시간 요금제 해야함. 요금폭탄 발생
- 2번에 추가만 누르면 아무것도 설정안해도 자동으로 뭔가 추가됨. 꼭 추가 누르기
- 배포할거면 공인 IP 할당
- 보유하고 있는거 없으면 새로운 인증키 생성하면 됨.
- 만들 때 기억이 잘안나는데 아마 ACG도 자동으로 생성되어 있었던 것 같음.
7. 공인 IP 설정
8. ACG 설정
- ACG 설정으로 배포할 서버에 들어오는 포트를 허용해줌.
- 관리자 비밀번호 확인해아함
- 하는 이유는 ssh로 접속할 때 인증해야하기 때문임.
- 위에서 만들었던 인증키 사용하면 관리자 비밀번호 반환해줌.
9. ssh 접속 하고 비밀번호 변경
ssh root@공인ip -p 22
- password 입력하는 곳이 뜬다면 위에서 확인한 비밀번호 입력하기
- 접속이 됐다면 passwd 명령어로 비번 변경
passwd
3. 프로젝트 배포
Java 설치
오류 방지를 위해서 원래 로컬의 JVM에서 사용하던 Java 버전과 완벽하게 일치하는 버전의 Java를 설치하기로 계획함.
https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
원래 프로젝트에서 사용하는 것이 17.0.10 버전이라서 위에 링크로 들어가서 그에 맞는 정확한 버전을 찾아봄.
17.0.10 찾은 다음 ubuntu에 맞는 다운로드 경로를 복붙함.
서버 접속 후에 아무 경로나 가서 아래 명령어 실행
#jdk 다운로드
wget https://download.oracle.com/java/17/archive/jdk-17.0.10_linux-x64_bin.tar.gz
#jdk 압축파일 해제
tar -zxvf jdk-17.0.10_linux-x64_bin.tar.gz
#새로생긴 폴더 /opt/jdk-17/ 로 이동
sudo mv jdk-17.0.10 /opt/jdk-17/
#부팅 설정
vim ~/.bashrc
.bashrc에 적을 내용
########################## 위에 꺼 생략 ##########################
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
#if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
# . /etc/bash_completion
#fi
# 추가한 거
export JAVA_HOME=/opt/jdk-17
export PATH=$PATH:$JAVA_HOME/bin
#변경한거 바로 적용하기
source ~/.bashrc
#java 적용 됐는지 확인하기
java --version
Docker 설치
Docker Engine을 설치할 수 있도록 저장소를 추가
# apt-transport-https 설치
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# 도커 저장소 및 Key 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Repository 경로 추가하기 ( PPA )
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt-get update
도커 리포지토리가 사용되도록 설정되었으므로 다음을 입력하여 yum을 사용하여 최신 버전의 도커 CE(Community Edition)를 설치
# docker 설치
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
Docker 시작 및 서비스 등록
# 버전확인
docker -v
# 서비스 시작.
sudo systemctl start docker
# 부팅 시 서비스 자동 시작.
sudo systemctl enable docker
# 서비스 상태.
sudo systemctl status docker
docker-compose 설치
curl 명령어를 통해 docker-compose를 설치
sudo curl -L "https://github.com/docker/compose/releases/download/2.29.7/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
다운로드한 도커 컴포즈 파일을 실행 가능하도록 다운로드한 경로에 권한을 부여
sudo chmod +x /usr/local/bin/docker-compose
심볼릭 링크 설정으로 path 경로를 아래와 같이 설정함.
#path 경로 설정
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
#설치 확인
docker compose version
여기서 docker-compose -v 하니까 오류 남.
Docker Compose의 새로운 CLI 통합 버전을 사용하는 경우에는 옛날 방식인 docker-compose -v 에서 오류가 날 수 있다고 함.
근데 위에서 2.29.7로 다운로드 받았는데 더 낮은 버전인 2.27.1이 설치됨.
우분투 버전이랑 최신 버전이 달라서 그런 걸 수도 있고, 큰 문제가 아니라서 그냥 넘어감.
로컬에서 image build 하고 docker hub로 push
# docker hub login
docker login
#hub에 올리기
docker buildx build --platform linux/amd64,linux/arm64 -t playdodo/keupang-config-server:1.0 ./keupang-config-server --push
--platform linux/amd64, linux/arm64 : 로컬(mac os)와 서버(ubuntu)에서 둘다 사용하기 위해 둘다 호환되는 image를 생성하기 위해서 필요한 설정이다. amd64 - ubuntu, arm64 - mac os(M3 칩)
playdodo/keupang-config-server:1.0 : playdodo는 docker 사용자 이름이다. keupang-config-server는 컨테이너 이름이고, 1.0은 태그를 무조건 붙여야해서 그냥 붙인거임
./keupang-config-server 는 image 만들기 위해 필요한 dockerfile이 있는 위치임. 물론 dockerfile에서 지정해둔 위치에 jar 파일도 build 되어 있어야함.
--push 를 붙이면 Image 가 만들어지고 바로 hub로 올라감
로컬에서 docker-compose.yml 설정 후 .env 파일과 함께 서버로 전송
로컬에서 사용중인 docker-compose.yml
services:
config-server:
image: playdodo/keupang-config-server:1.0
container_name: keupang-config-server
platform: linux/arm64
ports:
- "9000:9000"
environment:
- SPRING_PROFILES_ACTIVE=prod
- private_key=${private_key}
networks:
- msa-network
api-gateway:
image: playdodo/keupang-api-gateway:1.0
container_name: keupang-api-gateway
platform: linux/arm64
ports:
- "8080:8080"
depends_on:
- eureka-server
environment:
- security_username=${security_username}
- security_password=${security_password}
networks:
- msa-network
service-user:
image: playdodo/keupang-service-user:1.0
container_name: keupang-service-user
platform: linux/arm64
deploy:
mode: replicated
restart_policy:
condition: on-failure
depends_on:
- eureka-server
- config-server
- mysql
environment:
- security_username=${security_username}
- security_password=${security_password}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}
- USER_DB_NAME=${USER_DB_NAME}
networks:
- msa-network
networks:
msa-network:
driver: bridge
몇 개 생략하고 보여줌
중요한건 각 서비스에다가 image 의 이름과 태그를 지정해줘야하는 것임.
그러면 밑에서 저 이름에 맞는 image를 docker hub에서 자동으로 pull 해올 수 있음
또 중요한 것은 로컬은 mac os 이기 때문에 image를 불러 올때 전부 platform을 linux/arm64로 맞춰야함.
이제 이 docker-compose.yml이 있는 폴더에서 서버로 docker-compose.yml을 전송해줌
#docker compose 전송
scp docker-compose.yml root@공인ip:/home/
#.env 사용중이라서 docker-compose.yml 과 같은 경로에 전송
scp .env root@공인ip:/home/
로컬에서 scp을 사용해서 서버의 원하는 경로에 복붙 가능함.
물론 서버로 접속해서 platform을 linux/amd64로 전부 수정해줘야함.
nano /home/docker-compose.yml
서버에서 docker hub image pull
먼저 docker hub에 로그인을 해아함.
로컬에서는 docker desktop 설치해서 사용중이라면 아마 docker login 했을 때 아무거도 안뜨고 바로 로그인 됐을 것임.
하지만 서버에서는 그렇지 않기 때문에 사용자 이름과 비번을 입력해줘야함
#docker hub 로그인
docker login
이렇게 뜨면 사용자 이름과 비번을 입력하면 됨.
그런데 아마 원래 쓰던 비번을 입력하면 비번을 아무리 맞게 써도 맞지 않다고 오류 날거임. 이거는 docker hub에서 토큰을 사용하도록 권장하기 때문에 일부러 막아둔 것 같음.
잠깐 이상태로 두고 토큰 만들어감 -> docker desktop 으로 이동
아래 그림과 같이 설정 페이지 불러오기
Security 탭에서 Psersonal access tokens 누르고 토큰 만들면 됨.
이제 만들어진 토큰을 비번 입력하는 곳에 복붙하면 끝
docker hub에 로그인이 되면 이제 image를 pull 받을 수 있음.
docker compose pull
서버에서 프로젝트 실행
이제 docker compose up -d 해서 잘 실행함.
4. SSL 인증서 적용
현재 가비아에서 도메인을 구매하고 프론트 서버인 AWS에 연결 돼있는 상황이다.
AWS에서 서브 도메인으로 백엔드에서 사용할 api.keupang.store를 백엔드(본인)가 NCP에서 만든 서버랑 연결해줘서 사용가능함.
여기에 ssl 인증을 도입해서 https 로 도메인을 사용하기로 함.
Let's encrypt를 이용해서 ssl인증서를 발급
무료로 인증서 발급하려고 Let's encrypt를 사용하게 됨.
서버에다가 letsencrypt 설치
sudo apt update
sudo apt-get install letsencrypt -y
그리고 인증서 만드는 도구인 certbot 설치
sudo apt update
sudo apt upgrade -y
sudo apt install certbot python3-certbot-nginx
Nginx 리버스 프록시 설정
Certbot이 도메인에 대한 인증을 수행하려면 Nginx 설정 파일에서 도메인 이름(ServerName 또는 ServerAlias)이 제대로 설정되어 있어야 한다.
Nginx 사이트 설정 파일을 열어 도메인이 올바르게 등록되었는지 확인함.
# /etc/nginx/sites-available 로 이동
cd /etc/nginx/sites-available
# 도메인 설정 파일 있는지 확인
ls
여기에 default 밖에 없어서 nano api.keupang.store 하고 밑에 내용 입력함
# HTTP 요청 처리 - HTTPS로 리다이렉트
server {
listen 80;
server_name api.keupang.store;
return 301 https://$host$request_uri;
}
# HTTPS 요청 처리
server {
listen 443 ssl;
server_name api.keupang.store;
ssl_certificate /etc/letsencrypt/live/api.keupang.store/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.keupang.store/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
proxy_pass http://localhost:8080; # 8080 포트로 요청 전달
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization $http_authorization;
}
}
- 80 포트로 오는 요청은 https 로 리다이렉트 하도록 설정함.
- 이때 http랑 같이 8080포트나 이런식으로 포트번호를 같이 주면 리다이렉트가 안됨. 이후 트러플 슈핑에 추가할 예정
- https (443) 으로 온 요청은 모두 apigateway의 포트번호인 8080으로 보내줌. 어차피 사용자는 eureka server를 볼일 도 없고, config-server에도 접근하면 안되기 때문에 굳이 설정 안해줌.
- location 부분을 그림으로 설명하면 다음과 같다.
- 443으로 들어오는 요청을 8080포트로 보내서 gateway 에서 요청을 처리하도록 한다.
그 다음 설정한 파일을 nginx 가 읽을 수 있도록 심볼릭 링크를 생성한다.
sudo ln -s /etc/nginx/sites-available/api.keupang.store /etc/nginx/sites-enabled/
설정 파일의 구문 오류를 확인하고, nginx 서비스를 재실행한다.
# 구문 오류 확인
sudo nginx -t
# nginx 재시작
sudo systemctl restart nginx
Certbot을 사용하여 SSL 인증서 발급
sudo certbot --nginx -d api.keupang.store
- 이런 식으로 고르는게 나온다. https로 리다이렉트 한다는 설정이 더 안전해 보여서 2번 선택함
- 이때 생기는 인증서는 /etc/letsencrypt/live/api.keupang.store 에 있음)
Let’s Encrypt 인증서는 90일 동안만 유효하므로 자동 갱신 설정이 필요하다.
#갱신 테스드
sudo certbot renew --dry-run
#Crontab을 설정
sudo crontab -e
#아래 내용을 추가하여 매일 새벽에 갱신하도록 설정
0 3 * * * /usr/bin/certbot renew --quiet
/etc/letsencrypt/live/api.keupang.store 여기 가서 ls 해봄
NCP의 Certificate Manager에 인증서를 등록해서 관리하려면 NCP 콘솔에서 아래와 같이 등록하면 된다.
여기에다가 /etc/letsencrypt/live/api.keupang.store 에 있던 인증서들을 차근차근 넣으면 된다.
이렇게 색깔 맞춰서 넣어주면 된다.
넣는 방법은 인증서가 있는 경로에서
cat cert.pem
할때 나오는 걸 빈칸이 들어가지 않도록 복사하고 붙여넣기 하면 된다.
이때 주의할점
제일 밑의 Certificate Chain 에는 추가로 넣어 줘야할 CA 인증서가 있다.
해당 인증서는 /etc/ssl/certs에 있다.
# 경로 이동
cd /etc/ssl/certs
# 내용 출력 (아래 적힌 놈만 출력해서 복붙해주면됨)
cat ISRG_Root_X1.pem
출력한 내용을 fullchain.pem 내용의 바로 밑줄에 붙여넣어 주면 된다.