Nginx Reverse Proxy 완벽 설정 가이드 - Docker와 Kubernetes 환경에서
Nginx 리버스 프록시 설정부터 Docker, Kubernetes 배포까지. 실무에서 바로 사용할 수 있는 설정 파일과 CLI 명령어를 포함한 완벽 가이드입니다.
Nginx Reverse Proxy 완벽 설정 가이드 - Docker와 Kubernetes 환경에서
현대적인 웹 애플리케이션 아키텍처에서 Nginx 리버스 프록시는 필수적인 구성 요소입니다. 로드 밸런싱, SSL 종료, 캐싱, 그리고 보안 강화까지 다양한 역할을 수행하며, 특히 마이크로서비스 환경에서는 API Gateway 역할까지 담당합니다. 이 글에서는 기본 설정부터 Docker와 Kubernetes 환경에서의 실제 배포까지 실무에서 바로 활용할 수 있는 완벽한 가이드를 제공합니다.
Nginx Reverse Proxy 기본 개념과 장점
리버스 프록시는 클라이언트 요청을 받아 백엔드 서버로 전달하고, 응답을 다시 클라이언트에게 반환하는 중간 서버 역할을 합니다. Nginx는 이벤트 기반 아키텍처로 높은 성능과 낮은 메모리 사용량을 자랑하며, 다음과 같은 장점을 제공합니다.
첫째, 로드 밸런싱을 통해 여러 백엔드 서버로 트래픽을 분산시킬 수 있습니다. 둘째, SSL/TLS 종료를 통해 암호화 처리 부담을 백엔드에서 제거할 수 있습니다. 셋째, 정적 콘텐츠 캐싱으로 응답 속도를 향상시키고 백엔드 서버 부하를 줄일 수 있습니다. 넷째, 요청 헤더 수정, IP 필터링 등 보안 기능을 제공합니다.
기본 Nginx 설정 파일 구성
Nginx 설정의 핵심은 nginx.conf 파일입니다. 다음은 리버스 프록시를 위한 기본 구성입니다:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/conf.d/*.conf;
}
이 설정에서 worker_processes auto는 CPU 코어 수에 맞게 워커 프로세스를 자동 설정하며, gzip 압축을 통해 전송 데이터 크기를 줄입니다.
실무 리버스 프록시 설정
실제 프로덕션 환경에서 사용할 수 있는 리버스 프록시 설정을 살펴보겠습니다. /etc/nginx/conf.d/default.conf 파일에 다음과 같이 구성합니다:
upstream backend {
least_conn;
server backend1:8080 max_fails=3 fail_timeout=30s;
server backend2:8080 max_fails=3 fail_timeout=30s;
server backend3:8080 max_fails=3 fail_timeout=30s backup;
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
location /api/ {
proxy_pass http://backend/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
이 설정에서 upstream 블록은 백엔드 서버들을 정의하며, least_conn 알고리즘을 사용해 연결 수가 가장 적은 서버로 요청을 라우팅합니다.
Docker 환경에서의 Nginx 배포
Docker를 사용하여 Nginx 리버스 프록시를 배포하는 방법을 살펴보겠습니다. 먼저 Dockerfile을 작성합니다:
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
COPY ssl/ /etc/ssl/
RUN nginx -t
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
Docker Compose를 사용한 전체 스택 구성은 다음과 같습니다:
version: '3.8'
services:
nginx:
build: .
ports:
- "80:80"
- "443:443"
depends_on:
- backend1
- backend2
networks:
- app-network
volumes:
- ./logs:/var/log/nginx
restart: unless-stopped
backend1:
image: node:16-alpine
command: npm start
working_dir: /app
volumes:
- ./app:/app
networks:
- app-network
environment:
- PORT=8080
backend2:
image: node:16-alpine
command: npm start
working_dir: /app
volumes:
- ./app:/app
networks:
- app-network
environment:
- PORT=8080
networks:
app-network:
driver: bridge
배포는 다음 명령어로 실행합니다:
# 이미지 빌드 및 컨테이너 실행
docker-compose up -d
# 로그 확인
docker-compose logs -f nginx
# 설정 테스트
docker exec nginx-container nginx -t
# 설정 리로드
docker exec nginx-container nginx -s reload
Kubernetes 환경에서의 Nginx 배포
Kubernetes 환경에서는 ConfigMap을 사용하여 Nginx 설정을 관리하고, Ingress Controller로 활용할 수 있습니다. 먼저 ConfigMap을 생성합니다:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: default
data:
nginx.conf: |
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream backend {
server backend-service:8080;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
Deployment와 Service 리소스를 정의합니다:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-proxy
spec:
replicas: 3
selector:
matchLabels:
app: nginx-proxy
template:
metadata:
labels:
app: nginx-proxy
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: nginx-config
configMap:
name: nginx-config
apiVersion: v1
kind: Service
metadata:
name: nginx-proxy-service
spec:
selector:
app: nginx-proxy
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
다음 명령어로 배포합니다:
# ConfigMap 적용
kubectl apply -f nginx-configmap.yaml
# Deployment와 Service 적용
kubectl apply -f nginx-deployment.yaml
# 배포 상태 확인
kubectl get pods -l app=nginx-proxy
kubectl get svc nginx-proxy-service
# 로그 확인
kubectl logs -l app=nginx-proxy -f
# 설정 업데이트 후 재배포
kubectl rollout restart deployment/nginx-proxy
고급 설정과 최적화
프로덕션 환경에서는 추가적인 최적화와 보안 설정이 필요합니다. 다음은 고급 설정 예시입니다:
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
server {
# Rate limiting 적용
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend/api/;
}
location /login {
limit_req zone=login burst=5 nodelay;
proxy_pass http://backend/login;
}
# 캐싱 설정
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# 압축 설정
location ~* \.(js|css|html|xml)$ {
gzip_static on;
expires 1h;
}
}
모니터링과 로깅
효과적인 운영을 위해서는 모니터링과 로깅이 중요합니다. Prometheus와 Grafana를 활용한 모니터링 설정을 살펴보겠습니다:
# Nginx Prometheus exporter 설치
docker run -d \
--name nginx-exporter \
--network app-network \
-p 9113:9113 \
nginx/nginx-prometheus-exporter:latest \
-nginx.scrape-uri=http://nginx:8080/stub_status
# 로그 분석을 위한 설정
tail -f /var/log/nginx/access.log | \
awk '{print $1, $7, $9, $10}' | \
grep -E "(4[0-9]{2}|5[0-9]{2})"
ELK 스택을 활용한 로그 수집 설정도 고려할 수 있습니다:
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/*.log
fields:
service: nginx
environment: production
output.elasticsearch:
hosts: ["elasticsearch:9200"]
마무리
Nginx 리버스 프록시는 현대적인 웹 애플리케이션 인프라의 핵심 구성 요소입니다. 기본 설정부터 Docker와 Kubernetes 환경에서의 배포, 그리고 고급 최적화까지 단계별로 구성하면 안정적이고 확장 가능한 시스템을 구축할 수 있습니다. 특히 마이크로서비스 아키텍처에서는 API Gateway 역할까지 수행하며, 적절한 모니터링과 로깅을 통해 시스템의 건강성을 지속적으로 관리할 수 있습니다. 실제 운영 환경에서는 보안, 성능, 가용성을 모두 고려한 종합적인 접근이 필요하며, 이 가이드가 그 출발점이 되길 바랍니다.
관련 게시글
GitOps Workflow 설계 가이드: Kubernetes와 CI/CD를 활용한 자동화
GitOps는 선언적 인프라 및 애플리케이션 관리를 위한 강력한 패러다임입니다. 이 가이드에서는 Git을 Single Source of Truth로 활용하여 Kubernetes 환경에서 안정적이고 효율적인 GitOps 워크플로우를 설계하는 방법을 Docker, CI/CD 자동화 예시와 함께 상세히 설명합니다.
GitHub Actions Advanced Workflows: Docker, Kubernetes CI/CD
GitHub Actions를 활용한 Docker, Kubernetes 기반 CI/CD 파이프라인 구축 심화 가이드. DevOps 엔지니어링 관점에서 자동화 전략을 탐구합니다.
Terraform Infrastructure Automation: DevOps 엔지니어링 가이드
Terraform을 활용한 인프라 자동화의 핵심 개념부터 실제 AWS 환경에서의 배포 예시까지, DevOps 엔지니어링 관점에서 자세히 알아봅니다. IaC, Docker, Kubernetes, CI/CD 파이프라인 통합 전략을 다룹니다.