Nginx Reverse Proxy Server 구축

Harry Lee·2023년 4월 9일
0
post-thumbnail

개요

Nginx reverse proxy server 구축 과정 및 방법 설명

목표

  • Reverse Proxy Server로 활용하여 Master, Slave 서버 간 custom health check를 통해 동적으로 nginx 내 upstream을 변경하는 기능(Load Balancing)을 구현 예정

환경 세팅

Nginx 설치

1. sudo apt update
2. sudo apt upgrade
3. sudo apt install nginx
4. sudo service nginx start
5. 127.0.0.1에서 nginx 서버 정상 실행 확인 가능

OpenResty

Nginx를 기반으로 한 웹 애플리케이션 서버 프레임워크. Nginx Module의 장점을 활요하여 다양한 Lua 라이브러리를 제공. Lua를 이용하여 Nginx의 기능을 확장, 높은 트래픽 처리 가능.

  • Nginx가 HTTP, TCP proxy와 웹 서버 기능 등은 훌륭하나 코드 베이스의 커스텀 로직을 반영하기는 어려움이 있음
  • Lua script를 사용해 커스텀 로직을 개발하면 nginx에서 지원하지 않는 기능(동적 응답 생성, 백엔드 서버의 health check 등)을 추가 가능
  • 하지만 Nginx 자체적으로 Lua script를 직접 실행할 수 있는 기능을 제공하지 않아 OpenResty 프레임워크를 사용하여 nginx에서 Lua script를 실행할 수 있도록 지원

설치

1. sudo service nginx stop # 실행중인 nginx를 멈춰 OpenResty 설치에 충돌이 일어나지 않도록 함
2. install OpenResty framework
3. sudo apt-get install libreadline-dev libncurses5-dev libpcre3-dev libssl-dev perl make build-essential # OpenResty를 빌드하고 실행하는데 필요한 dependency들을 설치
4. wget [https://openresty.org/download/openresty-1.19.9.1.tar.gz](https://openresty.org/download/openresty-1.19.9.1.tar.gz) # 웹사이트에서 OpenResty 소스 코드 다운
5. tar -xzf openresty-1.19.9.1.tar.gz # 압축 풀기
6. cd openresty-1.19.9.1/
7. ./configure --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_realip_module --with-http_stub_status_module --prefix=/opt/openresty # 지정된 옵션대로 빌드 환경을 설정하는 configure script를 실행.make # OpenResty binary들과 module들을 빌드sudo make install # 지정된 디렉토리에 OpenResty 설치
8. export PATH=/opt/openresty/nginx/sbin:$PATH # Nginx 실행 파일을 찾아서 실행시킬 수 있도록 하기 위해 시스템 PATH에 OpenResty 'sbin' 디렉토리를 추가

resty.http 설치

1. sudo apt-get install luarocks # lua module 설치에 필요한 luarocks 패키지 설치
2. sudo luarocks install lua-resty-http
3. sudo service nginx start # 서버 재시작

nginx.conf

worker_processes auto;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 1024;
}

http {
        server {
                listen 80; # Port
                server_name 127.0.0.1; # Proxy server IP

                location / {
                        set $ip 127.0.0.1;
                        set $master_port 7000;
                        set $slave_port 7001;
                        set $endpoint /status;
                        set $upstream ''; # Proxy 서버가 연결할 실제 서버를 담을 변수
                        access_by_lua_file "/etc/nginx/lua/check_script.lua";
                        proxy_pass $upstream;
                }
        }

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
}

Lua Script

local http = require "resty.http"

local ip = ngx.var.ip # Nginx.conf 에서 세팅해준 ip 변수
local master_port = ngx.var.master_port
local slave_port = ngx.var.slave_port
local endpoint = ngx.var.endpoint

local httpc = http.new()
http:set_timeout(5000)

local master_uri = "http://" .. ip .. ":" .. master_port
local master_res, master_err = httpc:request_uri(master_uri .. endpoint, {
        method = "GET",
})

local slave_uri = "http://" .. ip .. ":" .. slave_port
local slave_res, slave_err = httpc:request_uri(slave_uri .. endpoint, {
        method = "GET",
})

function healthCheck(uri, res)
        # 서버가 master 상태이고 200을 리턴한다면 upstream에 해당 서버의 URI를 담는다
        if res.body == "master" and res.status == 200 then
                ngx.var.upstream = uri
        else
                # master 서버라면 slave 서버를 한번 더 체크하여 slave 서버가 healthy한지 확인한다
                if uri == master_uri then
                        healthCheck(slave_uri, slave_res)
                # master, slave 서버 모두 정상 상태가 아니므로 503 Temporarily Unavailable 리턴
                else
                        ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
                        ngx.exit(ngx.status)
                end
        end
end

# master 서버에서 응답이 잘 오면
if master_res then
        healthCheck(master_uri, master_res)
else
        # slave 서버에서 응답이 잘 오면
        if slave_res then
                healthCheck(slave_uri, slave_res)
        # master, slave 서버 모두 running 상태가 아님
        else
                ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
                ngx.exit(ngx.status)
        end
end

Log 확인

  • sudo cat /var/log/nginx/access.log
  • sudo cat /var/log/nginx/error.log

0개의 댓글