NginX - Reverse Proxy

Jaeminst·2022년 3월 12일
2
post-thumbnail
post-custom-banner

Nginx

Nginx는 Igor Sysoev라는 러시아 개발자가 동시접속 처리에 특화된 웹 서버를 위해 만든 프로그램이다. 동작이 단순하고 정적파일을 다루기 때문에 동시접속 처리에 특화된 전달자 역할을 한다. 동시접속자가 약 700명 이상이라면 서버를 증설하거나 Nginx 환경을 권장한다고 한다.

특징

Nginx는 정적 컨텐츠를 고속으로 처리하기 위해, 프로세스나 스레드라는 개념 대신 이벤트 개념을 사용하여 여러 Request를 처리하는 Worker라는 내부 루핑 시스템을 사용한다.

장점

가상화, 클라우드, MSA와 같은 아키텍쳐에서 경량화와 높은 성능을 위해 사용하며, 멀티 태스킹 과정의 Context Switching 비용이 적은 Event Driven 방식을 사용한다.

프로세스 모델

Nginx는 Worker Process와 Cache Manager, Cache Loader를 구성하여 작동한다. config에서 worker_processes auto로 설정하면 필요한 리소스를 Master Process가 파악해서 효율적으로 관리한다.


활용

프록시 (Proxy)

Nginx는 다른 서버로 위임하는 프록시 서버 역할, 그 중에서도 리버스 프록시 기능을 제공한다. 이를 통해 Nginx는 정적 파일만 처리하며, 처리하지 못하는 동적 파일을 서버에게 처리 요청을 할 수 있다.
그리하여, 정적 컨텐츠를 효율적으로 제공하기 위한 Apache 서버와 함께 사용하는 기반이 되었다.
(그림: 네이버 메인 페이지의 서버 아키텍처)

장애 대응

Nginx의 upstream module을 통해 장애에 대한 대응을 쉽게 할 수 있다. 이 것은 내장된 모듈로써 부하 분산, 속도 개선과 같은 역할을 수행하고 요청받은 데이터를 서버에 전달한다. 이를 통해 nginx 서버 하나에 여러 서버를 붙일 수 있으며, 장애 발생 시 다른 서버로 연결하여 높은 사용자 경험을 제공한다.

로드 밸런서

Nginx에서는 서버 정보와 포트를 이용하여 처리할 작업을 지정하는 무중단 배포를 위해 사용할 수 있다.
현재 health check 기능은 상용 버전에서 사용가능하며, 오픈 소스 모듈을 사용하여도 무료로 구현가능하다.


설치

OS에서 빌드된 패키지 설치

  1. Update the Ubuntu repository infomation
    $ sudo apt-get update
  2. Install the NGINX Open Source package
    $ sudo apt-get install nginx
  3. Verify the installation
$ sudo nginx -v
nginx version: nginx/1.18.0 (Ubuntu)

공식 NGINX 사이트의 빌드된 패키지 설치하기

  1. Nginx 패키지 및 저장소에 서명하는 데 사용되는 키를 다운로드하고 apt 프로그램의 키 링에 추가합니다.
$ sudo wget https://nginx.org/keys/nginx_signing.key
$ sudo apt-key add nginx_signing.key
  1. /etc/apt/souces.list 파일을 편집합니다.
    $ sudo nano /etc/apt/sources.list

  2. NGINX 오픈 소스를 받아오기 위해 마지막 줄에 추가합니다.

deb https://nginx.org/packages/mainline/debian/ focal nginx
deb-src https://nginx.org/packages/mainline/debian/ focal nginx

참고사항
focal : Ubuntu 20.04.3 LTS version CODENAME

  1. 변경 사항을 저장하고 종료합니다. nano(Ctrl+X -> y -> 엔터)

  2. NGINX 패키지를 설치합니다.

$ sudo apt-get remove nginx-common
$ sudo apt-get update
$ sudo apt-get install nginx
  1. NGINX 오픈 소스 시작
    $ sudo nginx

  2. 실행 중인지 확인합니다.
    $ curl -I 127.0.0.1


구조

Nginx는 nginx.conf라는 파일에 여러가지 값을 지정하여 프로그램을 작동합니다.

디렉토리

먼저 nginx.conf 파일 위치를 파악해봅니다.
$ sudo find / -name nginx.conf
$ cd /etc/nginx
$ tree .

nginx.conf

Nginx의 conf파일은 논리적으로 작성되어 있는 지시어(Directives) 목록이라고 할 수 있습니다.
특정 지시어의 묶음 형태로 모듈을 만들어 이를 통해 작동하기도 하며 가장 기본적인 지시어들은 NGINX의 코어 모듈에 포함되어 있습니다.

지시어

nginx.conf에서 사용하는 지시어들을 알아보겠습니다.

  • user www-data;
    웹 서버 프로세스가 액세스할 수 있는 권한을 부여합니다.

  • worker_processes number | auto;
    프로세스 실행 가능 수를 정의합니다.
    보통은 CPU 코어 수 만큼 할당하며, auto로 설정해두면 자동으로 값을 알맞게 설정해 줍니다.

  • include file | mask;
    특정 파일을 해당 위치에 포함시켜 줍니다.
    필요한 설정을 파일 단위로 나누어 관리할 수 있습니다.

  • 지시어 블록 (directive block)
    블록 내에 작성된 지시어는 블록의 문맥에서만 의미를 갖습니다.
    예외로 일부 지시어들은 서버의 전 범위에 효력을 가지기 때문에 메인 블록이라 부르는 환경 설정 파일에 작성될 수도 있고, 경우에 따라서는 한 블록 안에 다른 블록이 삽입될 수도 있습니다.

  • events {...}
    네트워크 작동 환경을 설정하는 지시어를 제공합니다.

    worker_connections
    하나의 프로세스가 처리할 수 있는 연결의 수
    최대 연결 수는 worker_processes * worker_connections로 계산합니다.

  • http {...}
    웹 서버에 대한 동작을 설정합니다.
    http { ... server { ... location {...} } }
    위와 같이 계층 구조를 가지며, 해당 블록에 사용되는 지시어는 하위 블록의 기본값이 되며 하위 블록에서 지시어가 재선언되면 상위 블록의 지시어를 무시합니다.

  • server {...}
    하나의 호스트를 선언하는데 사용하며, http 블록 안에서만 사용될 수 있습니다. 여러개의 location 블록을 선언할 수 있습니다.

  • location {...}
    특정 URL을 처리하는 방법을 정의합니다.
    예를 들면 http://example.com/usershttp://example.com/carts에 접근하는 요청을 다르게 처리하거나 http://example.com/products에 접근할 때 특정 파일에 대한 요청을 다르게 처리할수도 있습니다.


Reverse Proxy

NGX를 이용하여 원(origin) 서버 앞 단에서 로드밸런싱, 캐싱, 보안 등을 위한 리버스 프록시 서버 역할을 수행할 수 있다.

그러면, 직접 Nginx를 통하여 리버스 프록시 서버를 구현해보자.

작업환경

  • OS : Linux Ubuntu 20.04.3 LTS (focal)
  • NGX : nginx/1.18.0 (Ubuntu)

참고 문서

nginx.conf 지시어 작성

우리는 위에서 알아본 include를 통하여 지시어 블록을 원하는 위치에서 불러와 사용할 수 있습니다.

먼저 터미널에서 $ cd /etc/nginx로 이동하여 nginx.conf 파일을 출력 $ cat nginx.conf 해보면 다음과 같이 include 지시어가 있는것을 찾았습니다.

그러면 서버, 로케이션 마다 원하는 설정을 해줄 수 있겠죠?

$ cd conf.d에 가보면

확장자명이 .conf로 끝나는 파일이 하나 있습니다.
다른 파일은 사용하지 않음으로 파일명을 바꾸어 놓았습니다.

/etc 관리자의 디렉토리 이므로 sudo를 이용하여 편집해야 됩니다.
$ sudo nano nginx.conf

지시어들을 보면, nginx 서버를 구동할 때 10026의 포트를 사용하고 서버이름을 localhost로 지시합니다.
location에서는 디렉토리 / 에 대해 지시하며, 그 안에는 프록시에 대한 지시어들이 있습니다.

지시어들을 간단히 설명하겠습니다.
proxy_set_header는 프록시 서버에 대한 헤더를 설정합니다.
proxy_pass는 여기에 지정된 서버에 요청 헤더를 전달합니다.
추 후 proxy_redirect 지시어를 사용할 시 필히 proxy_pass다음에 지시하여야 합니다.

Proxy Module

여러가지 프록시와 관련된 지시어들을 사용할 수 있습니다.

구분

  • 지시어 입력가능 값;
    지시어 default 값;
    설명

proxy_b~

  • proxy_bind address | off;
    proxy_bind $server_addr;
    발신 IP 주소를 선택합니다.
    프록시 서버가 특정 IP 네트워크 또는 IP 주소 범위의 연결을 허용하도록 구성된 경우에 유용할 수 있습니다.

  • proxy_buffer_size size;
    proxy_buffer_size 4k|8k;
    프록시 서버에서 수신한 응답의 첫 번째 부분을 읽는 데 사용되는 버퍼를 설정합니다.
    nginx가 서버로부터 한 번에 받을 수 있는 데이터의 최대 크기입니다.

  • proxy_buffering on | off;
    proxy_buffering on;
    프록시 서버의 응답 버퍼링을 활성화하거나 비활성화합니다.

  • proxy_buffers number size;
    proxy_buffers 8 4k|8k;
    단일 연결에 대해 프록시 서버에서 응답을 읽는 데 사용되는 number 및 버퍼를 설정합니다.

  • proxy_busy_buffers_size size;
    proxy_busy_buffers_size 8k|16k;
    프록시 서버의 응답 버퍼링이 활성화된 경우, 백 엔드에서 수신되는 데이터가 버퍼에 쌓이다가 이 지시어로 지정한 값을 초과하면 데이터를 클라이언트로 보내고 버퍼를 비웁니다. 필요한 경우 임시 파일에 대한 응답의 일부를 버퍼링합니다.

proxy_c~

  • proxy_cache zone | off;
    proxy_cache off;
    캐싱에 사용되는 공유 메모리 영역을 정의합니다.
    off는 이전 구성 수준에서 상속된 캐싱을 비활성화합니다.

  • proxy_cache_background_update on | off;
    proxy_cache_background_update off;
    만료된 캐시 항목을 업데이트하기 위해 백그라운드 하위 요청을 시작하는 것을 허용하고 오래전 캐시된 응답은 클라이언트에 반환됩니다.

  • proxy_cache_bypass string ...;
    proxy_cache_bypass $cookie_nocache;
    캐시에서 응답을 가져오지 않는 조건을 정의합니다.
    문자열 매개변수들의 값을 확인해서 캐시에서 응답을 가져오지 않습니다.

  • proxy_cache_convert_head on | off;
    proxy_cache_convert_head on;
    캐싱을 위해 GET Method로 "Head"를 변환하는 것을 활성화 또는 비활성화 합니다.

  • proxy_cache_key string;
    proxy_cache_key $scheme$proxy_host$request_uri;
    캐시 항목들을 서로 구분하는 캐시 키를 정의합니다.
    캐시 키에 설정된 모든 요청은 같은 캐시 항목으로 캐싱합니다.

  • proxy_cache_lock on | off;
    proxy_cache_lock off;

  • proxy_cache_lock_age time;
    proxy_cache_lock_age 5s;

  • proxy_cache_lock_timeout time;
    proxy_cache_lock_timeout 5s;

  • proxy_cache_max_range_offset number;
    -

  • proxy_cache_methods GET | HEAD | POST ...;
    proxy_cache_methods GET HEAD;
    클라이언트 요청 방법이 이 지시문에 있으면 응답이 캐시됩니다.
    GET, HEAD 메서드는 항상 추가되지만 명시적으로 지정하는 것이 좋습니다. (proxy_no_cache 참조 추천)

  • proxy_cache_min_uses
    proxy_cache_min_uses 1;
    요청이 캐시되는 데 필요한 최소 히트 수를 정의합니다.

  • proxy_cache_path path ...;
    -
    캐시의 경로 및 기타 매개변수를 설정합니다.
    levels : 하위 디렉토리의 깊이
    keys_zone:byte : 캐시 존의 키와 메모리 크기
    inactive : 캐시 활성화 시간
    max_size : 캐시 최대 크기

  • proxy_cache_purge string ...;
    -

  • proxy_cache_revalidate on | off;
    proxy_cache_revalidate off;

  • proxy_cache_use_stale error | timeout | ...;
    proxy_cache_use_stale off;
    프록시 서버와 통신하는 동안 오래된 캐시 응답을 사용할 수 있는 경우를 결정합니다.

  • proxy_cache_valid [code ...] time;
    -
    다른 응답 코드에 대한 캐싱 시간을 설정합니다.

  • proxy_connect_timeout time;
    proxy_connect_timeout 60s;
    프록시 서버와의 연결을 설정하기 위한 시간 초과를 정의합니다.
    이 시간 초과는 75초를 초과할 수 없습니다.

  • proxy_cookie_domain off | domain replacement;
    proxy_cookie_domain off;

  • proxy_cookie_flags off | cookie [flag ...];
    proxy_cookie_flags off;

  • proxy_cookie_path off | path replacement;
    proxy_cookie_path off;

proxy_f~

  • proxy_force_ranges on | off;
    proxy_force_ranges off;

proxy_h~

  • proxy_headers_hash_bucket_size size;
    proxy_headers_hash_bucket_size 64;

  • proxy_headers_hash_max_size size;
    proxy_headers_hash_max_size 512;

  • proxy_hide_header field;
    -
    기본적으로 'Date', 'Server', 'X-Pad', 'X-Accel-...'등은 클라이언트로 전달하지 않으며 추가적으로 이 지시어에서 전달하지 않을 헤더를 설정합니다.
    반대로 proxy_pass_header로 전달을 허용할 수 있습니다.

  • proxy_http_version 1.0 | 1.1;
    proxy_http_version 1.0;
    프록시용 HTTP 프로토콜 버전은 기본적으로 1.0이 사용되며 Keepalive 연결 및 NTLM 인증과 함께 사용하려면 1.1을 사용하는 것이 좋습니다.

proxy_i~

  • proxy_ignore_client_abort on | off;
    proxy_ignore_client_abort off;
    클라이언트가 응답을 기다리지 않고 연결을 닫을 때 프록시 서버와의 연결을 닫아야 하는지 여부를 결정합니다.
    on으로 설정하면 클라이언트가 요청을 중시시켜도 프록시 서버로 요청하는 것은 계속합니다.

  • proxy_ignore_headers field ...;
    -

  • proxy_intercept_errors on | off;
    proxy_intercept_errors off;
    300이상의 상태코드가 포함된 프록시 응답을 클라이언트로 전달할지 아니면 가로채서 error_page 지시문으로 처리하기 위해 nginx로 리디렉션할지 결정합니다.

proxy_l~

  • proxy_limit_rate rate;
    proxy_limit_rate 0;

proxy_m~

  • proxy_max_temp_file_size size;
    proxy_max_temp_file_size 1024m;

  • proxy_method method;
    -
    클라이언트 요청의 메서드 대신 이 지시어의 메서드로 요청합니다.

proxy_n~

  • proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | non_idempotent | off ...;
    proxy_next_upstream error timeout;
    다음 서버로 요청을 전달 해야하는 경우를 지정합니다.

  • proxy_next_upstream_timeout time;
    proxy_next_upstream_timeout 0;

  • proxy_next_upstream_tries number;
    proxy_next_upstream_tries 0;

  • proxy_no_cache string ...;
    -
    응답이 캐시에 저장되지 않는 조건을 정의합니다. 문자열 매개변수 중 하나 이상의 값이 비어 있지 않고 "0"이 아니면 응답이 저장되지 않습니다.

proxy_p~

  • proxy_pass URL;
    -
    프록시 서버의 프로토콜 및 주소와 위치가 매핑되어야 하는 선택적 URI를 설정합니다.
# TCP 소켓
  proxy_pass http://sample.com:port;

# 유닉스 도메인 소켓
  proxy_pass http://unx:/path/to/file.socket;

# 업스트림 블록 지정
  upstream myblock {
    server 127.0.0.1:8080;
    server 127.0.0.1:10026;
  }
  location ~* \.php$ {
    proxy_pass http://myblock;
  }

# 보안 프로토콜 사용
  proxy_pass https://sample.com:port;

# 변수 사용
  proxy_pass http://$server_name:8080;

# URI 사용
  proxy_pass http://sample.com:8080/uri;
  • proxy_pass_header field;
    -
    프록시 서버에서 클라이언트로 비활성화된 헤더 필드를 허용합니다.

  • proxy_pass_request_body on | off;
    proxy_pass_request_body on;
    요청 바디를 전달할지 여부를 설정합니다.

  • proxy_pass_request_headers on | off;
    proxy_pass_request_headers on;
    요청 헤더를 전달할지 여부를 설정합니다.

proxy_r~

  • proxy_read_timeout time;
    proxy_read_timeout 60s;
    프록시 서버에서 응답을 읽기 위한 시간 초과를 정의합니다. 시간 제한은 전체 응답의 전송이 아니라 두 개의 연속 읽기 작업 사이에서만 설정됩니다. 프록시 서버가 이 시간 내에 아무 것도 전송하지 않으면 연결이 닫힙니다.
  • proxy_redirect off | default | redirect replacement;
    proxy_redirect default
    off : 리다이렉션은 설정된 그대로 전달된다.
    default : 호스트명과 현재 문서 경로가 첨부된 proxy_pass 지시어 값이 사용된다. (환경설정은 순차적으로 파싱되므로 proxy_redirect 지시어는 proxy_pass 지시어 다음에 삽입해야 함에 유의한다.)
    URL : 백엔드 서버로부터 발생한 리다이렉션에 대한 URL을 재작성합니다. (replacement에 변수포함 가능)
    proxy_redirect http://localhost:8080 http://$host:$server_port;

  • proxy_request_buffering on | off;
    proxy_request_buffering on;

proxy_s~

  • proxy_send_lowat size;
    proxy_send_lowat 0;

  • proxy_send_timeout time;
    proxy_send_timeout 60s;
    프록시 서버에 요청을 전송하기 위한 시간 초과를 설정합니다. 시간 제한은 전체 요청의 전송이 아니라 두 개의 연속 쓰기 작업 사이에서만 설정됩니다. 프록시 서버가 이 시간 내에 아무 것도 수신하지 않으면 연결이 닫힙니다.

  • proxy_set_body value;
    -
    프록시 서버에 전달된 요청 본문을 재정의할 수 있습니다. value(텍스트, 변수) 및 이들의 조합을 포함할 수 있습니다.

  • proxy_set_header field value;
    proxy_set_header host $proxy_host;
    proxy_set_header Connection close;
    프록시 서버에 전달 된 요청 헤더에 필드를 재정의하거나 추가할 수 있습니다.

    $proxy_host : proxy_pass 지시문에 지정된 프록시 서버의 이름과 포트
    $proxy_port : proxy_pass 지시문에 지정된 프록시 서버의 포트 또는 프로토콜의 기본 포트
    $http_host : 변경되지 않은 호스트 변수
    $host : 기본 서버 이름 변수
    $host:$proxy_port; : 프록시 서버의 포트와 함께
    proxy_set_header Accept-Encoding ""; : 프록시 서버에 전달 되지 않게
    $proxy_add_x_forwarded_for : “X-Forwarded-For” 요청 헤더와 $remote_addr 변수가 함께 추가되고 콤마로 구분됩니다. 만약 "X-Forwarded-For" 필드가 클라이언트 요청 헤더에 존재하지 않는 경우, 이 변수는 $remote_addr 변수와 같습니다.

  • proxy_socket_keepalive on | off;
    `proxy_socket_keepalive off;

  • proxy_ssl_certificate file;
    -

  • proxy_ssl_certificate_key file;
    -

  • proxy_ssl_ciphers ciphers;
    `proxy_ssl_ciphers DEFAULT;

  • proxy_ssl_conf_command command;
    -

  • proxy_ssl_crl file;
    -

  • proxy_ssl_name name;
    `proxy_ssl_name $proxy_host;

  • proxy_ssl_password_file file;
    -

  • proxy_ssl_protocols [SSLv2][SSLv3] [TLSv1][TLSv1.1] [TLSv1.2][TLSv1.3];
    proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  • proxy_ssl_server_name on | off;
    proxy_ssl_server_name off;

  • proxy_ssl_session_reuse on | off;
    proxy_ssl_session_reuse on;

  • proxy_ssl_trusted_certificate file;
    -

  • proxy_ssl_verify on | off;
    proxy_ssl_verify off;

  • proxy_ssl_verify_depth number;
    proxy_ssl_verify_depth 1;

  • proxy_store on | off | string;
    proxy_store off;

  • proxy_store_access users:permissions ...;
    proxy_store_access user:rw;

proxy_t~

  • proxy_temp_file_write_size size;
    proxy_temp_file_write_size 8k|16k;

  • proxy_temp_path path [level1 [level2 [level3]]];
    proxy_temp_path proxy_temp;

profile
DevOps !
post-custom-banner

0개의 댓글