Nginx 설치 및 로드밸런싱과 무중단 배포(+Docker)

devdo·2022년 2월 24일
0

Docker

목록 보기
8/9

소프트웨어에서의 로드밸런싱

기본적으로 Reverse Proxy를 기반으로 동작한다.

로드밸런싱 소프트웨어 종류

1) Nginx
오픈소스 소프트웨어
특정 알고리즘은 Nginx Plus에서만 사용이 가능하다.

2) HAProxy
오픈소스 소프트웨어
여러 로드밸런싱 기능을 지원한다.


Nginx로 로드밸런싱 구현

https://velog.io/@mooh2jj/docker-jenkins-github-%EB%B0%B0%ED%8F%AC

이 블로그를 기반으로 다음을 진행했습니다.

Nginx는 리버스 프록시, 로드밸런싱을 위해 서버를 감추기 위한 웹서버입니다. 실습을 위해서 nginx 인스턴스를 따로, jenkins로 배포할 원격 ssh 인스턴스 3개를 가지고 진행하겠습니다.


Nginx 설치 및 실행

# ubuntu 기준
sudo apt-get install nginx -y 
sudo systemctl start nginx
sudo systemctl enable nginx
ps -ef | grep nginx ( nginx 프로세스 상태 확인 )

restart vs reload

sudo systemctl restart nginx
sudo systemctl reload nginx
  • restart
    서버를 shutdown 한 뒤 재 기동, 즉 서버가 운영되지 않는 시간이 존재
    설정 파일에 문법적 에러가 존재할 경우, 서버는 죽게 된다.

  • reload
    새로운 설정 파일을 반영할 때 서버는 살아서 동작한다.
    설정 파일에 문법적 에러가 존재할 경우, reload는 실패하지만 서버는 기존 설정을 기반으로 정상적으로 동작한다.


Docker로 설치 및 실행

sudo docker run --name webserver -d -p 80:80 nginx

[설치 ip주소]:80 or [설치 ip주소] 을 치면 화면에 나오는지 확인합니다.

로컬에서 설치했다면 http://localhost:80 으로 확인합니다.


Nginx 정지

# ngnix 중지
sudo docker stop [nginx containerID] or webserver
# ngnix 시작
sudo docker start [nginx containerID] or webserver

Jenkins SSH 서버 추가

이제 로드밸런싱 확인을 위해 Jenkins 인스턴스로 돌아가는 SSH 인스턴스 3개를 준비합니다.
Jenkins 인스턴스가 SSH 인스턴스를 접속하게 만드는 방법은 다음 블로그를 참조하였습니다.

https://velog.io/@mooh2jj/JeinkinsDocker-명령어로-AWS-EC2서버-publish-over-ssh-배포하기

각 SSH 인스턴스에는 docker 명령어가 내려지니

# ec2 인스턴스 재시작 이후에도 docker 연결이 될 수 있음!
sudo usermod -aG docker ${USER}

# 그룹에 대한 변경 사항을 활성화
newgrp docker

# docker 재시작 -> 안해도 됨!
# sudo systemctl restart docker

or

# 2) /var/run/docker.sock 접근 권한 허용
sudo chmod 666 /var/run/docker.sock (비추)

이 명령어로 Permission 문제를 해결해주면 됩니다.

그리고 SSH 서버를 n개 이상 더 추가할려면 Jenkins 홈페이지 > Jenkins 관리 > 환경설정 > Publish over SSH 에 가면 SSH 서버 Add 버튼을 누르고 jenkins 공개키를 등록한 SSH 인스턴스 네임, ip주소 를 넣어주어 추가해줘야 됩니다.

그다음 Item 프로젝트 > 구성 에서
SSH서버execute shell 또 추가해주어야 합니다.


Nginx 로드밸런싱 conf 파일 작성

자 nginx 인스턴스에 가서 리버스 프록시 설정과 로드밸런싱 설정을 위한 conf 파일을 열어 봅니다.

nginx 설정파일 찾기(nginx.conf)

  • Ubuntu
vim /etc/nginx/nginx.conf 
  • Docker
docker exec -it {nginx docker container ID} bash
## 기존 default nginx conf 파일 삭제
sudo rm -rf /etc/nginx/sites-enabled/default

bash에 들어가서 vi 편집기 설치

cat /etc/issue
# 데비안 확인

apt-get upgrade
apt-get update

apt-get install vim
# load-balancing.conf는 새로 만들어준다.
sudo vi /etc/nginx/conf.d/load-balancing.conf

이렇게 아래 내용으로 바꿔줍니다.

upstream cpu-bound-app { ## cpu-bound-app이라고 네임을 지정할 수 있다.
	## 기본: 라운드 로빈
  server {instance_1번의_ip}:{지정한 포트번호};
  server {instance_2번의_ip}:{지정한 포트번호}; 
  server {instance_3번의_ip}:{지정한 포트번호}; 

}

server {
		listen     80;     
    
		location / {
			proxy_pass http://cpu-bound-app;	## 지정 네임으로 요청하기
	        proxy_redirect      off;
	        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;
		}

	}

이로써,

  • 80번 포트에 요청이 들어오면 {지정한 포트번호}들에 열려있는 3개의 서버로 로드밸런싱이 진행된다.
  • 요청 받는 방식 알고리즘(기본: round-robin)
round-robin(디폴트) - 그냥 돌아가면서 분배한다.
hash - 해시한 값으로 분배한다 쓰려면 hash <> 형태로 쓴다. ex)hash $remote_addr <- 이는 ip_hash와 같다.
ip_hash - 아이피로 해싱해서 분배한다.
random - 그냥 랜덤으로 분배한다.
least_conn - 연결수가 가장 적은 서버를 선택해서 분배, 근데 가중치를 고려함
least_time - 연결수가 가자 적으면서 평균 응답시간이 가장 적은 쪽을 선택해서분배
  • 이제 nginx를 재가동 시켜주면 된다.
sudo systemctl restart nginx

그리고 실제 nginx ip주소로 애플리케이션이 실행되는지 확인합니다.

url : {nginx ip주소}:80


Nginx 확인

ps -ef | grep nginx

netstat -antup | grep LISTEN

80포트가 정상적으로 열렸는지 확인

# nginx 문법 테스트 명령어
sudo nginx -t  
# Nginx error log 확인 tail -f 는 끝까지 log를 보는 리눅스 명령어
sudo tail -f /var/log/nginx/error.log

무중단 배포 : sleep

배포를 하는 동안 인스턴스가 내려가기 때문에 사용자가 502에러같은 사이트 중단을 경험할 수 있습니다. 그래서 사이트가 내려가지 않는 무중단 배포를 해야 하는데 여러가 지 방법이 있지만 인스턴스 사이에 딜레이를 주는 방법인 sleep을 이용해 보겠습니다.

SSh 인스턴스2번과 3번 Exec commaned 에 30초 정도 딜레이를 줄 수 있게 sleep 30을 추가 하겠습니다.

# 인스턴스 2번, 3번에 추가
sleep 30
sudo docker rm -f $(sudo docker ps -aq)
sudo docker rmi -f mooh2jj/docker-test
sudo nohup docker run -p 8080:8080 mooh2jj/docker-test > /dev/null 2>&1 &

이러면 사용자가 배포하는 동안에 사용자의 요청에도 사이트가 502에러가 나는 상황을 막을 수 있었습니다.



참고

profile
배운 것을 기록합니다.

0개의 댓글