[DevOps] 주로 사용하는 Nginx 설정

안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 주로 사용하는 Nginx 설정들에 대해서 정리를 해보도록 하겠습니다.

필자가 속한 프로젝트에서는 FE에 대한 서버를 Nginx로 사용하고 있습니다. Nginx에 index.html을 서빙하는 방식으로 이용하고 있습니다.

그러다보니 Nginx에 대한 셋팅 혹은 설정을 많이 하게 되는데 주로 사용하는 것들에 대해서 정리를 해두어서 참고하고자 합니다.

1. nginx.conf 설정

worker_process

nginx의 실행 가능한 worker 프로세스의 수를 지정해 줄 수 있습니다. nginx는 master와 worker 프로세스로 구성이 되는데요.

공식문서에 의하면, 최적값은 cpu core를 사용하라고 권고 하고 있습니다.

worker_processes        4; # number of CPU cores

worker_rlimit_nofile

worker process들에서 최대로 열린 파일들의 수를 제한 할 수 있습니다. 이 수가 클 수록 메인 프로세스를 재시작 할 필요가 없어진다고 합니다. 하지만 너무 많은 수의 파일이 열려있으면, 서버에 부하를 발생시킵니다.

worker_rlimit_nofile    20000; # sockets, fds per worker process

events 블록 – worker_connections

Proxy 서버를 통해 연결된 커넥션들을 포함한 클라이언트들의 모든 커넥션들의 숫자를 고려해야 합니다. worker_rlimit_nofile의 값을 넘어서는 안된다.

events {
    worker_connections  3000; # total supported connection : 4 x 3000 = 12000
}

2. http 블록

Include & default_type

core_module에 있는 설정으로, include는 다른 파일을 가져올 수 있습니다. 아래의 mime.types와 같이 위에서 정의한 types를 파일로 빼내서, include지시어를 이용해 가져올 수 있습니다.

아래에서는 types의 default_type도 정의해 주었습니다.

include       mime.types;
default_type  application/octet-stream;

keepalive

한번 맺어 놓은 연결에 대해서는 keepalive timeout 시점까지는 연결을 지속적으로 허용해두는 설정입니다. 서버를 사용하지 않는 혹은 못하는 Connection까지 모두 keep 하고 있으므로 자원의 손실이 발생하게 됩니다.

keepalive_timeout   30s;
keepalive_requests  128; 

client_body_timeout

client의 request body를 읽을 때의 timeout을 정의합니다. 기본값은 60s로 되어 있습니다.

# timeout for client
client_body_timeout     3s;
client_header_timeout   3s;
client_max_body_size    1m;

send_timeout

client에게 response를 전송할 떄의 timeout값을 설정합니다. client가 아무것도 받지 못하면, connection이 closed 됩니다. 기본값은 60초로 되어있습니다.

send_timeout            3s;

3. Server 블록

server

server_name은 가상 서버의 이름을 정할 때 사용합니다. 아래는 80 port로 접속시 443으로 전환 시켜주는 내용입니다.

server {
    listen 80;
    server_name test.store.com;
    rewrite ^(.*) https://test.store.com$1 permanent;
}

Location 우선순위

nginx에서 가장 중요한 부분입니다. request URI에 따른 설정을 하는 곳입니다. URI에 대한 매칭은 텍스트 값을 prefix로 하여서 매칭하거나 주어진 정규식을 이용해서 매칭할 수 있습니다.

= 패턴과 정확하게 일치 할 때 사용. URI검색시 가장 우선순위가 높습니다. $host정보에 /test.png로 정확하게 매치가 될 때 사용합니다. 하지만, 만약 “=/test”와 같이 사용할 경우, “$host/test”는 일치하여서 매칭이 되지만, “$host/test/”는 매칭되지 않아버리므로, 주의를 기울여서 사용해야 합니다.
~ 대소문자를 구별하여 정규표현식과 일치할 때 사용 보통은 아래의 기호를 더 많이 사용하게 됩니다.
~* 대소문자 구별하지 않고 정규표현식과 일치할 때 사용 ex) location ~* .(gif|jpg|jpeg)$ { return 200 “found” }
^~ 지정한 패턴으로 시작할 때 사용.
아무기호도 없이 텍스트를 사용하면, prefix로 사용해서 해당 텍스트로 시작하는 URI를 찾는다.
@name 이름을 붙여서, location 블럭을 정의한다. 내부 요청에 의해서만 접근할 수 있는데요. 아래와 같이 사용될 수 있습니다. location { try_files $uri @mylabel; } location @mylabel { return 404 “Not Found”}

Header Setting

FE에 대한 서빙을 하다보면, index.html 페이지의 배포가 자주 일어나는데, 이부분이 브라우저 혹은 중간 CDN 서버에 캐싱이 되어있으면, 사용자 측에서 변경이 반영이 안된것으로 노출이 되게 됩니다.

이러한 부분을 캐시 설정을 통해서 서버의 변경사항을 바로 보여줄 수 있도록 설정할 수 있습니다.

        location / {
...
...
            add_header Cache-Control "no-cache, no-store, max-age=0, must-revalidate";
        }

Access Control

Public open을 앞둔 서비스는 사내망에서 혹은 특정 허용된 사용자만을 노출하기 위해서 제한을 할 수 있습니다.

location ~ ^/internal-api/v1/circuit-breaker/(turn-off|turn-on)$ {
            if ($request_method != POST ) {
                    return 405;
            }
            allow 10.XXX.XX.X/32;
            deny all;
}

Rewrite

rewrite은 server, location, if블록에서 사용할 수 있습니다. 마지막 flag값으로는 last, break, redirect, permanent가 있습니다. 마지막 permanent의 값은 301코드와 함께, 영원히 redirect시키는 flag입니다.

location /test/api {
    rewrite ^/test/api(/.*)$ $1 break; // "/test/api를 제외한 URI로 전달"
    proxy_pass https://lan3rd.line.me;
    proxy_next_upstream error timeout;
    proxy_redirect off;
    proxy_connect_timeout 2s;

    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}  

Return

nginx에서 rewrite를 하는 방법으로는 지시어 rewrite와 return하는 두가지 방법이 있습니다. 되도록 return을 사용하도록 권고하고 있습니다.

server {
    listen 80;
    server_name .test.com;
    location / {
        return 301 https://$host$request_uri;
    }
}

Proxy_set_header

중계 받는 nodejs 같은 서버에 request header를 다시 재정의해서 전달할 때 사용합니다.

        location / {
            proxy_pass http://test_upstream;
            proxy_next_upstream error timeout;
            proxy_redirect off;
            proxy_connect_timeout 2s;

            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_http_version 1.1;
            proxy_set_header Connection "";

            proxy_hide_header x-envoy-decorator-operation;
            proxy_hide_header x-envoy-upstream-service-time;

            add_header Cache-Control "no-cache, no-store, max-age=0, must-revalidate";
        }

4. 마치며..

Nginx 는 이미 만들어진 미들웨어(중간 소프트웨어) 제품입니다. 여러가지 설정들을 통해서 필자가 운영하는 서비스들에 좀 더 안정적으로 트래픽 제어 혹은 보안적인 측면에서 효율적으로 관리를 할 수 있다는 생각을 했습니다.

설정들에 대해서 하나하나 세세히 알기 쉽지는 않겠지만, 주로 설정하는 내용들에 대해서 미리 알고 있다면 조금 더 운영함에 있어서 손 쉽게 운영할 수 있을 것이라는 생각을 해봤습니다.

다음시간에는 Nginx의 통합 시리즈에 대해서 정리를 해보겠습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다