๐ ๋ค์ด๊ฐ๋ฉฐ
์ด๋ฒ ๊ธ์์๋ ๊ณ ์ฑ๋ฅ ์น ์๋ฒ์ด์ ๋ฆฌ๋ฒ์ค ํ๋ก์์ธ Nginx๋ฅผ ์ ๋ฆฌํ๋ค. ์ํคํ
์ฒ(Master/Worker)๋ถํฐ reload vs restart, ์ฃผ์ ํจํด(์ ์ ยทํ๋ก์ยทLBยทSSL), DNS resolver ํจ์ , ๋ณด์(Rate Limit), ํธ๋ฌ๋ธ์ํ
, ์ฟ ๋ฒ๋คํฐ์ค ์ฐ๋๊น์ง ๋ค๋ฃฌ๋ค.
Nginx๋? Event-driven(๋น๋๊ธฐ) ๊ตฌ์กฐ์ ๊ณ ์ฑ๋ฅ ์น ์๋ฒยท๋ฆฌ๋ฒ์ค ํ๋ก์. ์ ์ ํ์ผ ์๋น, ๋ฆฌ๋ฒ์ค ํ๋ก์, ๋ก๋๋ฐธ๋ฐ์, SSL/TLS ์ข
๋ฃ, ์บ์ฑ์ ๋๋ฃจ ์ฐ์ธ๋ค.
Nginx vs Apache
| ํญ๋ชฉ | Nginx | Apache |
|---|
| ์ํคํ
์ฒ | 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 ์บ์ ์ด๊ธฐํ | restart | reload๋ ์บ์ ์ ์ง |
๐ก 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 ์บ์ ํจ์ ์ ํผํ๋ ๊ฒ์ด๋ค. ์ด ๋ ์ต๊ด๋ง ์ง์ผ๋ ๋๋ถ๋ถ์ ์ด์ ์ฌ๊ณ ๋ฅผ ์๋ฐฉํ ์ ์๋ค.
๐ ์ฐธ๊ณ
Comments powered by Disqus.