앞서 작성한 code-server에 HTTPS를 적용해 보도록 하겠습니다. 이번 글에선 certbot의 nginx옵션 이용해 인증서를 발급받고 적용해 보도록 하겠습니다.

 

편의를 위해 code-server 설치와 nginx를 통한 역방향 프록시 설정에 대한 설명은 스킵하도록 하겠습니다.

 

 

 

01. code-server 설치 및 역방향 프록시 설정.

 

다음 글을 참고하여 code-server를 미리 준비합니다: https://smoh.tistory.com/456

 

[Ubuntu] 아이패드에서 code-server로 코딩 공부 해보기.

아이패드에서 프로그래밍 공부를 해보고자 여러 어플을 찾아봤습니다. 파이썬 같은 경우는 적당한 유료 어플이 있었지만 VSCode와 같은 무료면서 강력한 기능을 가진 어플은 없었습니다. 다양한

smoh.tistory.com

 

** 위 글에선 예시를 위해 AWS의 EC2를 사용하였습니다만 현재는 관리하는 서버에 code-server를 옮겨둔 상태입니다.

** NGINX를 통한 역방향 프록시 설정 방법은 별도로 설명하지 않습니다.

 

 

 

02. CERTBOT 설치.

 

만약 apt 같은 OS 패키지 관리자를 사용하여 설치된 Certbot 패키지가 있는 경우 기존 Certbot은 제거해야 합니다. 다음 명령어로 Certbot을 제거해 주세요.

sudo apt-get remove certbot

 

이제 snap을 사용해 최신 Certbot을 설치해 줍니다. 다음 명령어로 snap을 사용해 Certbot을 설치합니다.

sudo snap install --classic certbot

 

설치가 완료되면 다음 명령어를 실행해 certbot 명령을 실행할 수 있는지 확인합니다.

sudo ln -s /snap/bin/certbot /usr/bin/certbot

 

이제 다음 명령어를 수행해 인증서를 발급받습니다.

sudo certbot certonly --nginx

 

만약 nginx에 여러 개의 사이트가 등록되어 있으면 위의 그림처럼 리스트가 나열됩니다. 발급을 원하는 사이트의 번호를 입력합니다. 만약 입력하지 않는 경우 모든 사이트가 선택됩니다. 

 

이제 인증서 발급이 완료되었습니다. 인증서의 위치는 /etc/letsencrypt/live/사이트명 폴더에 저장됩니다.

 

 

 

03. NGINX 설정 변경.

 

다음 명령어를 통해 nginx의 설정 파일을 엽니다. 전 별도 설정 파일에 server 설정을 관리하고 있습니다. 설정 파일 이름은 사용자에 따라 다릅니다.

sudo vi /etc/nginx/conf.d/my-server.conf

 

설정 파일을 열고 다음과 같이 설정을 추가합니다.

#/etc/nginx/conf.d/my-server.conf
#code-server
server {
  listen 80;
  server_name your.domain.here;
  location / {
    proxy_pass http://localhost:{PORT};
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection upgrade;
    proxy_set_header Accept-Encoding gzip;
  }
  listen [::]:443 ssl ipv6only=on;
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/your.domain.here/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/your.domain.here/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

 

이제 다음 명령어로 nginx 서비스를 재시작합니다.

sudo service nginx restart

 

접속해서 확인해 봅시다.

 

 

도메인에 접속하면 https가 정상적으로 적용된 것을 확인할 수 있습니다.

 

 

 

 

 

 

반응형

https://dev.to/sowmenappd/build-a-highly-available-node-js-application-using-docker-nginx-and-aws-elb-3cjp

 

Docker, Express, NGINX, AWS ELB를 복합적으로 사용해 고가용성을 위한 애플리케이션 환경을 구축해 봅니다.

 

 

 

로드 밸런싱이 무엇인가요?

 

 

로드 밸런싱은 들어오는 네트워크 트래픽을 서버 그룹에 분산하는 데 사용되는 기술 혹은 알고리즘입니다. 모든 공용 사용자에게 서버에서 호스팅 하는 서비스에 대한 단일 진입점을 제공합니다.

 

프로덕션 서버는 일반적으로 로드 밸런서 뒤에서 실행됩니다. 서버 전체에서 들어오는 부하를 "균등"하게 나워 서버 과부하를 방지할 수 있기 때문입니다.

 

또한 로드 밸런서는 트래픽을 라우팅 하는 서버에 보조 기능을 제공합니다. 로드 밸런서는 역방향 프락시 역할을 합니다. 역방향 프락시는 서버 그룹과 사용자 간의 중개자와 같습니다. 역방향 프락시가 처리하는 모든 요청은 요청 조건에 따라 적절한 서버로 전달됩니다. 이런 방식으로 역방향 프락시는 구성파일, 토큰, 암호와 같은 민감한 데이터가 저장되는 주 서버에 대한 액세스를 방지하면서 서버의 ID를 익명으로 유지합니다.

 

 

 

로드 밸런서로서의 NGINX와 AWS ELB

 

NGINX는 역방향 프락시의 역할도 할 수 있는 빠른 무료 오픈소스 로드 밸런서입니다.

 

반면에 ELB는 아마존 AWS에서 제공하는 로드 밸런싱 서비스입니다. ELB는 ALB, CLB, NLB의 세 가지 유형이 있습니다. 게이트웨이 로드 밸런서라고 하는 새로운 로드 밸런서도 AWS가 제공하는 클라우드 서비스 제품군에 추가되었습니다.

 

이 튜토리얼의 아이디어는 다중 포트에서 실행되는 고 가용성 Node.js 서버를 제공할 수 있는 계단식의 다중 로드 밸런서 구조를 만드는 것입니다.

 

* 참고사항

Docker 애플리케이션을 위해 AWS의 자체 ECS, ECR 환경을 활용하는 방법을 포함해 AWS에서 Node.js 애플리케이션을 위한 인프라를 구축하는 방법에는 여러 가지 방법이 있습니다. 하지만 이 자습서에서는 이에 초점을 맞추지 않고 EC2 인스턴스, 로드 밸런서의 메커니즘, 로드밸런싱, 프락시 포트를 통해 Docker와 상호작용 하는 방법을 더 잘 이해하는 것을 목표로 합니다.

 

 

 

아키텍처 개요

 

 

이것이 우리가 목표로 하는 아키텍처입니다. AWS와 NGINX에서 관리하는 다중 로드 밸런서는 node 앱을 위한 EC2 인스턴스에서 여러 포트를 관리하는데 도움이 됩니다. 이 아키텍처의 장점은 두 인스턴스가 AZ1과 AZ2의 서로 다른 가용 영역을 가진다는 것입니다. 이로 인해 한 영역이 다운되더라도 다른 영역은 계속 동작할 것이며 두 애플리케이션은 충돌하지 않게 됩니다.

 

 

 

Node.js 앱

 

단순하게 하기 위해 다음과 같은 표준 스타터 express node 앱을 사용합니다:

 

const express = require("express");
const app = express();
const PORT = process.env.PORT;
const SERVER_ID = process.env.SERVER_ID;

app.get("/", (req, res)=>{
  res.send({server: SERVER_ID, port: PORT});
});

app.listen(PORT, ()=>{
  console.log(`Server ${SERVER_ID} is running at ${PORT}.`);
});

 

 포트는 환경변수의 PORT를 사용해 express 앱에 제공됩니다. Docker를 통해 이 포트 값을 제공할 것입니다. docker-compose를 이용하면 간단한 작업입니다. 또 다른 환경 변수인 SERVER_ID가 있지만 데모용일 뿐이므로 걱정하지 마세요.

 

전체 설정이 준비되면 SERVER_ID는 로드 밸런서가 응답을 가져오는 서버를 알려주는 데 사용됩니다. 이를 통해 다중 로드 밸런서 / 역방향 프락시를 사용하는 인프라 구성이 올바른 방식으로 실행되고 있는지 확인하는데 도움이 됩니다.

 

이러한 유형의 구성은 프로덕션 파이프라인에서 일반적인 구성입니다. 일반적으로 이 경우 기본 앱 서버는 VPC에 배치됩니다. 

 

한 가지 알아둘 점은 레벨 1 로드 밸런서가 실제 클라이언트의 요청을 처리하기 때문에 공용으로 분류되는 반면 레벨 2 로드 밸런서는 소스 간의 요청을 라우팅 하는 역할을 하는 내부의 로드 밸런서라는 것입니다.

 

 

 

EC2 서버 실행하기.

 

AWS 계정에 로그인하고 EC2 대시보드로 이동합니다. 다음 단계에 따라 새 서버를 설정하고 Docker를 사용할 준비를 합니다.

 

1. 대시보드에서 인스턴스 시작을 클릭합니다.

 

 

2. 빠른 시작 섹션에서 Amazon Linux 2 AMI를 선택합니다.

 

 

3. 인스턴스 유형에서 t2.micro를 선택합니다. 이 대신 원하는 다른 유형을 선택할 수도 있습니다.

 

 

4. 이 데모에서 두 인스턴스를 서로 다른 가용 영역에서 동작하길 원하므로 두 인스턴스를 별도로 시작해야 합니다. 이 글에서 리전은 ap-northeast-2 이므로 서브넷은 ap-northeast-2a를 선택했습니다.

 

 

5. 사용자 데이터 섹션 아래에 이 스크립트 코드를 붙여 넣어 node.js Docker 앱을 실행하기 위한 필수 소프트웨어를 설치하게 합니다.

 

 

#!/bin/bash
sudo amazon-linux-extras install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user
sudo chkconfig docker on
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo yum install -y gcc-c++ make
curl -sL https://rpm.nodesource.com/setup_14.x | sudo -E bash -
sudo yum install -y nodejs git

 

6. 스토리지 추가와 태그 추가 섹션은 기본값을 유지한 채 건너뜁니다.

 

7. 보안 그룹 우성의 경우 포트 22(SSH)와 80(HTTP)이 열려있는 새 보안 그룹을 생성합니다.

 

 

IP 범위의 경우 Anywhere  또는 MyIP*8을 선택할 수 있습니다. 테스트 용이므로 아무거나 선택해도 됩니다. 전 Anywhere인 0.0.0.0을 선택하였습니다.

 

8. 검토 및 시작 버튼을 클릭해 실행시킵니다.

 

9. 인스턴스에 SSH를 위한 새 키 페어를 생성합니다. 나중에 앱이나 내부 로드 밸런서에 대한 Docker 이미지를 빌드하는데 필요합니다.

 

 

이제 두 개의 인스턴스 중 첫 번째 인스턴스가 시작되었습니다. 동일한 단계를 거쳐 다음 인스턴스를 시작하고 서브넷 값을 앞서 생성한 값이 아닌 다른 값으로 변경하고 방금 생성한 SSH 키 페어를 사용해 두 번째 인스턴스를 생성합시다.

 

 

 

 

앱 컨테이너화와 NGINX 구성.

 

여기서는 앱을 위해 다음 저장소를 사용합니다: load_balanced_nodejs_app

 

sowmenappd/load_balanced_nodejs_app

Source code for docker configuration of highly available Node JS app configured with NGINX running on multiple ports - sowmenappd/load_balanced_nodejs_app

github.com

 

이를 통해 프로세스 속도를 높일 수 있습니다. 저장소의 계층을 보자면 다음과 같습니다.

 

 

앱 폴더에는 Dockerfile과 함께 노드 서버 소스 코드가 포함되어 있습니다. nginx 폴더에는 업스트림 서버 포트 구성을 정의하는 구성 파일인 nginx.conf가 있으며 다음과 같습니다:

 

http{    
    upstream lb {        
        server 172.17.0.1:1000 weight=1;        
        server 172.17.0.1:2000 weight=1;        
        server 172.17.0.1:3000 weight=1;    
    }     
    server {        
        listen 80;        
        location / {            
            proxy_pass http://lb;        
        }    
    }
}

 

이 구성 파일은 메인 NGINX 서버가 포트 80번에서 동작한다고 지정하고 루트 위치 "/"은 lb라는 이 구성 파일에 정의된 업스트림으로 요청(프락시 패스)을 릴레이 합니다. lb는 서버 수를 지정하는 업스트림 객체이며 이 객체는 포함될 서버의 수와 이러한 서버가 내부적으로 실행될 포트를 지정합니다. 여기서 포함될 서버란 docker-compose를 통해 마운트 되는 서버이며 이는 이후 섹션에서 좀 더 자세히 다룹니다. 프락시는 80번 포트의 트래픽 부하를 분산시키게 됩니다. 

 

우리의 경우 업스트림 프락시는 트래픽을 1000번, 2000번, 3000번 포트로 보냅니다. 이 포트 번호는 docmer-compose YAML 파일에서 작성되는 env 변수로 익스프레스 서버 인스턴스에 전송되는 내부 PORT 값과 일치해야 합니다. 

 

각각의 시작되는 인스턴스에 대해 다음 작업을 수행해 줍니다.

 

1. 생성했던 키 페어를 이용해 인스턴스에 SSG로 연결합니다.

 

2. 다음 터미널 명령을 수행해 dockerfile로 앱 이미지를 빌드합니다.

 

git clone https://github.com/sowmenappd/load_balanced_nodejs_app.git
cd load_balanced_nodejs_app/app
docker build -t app .

 

 

3. 다음으로 NGINX 서버 이미지를 빌드합니다.

 

cd ../nginx
docker build -t nginx-s .

 

 

4. docker images 명령어를 실행 해 다음과 같은 내용이 표시되는지 확인합니다.

 

 

5. 두 번째 서버는 docker-compose.yml 파일을 수정해야 합니다. env 변수중 SERVER_ID는 모든 앱인 app1, app2, app3에 대해 2로 변경해야 합니다.

 

 

걱정하지 마세요 프로덕션 서버에서는 이런 일을 할 필요가 없습니다. 이는 데모 목적만을 위한 것입니다.

 

6. 마지막으로 다음 명령어를 실행합니다.

 

cd ..
docker-compose up -d

 

격리된 서버는 이제 백그라운드에서 세 개의 express 앱을 실행하게 됩니다. 이제 필요한 것은 AWS가 제공하는 로드 밸런서인 AWS ALB를 사용하여 이 시스템을 마운트 하는 것입니다.

 

 

 

AWS ALB에 시스템 마운트 하기.

 

이제 두 인스턴스 모두 마운트 할 준비가 되었습니다. 다음 단계를 따라 AWS에 애플리케이션 로드 밸런서를 설정하도록 합시다.

 

1. EC2 대시보드의 대상 그룹으로 이동해 대상 그룹을 만듭니다.

 

 

2. 대상 유형은 인스턴스를 선택 한 뒤 대상 그룹 이름을 작성하고 다음을 클릭하세요.

 

 

3. 실행 중인 두 인스턴스를 선택하고 선택한 인스턴스를 위한 포트를 80으로 설정한 뒤 아래에 보류 중인 것으로 포함 버튼을 클릭합니다.

 

 

4. 보류 중인 항목에 추가된 인스턴스를 확인한 뒤 대상 그룹을 생성합니다.

 

 

5. 이제 로드 밸런서로 이동해 로드 밸런서 생성 버튼을 클릭한 뒤 Application Load Balancer 생성을 클릭합니다.

 

 

6. 앞서 인스턴스를 생성할 때 선택한 가용 영역을 고른 뒤 계속합니다.

 

 

7. 보안 그룹 구성으로 이동해 모든 IP에 대해 80번 포트가 열려있는 새 보안 그룹을 만들고 다음을 클릭합니다.

 

 

8. 라우팅 구성에서 앞서 기존 대상 그룹을 고른 뒤 앞서 생성한 대상 그룹을 선택합니다.

 

 

9. 설정을 검토 한 뒤 로드 밸런서를 생성합니다. 로드 밸런서는 생성 후 상태 확인을 실행 한 뒤 몇 분 내로 실행되어야 합니다.

 

 

이제 EC2 대시보드의 로드 밸런서에서 방금 생성한 로드 밸런서의 DNS이름을 복사합니다. 

 

 

이 DNS 주소를 브라우저에 붙여 넣고 엔터를 누르세요. 브라우저를 새로 고칠 때마다 SERVER_ID와 PORT가 다른 값을 전송하는 것을 볼 수 있습니다.

 

 

이는 기본적으로 NGINX와 AWS 로드 밸런서가 로드 밸런싱을 위해 기본적으로 라운드 로빈 알고리즘을 사용하기 때문입니다.

 

 

 

맺는 글.

 

이렇게 배포된 시스템은 다중 로드 밸런서의 구성을 통해 높은 가용성을 보장하고 오랜 기간 동작하는 동안 많은 양의 트래픽을 견딜 수 있게 되었습니다. 이 자습서를 뒤이어 소스 제어와 통합 배포 파이프라인을 관리하고 GitHub 저장소에 커밋할 때 변경사항을 서버에 배포하는 방법을 보여주는 또 다른 기사를 게시할 예정입니다.

 

해당 글은 다음 글을 참고해 번역한 글입니다: Build a highly available Node.js application using Docker, NGINX and AWS ELB

 

Build a highly available Node.js application using Docker, NGINX and AWS ELB

What is load balancing? Load balancing is a technique(algorithm) used to distribute incomi...

dev.to

 

 

 

 

 

 

반응형

https://dev.to/vishnuchilamakuru/nginx-cheatsheet-24ph

 

NGINX는 웹 서비스, 역방향 프록시, 캐싱, 로드밸런싱, 미디어 스트리밍등을 위한 오픈소스 소프트웨어 입니다. 이 글에서는 자주 사용하는 NGINX 구성을 몇가지 다루도록 하겠습니다.

 

 

 

1. Listen To Port

 

server {
  # Standard HTTP Protocol
  listen 80;

  # Standard HTTPS Protocol
  listen 443 ssl;

  # Listen on 80 using IPv6
  listen [::]:80;

  # Listen only on using IPv6
  listen [::]:80 ipv6only=on;
}

 

 

 

2. Access Logging

 

server {
  # Relative or full path to log file
  access_log /path/to/file.log;

  # Turn 'on' or 'off'
  access_log on;
}

 

 

 

3. Domain Name

 

server {
  # Listen to yourdomain.com
  server_name yourdomain.com;

  # Listen to multiple domains
  server_name yourdomain.com www.yourdomain.com;

  # Listen to all domains
  server_name *.yourdomain.com;

  # Listen to all top-level domains
  server_name yourdomain.*;

  # Listen to unspecified Hostnames (Listens to IP address itself)
  server_name "";

}

 

 

 

4. Static Assets

 

server {
  listen 80;
  server_name yourdomain.com;

  location / {
          root /path/to/website;
  } 
}

 

 

 

5. Redirect

 

server {
  listen 80;
  server_name www.yourdomain.com;
  return 301 http://yourdomain.com$request_uri;
}

 

server {
  listen 80;
  server_name www.yourdomain.com;

  location /redirect-url {
     return 301 http://otherdomain.com;
  }
}

 

 

 

6. Reverse Proxy

 

server {
  listen 80;
  server_name yourdomain.com;

  location / {
     proxy_pass http://0.0.0.0:3000;
     # where 0.0.0.0:3000 is your application server (Ex: node.js) bound on 0.0.0.0 listening on port 3000
  }

}

 

 

 

7. Load Balancing

 

upstream node_js {
  server 0.0.0.0:3000;
  server 0.0.0.0:4000;
  server 123.131.121.122;
}

server {
  listen 80;
  server_name yourdomain.com;

  location / {
     proxy_pass http://node_js;
  }
}

 

 

 

8. SSL

 

server {
  listen 443 ssl;
  server_name yourdomain.com;

  ssl on;

  ssl_certificate /path/to/cert.pem;
  ssl_certificate_key /path/to/privatekey.pem;

  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_trusted_certificate /path/to/fullchain.pem;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_connection_timeout 1d;
  ssl_session_cache shared:SSL:50m;
  add_header Strict-Transport-Security max-age=15768000;
}

# Permanent Redirect for HTTP to HTTPS
server {
  listen 80;
  server_name yourdomain.com;
  return 301 https://$host$request_uri;
}

 

 

 

개인적으로 사용하는 서버에서 NGINX를 사용하고 있습니다. dev.to를 보던 중 저장해 두고 필요할 때마다 참고하기 위해 포스팅 하였습니다. 해당 글의 출처는 다음과 같습니다: Nginx Cheatsheet

 

Nginx Cheatsheet

Nginx is open-source software for web serving, reverse proxying, caching, load balancing, media strea...

dev.to

 

 

 

 

 

 

반응형

 

Ubuntu 20.04에 설치된 pgAdmin4의 여러 설정을 변경하는 방법에 대해 알아봅니다.

 

다음 글을 참고해 Postgresql 및 pgAdmin4를 준비합니다.

제 서버에선 NGINX가 돌고 있어서 pgAdmin4 설치 후 Apache Web Server 실행 도중 에러가 나 NGINX를 잠시 끈 상태로 설치를 했습니다.

 

계속 이렇게 둘 순 없어서 NGINX와 pgAdmin4를 동시에 사용할 수 있는 방법에 대해 알아봤습니다. 가장 먼저 Apache Web Server의 기본 동작 포트를 변경하도록 합니다.

 

> sudo vi /etc/apache2/port.conf

 

 

적당한 값으로 변경합니다. 다음으로 virtual host의 포트 정보도 변경해야 합니다.

 

> sudo vi /etc/apache2/sites-enabled/000-default.conf

 

 

앞서 변경한 값으로 맞춰줍니다. 이제 Apache Web Server를 재시작합니다.

 

> sudo service apache2 restart

 

그 후 http://your.domain.com:8080/pgadmin4로 접속합니다. 

 

 

정상 동작이 확인됩니다. 이제 NGINX 설정을 변경합니다.

 

> sudo vi /etc/nginx/conf.d/my-server.conf

 

 

** conf 파일의 위치 및 이름은 NGINX 구성에 따라 달라질 수 있습니다.

 

NGINX를 재시작합니다.

 

> sudo service niginx restart

 

이제 외부에서 http://your.domain.com/pgadmin4를 이용해 pgadmin4에 접속할 수 있습니다.

 

 

 

 

 

반응형

 

413 Request Entity Too Large 에러 발생 시 해결 방법에 대해 알아봅니다.

 

 

 

1. 원인

 

Nginx에 설정해둔 요청 사이즈 제한을 초과한 요청이 들어온 경우 발생하는 에러입니다.

 

 

설정 파일에 "client_max_body_size"로 값을 설정할 수 있습니다. 만약 설정해 두지 않았다면 기본값은 1M가 됩니다. 즉 1M가 넘는 요청이 들어오면 414 에러가 발생합니다. 

 

 

 

2. client_max_body_size

 

client_max_body_size은 다음과 같이 설정할 수 있습니다.

 

#Syntax: client_max_body_size size; 
#Default: client_max_body_size 1m; 
#Context: http, server, location
http {
  client_max_body_size 10M;
  ...
}

 

기본값은 1M이며 만약 제한을 두고 싶지 않을 경우 0으로 설정하면 됩니다.

 

 

3. 해결방법

 

config에서 client_max_body_size를 수정 혹은 추가해줍니다.

 

http {
  client_max_body_size 0;
  ...
}

 

저장 후  nginx를 재시작해주시면 정상적으로 동작합니다.

 

 

 

 

 

반응형

 

앞선 글에서 Express를 이용해 클러스터를 구성해 여러 워커를 가진 서버를 띄워보았습니다. 이번에는 제작한 웹 서버를 이용해 이중화 구성을 한 뒤 nginx를 이용해 로드밸런서를 만들어 그럴듯한 운영 환경을 구성해 보도록 하겠습니다.

 

 

 

0. 사전 준비.

 

이 글에서는 앞선 글에서 작성한 웹 서버를 사용합니다. 이전 글을 참고해 웹 서버를 준비해 주세요.

Nginx를 사용할 예정이니 미리 서버를 다운로드하여 주셔도 좋습니다. 단, Docker를 이용하실 분은 별도의 Nginx를 준비하지 않으셔도 됩니다.

모든 결과물을 한번에 배포하기 위해 docker-compose를 사용할 예정입니다. docker-compose를 준비해 주세요.

 

 

 

1. Nginx를 이용한 이중화 구성.

 

이제 우리가 만든 서버는 여러 개의 워커를 갖고 도커 위에서 동작합니다. 이제 안정성을 위해 두 개의 서버를 올려두고 그 앞에 Nginx를 둬서 로드밸런서의 역할을 하도록 합시다.

 

우리가 할 일은 단지 nginx의 config파일을 추가하는것 뿐 입니다. 아무런 추가 작업을 진행하지 않은 채 설정 파일을 추가해 주는 것만으로도 로드밸런서를 구성할 수 있습니다.

 

새로운 폴더인 my-nginx를 생성하고 그 안에 nginx 폴더를 만들어줍니다. 그리고 그 안에 nginx.conf 파일을 작성합니다.

 

#./nginx/nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

 

사실 위의 설정파일은 nginx를 설치하면 가장 기본으로 들어가 있는 값입니다. 스킵하셔도 무방합니다만 나중에 수정된 값을 사용할 수 있으므로 넣어주었습니다.

 

설정 파일을 살펴봅시다. nginx.conf의 맨 아래 include를 보세요. 이 include가 의미하는 바는 /etc/nginx/conf.d폴더 내의 모든 conf파일을 가져와 http 아래에 두겠다는 뜻입니다.

 

따라서 우리가 다음에 작성할 설정 파일이 바로 아래 추가될 것이란 의미가 됩니다. 이 외에도 nginx의 default 페이지가 담긴 default.conf도 추가될 것입니다. 

 

 

그다음으로nginx 안에 conf.d 폴더를 생성 한 뒤 my-react-lb.conf파일을 작성합니다.

 

# ./nginx/conf.d/my-react-lb.conf

upstream my-react {
    #least_conn;
    #ip_hash;
    server localhost:3000 weight=10 max_fails=3 fail_timeout=10s;
    server localhost:3001 weight=10 max_fails=3 fail_timeout=10s;
}    
server {
    listen                8080;
    server_name  localhost;
    location / {
        proxy_pass http://my-react;
    }
}

 

이 파일의 폴더 경로도 실제 리눅스 시스템에서 nginx가 위치하는 폴더의 경로를 맞추기 위함이므로 임의의 폴더에 작성하셔도 됩니다.

 

server항목을 먼저 봅시다. 이 서버는 8080 포트에서 동작하고 리버스 프록시로 동직 합니다. 즉, localhost:8080으로 들어오면 내부적으로 my-react로 연결시킨다는 뜻입니다. 이때 연결하는 my-react가 위에서 정의한 upstream입니다.

 

upstream 내부에 두 개의 서버가 정의되어 있습니다. 유저가 들어올 때마다 번갈아 가면서 3000, 3001 포트에 올라간 서버가 접속을 수용할 겁니다. 정리하자면 localhost:8080으로 접속하게 되면 내부적으로 로드밸런싱을 거쳐 localhost:3000, locahost:3001로 이동하게 된다는 겁니다.

 

주석 처리한 least_conn은 번갈아 가면서 수용하는 게 아닌 현재 접속이 가장 적은 곳에 우선 접속할 수 있도록 하는 기능이며 ip_hash는 접속한 사용자의 ip를 해싱해서 같은 사용자는 같은 서버로 접속할 수 있게 해 세션 문제 등을 해결할 수 있도록 하는 기능입니다.

 

따라서 메인 서버에 위의 설정 파일을 갖는 nginx를 설치한 뒤 Docker로 3000, 3001 포트에 앞서 작성한 웹 서버를 두대 올려 둔 후 localhost:8080으로 접속하면 정상적으로 로드밸런싱이 동작할 겁니다. 

 

 

 

2. Docker compose를 이용해 한번에 배포하기.

 

 

사실 위와 같이 배포하기 위해서는 서버에 nginx를 직접 설치해야 하며 그 서버에서 Docker가 동작 해 웹서버가 돌아야 합니다. 즉, nginx가 돌아가는 localhost에 웹서버가 동작해야 한다는 뜻입니다.

 

서버에 접속해 nginx를 설치하고 conf 파일을 수정해준 뒤 그 서버에 docker를 설치하고 docker 명령어로 두 개의 웹서버를 실행시키는 과정이 필요하게 됩니다. 이것만 해도 귀찮아지기 시작합니다. 게다가 수작업이 들어가는 만큼 오류의 가능성도 높아집니다.

 

이제 좀 더 편하게 위 과정을 다음과 같이 변경할 겁니다.

  1. Nginx를 직접 설치하지 않고 Docker Image로 빌드 해 Docker 명령어로 배포한다
  2. 명령어를 미리 작성해 둬 한번에 여러 이미지를 배포한다.

그러기 위해선 docker-compose와 nginx를 docker image로 빌드하는 작업이 필요합니다. 우선 nginx를 docker image로 빌드하기 위해 Dockerfile을 작성합니다.

 

# ./Dockerfile

FROM nginx:stable

COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./nginx/conf.d/my-react-lb.conf /etc/nginx/conf.d/my-react-lb.conf

CMD ["nginx", "-g", "daemon off;"]

 

매우 간단합니다. nginx 안정화 버전을 받아 우리가 작성한 conf파일을 복사 한 뒤 실행합니다. 이제 다음 명령어로 docker image를 빌드합니다.

 

$ docker build . -t my-nginx:0.0.1

 

그리고 빌드한 이미지를 실행해 봅시다. 

 

$ docker run -itd -p 3000:3000 my-react:0.0.1

$ docker run -itd -p 3001:3000 my-react:0.0.1

$ docker run -itd -p 8080:8080 my-nginx:0.0.1

 

localhost:8080으로 이동하면 어떻게 될까요?

 

 

에러가 보이는 이유에 대해 생각해 봅시다. 우리는 nginx를 도커로 돌렸으며 my-react-lb.conf의 upstream에 server로 localhost:3000와 localhost:3001을 등록했습니다. 과연 nginx 컨테이너 내에서 이 두 서버에 접속할 수 있을까요?

 

궁금하신 분은 다음 명령어로 한번 테스트해보시기 바랍니다.

 

$ docker exec -u 0 -it (my-nginx 컨테이너 ID) bash

$ apt-get update

$ apt-get intall telnet

$ telnet localhost 3000

 

당연히 독립된 네트워크 이므로 접속을 할 수 없습니다.

 

 

그러므로 우리는 Docker compose를 이용해야 합니다. Docker compose는 같이 배포되는 컨테이너끼리 미리 정의된 이름으로 접속이 가능합니다. 마치 도메인 네임처럼 말입니다.

 

최상위 폴더로 이동해 docker-compose.yml 파일을 생성합니다 저 같은 경우엔 my-react와 my-nginx를 포함하고 있는 폴더에 작성하였습니다.

 

 

그리고 docker-compose.yml을 다음과 같이 작성해 줍니다.

 

# docker-compose.yml

version: "3"
services:
    my-react-A:
        image: my-react:0.0.1
        ports:
            - "3000:3000"
    my-react-B:
        image: my-react:0.0.1
        ports:
            - "3001:3000"
    nginx:
        image: my-nginx:0.0.1
        ports:
            - "8080:8080"

 

여기서 서비스 항목을 봅시다. 우리는 my-react-A, my-react-B, nginx 이렇게 총 세 개의 컨테이너를 생성하도록 작성하였습니다. 당연히 이름은 변경해도 됩니다. 서비스 내의 image는 도커 이미지를 의미합니다. ports는 docker run의 -p 옵션과 동일합니다. 

 

이런 식으로 docker-compose를 구성하게 되면 위의 세 컨테이너 간에는 서비스에 작성한 이름으로 서로 접근이 가능해집니다. 따라서 우리의 my-react-lb.conf가 바뀌어야 함을 의미하죠.

 

# ./nginx/conf.d/my-react-lb.conf

upstream my-react {
    #least_conn;
    #ip_hash;
    server my-react-A:3000 weight=10 max_fails=3 fail_timeout=10s;
    server my-react-B:3000 weight=10 max_fails=3 fail_timeout=10s;
}    
server {
    listen                8080;
    server_name  localhost;
    location / {
        proxy_pass http://my-react;
    }
}

 

그리고 다시 도커 이미지를 빌드해 줍니다.

 

$ docker build ./my-nginx -t my-nginx:0.0.2

 

잊지 마세요. 태그에 버전을 0.0.2로 변경하였으므로 당연히 docker-compose를 변경해야 합니다. 이제 docker-compose를 통해 컨테이너를 올려보겠습니다.

 

$ docker-compoase up -d

 

우리가 작성한 docker-compomse파일 대로 컨테이너가 실행되었습니다. 이제 localhost:8080으로 이동해 보세요. react페이지가 보이시나요? 

 

그렇다면 우리가 어떤 서버로 접속했는지 알아보기 위해 localhost:8080/where로 이동해 봅시다.

 

 

위와 같이 접속할 때마다 서버 정보가 변경되는 것을 확인할 수 있습니다. 실제 운영환경에선 이렇게 하면 서버가 바뀌며 세션정보가 유실되므로 앞서 설명한 ip_hash와 least_conn옵션을 켜고 서버를 배포해야 합니다.

 

 

 

 

 

 

반응형

+ Recent posts