1. 서버 설정
가. EC2 생성 시 참고사항
서버 환경: AWS Ubuntu 20.04, Intel CPU
1) EC2 instance 생성 시 참고
•
Storage의 경우 프리티어 사용자에게 30GB까지 무료로 제공
•
보안그룹 설정 시, HTTP & HTTPS에 대한 인바운드 정책을 모든 사용자에게 허용 권장
: SSH의 경우, 내 PC의 IP에 대해서만 허용 권장
2) Elastic IP 등록 필요
•
고정 IP 활용 위해 Elastic IP 할당 받아서 EC2 인스턴스와 연결
•
Elastic IP는 사용하면 과금 X, 사용하지 않고 방치하면 과금
3) SSH로 EC2 Instacne 접속
•
ssh key 파일에 대한 접근권한 변경하고 접속
•
‘EC2/인스턴스/인스턴스에 연결’ 참고할 것
•
인스턴스 생성 시 기존 보안 그룹 선택 시 SSH 연결이 안될 수 있음
: 포트 및 일부 방화벽 정책에 닫혀 있임
: 새로운 보안 그룹 생성 권장
나. Java & Git & MySQL 설치
1) Ubuntu 패키지 업그레이드 및 한글 설정
•
패키지 업데이트 & 업그레드
sudo apt update
sudo apt upgrade
Bash
복사
•
locale 설정
sudo apt install language-pack-ko
sudo locale-gen ko_KR.UTF-8
sudo update-locale LANG=ko_KR.UTF-8 LC_MESSAGES=POSIX
Bash
복사
•
재부팅 후 로케일 확인
$ locale
LANG=ko_KR.UTF-8
LANGUAGE=
LC_CTYPE="ko_KR.UTF-8"
LC_NUMERIC="ko_KR.UTF-8"
LC_TIME="ko_KR.UTF-8"
LC_COLLATE="ko_KR.UTF-8"
LC_MONETARY="ko_KR.UTF-8"
LC_MESSAGES=POSIX
...
Bash
복사
2) Java 설치
•
Ubuntu Linux 기준 아래와 같이 설치
: Java Version에 따라 JDK 설치
ex) sudo apt-get install openjdk-8-jdk
sudo apt-get install openjdk-17-jdk
•
정상 설치 확인(java version 확인)
: java -version
3) Git 설치 및 Clone
•
패키지 리스트 업데이트
: sudo apt-get install git
•
Git 설치
: sudo apt install git
•
Git 정상 설치 확인(버전 확인)
: git --version
•
레파지토리 Clone
4) MySQL 설치 및 설정
•
MySQL 설치
sudo apt install mysql-server
sudo mysql
Bash
복사
: local pwd: mysql123456
•
하나의 서버에 WAS와 DB가 동시에 존재하는 경우 설정
: 사용자 생성 및 권한 부여
CREATE USER 'difs'@'localhost' IDENTIFIED BY 'p#jJIL3432as491!#$';
GRANT ALL PRIVILEGES ON `ocp`.* TO 'difs'@'localhost';
flush privileges;
SQL
복사
CREATE USER 'ocp'@'localhost' IDENTIFIED BY '1234qwer';
GRANT ALL PRIVILEGES ON `image-platform`.* TO 'ocp'@'localhost';
flush privileges;
SQL
복사
: 스키마(또는 데이터베이스) 생성
CREATE SCHEMA `image-platform`;
quit
SQL
복사
•
WAS, DB 서버가 분리되어 있는 경우 설정
: 데이베이스 생성
CREATE SCHEMA `growth_analysis`;
SQL
복사
: 사용자 생성 및 권한 부여
CREATE USER 'airbnb'@'%' IDENTIFIED BY 'MySqlppqweas4565987!#$';
GRANT ALL PRIVILEGES ON airbnb_db.* TO 'airbnb'@'%';
flush privileges;
quit
SQL
복사
2. API 배포
배포환경: AWS Ubuntu 20.04
가. 빌드파일 전송(로컬 → 서버)
1) 로컬에서 .jar 파일 생성
•
Gralde - build - bootJar
•
.jar 파일 생성 확인
2) scp 활용해서 서버로 .jar 파일 전송
•
.jar 파일이 위치한 경로에서 터미널 열기
: intelliJ에 내장된 터미널로 접근하면 Operation not permitted 로그 발생하고 접속이 안됨
: 접근권한이 없기 때문임
: .jar 파일 위치에서 터미널 창을 열어서 접근하면 정상 동작
•
ssh 접속 확인
: ssh -i [pem 파일 경로] [ec2 계정명]@[ec2 intance의 pulbic IP or DNS]
ssh -i "/Users/mj/Documents/ssh-keys/code_squard.pem" ubuntu@ec2-15-164-68-136.ap-northeast-2.compute.amazonaws.com
Bash
복사
•
scp로 파일 전송
: scp -i [pem 파일 경로] [.jar파일] [ec2 계정명]@[ec2 intance의 pulbic IP or DNS]:[경로]
: .jar 파일이 위치한 경로에서 scp 명령이 내려지므로 .jar 파일의 이름만 추가하면 됨
: 마지막에 :~ 추가, 추가 안하면 로컬의 .jar 파일과 같은 폴더에 생성됨
scp -i "/Users/mj/Documents/ssh-keys/code_squard.pem" "side-dish-0.0.6-SNAPSHOT.jar" ubuntu@ec2-15-164-68-136.ap-northeast-2.compute.amazonaws.com:~
Bash
복사
scp -i "/Users/mj/Documents/keys/child-growth.pem" "childGrowth-0.0.1-SNAPSHOT.jar" ubuntu@ec2-3-37-248-174.ap-northeast-2.compute.amazonaws.com:~
Shell
복사
참고)
•
.pem 경로 복사
: finder에서 경로 이름 복사 기능 활용
: Reference 참고
•
.jar 파일 이름 복사
: intelliJ copy path 기능 활용
나. 빌드파일 실행
1) 서버에서 .jar 파일 실행
•
데몬 백그라운드 없이 실행
: java -jar [.jar 파일]
: java -jar backend-0.0.1-SNAPSHOT.jar
•
데몬의 형태로 실행
: 데몬이란 사용자가 직접 제어하지 않는 상태에서 작동되는 프로그램
: nohup java -jar [.jar 파일]
: nohup java -jar backend-0.0.1-SNAPSHOT.jar
•
데몬 + 백그라운드 형태로 실행
: nohup → java -jar [.jar 파일] &
: nohup java -jar backend-0.0.1-SNAPSHOT.jar &
•
프로세스 종료
프로세스 아이디 알아내기
: ps -ef | grep [빌드 파일]
프로세스 종료
: kill -9 <프로세스 아이디>
•
포트번호 8080 트래픽 허용
: 웹서버 설정 하지 않았다면 8080포트 트래픽을 인바운드에서 허용하도록 네트워크 설정 필요
2) 서버에서 직접 jar 파일 생성해서 실행
•
프리티어의 1GB RAM으로는 빌드가 어려움
: 프리티어 환경에서는 직접 jar 파일 생성(빌드)를 권장하지 않음
•
Gradle 빌드
: ./gradlew build jar
•
스프링부트 실행
: ./gradlew bootrun
다. 프록시 서버 설정
프록시 서버 사용 목적: 모든 인바운드 트래픽을 80포트의 웹서버를 거침으로써 사용자의 WAS에 직접 접근 방지
1) Nginx 설치
•
설치
sudo apt-get install nginx -y
Bash
복사
•
사용
: sudo service nginx start 후에 public ip로 접속 했을 때, Nginx welcome 페이지 확인
: 또는 프로세스 확인해서 실행상태 확인
ps -ef|grep nginx
•
Nginx 기타 명령
sudo service nginx start
sudo service nginx stop
sudo service nginx restart
Bash
복사
2) Nginx.conf 수정
•
기존 설정 파일 제거
sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default
Bash
복사
•
'/etc/nginx/sites-available' 경로(Ubuntu의 경우)에 설정파일(**.conf) 생성 및 이하 설정 작업
참고) amazone Linux의 경우 nginx 설정파일의 위치가 '/etc/nginx/nginx.conf' 경로에 있음
•
8080포트로 들어오는 트래픽을 Nginx에서 80포트로 리다이렉트
: 설정파일 이름은 proxy.conf(예시)로 지정하여 이하 설정 작업 진행
cd /etc/nginx/sites-available
sudo vim proxy.conf
Bash
복사
•
proxy.conf 파일에 이하 설정값 입력
: 80포트로 Nginx 에 요청이 오면 http://localhost:8080/ 경로로 해당 트래픽 전달
: X-Real-IP 에 요청자의 IP 저장
server {
listen 80;
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
Bash
복사
•
심볼릭 링크 생성
: 웹서버 동작 시 sites-enabled의 설정파일 참조
sudo ln -s /etc/nginx/sites-available/proxy.conf /etc/nginx/sites-enabled/proxy.conf
Bash
복사
•
nginx server 재시작
sudo service nginx restart
Bash
복사
3) Web Socket proxy 설정
•
'/ws' 경로로 들어오는 트래픽에 대한 트래픽 처리
•
WS은 프로토콜 상 http와 완전히 다르지만 동작 시 http로부터 유도됨
location / {
// 생략
}
location /ws/ {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
Bash
복사
3. React 배포
배포환경: AWS Ubuntu 20.04 + Yarn
가. 주요 프로그램 설치
1) Node, NPM, Yarn 설치
sudo apt-get install nodejs -y
sudo apt-get install npm -y
sudo npm install -g yarn
Bash
복사
2) Git Clone
git clone -b FE-dev --single-branch https://github.com/JUNGYUN-Daegu/issue-tracker
Bash
복사
3) NPM Module 설치
•
node_modules의 경우 매우 크기 때문에 버전관리하지 않음
: 서버에서 관련 파일을 다운로드해야 함
•
위의 명령으로 package의 종속성을 확인하고 설치하는 작업
: 이하 명령은 package.json 파일이 있는 경로에서 실행해야 함
: npm의 경우 npm install
yarn install
Bash
복사
•
만약 node_modles가 이미 있는데 부분만 다운된 경우, 기존 파일 삭제 후 재설치
: rm -rf node_modules
: yarn install
4) Nginx 설치 및 사용
•
설치
sudo apt-get install nginx -y
Bash
복사
•
사용
: nginx start 후에 public ip로 접속 했을 때, Nginx welcome 페이지 확인
: 또는 프로세스 확인해서 실행상태 확인
ps -ef|grep nginx
sudo service nginx start
sudo service nginx stop
sudo service nginx restart
Bash
복사
나. 빌드파일 생성 및 실행
1) 빌드파일 생성
•
build 파일 생성
: npm의 경우 npm run build
yarn build
Bash
복사
2) Nginx 설정
•
Nginx 설정 파일 삭제
: 개인 설정과 겹칠 수 있으므로 에러 예방차원에서 기본 설정값 제거
sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default
Bash
복사
•
Nginx 설정 파일 생성
cd /etc/nginx/sites-available
sudo vim proxy.conf
Bash
복사
•
설정값 입력
: listen 인바운드 포트 설정
: root 실행파일(빌드파일) 위치
: index 인덱스 파일 지정
server {
listen 80;
location / {
root /home/ubuntu/airbnb_fe/build;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
Bash
복사
•
API와 함께 Nginx에 빌드파일을 적용하는 경우
: react app의 빌드 파일의 경로를 root 이하에 설정
server {
listen 80;
location / {
root /home/ubuntu/issue-tracker-fe/issue-tracker/build;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
Java
복사
•
심볼릭 링크 생성
: 웹서버 동작 시 sites-enabled의 설정파일 참조
: 심볼릭 링크: 일종의 바로가기
sudo ln -s /etc/nginx/sites-available/proxy.conf /etc/nginx/sites-enabled/proxy.conf
Bash
복사
3) Nginx 재시작
sudo systemctl stop nginx
sudo systemctl start nginx
Bash
복사
다. 빌드파일 갱신
1) 빌드파일 생성
•
node_modules 추가 생성
yarn install
Bash
복사
•
빌드파일 생성
yarn build
Bash
복사
2) Nginx 재시작
•
nginx server 재시작
→ 설정 정보 반영
sudo service nginx restart
Bash
복사
4. 배포 스크립트
가. 스크립트 파일 설정
1) 권한부여
•
chmod 755 [script 파일]
•
chmod 755 re_start_build.sh
2) 실행
•
sudo ./[script 파일]
•
sudo ./re_start_build.sh
나. 스크립트 기본
1) 프로세스 중단 및 재실행
echo ">start rerun"
PID=$(pgrep java)
echo "> check Process ID: $PID"
echo "> kill Process"
kill -9 $PID
echo "> rerun Process"
nohup java -jar baseballGameApi-0.0.1-SNAPSHOT.jar &
Bash
복사
2) 빌드 및 빌드파일 복사
#!/bin/bash
./gradlew build
aws s3 cp build/libs/issue-tracker-0.0.1-SNAPSHOT.jar s3://issue-tracker-storage
Bash
복사
다. S3 CLI 활용
1) 로컬에 AWS CLI 설치 및 설정
•
AWS CLI 설치
: unzip이 미설치 시, sudo apt install unzip
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
Bash
복사
•
AWS 설정
: aws configure
: AWS IAM의 AWS CLI 부분 참고
2) 로컬의 빌드 파일을 S3로 복사
•
aws s3 cp <builded_file> s3://honuxkq
3) WAS에 AWS CLI 설치 및 설정
•
aws s3 cp s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar ./
4) S3의 빌드 파일을 WAS로 복사
라. SLACK BOT 활용
1) 슬랙 알람
•
curl -X POST --data-urlencode "payload={\"text\": \"msg\"}" https://hooks.slack.com/services/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
2) 슬랙 알람 활용 스크립트
#!/bin/bash
IP=`curl -s 169.254.169.254/latest/meta-data/public-ipv4`
START="배포 시작"
END="배포 완료\n 배포주소: http:/$IP"
SLACK_CHANNEL="https://hooks.slack.com/services/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"
# real deploy script
CK=`aws s3 ls s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar`
if [ -z $CK ]; then
echo "no need to build"
exit 0
fi
curl -X POST --data-urlencode "payload={\"text\": \"$START\",\"username\": \"deploy-bot\", \"icon_emoji\": \":ghost:\"}" $SLACK_CHANNEL
fuser -k 8080/tcp
aws s3 cp s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar ./
nohup java -jar issue-tracker-0.0.1-SNAPSHOT.jar &
aws s3 rm s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar
curl -X POST --data-urlencode "payload={\"text\": \"$END\",\"username\": \"deploy-bot\", \"icon_emoji\": \":ghost:\"}" $SLACK_CHANNEL
Bash
복사
5. 이슈 정리
가. ssh 접속 이슈
•
현상: ssh 접속 시도에 따라 아래와 같은 에러 발생
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:526T1ds6Jf7m3RiIzH4yts0w8q7B86D77O7fuen/Keo.
Please contact your system administrator.
Add correct host key in /Users/mj/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/mj/.ssh/known_hosts:4
ECDSA host key for ec2-13-209-102-10.ap-northeast-2.compute.amazonaws.com has changed and you have requested strict checking.
Host key verification failed.
JSON
복사
•
원인
: Elastic IP 서비스를 이용해서 여러 인스턴스를 바꿔가며 같은 고정 IP로 연결을 시도함
: 같은 고정 IP에 대해 여러 host가 ssh 접속을 함에 따라 에러 발생
•
해결
1) 기존 Elastic IP 주소(여러 인스턴스에 연결했던)를 릴리즈하고 새로운 Elastic IP를 할당 받아서 연결함
2) .ssh 파일 내 known_hosts 파일 내 관련 정보 삭제. 대게 최신(맨 아래) host 정보(ip - hash 쌍) 제거 후 해결
cd ~
cd .ssh
vim known_hosts
Bash
복사
나. EC2 메모리 부족에 따른 빌드 실패 1
•
현상: Creating an Opcreating an optimized production build... stuck
•
원인: ec2 인스턴스의 메모리 부족(RAM 1G)
•
시도한 방법
1) 기존에 동작 중인 프로세스 중단(API, Nginx 등)
2) frontend 폴더 삭제(rm -rf forntend) 후 원격 저장소에서 다시 클론
3) 1, 2 번 시도 후 인스턴스 재부팅
4) GENERATE_SOURCEMAP 옵션 제거
•
해결
: 4번째 방법 시도 후 성공
: 관련 링크는 Reference에서 참고
다. EC2 메모리 부족에 따른 빌드 실패 2
•
현상: 동일
•
원인: 동일
•
해결
: 로컬 PC에서 빌드 완료 후 빌드된 파일을 원격 서버로 전송
: 빌드폴더를 압축 후, 압축된 파일을 원격 서버로 전송
: scp -i /Users/mj/Documents/ssh-keys/airbnb_key.pem issue-tracker-fe.zip ubuntu@15.164.68.136:~/issue-tracker-fe
•
참고 scp -r 옵션으로 디렉토리를 전송할 수 있지만 일반적으로 build 폴더 크기로 인하여 lost connection 에러 발생
: 로컬 PC에서 zip 명령으로 압축 후 원격 서버에서 unzip으로 압축해제하여 사용
: zip 명령 사용 시, test 디렉토리 이하 모든 파일 압축: zip -r test.zip test
라. EC2 메모리 부족에 따른 인스턴스 중지
•
현상: 평상시에는 CPU 사용률이 13%이지만 갑자기 과부화 현상이 발생함
→ EC2 모니터링 데이터 참고
•
원인 가능성
1) 메모리 부족에 따른 CPU 과부하
2) 외부에서 해당 CPU 무단 사용 가능
3) EC2 하드웨어 이슈
•
해결방안
1) SWAP 메모리 설정 또는 수직확장
2) 보안그룹의 인바운드 규칙을 작업공간의 IP에 SSH 연결만 허용
3) 인스턴스 교체
•
해결
: 평상시 메모리 사용률이 88%에 달하기 때문에 남는 디스크의 일부를 swap으로 설정
# swap 설정 전 메모리 사용률 확인
~$ free -h
total used free shared buff/cache available
Mem: 966Mi 557Mi 70Mi 0.0Ki 337Mi 257Mi
Swap: 0B 0B 0B
# disk 내 2GB를 활용하여 빈 파일 생성
~$ sudo dd if=/dev/zero of=/root/swapfile bs=1k count=2000000 conv=excl
2000000+0 records in
2000000+0 records out
2048000000 bytes (2.0 GB, 1.9 GiB) copied, 29.9611 s, 68.4 MB/s
# swapfile로 사용하기 위한 권한설정
~$ sudo chmod 600 /root/swapfile
ubuntu@ip-172-31-44-138:~$ free -h
total used free shared buff/cache available
Mem: 966Mi 548Mi 79Mi 0.0Ki 337Mi 260Mi
Swap: 0B 0B 0B
# swapfile로 지정
~$ sudo mkswap /root/swapfile
Setting up swapspace version 1, size = 1.9 GiB (2047995904 bytes)
no label, UUID=3e951b0d-5c38-4242-94dd-687103498d59
# swapfile 실행
~$ sudo swapon /root/swapfile
# swap 동작 확인
ubuntu@ip-172-31-44-138:~$ free -h
total used free shared buff/cache available
Mem: 966Mi 550Mi 62Mi 0.0Ki 352Mi 261Mi
Swap: 1.9Gi 0B 1.9Gi
Shell
복사
•
결과: 컴퓨팅 자원의 안정화
: 메모리 사용률 감소(88% → 59%)
: CPU 사용률 감소(13% → 4%)
마. EC2 내 DB Server 접근 이슈
•
현상: 로컬 DB Client에서 EC2 내 DB Server에 접근 이슈 발생
•
해결: MySQL Workbench로 SSH 베이스로 접근
Reference
서버/API 배포
•
우분투 최초 세팅 및 MySQL 설치, https://lucas.codesquad.kr/main/course/마스터즈-백엔드-Java-클래스-2021/RDBMS/Linux-MySQL-설치
•
mac local 환경에 mysql server 설치, https://daimhada.tistory.com/121
•
finder에서 경로 위치 복사, https://androphil.tistory.com/728?category=640236
•
nohup & background, https://joonyon.tistory.com/98
•
Nginx 활용하여 80포트로 배포, https://velog.io/@johnwi/Ch10.-NginX를-활용한-무중단-배포
•
Web Socket 프록시 서버 설정, https://www.joinc.co.kr/w/man/12/Nginx/wsproxy
•
API 배포 중 DB 설정(WAS, DB 서버 분리 시), https://nickjoit.tistory.com/144
React 배포
•
yarn 설치, https://blog.system32.kr/205
에러
•
메모리 부족 현상 해결, https://progdev.tistory.com/26