로드 밸런싱(load balancing)은 컴퓨터 네트워크 기술의 일종으로 둘 혹은 셋 이상의 중앙처리장치 혹은 저장장치와 같은 컴퓨터 자원들에게 작업을 나누는 것을 의미한다. (출처)
nginx는 로드 밸런싱을 지원한다.
시작하기 앞서 도커에 관한 기본 지식에 대해선 https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html을 참고하자.
실습은 집에 개인 서버로 구축해놓은 라즈베리파이에서 진행하였다.
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/을 참고하자.
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가 있다고 한다. 이 부분에 대해선 다음에 공부해봐야겠다.
'Docker' 카테고리의 다른 글
[도커] docker-compose 사용 예시 (0) | 2020.01.01 |
---|---|
[도커] Docker Hub에 이미지 올리기 (1) | 2019.12.31 |