DevOps & SRE/Nginx

Nginx 동작 방식부터 프록시, 로드밸런서까지

반응형

nginx란?


Apache와 같은 웹 서버로 클라이언트로부터의 요청에 맞는 정적 파일을 응답해주는 WebServer로 사용되기도 하고, 동적인 리소스를 처리하기 위해 WAS로 요청을 전달해주기도 한다.
이러한 역할들을 나열해보면

  • 정적 파일을 처리한다.
  • WAS 서버에 요청을 보내주는 프록시 기능 수행.
  • 다수의 WAS 서버로 요청을 분배하는 로드밸런서의 역할을 수행.
  • SSL 혹은 프록시를 통해서 보안 강화.
  • 캐싱 처리.

등의 역할을 수행한다고 할 수 있다.


Apache vs Nginx


웹 서버 중 Apache, Nginx가 가장 유명하다고 할 수 있는데, 어떠한 차이가 있는지 봐볼까요?

Apache

  • 아파치 서버는 클라이언트로부터의 요청마다 프로세스, 스레드가 처리하는 구조.
  • Prework, Worker 두 가지 방식이 있는데
  • 멀티 프로세스 방식인 Prework 방식은 1개의 자식 프로세스 당 1개의 스레드를 가지는 구조로 1개의 요청이 들어오면 독립적인 메모리 공간을 가지는 1개의 자식 프로세스가 생성된다. (물론 어느 정도는 미리 준비해둡니다)
  • 멀티 프로세스 + 멀티 스레드 방식인 Worker 방식은 1개의 자식 프로세스가 여러 개의 스레드를 가지며 하나의 스레드에서 하나의 요청을 처리하는 방식으로 동작.
  • 이러한 구조로 요청이 많아지면 많아질 수록 많은 프로세스 & 스레드 생성을 생성해서 메모리 & CPU 등 컴퓨팅 소모가 많아지는 문제가 발생. (대략 동시접속자수가 만 명 이상이 되면 문제가 발생한다고 한다)


Nginx

  • Nginx는 멀티 프로세스 싱글 스레드 방식으로 동작한다.
  • 뽀인트는 비동기 이벤트 방식으로 동작해서 더 적은 메모리로 운영할 수 있다.
  • Apach와 같이 요청이 들어올 때마다 프로세스 & 스레드를 생성하지 않고, N개의 고정된 프로세스로 처리하기 때문에 *프로세스 & 스레드에 대한 생성 및 제거 비용이 들지 않는다. *(이러한 이유로 요청이 많아져도, Apache에 비해 적절한 메모리 및 CPU 사용을 유지할 수 있다.)


Nginx Architecture

  • Nginx은 하나의 Master ProcessN개의 고정된 Worker Process로 구성되어 있다.
  • Master Process의 주 역할은 설정 파일을 읽거나 검증하며 Worker Process를 관리하는 역할을 수행한다.
  • Worker Process에서 요청에 대한 실질적인 처리를 수행한다. Nginx는 비동기 이벤트 기반 모델을 통해서 Worker Process 간에 요청을 효율적으로 분산한다.


Nginx 설치


sudo apt-get update 

sudo apt-get install nginx


Worker Process의 수

  • nginx.conf 파일을 통해서 Worker Process의 수를 지정할 수 있으며, auto로 설정 시 사용 가능한 Core 수만큼 지정된다.
# /etc/nginx/nginx.conf

worker_processes 1; 
# Worker Process의 수
# auto로 설정하면 사용 가능한 코어의 수 만큼 설정된다.

events {
    worker_connections 1024; 
    # Worker Process의 커넥션 수
}


Reverse Proxy란?


1. Forward Proxy

내부망에 있는 클라이언트들이 외부망에 접속할 때, Proxy Server를 거쳐 연결되는 방식.
이점

  • 프록시 서버로 들어오는 패킷에 대해 보안정책을 적용할 수 있음.
  • 프록시 서버 내부에 캐싱 기능이 있어, 이미 가져온 (캐싱에 있는) 데이터에 대해 외부 서버로부터 가져올 필요가 없어, 빠른 통신을 지원해 성능상 이점이 있다.


2. Reverse Proxy

외부망에 있는 클라이언트들이 내부망에서 제공하는 서비스에 접근할 때, 리버스 프록시 서버를 먼저 거쳐서 내부 서버로 들어오는 방식
이점

  • 외부망에 있는 클라이언트는 실제로 내부망에 있는 서버의 존재를 모른다. 모든 접속은 리버스 프록시 서버에게 들어오며, 리버스 프록시는 요청에 매핑되는 내부 서버의 정보를 알고 있고, 그에 따라 요청을 넘겨준다. 따라서 내부 서버의 존재를 외부로부터 숨길 수 있어 보안상 이점이 있다.
  • 리버스 프록시 서버가 내부 서버들의 정보를 알고 있어, 로드밸런싱을 통해 부하 여부에 따라 요청을 분배할 수 있다.
  • 필요에 따라 리버스 프록시 서버와 WAS 서버 사이에 캐싱 서버를 두어 성능면이나 서버 부하면에서 향상할 수 있다.

 

리버스 프록시 설정


sudo unlink /etc/nginx/sites-enabled/default 

sudo vim /etc/nginx/sites-available/proxy.conf


proxy.conf

server {
    listen 80;    
    listen [::]:80;

    server_name # <서버 URL> ex) naver.com

    location / {
        include /etc/nginx/proxy_params;
        proxy_pass http://127.0.0.1:3000; # WAS 서버
    }
}
  • 80번 포트로 요청이 들어오면, proxy_pass를 통해 Nginx 뒷단에 있는 WAS 서버로 요청을 넘겨준다.
  • 이러한 구성을 통해서 클라이언트 입장에서는 위의 경우 3000번에 실행 중인 WAS의 존재를 모른다. 이로 인해서 보안상 강화할 수도 있고, 서버 내부에서 여러 WAS 서버를 두어 로드밸런싱 하는 등 유연한 방식으로 구성할 수 있다.
sudo ln -s /etc/nginx/sites-available/proxy.conf /etc/nginx/sites-enabled/proxy.conf 

sudo nginx -t 

sudo systemctl restart nginx

 

Load Balancing 설정


proxy.conf

upstream api {
    least_conn;
    server 127.0.0.1:8080 weight=1 max_fails=3 fail_timeout=10s;
}

server {
    listen 80;    
    listen [::]:80;

    server_name # <서버 URL> ex) naver.com

    location / {
        include /etc/nginx/proxy_params;
        proxy_pass http://api; # WAS 서버의 포트 지정.
    }
}


upstream

  • 부하분산, 속도 개선과 같은 역할을 수행한다.


least_conn

  • least_conn 방식은 여러 서버 중에서 가장 커넥션 수가 적은 서버로 요청하는 방식.
  • 다른 방식으로는 IP에 해당하는 해시 값으로 요청을 분배하는 ip_hash 등이 있다.


weight

  • 요청을 분배하는 가중치이다. (default: 1)
  • 예를 들어서 weight가 1(A), 2(B), 3(C)인 서버가 3개 있다고 하면 6번 요청이 들어오면 1번은 A로, 2번은 B로, 1번은 3번은 C로 요청이 분배된다.


fail_timeout

  • 커넥션 연결 시도가 실패했다고 간주하는 시간.
  • 예를 들어서 fail_timeout이 10s로 설정되면 10초 동안 연결이 성공하지 않으면 연결 실패라고 간주한다
  • 또한 서버가 사용할 수 없다고 판단하면 10초동안 Down 시킨다.


max_fails

  • fail_timeout이 N번 발생하면 해당하는 서버를 사용할 수 없다고 판단해서 fail_over 처리한다.
  • fail_timeout=10s max_fails=3의 의미는 (10초 동안) 연결 실패가 3번 발생하면 해당 서버를 Down 처리한다.


SSL 적용


HTTP 프로토콜은 데이터가 평문으로 전송되서 도청 등 여러 보안 문제가 발생할 수 있다.
이를 해결하기 위해서 HTTP 프로토콜에 SSL/TLS를 적용한 HTTPS 프로토콜을 사용할 수 있는데, certbot 등으로 인증서를 발급받았을 경우 다음과 같이 nginx를 설정할 수 있다.

SSL 인증서 발급은 다음 링크를 참고해주세요!

 

Nginx에서 Letsencrypt를 통해 SSL을 적용하는 방법

Ubuntu의 Nginx 환경에서 Letsencrypt를 통해 SSL인증서를 발급받았습니다. Letsencrypt에서 인증서를 발급 받는 방법 중에 standalone, webroot 방식이 있고, Certbot을 이용하여 SSL을 발급 받을 수 있습니다. webroo

codechacha.com

 

proxy.conf

upstream api {
	least_conn;
	server 127.0.0.1:3001 weight=1 max_fails=3 fail_timeout=10s;
	server 127.0.0.1:3002 weight=1 max_fails=3 fail_timeout=10s;
}

server {
	listen 443 ssl http2;
	server_name <server_name ex) www.naver.com>

  	ssl_certificate /etc/letsencrypt/live/<server_name>/fullchain.pem;
    	ssl_certificate_key /etc/letsencrypt/live/<server_name>/privkey.pem;

	location / {
		include /etc/nginx/proxy_params;
		proxy_pass http://api;
	}
}

server {
	listen 80;	
	listen [::]:80;

	server_name <server_name ex) www.naver.com>

	location / {
		return 301 https://<server_name>$request_uri;
	}
}
  • HTTPS 프로토콜만 사용하되, 사용자로 하여금 http, https로 요청이 들어오든 무조건 https를 사용하게 하기 위해 80번 포트로 요청이 들어오면 HTTPS(443)으로 요청을 301 Redirect 한다.
반응형

'DevOps & SRE > Nginx' 카테고리의 다른 글

[Nginx RateLimit] Nginx에 RateLimit 적용해보기  (0) 2022.07.20