Post

[Network] Nginx

๐Ÿ“Œ ๋“ค์–ด๊ฐ€๋ฉฐ

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ๊ณ ์„ฑ๋Šฅ ์›น ์„œ๋ฒ„์ด์ž ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ์ธ Nginx๋ฅผ ์ •๋ฆฌํ•œ๋‹ค. ์•„ํ‚คํ…์ฒ˜(Master/Worker)๋ถ€ํ„ฐ reload vs restart, ์ฃผ์š” ํŒจํ„ด(์ •์ ยทํ”„๋ก์‹œยทLBยทSSL), DNS resolver ํ•จ์ •, ๋ณด์•ˆ(Rate Limit), ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์—ฐ๋™๊นŒ์ง€ ๋‹ค๋ฃฌ๋‹ค.

Nginx๋ž€? Event-driven(๋น„๋™๊ธฐ) ๊ตฌ์กฐ์˜ ๊ณ ์„ฑ๋Šฅ ์›น ์„œ๋ฒ„ยท๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ. ์ •์  ํŒŒ์ผ ์„œ๋น™, ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ, ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ, SSL/TLS ์ข…๋ฃŒ, ์บ์‹ฑ์— ๋‘๋ฃจ ์“ฐ์ธ๋‹ค.

Nginx vs Apache

ํ•ญ๋ชฉNginxApache
์•„ํ‚คํ…์ฒ˜Event-driven(๋น„๋™๊ธฐ)Process/Thread
๋™์‹œ ์ ‘์†์ˆ˜๋งŒ ๊ฐœ์ˆ˜์ฒœ ๊ฐœ
๋ฉ”๋ชจ๋ฆฌ์ ์Œ๋งŽ์Œ
์ •์  ํŒŒ์ผ๋งค์šฐ ๋น ๋ฆ„๋ณดํ†ต
๋™์  ์ฒ˜๋ฆฌํ”„๋ก์‹œ ํ•„์š”(PHP-FPM)๋ชจ๋“ˆ ์ง์ ‘

1. ์•„ํ‚คํ…์ฒ˜ โ€” Master & Worker

flowchart TD
    M["Master Process (root)<br/>์„ค์ • ์ฝ๊ธฐยทWorker ๊ด€๋ฆฌยท์‹œ๊ทธ๋„ ์ฒ˜๋ฆฌ"]
    M --> W1["Worker 1<br/>(์š”์ฒญ ์ฒ˜๋ฆฌ)"]
    M --> W2["Worker 2"]
    M --> W3["Worker N"]
1
2
worker_processes auto;   # CPU ์ฝ”์–ด ์ˆ˜๋งŒํผ ์ž๋™
events { worker_connections 1024; }  # Worker๋‹น ์ตœ๋Œ€ ์—ฐ๊ฒฐ

๐Ÿ’ก Master๋Š” ๊ด€๋ฆฌ, Worker๋Š” ์š”์ฒญ ์ฒ˜๋ฆฌ๋กœ ์—ญํ• ์ด ๋‚˜๋‰œ๋‹ค. Master๊ฐ€ root๋กœ ์„ค์ •์„ ์ฝ๊ณ  Worker๋ฅผ ๋„์šฐ๋ฉฐ, ์‹ค์ œ ํŠธ๋ž˜ํ”ฝ์€ Worker๊ฐ€ ๋‹ด๋‹นํ•œ๋‹ค. Worker ์ˆ˜๋ฅผ ์ฝ”์–ด ์ˆ˜์— ๋งž์ถฐ์•ผ ์„ฑ๋Šฅ์ด ๋‚˜์˜จ๋‹ค.


2. ์ฃผ์š” ๋ช…๋ น์–ด & reload vs restart

1
2
3
4
sudo nginx -t                     # ์„ค์ • ํ…Œ์ŠคํŠธ(ํ•„์ˆ˜!)
sudo systemctl reload nginx       # ๋ฌด์ค‘๋‹จ ์„ค์ • ๋ฐ˜์˜
sudo nginx -T                     # include ํฌํ•จ ์ „์ฒด ์„ค์ • ์ถœ๋ ฅ
sudo tail -f /var/log/nginx/error.log
์ƒํ™ฉ๋ช…๋ น์ด์œ 
์„ค์ • ๋ณ€๊ฒฝreload๋ฌด์ค‘๋‹จ
๋ชจ๋“ˆ ์ถ”๊ฐ€ยท๋ฒ„์ „ ์—…๊ทธ๋ ˆ์ด๋“œrestartํ”„๋กœ์„ธ์Šค/๋ฐ”์ด๋„ˆ๋ฆฌ ๊ต์ฒด
DNS ์บ์‹œ ์ดˆ๊ธฐํ™”restartreload๋Š” ์บ์‹œ ์œ ์ง€

๐Ÿ’ก reload๋Š” ๋‹ค์šดํƒ€์ž„ 0์ด๋‹ค. ์ƒˆ Worker๋ฅผ ๋งŒ๋“ค์–ด ์ƒˆ ์„ค์ •์„ ์ ์šฉํ•˜๊ณ , ๊ธฐ์กด Worker๋Š” ์ฒ˜๋ฆฌ ์ค‘์ธ ์—ฐ๊ฒฐ์„ ๋๊นŒ์ง€ ๋งˆ์นœ ๋’ค(graceful) ์ข…๋ฃŒํ•œ๋‹ค. ๋ฐ˜๋ฉด restart๋Š” ๋ชจ๋“  ์—ฐ๊ฒฐ์ด ๋Š๊ธด๋‹ค. ๊ทธ๋ž˜์„œ ์„ค์ • ๋ณ€๊ฒฝ์€ ํ•ญ์ƒ reload๋ฅผ ์“ด๋‹ค.


3. ์ฃผ์š” ์‚ฌ์šฉ ํŒจํ„ด

์ •์  ํŒŒ์ผ + ์บ์‹ฑ

1
2
3
4
5
6
7
8
9
server {
    listen 80;
    root /var/www/html;
    location / { try_files $uri $uri/ =404; }
    location ~* \.(jpg|png|css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ

1
2
3
4
5
6
location / {
    proxy_pass http://localhost:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ & SSL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
upstream backend_servers {
    server backend1:8080 weight=3;
    server backend2:8080 weight=1;
    server backend3:8080 backup;      # ์˜ˆ๋น„ ์„œ๋ฒ„
}
server {
    listen 443 ssl;
    ssl_certificate     /etc/nginx/ssl/example.crt;
    ssl_certificate_key /etc/nginx/ssl/example.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    location / { proxy_pass http://backend_servers; }
}
server {   # HTTP โ†’ HTTPS ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
    listen 80;
    return 301 https://$host$request_uri;
}

4. DNS resolver ํ•จ์ • (์ค‘์š”!)

Nginx์˜ ์ž์ฒด DNS๋Š” OS DNS์™€ ์™„์ „ํžˆ ๋ณ„๊ฐœ๋‹ค. proxy_pass์— ๋„๋ฉ”์ธ์„ ์ง์ ‘ ์“ฐ๋ฉด, ์‹œ์ž‘ ์‹œ ํ•œ ๋ฒˆ ์กฐํšŒํ•œ IP๋ฅผ ์˜๊ตฌ ์บ์‹œํ•œ๋‹ค.

flowchart LR
    subgraph ๋ฌธ์ œ["resolver ์—†์Œ"]
        A["์‹œ์ž‘ ์‹œ ๋„๋ฉ”์ธ ์กฐํšŒ"] --> B["IP ์˜๊ตฌ ์บ์‹œ"] --> C["IP ๋ณ€๊ฒฝ๋ผ๋„ ๋ชจ๋ฆ„!"]
    end

โš ๏ธ proxy_pass http://๋„๋ฉ”์ธ;์€ IP ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ ๋ชป ํ•œ๋‹ค. ๋ฐฑ์—”๋“œ ๋„๋ฉ”์ธ์˜ IP๊ฐ€ ๋ฐ”๋€Œ๋ฉด 502๊ฐ€ ๋‚˜๊ณ , restart ์ „๊นŒ์ง€ ๋ณต๊ตฌ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋Œ€ํ‘œ์ ์ธ ์šด์˜ ํ•จ์ •์ด๋‹ค.

ํ•ด๊ฒฐ โ€” resolver + ๋ณ€์ˆ˜ ์‚ฌ์šฉ:

1
2
3
4
5
6
7
8
9
10
http {
    resolver 168.126.63.1 8.8.8.8 valid=60s ipv6=off;
    resolver_timeout 5s;
    server {
        location / {
            set $backend "apis.data.go.kr";   # ๋ณ€์ˆ˜ ์‚ฌ์šฉ ํ•„์ˆ˜!
            proxy_pass http://$backend;
        }
    }
}
ํŒจํ„ดIP ๋ณ€๊ฒฝ ๋Œ€์‘
๋„๋ฉ”์ธ ์ง์ ‘(proxy_pass http://๋„๋ฉ”์ธ)โŒ restart ํ•„์š”
๋ณ€์ˆ˜ + resolverโœ… ์ž๋™ ๊ฐฑ์‹ (valid=60s)

5. ๋ณด์•ˆ โ€” Rate Limit & ํ—ค๋”

1
2
3
4
5
6
7
8
http {
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
    server {
        location /api/ {
            limit_req zone=mylimit burst=20 nodelay;  # ์ดˆ๋‹น 10, ์ˆœ๊ฐ„ 20 ํ—ˆ์šฉ
        }
    }
}
1
2
3
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";

IP ์ฐจ๋‹จ(deny 10.0.0.0/8;), ๊ด€๋ฆฌ์ž ๊ฒฝ๋กœ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ(allow 192.168.1.0/24; deny all;), Basic Auth(auth_basic + .htpasswd)๋„ ์ž์ฃผ ์“ด๋‹ค.


6. ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

์—๋Ÿฌ์›์ธ์กฐ์น˜
502 Bad Gateway๋ฐฑ์—”๋“œ ๋‹ค์šดยท๋ฐฉํ™”๋ฒฝยท์ž˜๋ชป๋œ proxy_pass๋ฐฑ์—”๋“œ curl, error.log, SELinux(httpd_can_network_connect)
504 Gateway Timeout๋ฐฑ์—”๋“œ ์‘๋‹ต ๋А๋ฆผproxy_read_timeout ์ฆ๊ฐ€
413 Too Large์—…๋กœ๋“œ ํฌ๊ธฐ ์ดˆ๊ณผclient_max_body_size 100M
1
2
3
sudo nginx -t                    # ๋ฌธ๋ฒ• ์˜ค๋ฅ˜
sudo ss -tlnp | grep nginx       # ํฌํŠธ ํ™•์ธ
sudo nginx -T | grep resolver    # resolver ์„ค์ • ํ™•์ธ

7. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์—ฐ๋™

ConfigMap์œผ๋กœ ์„ค์ • ๊ด€๋ฆฌ ์‹œ, ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€ ๋„๋ฉ”์ธ์€ CoreDNS(10.96.0.10)๋ฅผ resolver๋กœ ์ง€์ •ํ•œ๋‹ค.

1
2
3
resolver 10.96.0.10 valid=30s;   # CoreDNS
set $backend "backend-service.default.svc.cluster.local";
proxy_pass http://$backend;

Ingress๋กœ๋Š” Nginx Ingress Controller๋ฅผ ์จ์„œ ingressClassName: nginx๋กœ ๋ผ์šฐํŒ…ํ•œ๋‹ค.


๐Ÿ“ ์ •๋ฆฌ

1
2
3
4
5
6
Nginx
โ”œโ”€ ๊ตฌ์กฐ   Master(๊ด€๋ฆฌ) + Worker(์ฒ˜๋ฆฌ), Event-driven
โ”œโ”€ ๋ฐ˜์˜   reload(๋ฌด์ค‘๋‹จ) vs restart(DNS ์บ์‹œ ์ดˆ๊ธฐํ™”)
โ”œโ”€ ํŒจํ„ด   ์ •์ ยท๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œยทLB(upstream)ยทSSL ์ข…๋ฃŒ
โ”œโ”€ ํ•จ์ •   proxy_pass ๋„๋ฉ”์ธ โ†’ IP ์บ์‹œ โ†’ resolver+๋ณ€์ˆ˜๋กœ ํ•ด๊ฒฐ
โ””โ”€ ๋ณด์•ˆ   Rate Limitยท๋ณด์•ˆ ํ—ค๋”ยทIP ์ฐจ๋‹จ
๊ฐœ๋…ํ•œ ์ค„ ์ •์˜
reload๋ฌด์ค‘๋‹จ ์„ค์ • ๋ฐ˜์˜
resolverํ”„๋ก์‹œ DNS ๋™์  ๊ฐฑ์‹ 
upstream๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๊ทธ๋ฃน

Nginx ์šด์˜์˜ ํ•ต์‹ฌ์€ nginx -t && reload๋กœ ๋ฌด์ค‘๋‹จ ๋ฐ˜์˜ํ•˜๊ณ , ํ”„๋ก์‹œ ์‹œ resolver+๋ณ€์ˆ˜๋กœ DNS ์บ์‹œ ํ•จ์ •์„ ํ”ผํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด ๋‘ ์Šต๊ด€๋งŒ ์ง€์ผœ๋„ ๋Œ€๋ถ€๋ถ„์˜ ์šด์˜ ์‚ฌ๊ณ ๋ฅผ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ”— ์ฐธ๊ณ 

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.