[도커] docker, nginx 사용하여 로드 밸런싱, 무중단 배포하기
Docker

[도커] docker, nginx 사용하여 로드 밸런싱, 무중단 배포하기

728x90

 

 

 로드 밸런싱(load balancing)은 컴퓨터 네트워크 기술의 일종으로 둘 혹은 셋 이상의 중앙처리장치 혹은 저장장치와 같은 컴퓨터 자원들에게 작업을 나누는 것을 의미한다. (출처)

 nginx는 로드 밸런싱을 지원한다.

https://www.cloudv.kr/etc/lb.html

 

 시작하기 앞서 도커에 관한 기본 지식에 대해선 https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html을 참고하자.

 

초보를 위한 도커 안내서 - 도커란 무엇인가?

도커를 처음 접하는 시스템 관리자나 서버 개발자를 대상으로 도커 전반에 대해 얕고 넓은 지식을 담고 있습니다. 도커가 등장한 배경과 도커의 역사, 그리고 도커의 핵심 개념인 컨테이너와 이미지에 대해 알아보고 왜 이렇게 도커가 인기 인지 하나하나 살펴보겠습니다.

subicura.com

 실습은 집에 개인 서버로 구축해놓은 라즈베리파이에서 진행하였다.

 

1. 실습을 진행할 폴더 생성 및 이동

mkdir load_balancing
cd load_balancing

 

2. package.json 생성

npm init

 

3. express와 uuid 설치

 uuid는 컨테이너로 구축한 서버의 고유한 임의 ID값을 불러오기 위해 사용한다.

npm install --save express uuid

 

4. index.js 파일 작성

 index.js 파일을 작성해준다. uuid 모듈을 사용하여 서버 각각에 임의로 생성된 ID값을 부여해준다.

var express = require('express');
var app = express();

var uuid = require('uuid');
var id = uuid.v4();
var port = 3000;

app.get('/', (req, res) => {
	res.send(id);
});

app.listen(port, function(){
	console.log('port : ', + port);
});

 

5. 실행하여 정상적으로 출력되는지 확인

 서버 실행 후, 개인 컴퓨터로 실습을 한다면 localhost:3000으로 들어가 보자. 임의로 생성된 ID값이 출력되는 것을 확인할 수 있다. 

node index.js

 

 

6. docker 이미지 생성을 위한 Dockerfile 작성

 docker container에서 nodejs 서버를 구동하기 앞서 Dockerfile을 작성해주자. docker image를 만들 때 Dockerfile을 이용하면 간단하다. (Dockerfile의 D는 대문자여야 한다.)

FROM node:6

COPY package.json /src/package.json

RUN cd /src/; npm install

COPY . /src

EXPOSE 3000

WORKDIR /src

CMD node index.js

 

 Dockerfile 작성 요령에 대해선 https://mino-park7.github.io/docker/2018/12/10/dockerfile/을 참고하자.

 

Dockerfile 작성방법 및 읽는 법 · MinhoPark

 

mino-park7.github.io

 

7. docker 이미지 빌드하기

 작성한 Dockerfile로 docker 이미지를 생성한다. 처음 생성할 때는 시간이 조금 걸릴 수 있다.

docker build --tag [이미지 이름]:[태그] [Dockerfile이 위치하는 경로]
docker build --tag node_server:test .

 이미지가 생성되면 docker images 명령어로 생성된 이미지를 확인할 수 있다.

docker images

 

8. docker 컨테이너 생성

 만들어진 image로 컨테이너를 만든다. 

docker create --name [컨테이너 이름] -p [외부 포트]:[내부 포트] [이미지 이름]:[태그]
docker create --name NODE_SERVER_0 -p 3000:3000 node_server:test

 생성된 컨테이너는 docker ps -a 명령어로 확인할 수 있다.

docker ps -a

 

9. 컨테이너 실행

 생성한 컨테이너를 실행해보자. 

docker start [컨테이너 이름]
docker start NODE_SERVER_0

 이제 컨테이너 안에서 서버가 실행된다. 컨테이너를 생성할 때, 3000번 포트로 접근하면 컨테이너 내부의 3000 포트로 연결되게끔 설정해줬으므로 localhost:3000으로 들어가 본다.

 서버 임의의 ID값을 확인할 수 있다. 또한 실행 중인 컨테이너 목록은 docker ps 명령어로 확인 가능하다.

 

10. 컨테이너 여러 개 생성

 만들어뒀던 node_server 이미지로 컨테이너를 여러 개 생성해준다. 서버를 확장할 때 docker 이미지로 만들어두면 컨테이너만 만들면 돼서 쉽게 확장이 가능하다.

 3001번, 3002번 외부 포트를 사용하는 서버를 2개 더 만들었다. 3000번 포트는 NODE_SERVER_0에서 사용 중이므로 중복되지 않게 3001번과 3002번을 사용해준다. 이후 두 컨테이너도 실행해준다.

 두 컨테이너도 실행해주면 현재 총 3대의 컨테이너가 돌아간다. docker ps 명령어로 확인해본다.

 각각의 서버에 들어가 보면 서로 다른 ID값이 출력된다.

 

11. nginx 설치

 nginx로 로드 밸런싱을 하기 위해 nginx를 설치해준다.

sudo apt-get install nginx

 

12. nginx.conf 작성

 nginx.conf를 작성하기 위해 우선 nginx 폴더부터 만들어준다.

mkdir nginx
cd nginx

 nginx.conf에 아래의 코드를 삽입해준다. YOUR_IP_ADDRESS에는 본인의 ip 주소를 적어주면 된다.

worker_processes 4;

events { worker_connections 1024; }

http {
  upstream node-app {
    least_conn;
    server YOUR_IP_ADDRESS:3000 weight=10 max_fails=3 fail_timeout=30s;
    server YOUR_IP_ADDRESS:3001 weight=10 max_fails=3 fail_timeout=30s;
    server YOUR_IP_ADDRESS:3002 weight=10 max_fails=3 fail_timeout=30s;
  }

  server {
    listen 80;

    location / {
      proxy_pass http://node-app;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_cache_bypass $http_upgrade;
    }
  }
}

 

로드 밸런싱은 upstream 이라는 옵션으로 설정할 수 있는데, least_conn 은 연결이 가장 적은 서버로 트래픽을 전달하는 역할을 한다. 설정할 수 있는 옵션은 다음과 같다.

옵션 설명
p_hash 같은 방문자로부터 도착한 요청은 항상 같은 업스트림 서버가 처리 할 수 있게 한다.
weight=n 업스트림 서버의 비중을 나타낸다. 이 값을 2로 설정하면 그렇지 않은 서버에 비해 두배 더 자주 선택된다.
max_fails=n n으로 지정한 횟수만큼 실패가 일어나면 서버가 죽은 것으로 간주한다.
fail_timeout=n max_fails가 지정된 상태에서 이 값이 설정만큼 서버가 응답하지 않으면 죽은 것으로 간주한다.
down 해당 서버를 사용하지 않게 지정한다. `ip_hash;` 지시어가 설정된 상태에서만 유효하다.
backup 모든 서버가 동작하지 않을 때 backup으로 표시된 서버가 사용되고 그 전까지는 사용되지 않는다.
출처 : https://opentutorials.org/module/384/4328

 

13. nginx도 Dockerfile 작성

FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf

 

14. nginx 이미지 빌드하기

docker build --tag node_nginx:test .

 

15. nginx 컨테이너 생성 및 실행

 nginx 컨테이너도 생성한 후 실행해본다.

docker create --name NODE_NGINX -p 80:80 node_nginx:test
docker start NODE_NGINX

 http://localhost로 접속해보면 아까 봤던 서버 임의의 ID를 볼 수 있다. 하지만 nginx로 3개의 서버를 로드 밸런싱 해준 상태이므로 새로고침 할 때마다 ID값이 달라진다.

 

 

16. 정리

 클라이언트가 서버로 요청을 하면 세 개의 서버 중 한 곳으로 나누어서 요청을 보낸다. 이런 식으로 가용성 및 응답 시간을 최적화시킬 수 있다. 세 개의 서버 중 한 곳의 서버가 정지된다면 로드 밸런서는 살아 있는 두 서버로 요청을 보내게 된다. 실제로 docker를 사용할때는 docker-compose를 사용한다. docker-compose를 활용한 글은 docker-compose 사용 예시 글을 참고하자.

 하나의 서버만 돌리게 되는 경우엔 서버를 업데이트할 때 서버를 정지한 후 업데이트된 서버를 켜야 했지만, 이런 방식으로 운영하게 되면 언제나 하나 이상의 서버가 돌아가므로 무중단 배포가 가능해진다. 로드 밸런서가 서버를 선택하는 기준에는 Round Robin, Least Connections, Source가 있다고 한다. 이 부분에 대해선 다음에 공부해봐야겠다.

728x90

'Docker' 카테고리의 다른 글

[도커] docker-compose 사용 예시  (0) 2020.01.01
[도커] Docker Hub에 이미지 올리기  (1) 2019.12.31