-
AWS 망 구성하고 서비스 배포하기네트워크 & 인프라 2022. 3. 28. 14:33
이번에는 AWS를 통해 망을 구성하고 서비스를 배포하는 미션을 진행했다.
배포부분은 heroku 배포를 제외하고는 진행해본 적이 없기에 이번 미션을 통해서 배포에 대해 많은 부분을 배울 수 있어 뿌듯했다! 👏
미션을 진행하던 도중 주의를 기울이지 않은 부분에서 문제가 발생한 부분도 있었지만
해당 부분을 해결하면서 더 많이 배울 수 있었다!😀
망 구성하기
망 생성
- VPC 생성
- Subnet 생성
- 외부망 : 64개씩 2개 (AZ 다르게 구성) (a, b)
- 내부망 : 32개씩 1개 (c)
- 관리용(bastion server) : 32개씩 1개 (d)
- 인터넷 게이트웨이 연결
- 라우팅 테이블 생성 (외부망용 1개, 내부망용 1개)
- 시큐어리티 그룹 설정
- 외부망
- 전체대역 : 8080 포트 오픈
- 관리망 : 22번 포트 오픈
- 내부망
- 외부망 : 3306포트 오픈
- 관리망 : 22번 포트오픈
- 관리망
- 자신의 공인 IP : 22번 포트 오픈
- 외부망
- 서버 생성
- 외부망에 웹 서비스 용도 EC2
- 내부망에 데이터베이스용 EC2
- 관리망에 베스천 서버 용도 EC2
- 베스천 서버에 Session Timeout 600s 설정
- 베스천 서버에 Command 감사로그 설정
- ubuntu 64 bit (Ubuntu Server 18.04 LTS)
- Instance Type : t3.medium
- 서브넷 : 서브넷 선택, 퍼블릭 IP 자동 할당 (활성화)
- 내부망은 퍼블릭 IP 자동 할당 비활성화 후 탄력적 아이피 생성
- Nat gateway 생성 (같은 리전 안에있는 a 서브넷에 생성)
- 연결 ip 할당
- 내부망 라우팅에서 nat gateway 0.0.0.0/0으로 추가 생성
- 스토리지
- 보안그룹 : 위의 포트에 맞춰서 선택
Bastion 서버
먼저 생성한 서버에 접속해보자.
발급받은 pem 키 위치에 가서 pem키에 권한 설정 후 접속을 실행한다.
$ chmod 400 [pem파일명] $ ssh -i [pem파일명] ubuntu@[SERVER_IP]
이제 Bastion 서버를 구성해보자.
Bastion이란 성 외곽을 보호하기 위한 돌출 부분이라는 뜻으로 Bastion 서버 란 서버가 악성 루트킷, 랜섬웨어 등으로 피해를 보더라도 Bastion 서버 재구성을 통해 서비스에 영향을 최소화 하기 위한 서버를 뜻한다. 예를 들어 22번 포트의 보안이 뚫리면 심각한 문제가 되지만 모든 서버에 동일 수준의 보안을 설정하면 Auto-Scaling 등 확정성을 고려한 구성과 배치되어 보안 설정의 일정 부분을 포기하게 된다. 이 경우 Bastion Server를 통해 문제를 해결할 수 있다. 추가로 Bastion 서버 구성시 서비스 정상 트래픽과 관리자용 트래픽을 구분할 수 있다는 이점이 있다. 서비스가 DDos 공격을 받는 것에 대비하여 Bastion 서버에 22번 포트를 오픈하고 그 서버에 보안을 집중할 수 있다.
## 우선 pem 키를 복사한다 $ cat [pem 파일명] $ ssh -i [pem 파일명] ubuntu@[베스천 서버 public ip] ## bastion 서버에 pem 키를 복사한다 bastion $ vi [pem 키] bastion $ chmod 400 [pem파일명] ## bastion 서버에서 pem 키를 이용해서 서비스용 서버를 실행한다. ## 같은 vpc 안에 위치하기 때문에 서비스 서버의 private ip로 진행한다. ## 먼저 telnet으로 22번포트 연결 가능 여부 확인 bastion $ telnet [서비스용 서버 private ip] 22 Connected ... ## 연결이 안되면 ufw 방화벽 확인 bastion $ sudo ufw enable bastion $ sudo ufw allow ssh bastion $ sudo ufw allow 22 ## 연결 되었으면 서버 접속 ## 우선 pem 키로 실행을 해야 ssh 키를 이용한 접속을 설정할 수 있다. bastion $ ssh -i [pem 파일명] ubuntu@[서비스용 서버 private ip] service $ exit ## ssh 키 설정 bastion $ ssh-keygen -t rsa ## 생성된 id_rsa.pub 복사 (~ubuntu@ 부분만 제거하고 앞까지 복사) bastion $ cat ~/.ssh/id_rsa.pub ## 권한이 없다고 하면 설정해준다. bastion $ sudo chmod 600 ~/.ssh/id_rsa bastion $ sudo chmod 644 ~/.ssh/id_rsa.pub bastion $ sudo nano ~/.ssh/authorized_keys ## 서비스용 서버 접속 bastion $ ssh -i [pem 파일명] ubuntu@[서비스용 서버 private ip] ## PasswordAuthentication yes 설정 service $ sudo nano /etc/ssh/sshd_config ## 아까 복사한 id_rsa.pub 키 복사 service $ vi ~/.ssh/authorized_keys service $ exit ## 베스천 서버에서 ssh 키를 이용해서 서버 실행 정상적으로 실행 되는 것을 확인 bastion $ ssh ubuntu@[서비스용 서버 private ip] service $ exit ## 베스천 서버에서 별칭 등록해준다. ## [서비스용 private ip] [별칭] bastion $ vi /etc/hosts ## 베스천 서버에서 별칭으로 접속 확인 bastion $ ssh [별칭]
홤경변수 설정
서버 환경변수를 설정하여(session Timeout 설정) 일정시간 작업을 하지 않을 경우 터미널 연결을 해제하도록 하자.
bastion $ sudo vi ~/.profile HISTTIMEFORMAT="%F %T -- " ## history 명령 결과에 시간값 추가 export HISTTIMEFORMAT export TMOUT=600 ## 세션 타임아웃 설정 bastion $ source ~/.profile bastion $ env
shell prompt 변경하여 bastion 등 구분해야 하는 서버의 shell prompt 를 설정하여 관리자의 인적 장애를 방지하자.
bastion $ sudo vi ~/.bashrc USERNAME=BASTION PS1='[\e[1;31m$USER\e[0m][\e[1;32m\t\e[0m][\e[1;33m\u\e[0m@\e[1;36m\h\e[0m \w] \n\$ \[\033[00m\]' bastion $ source ~/.bashrc
logger를 이용하여 감사로그를 작성하도록 남기도록 하자. 작업 이력 히스토리를 기록해두어야 장애 발생시 원인을 분석할 수 있다.
bastion $ sudo vi ~/.bashrc tty=`tty | awk -F"/dev/" '{print $2}'` IP=`w | grep "$tty" | awk '{print $3}'` export PROMPT_COMMAND='logger -p local0.debug "[USER]$(whoami) [IP]$IP [PID]$$ [PWD]`pwd` [COMMAND] $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"' bastion $ source ~/.bashrc bastion $ sudo vi /etc/rsyslog.d/50-default.conf local0.* /var/log/command.log # 원격지에 로그를 남길 경우 local0.* @원격지서버IP bastion $ sudo service rsyslog restart bastion $ tail -f /var/log/command.log
환경 세팅 확인
환경 세팅 확인하자.
# 현재 위치를 확인합니다. $ pwd # 파일시스템별 가용공간을 확인합니다. $ df -h # 각 디렉토리별로 디스크 사용량을 확인합니다. $ sudo du -shc /* # 현재 경로의 파일들(숨김파일 포함)의 정보를 확인합니다. $ ls -al # 소스코드를 관리할 디렉토리를 생성하고 이동합니다. $ mkdir nextstep && cd nextstep # git 명령어의 위치를 확인해봅니다. $ which git && which java
프로그램 실행
자바 설치하고 작성한 프로젝트를 실행시켜 보도록 하자.
service $ sudo apt update service $ sudo apt install default-jre service $ sudo apt install default-jdk service $ java --version openjdk 11.0.14 2022-01-18 OpenJDK Runtime Environment (build 11.0.14+9-Ubuntu-0ubuntu2.18.04) OpenJDK 64-Bit Server VM (build 11.0.14+9-Ubuntu-0ubuntu2.18.04, mixed mode, sharing)
git 레파지토리 복사하자.
service $ git clone [git 레파지토리 url] ## 빌드 service $ cd [해당 폴더] service $ ./gradlew clean build # jar파일을 찾아본다. service $ find ./* -name "*jar" ## 어플리케이션 실행 후 정상 작동 확인 service $ java -jar [jar파일명] & service $ curl http://localhost:8080
- -Dserver.port=8000 옵션을 활용하여 port를 변경할 수 있다.
- 서버를 시작 시간이 너무 오래 걸리는 경우 -Djava.security.egd 옵션을 적용하자.
$ java -Djava.security.egd=file:/dev/./urandom -jar [jar파일명] &
터미널 세션이 끊어질 경우 background로 돌던 프로세스에 hang-up signal이 발생해 죽는 경우가 있는데 nohup 명령어를 활용하여 이를 방지할 수 있다.
$ nohup java -jar [jar파일명] 1> [로그파일명] 2>&1 &
로그를 확인하자.
# java applicaion이 남기는 로그를 확인합니다. $ tail -f [로그파일명] # 파일을 압축하고 파일 소유자와 모드를 변경해봅니다. $ tar -cvf [파일명] [압축할파일 또는 디렉터리] $ sudo chown [소유자계정명]:[소유그룹명] [file이름] $ chmod [옵션] [파일명] > https://ko.wikipedia.org/wiki/Chmod
브라우저에서 http://[서버 ip]:[port]로 접근
프로그램을 종료하자.
## 프로세스 pid를 찾는 명령어 $ ps -ef | grep java $ pgrep -f java ( losf -i : [포트번호]) ## 프로세스 종료 명령어 $ kill -2 [PID] (kill -9 [PID]) ## 명령 이력 확인 $ history
배포하기
개요
외부망에 웹 어플리케이션 배포 및 DNS 설정
- 운영환경
- 웹 어플리케이션 앞단에 Reverse Proxy 구성
- 외부망에 Nginx로 Reverse Proxy 구성
- Reverse Proxy에 TLS 설정
- 운영 데이터베이스 구성
- 웹 어플리케이션 앞단에 Reverse Proxy 구성
- 개발환경
- 설정파일 나누기
- JUnit : h2
- Local : docker(mysql)
- Prod : 운영 DB를 사용하도록 설정
- 데이터 베이스 테이블 스키마 버전 관리
- 설정파일 나누기
Reverse Proxy
우선 도커를 설치하자.
## 서비스용 서버 접속 bastion $ ssh [서비스용 서버 별칭] ## 도커 설치 service $ sudo apt-get update && \ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \ sudo apt-key fingerprint 0EBFCD88 && \ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \ sudo apt-get update && \ sudo apt-get install -y docker-ce && \ sudo usermod -aG docker ubuntu && \ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \ sudo chmod +x /usr/local/bin/docker-compose && \ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
Reverse proxy를 설정하자. 클라이언트로부터 요청을 받아 웹 서버로 요청을 전송하면 웹서버는 응답을 클라이언트가 아닌 Reverse proxy로 반환하고 리버스 프록시는 다시 이 응답을 클라이언트로 반환한다. 이를 통해 WAS는 비지니스 로직만 담당하여 TLS와 같은 부수적인 기능에 영향받지 않게 된다.
- 통상 Proxy Server
- LAN -> WAN의 요청을 대리 수행
- Reverse Proxy
- WAN -> LAN의 요청을 대리 수행
- 보안성 향상, 향상성 향상, 웹 가속 (압축/SSL 처리로 백엔드 리소스 확보/캐싱)
- Load Balancer
- 부하 분산, 서버상태 체크, 세션 관리
- Nginx
- Reverse Proxy 역할 + Load Balancer 역할 모두 수행
이용할 무료도메인 생성하자.
https://xn--220b31d95hq8o.xn--3e0b707e/
로그인 하고 도메인을 등록한다
패킷 스니핑을 방지하기 위해 서버의 보안과 별개로 서버와 클라이언트간 통신상의 암호화(TLS)를 이용해 통신하도록 설정하자.
letsencrypt를 이용하여 무료로 TLS 인증서를 사용하자.
service $ docker run -it --rm --name certbot \ -v '/etc/letsencrypt:/etc/letsencrypt' \ -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \ certbot/certbot certonly -d 'yourdomain.com' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory ## 오류발생 시 다음과 같이 권한 부여 후 다시 실행 docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create?name=certbot": dial unix /var/run/docker.sock: connect: permission service $ sudo chmod 666 /var/run/docker.sock
이메일 입력 후 약관동의 (Y), 메일 수신 (N)
인증서가 생성된것을 확인하면 바로 엔터를 누르지 말고 내 도메인에 생성된 인증서를 DNS TXT 레코드로 추가한다. 그 이후 터미널에서 엔터를 눌러준다.
## 잘 생성되었는지 확인 service $ sudo ls /etc/letsencrypt/live/[내 도메인] README cert.pem chain.pem fullchain.pem privkey.pem
생성한 인증서를 활용하여 Reverse Proxy에 TLS 설정을 해봅시다. 우선 인증서를 현재 경로로 옮깁니다.
service $ sudo cp /etc/letsencrypt/live/[내 도메인]/fullchain.pem ./ service $ sudo cp /etc/letsencrypt/live/[내 도메인]/privkey.pem ./
현재 폴더에 Dockerfile, nginx.conf 파일을 생성한다.
service $ vi Dockerfile FROM nginx COPY nginx.conf /etc/nginx/nginx.conf COPY fullchain.pem /etc/letsencrypt/live/[도메인주소]/fullchain.pem COPY privkey.pem /etc/letsencrypt/live/[도메인주소]/privkey.pem service $ vi nginx.conf events {} http { upstream app { server 172.17.0.1:8080; } # Redirect all traffic to HTTPS server { listen 80; return 301 https://$host$request_uri; } server { listen 443 ssl; ssl_certificate /etc/letsencrypt/live/[도메인주소]/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/[도메인주소]/privkey.pem; # Disable SSL ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # 통신과정에서 사용할 암호화 알고리즘 ssl_prefer_server_ciphers on; ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5; # Enable HSTS # client의 browser에게 http로 어떠한 것도 load 하지 말라고 규제합니다. # 이를 통해 http에서 https로 redirect 되는 request를 minimize 할 수 있습니다. add_header Strict-Transport-Security "max-age=31536000" always; # SSL sessions ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; location / { proxy_pass http://app; } } }
docker컨테이너 생성하고 Reverse Proxy를 실행시켜보자. (-it 옵션을 주어야 exit 해도 종료되지 않는다)
service $ sudo docker build -t nextstep/reverse-proxy:0.0.2 . service $ sudo docker run -d -it -p 80:80 -p 443:443 --name proxy nextstep/reverse-proxy:0.0.2
reverse proxy의 포트를 443으로 설정하였으므로, 서비스 서버(public)의 443 포트를 보안규칙에 0.0.0.0/0으로 열어주어야 한다.
git 폴더로 이동 해서 우리의 프로그램 실행시키자.
service $ ./gradlew clean build service $ find ./* -name "*jar" service $ java -jar [jar 파일 위치]
https://[내도매인]에서 올바르게 실행되는 것을 확인할 수 있다.
여기서 만약 서버 exit 해도 계속 살아있도록 하기위해서는 nohup을 사용한다.
service $ nohup java -jar [jar 파일 위치] &
운영 데이터베이스 연결
이제 운영 데이터베이스를 연결하자.
이번 미션에서는 컨테이너로 운영 DB 사용했다. (하지만 실무에서는 컨테이너를 DB로 사용해서는 안된다)
베스천 서버에서 내부망으로 들어가서 도커 실행해준다.
여기서도 -it 옵션을 해주어야 exit 해도 서버가 살아있는다.
bastion $ ssh -i [pem 파일명] ubuntu@[내부망 private ip] internal $ $ docker run -d -it -p 3306:3306 [운영DB 컨테이너]
Flyway
이제 프로젝트 설정파일을 나누어 실행 옵션에 따라서 데이터베이스 운용이 다르게 설정되도록 적용하자.
//application.properties spring.profiles.active=local handlebars.suffix=.html handlebars.enabled=true logging.level.org.hibernate.type.descriptor.sql=trace spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.format_sql=true security.jwt.token.secret-key= eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.ih1aovtQShabQ7l0cINw4k1fagApg3qLWiB8Kt59Lno security.jwt.token.expire-length= 3600000
//application-test.propertes spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.datasource.url=jdbc:h2:mem:test spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=
//application-local.properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true spring.datasource.username=root spring.datasource.password=00000 spring.jpa.show-sql=true spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.hibernate.ddl-auto=validate
//application-prod.properties spring.datasource.url=jdbc:mysql://[내부망 private ip]:3306/subway?serverTimezone=Asia/Seoul&characterEncoding=UTF-8&enabledTLSProtocols=TLSv1.2 spring.datasource.username=[사용자이름] spring.datasource.password=[패스워드] spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=validate spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
설정파일에 따라 프로그램을 실행할 때에는 다음과 같이 실행해준다.
$ java -jar -Dspring.profiles.active=prod [jar파일명]
여기서 Flyway 를 적용하여 데이터베이스 테이블 스키마를 관리하도록 하자. 운영중인 서비스의 경우 JPA등 ORM을 사용하여 기존의 테이블을 변경하는 것은 데이터 유실 , 참조 무결성 제약 등으로 인해 어려움이 존재하는데 이럴때 로컬에서 개발중일 때는 h2 등 in-memory 형태의 데이터베이스를 사용하여 빠르게 개발하고 운영 DB는 점진적으로 migration 하는 것이 유용한데 이때 사용하는 것이 Flyway이다.
gradle에 다음과 같이 flyway dependency를 추가해준다.
// mysql implementation 'mysql:mysql-connector-java' // flyway implementation('org.flywaydb:flyway-core:6.4.2')
src/main/resources/db/migration 폴더에 V1__init.sql파일을 생성해준다. (데이터베이스 초기 생성 테이블)
create table favorite ( id bigint auto_increment, created_date timestamp, modified_date timestamp, member_id bigint, source_station_id bigint, target_station_id bigint, primary key (id) ); create table line ( id bigint auto_increment, created_date timestamp, modified_date timestamp, color varchar(255), name varchar(255), primary key (id) ); create table member ( id bigint auto_increment, created_date timestamp, modified_date timestamp, age integer, email varchar(255), password varchar(255), primary key (id) ); create table section ( id bigint auto_increment, distance integer not null, down_station_id bigint, line_id bigint, up_station_id bigint, primary key (id) ); create table station ( id bigint auto_increment, created_date timestamp, modified_date timestamp, name varchar(255), primary key (id) ); alter table line add constraint line_name_unique unique (name); alter table station add constraint station_name_unique unique (name); alter table section add constraint fk_section_down_station_id foreign key (down_station_id) references station (id); alter table section add constraint fk_section_line_id foreign key (line_id) references line (id); alter table section add constraint fk_section_up_station_id foreign key (up_station_id) references station (id);
application-local.properties와 application-prod.properties에 다음과 같이 flyway옵션을 추가해준다. 기존 테이블이 존재하는 경우 다음과 같이 버전을 만들어 생성할 것이다.
spring.flyway.enabled=true spring.flyway.baseline-on-migrate=true spring.flyway.baseline-version=2
데이터테이블을 보면 다음과 같이 버전으로 스크립트가 관리되는 것을 확인할 수 있다.
이번엔 키, 계정 정보, 접속 URL등을 포함한 설정파일이 private 저장소에서 별도로 관리되도록 하자.우선 private 저장소를 생성 후 설정파일들을 모두 옮겨 놓는다.git 서브모듈 기능을 사용하여 특정경로의 private repository를 참조하도록 한다.$ git submodule add [자신의 private 저장소] ./src/main/resources/config
소스코드를 받을 때에는 submodule을 포함하여 clone 하도록 한다.
$ git clone --recurse-submodules [자신의 프로젝트 저장소]
설정파일이 변경된 경우 다음과 같이 반영해준다.git submodule foreach git pull origin main git submodule foreach git add . git submodule foreach git commit -m "commit message" git submodule foreach git push origin main
SonarLint
Sonarqube / ESLint 등 정적테스트, Maven / Gradle 등을 활용한 Build, JUnit 등을 활용한 동적 테스트를 통해 Code로 조기에 문제를 발견할 수 있다.plugin에서 SonarLint를 다운받아 적용해준다.Multirun
로컬에서 서버를 띄울 때, Multirun 플러그인을 활용하면 쉽게 서버를 띄울 수 있다.배포 스크립트 작성하기
#!/bin/bash ## 변수 설정 txtrst='\033[1;37m' # White txtred='\033[1;31m' # Red txtylw='\033[1;33m' # Yellow txtpur='\033[1;35m' # Purple txtgrn='\033[1;32m' # Green txtgra='\033[1;30m' # Gray PROJECT_NAME=infra-subway-deploy BRANCH="$1" CASE="$2" SLACK_MESSAGE="Deployed New App Successfully!" SLACK_URL=[slack web hook url] echo -e "${txtylw}=======================================${txtrst}" echo -e "${txtgrn} << 스크립트 🧐 >>${txtrst}" echo -e "${txtylw}=======================================${txtrst}" function check_df() { git fetch master=$(git rev-parse $BRANCH > /dev/null 2>&1) remote=$(git rev-parse origin $BRANCH > /dev/null 2>&1) if [[ $master == $remote ]]; then echo -e "[$(date)] Nothing to do!!! 😫" exit 0 fi } ## 저장소 pull function pull() { echo -e "" echo -e ">> Pull Request 🏃♂️ " git pull origin yunhalee05 } ## 프로세스 pid를 찾는 명령어 function findProcess() { CURRENT_PID=$(pgrep -f java.*.jar) echo -e "" echo -e ">> Current pid 📡 : $CURRENT_PID" } ## 프로세스를 종료하는 명령어 function killProcess() { if [ -z "$CURRENT_PID" ]; then echo -e ">> There's no running app." else echo -e ">> Kill Process 🪓" kill -15 $CURRENT_PID sleep 5 fi } ## gradle build function gradleBuild() { echo -e ">> Build Gradle... ⌛️" ./gradlew clean build } ## 새 어플리케이션 배포 function deployNewApp() { JAR_FILE=$(./build/libs/subway-0.0.1-SNAPSHOT.jar) echo -e ">>" nohup java -jar -Dspring.profiles.active=prod & } function send_slack() { curl -X POST --data "payload={\"text\": \"${SLACK_MESSAGE}\"}" ${SLACK_URL} } function deploy(){ cd $PROJECT_NAME pull; findProcess; killProcess; gradleBuild; deployNewApp; send_slack; } check_df; case $CASE in -f) deploy; exit 0;; esac echo -e ">> ${txtred} Are you sure to deploy new APP 🤔? ${txtrst} [Y/N] " read react case $react in [Yy]* ) deploy; exit 0;; esac
추가로 메일로 결과를 받기 위해서는 다음과 같이 설정할 수 있다.
$ sudo apt update $ sudo apt upgrade $ sudo apt install mailutils $ vi mail.sh #!/bin/bash TO=$1 function send_mail() { echo "Hello, this is $(hostname). --- $(date)" | mail -s "Mail Test $(date)" $TO } send_mail $ ./mail.sh [받을 메일 주소]
이번에 crontab을 이용해서 정해진 시간마다 배포스크립트가 작동하도록 설정하자.
$crontab -e ## *(분 0-59) *(시간 0-23) *(일 1-31) *(월 1-12) *(요일 1-7) ## 매주 금요일 5시 45분마다 배포스크립트 동작 45 5 * * 5 /home/ubuntu/deploy.sh
( 참고한 사이트 )
프로젝트 공방
https://aws.amazon.com/ko/premiumsupport/knowledge-center/ec2-linux-resolve-ssh-connection-errors/
https://happy-coding-day.tistory.com/178?category=807028
https://deeplify.dev/back-end/spring/port-is-already-in-use
https://steady-coding.tistory.com/439
https://jerry92k.tistory.com/49?category=981718
https://github.com/occidere/TIL/issues/116
https://velog.io/@max9106/AWS-EC2-Reverse-Proxy-WAS-MySQL
https://hyeon9mak.github.io/reverse-proxy-was-db-infrastructure/
https://wlsvud84.tistory.com/32
https://velog.io/@nefertiri/AWS-EC2-%EC%84%9C%EB%B2%84%EC%97%90-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0
https://velog.io/@honux/Git-submodule-%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9%EB%B2%95-1
https://ecsimsw.tistory.com/entry/Flyway%EB%A1%9C-DB-Migration
https://hyeon9mak.github.io/reverse-proxy-was-db-infrastructure/
https://dev-coco.tistory.com/85
https://velog.io/@max9106/AWS-EC2-Reverse-Proxy-WAS-MySQL
https://stackoverflow.com/questions/64069312/ssh-connection-timed-out-on-ec2-ubuntu
https://happy-coding-day.tistory.com/178?category=807028
'네트워크 & 인프라' 카테고리의 다른 글
부하 테스트 ( + k6, grafana + influxdb, ngrinder) (0) 2022.04.14 웹 성능 진단하기 (0) 2022.04.14 Mac에서 docker, docker machine, virtualbox설치하기 (0) 2022.03.28 통신 확인하기 (0) 2022.03.23 통신망 ( + AWS 에서 망 분리하기) (0) 2022.03.23