Nginx
는 대표적인 웹 서버(Web Server, WS)로, 리버스 프록시(Reverse Proxy) 역할의 중계 서버로도 사용할 수 있다. 오늘은 Nginx를 통해 중계 서버(리버스 프록시)를 구성해보자.
Nginx란?
Nginx는 가벼우면서도 고성능을 제공하여, 현재 많은 사랑을 받고 있는 웹 서버이다. 리버스 프록시, 로드 밸런서 등 다양한 용도로 활용된다. Nginx에 대해서는 자세히 다뤄본 포스팅(역사와 구조 등)이 있으니 참고할 수 있다.
오늘은 Nginx의 설정 파일인 nginx.conf
를 작성해보며, 중계 서버(리버스 프록시 서버)로 활용해보자.
nginx.conf
nginx.conf
는 Nginx의 핵심 설정 파일로, Nginx 서버의 동작 방식을 정의하는 파일이다. 주로 다음과 같은 설정들을 포함한다:
- 서버의 기본 동작 설정 (워커 프로세스 수, 로깅 등)
- 가상 호스트(Virtual Host) 설정
- 프록시 설정
- SSL/TLS 설정
- 캐시 설정
설정 파일은 기본적으로 /etc/nginx/nginx.conf
경로에 위치하며, 계층 구조로 구성된다.
기본 구조
아래 Sample은 Nginx를 웹 서버로서 활용할 때의 대표적인 기본 설정이다.
# 메인 컨텍스트
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
# 이벤트 컨텍스트
events {
worker_connections 1024;
}
# HTTP 컨텍스트
http {
# 서버 컨텍스트
server {
listen 80;
server_name example.com;
access.log /var/log/nginx/access.log
keepalive_timeout 65;
# 로케이션 컨텍스트
location / {
root /usr/share/nginx/html;
index index.html;
}
}
}
각 컨텍스트는 특정한 범위의 설정을 담당하며, 중괄호({})를 사용하여 계층 구조를 형성한다. 이러한 구조적 특성 덕분에 설정을 체계적으로 관리할 수 있다.
중계 서버(리버시 프록스)의 관점에서 설정을 더 살펴보자. 중계 서버로서 Nginx는 클라이언트의 요청을 받아 내부의 다른 서버로 전달하고, 그 서버의 응답을 클라이언트에게 다시 전달하는 역할을 한다.
http {
upstream server1 {
server server1.example.com;
}
upstream server2 {
server server2.example.com;
}
server {
listen 80;
server_name example.com;
#ssl 설정
#ssl_certificate /app/ssl/nginx/prox_ssl/access.log;
#ssl_certificate_key /app/ssl/...key
#ssl_session_cache shared:SSL:1m;
#ssl_session_timeout 5m;
#ssl_protocols TLSv1.2 TLSv1.3;
#ssl_ciphers HIGH:!aNULL:!MD5;
#ssl_prefer_server_ciphers on;
# 로그 설정
access_log /var/log/nginx/access.log; # 접근 로그 파일 설정
error_log /var/log/nginx/error.log; # 에러 로그 파일 설정
location /server1 {
proxy_pass <http://server1>; # HTTP 요청을 server1으로 전달
}
location /server2 {
proxy_pass <http://server2>; # HTTP 요청을 server2로 전달
}
}
}
stream {
upstream tcp_backend {
server tcp1.example.com:12345; # TCP 요청을 처리할 서버
server tcp2.example.com:12345; # 또 다른 TCP 서버
}
server {
listen 12345; # TCP 요청을 수신할 포트
proxy_pass tcp_backend; # TCP 요청을 tcp_backend로 전달
# TCP 로그 설정
access_log /var/log/nginx/tcp_access.log; # TCP 접근 로그 파일 설정
error_log /var/log/nginx/tcp_error.log; # TCP 에러 로그 파일 설정
}
}
http
http 요청을 처리하는 설정을 포함하는 블록이다. upstream
, server
블록 등이 하위에 작성된다.
upsream 블록
라우팅할 서버를 정의하는 블록이다. 여러 대의 서버를 정의할 수 있다.
예를 들어 다음과 같이 여러 대를 작성하면, 2개의 서버에 로드밸런싱된다.
upstream server1 {
server server11.example.com;
server server12.example.com;
}
server
http 요청을 수신하고 처리하는 서버 블록이다. listen
은 요청을 수신할 포트를, server_name
은 서버 블록이 응답할 도메인을 설정한다.
server {
listen 80;
server_name example.com;
location
location은 특정 경로로 들어오는 요청을 처리하는 블록이다.
다음과 같이 작성하면 /server1
경로로 들어오는 요청을 upstream server
으로 전달한다.
location /server1 {
proxy_pass <http://server1>; # HTTP 요청을 server1으로 전달
}
stream
tcp/udp 요청을 처리하는 설정을 포함하는 블록이다.
upstream tcp_backend {
server tcp1.example.com:12345; # TCP 요청을 처리할 서버
server tcp2.example.com:12345; # 또 다른 TCP 서버
}
Nginx 중계 서버 구축하기
다음 그림과 같이 Nginx 서버로 요청을 보냈을 때 Server1과 Server2로 라우팅되도록 구성해보자.
nginx-server.com:3000/server1
→http://server1:5000
nginx-server.com:3000/server2
→http://server2:4000
다음과 같이 nginx를 구성할 수 있다.
nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
}
# HTTP 블록
http {
include mime.type;
default_type application/octet-stream;
send_file on;
keepalive_timeout 65;
upstream server1 {
server 54.242.167.98:5000;
}
upstream server2 {
server 3.81.137.250:4000;
}
server {
listen 3000;
server_name example.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /server1 {
proxy_pass http://server1; # HTTP 요청을 server1으로 전달
}
location /server2 {
proxy_pass http://server2; # HTTP 요청을 server2로 전달
}
}
}
nginx -t
를 통해 nginx.conf
파일의 문법을 검사할 수 있다.
syntax is ok
가 표시된다면, 문법적으로는 오류가 없다는 것이다.
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
nginx
기동하기
$ nginx
기동 후 다음과 같이 nginx
프로세스가 떠 있는 것을 확인할 수 있고,
$ ps -ef | grep nginx
root 4504 1 0 12:35 ? 00:00:00 nginx: master process nginx
www-data 5172 4504 0 12:36 ? 00:00:00 nginx: worker process
ubuntu 5230 1112 0 12:36 pts/0 00:00:00 grep --color=auto nginx
netstat
로 확인해보면, 3000
번 포트를 리스닝 중인 것을 확인할 수 있다.
$ netstat -anp | grep LISTEN
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.54:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
unix 2 [ ACC ] STREAM LISTENING 8287 - /var/lib/amazon/ssm/ipc/health
unix 2 [ ACC ] STREAM LISTENING 8288 - /var/lib/amazon/ssm/ipc/termination
unix 2 [ ACC ] STREAM LISTENING 8950 - /run/user/1000/systemd/private
unix 2 [ ACC ] STREAM LISTENING 8960 - /run/user/1000/bus
unix 2 [ ACC ] STREAM LISTENING 8964 - /run/user/1000/gnupg/S.dirmngr
unix 2 [ ACC ] STREAM LISTENING 8966 - /run/user/1000/gnupg/S.gpg-agent.brow
....
server1, server2 각각에는 간단한 Flask 앱을 실행하여, 자신의 서버를 확인하는 텍스트를 출력할 수 있도록 해보자.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "I am server1!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000) #server2는 port=4000으로
Flask 앱을 통해 server1
의 /
으로 요청을 보내면 다음과 같이 I am Server1!
을 출력한다.
$ curl localhost:5000
I am server1!
이제 Nginx 중계서버로 요청을 보내보자.
---
/server1
으로 보냈을 때는 1번 서버의 5000번 포트로,
$ curl http://nginx-server.com:3000/server1
I am server1!
/server2
로 보냈을 때는 2번 서버의 4000번 포트로 잘 중계되는 것을 확인할 수 있다.
$ curl http://nginx-server.com:3000/server2
I am server2!
이처럼 Nginx는 웹 서버 뿐만 아니라, 리버시 프록시 서버로서의 기능을 제공하여 다양하게 활용될 수 있다.
지금까지 Nginx를 중계서버(리버스 프록시 서버)로 구성하는 것을 진행해보았다.
Reference