ロードバランサーOSS比較:Nginx vs HAProxy vs Traefik でAWS ELB代替をセルフホスト
オープンソースラボ編集部 ・ 2026年6月13日
ロードバランサーOSS比較:Nginx vs HAProxy vs Traefik でAWS ELB代替をセルフホスト
AWS ALB/ELBは月$0.008/LCU+トラフィック量課金で、高トラフィック環境では月数万円になります。Nginx(デファクトスタンダード・高機能Web+LB)・HAProxy(純粋L4/L7LB・金融系で多用)・Traefik(コンテナ自動検出・Let's Encrypt内蔵)はOSSのロードバランサーで、VPS1台からKubernetesまで幅広く使えます。
ロードバランサー選定の背景
- コスト削減: AWS ALBの月$100〜を、VPS $5/月のNginxで代替する
- Kubernetes Ingress: NginxやTraefikをK8s Ingressコントローラーとして使う
- Let's Encrypt自動SSL: TraefikはHTTPS証明書の自動取得・更新が設定1行で完了
- Blue/Green・カナリア: バックエンドの重み付けルーティングで段階的なデプロイを実現
- WebSocket・gRPC: 長期接続・HTTP/2のロードバランシングが必要
主要ツールの概要
Nginx
Igor Sysoevが開発した高性能Webサーバーかつリバースプロキシです。GitHubスター(nginx本体は公式Gitlabのみ)。HTTPサーバー・リバースプロキシ・ロードバランサー・メールプロキシ機能を持ち、現在世界のWebサーバーシェア約30%を占めます。
# nginx.conf - リバースプロキシ + ロードバランシング設定
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 10000;
use epoll;
multi_accept on;
}
http {
# ロードバランシング: 重み付きラウンドロビン
upstream backend {
least_conn; # 最小接続数ベース(デフォルトはround_robin)
server app1.internal:3000 weight=5; # 50%のリクエスト
server app2.internal:3000 weight=3; # 30%のリクエスト
server app3.internal:3000 weight=2; # 20%のリクエスト
# ヘルスチェック(Nginx Plus機能。OSS版は下記passive方式)
server app4.internal:3000 backup; # 全サーバーダウン時のフォールバック
keepalive 32;
}
server {
listen 80;
server_name yoursite.com www.yoursite.com;
return 301 https://$host$request_uri; # HTTPSにリダイレクト
}
server {
listen 443 ssl http2;
server_name yoursite.com www.yoursite.com;
ssl_certificate /etc/letsencrypt/live/yoursite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yoursite.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# セキュリティヘッダー
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=63072000" always;
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 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# バッファリング
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
}
# WebSocketのプロキシ
location /ws {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 静的ファイルはNginxが直接配信
location /static/ {
root /var/www/html;
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
# Ubuntu/DebianにNginxをインストール
sudo apt update && sudo apt install -y nginx certbot python3-certbot-nginx
# Let's Encryptで自動SSL証明書を取得(Nginx設定を自動変更)
sudo certbot --nginx -d yoursite.com -d www.yoursite.com --non-interactive --agree-tos -m admin@yoursite.com
# 証明書自動更新のcron確認
sudo systemctl list-timers | grep certbot
# または手動テスト
sudo certbot renew --dry-run
HAProxy
Willy Tarreauが開発する高性能なTCP/HTTPロードバランサーです。GitHubスター5k+。L4(TCP)・L7(HTTP)両方のロードバランシングに対応し、金融機関・大規模EC・高トラフィックAPIで採用実績が豊富です。Nginxより設定が直感的なACL(アクセスコントロールリスト)によるトラフィック振り分けが特徴です。
# haproxy.cfg - 本番向け設定例
global
maxconn 50000
log 127.0.0.1 local0
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
stats socket /var/run/haproxy/admin.sock mode 660 level admin
tune.ssl.default-dh-param 2048
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout connect 5s
timeout client 30s
timeout server 30s
timeout http-request 10s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 503 /etc/haproxy/errors/503.http
# 統計ダッシュボード
listen stats
bind *:8080
stats enable
stats uri /haproxy?stats
stats realm HAProxy\ Statistics
stats auth admin:your-stats-password
stats refresh 30s
# HTTPSフロントエンド
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/yoursite.pem alpn h2,http/1.1
bind *:80
http-request redirect scheme https code 301 unless { ssl_fc }
# ACL: パスによるバックエンド振り分け
acl is_api path_beg /api/
acl is_ws hdr(Upgrade) -i websocket
use_backend api_servers if is_api
use_backend ws_servers if is_ws
default_backend web_servers
# Webバックエンド(ラウンドロビン)
backend web_servers
balance roundrobin
option httpchk GET /health HTTP/1.1
Host:\ yoursite.com
http-check expect status 200
server web1 10.0.0.1:3000 check inter 2s fall 3 rise 2
server web2 10.0.0.2:3000 check inter 2s fall 3 rise 2
server web3 10.0.0.3:3000 check inter 2s fall 3 rise 2
# APIバックエンド(最小接続数)
backend api_servers
balance leastconn
option httpchk GET /api/health
http-check expect status 200
server api1 10.0.1.1:8080 check inter 1s fall 2 rise 3
server api2 10.0.1.2:8080 check inter 1s fall 2 rise 3
# WebSocketバックエンド(ソースIP固定)
backend ws_servers
balance source
timeout tunnel 1h
server ws1 10.0.2.1:3001 check
server ws2 10.0.2.2:3001 check
Traefik
Containous(現Traefik Labs)が開発するクラウドネイティブなリバースプロキシです。GitHubスター51k+。Docker/Kubernetes/Consul/ECSなどのプロバイダーを自動検出してルーティングを動的に設定でき、Let's Encrypt証明書の自動取得・更新が設定1行で完了します。Docker Composeで新しいコンテナを起動するだけで自動的にHTTPS対応のサブドメインが割り当てられます。
# docker-compose.yml でTraefikを起動
version: "3"
services:
traefik:
image: traefik:v3.0
restart: always
command:
# ダッシュボードを有効化
- "--api.dashboard=true"
# Dockerプロバイダーを有効化
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
# エントリポイント設定
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Let's Encrypt自動SSL
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=admin@yoursite.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
# アクセスログ
- "--accesslog=true"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
labels:
# ダッシュボードにアクセス(Basic認証)
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.yoursite.com`)"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$05$$... "
# アプリコンテナはラベルを追加するだけで自動でHTTPS化
my-app:
image: my-app:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.my-app.rule=Host(`app.yoursite.com`)"
- "traefik.http.routers.my-app.entrypoints=websecure"
- "traefik.http.routers.my-app.tls.certresolver=letsencrypt"
- "traefik.http.services.my-app.loadbalancer.server.port=3000"
# HTTPSにリダイレクト
- "traefik.http.routers.my-app-http.rule=Host(`app.yoursite.com`)"
- "traefik.http.routers.my-app-http.entrypoints=web"
- "traefik.http.routers.my-app-http.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
volumes:
letsencrypt:
機能比較表
| 比較項目 | Nginx | HAProxy | Traefik |
|---|---|---|---|
| ライセンス | BSD-2-Clause | GPL/LGPL | MIT |
| L4 TCP LB | ✅ | ✅ 優秀 | ✅ |
| L7 HTTP LB | ✅ 優秀 | ✅ | ✅ |
| Let's Encrypt | 要certbot | 要手動 | ✅ 自動 |
| Docker自動検出 | ❌ | ❌ | ✅ |
| K8s Ingress | ✅ Nginx Ingress | ✅ | ✅ Traefik IngressRoute |
| 設定のホットリロード | ❌ | ✅ | ✅ |
| 最小リソース | 低 | 最小 | 低 |
| GitHub Stars | - | 5k+ | 51k+ |
KubernetesでのGitOpsとロードバランサーの組み合わせはDevOpsカテゴリ/categories/devopsを参照。SSLとセキュリティ設定はセキュリティカテゴリ/categories/securityにまとめています。
FAQ
Q. NginxとTraefikはどちらをKubernetes Ingressコントローラーとして使うべきですか?
A. どちらも成熟していますが選択基準が異なります。Nginx Ingress Controller推奨のケース: ①チームがNginx設定に慣れており追加学習コストを避けたい②細かいNginx固有の設定(upstream zone・lua-nginx-module等)が必要③アノテーション数が少なくシンプルな設定で済む。Traefik IngressRoute推奨のケース: ①Docker Composeとの一貫性を保ちたい(dev/prod同じ設定方針)②ミドルウェア(レートリミット・認証・圧縮)をYAMLで宣言的に管理したい③カナリアリリースをTraefikのWeighted Round Robinで簡単に設定したい。AWSではaws-load-balancer-controller(NLB/ALBをK8sから操作)とNginx/Traefikを組み合わせるハイブリッド構成も一般的です。
Q. HAProxyでカナリアリリースの段階的なトラフィック移行を設定する方法は?
A. HAProxyのランタイムAPIを使ってサービスを止めずにバックエンドの重みを動的に変更できます。
# HAProxyのランタイムAPI経由で重みを変更(サービス無停止)
echo "set weight web_servers/web-v2 10" | socat stdio /var/run/haproxy/admin.sock
# 段階的に重みを増やすスクリプト
for weight in 10 20 30 50 80 100; do
echo "set weight web_servers/web-v2 $weight" | socat stdio /var/run/haproxy/admin.sock
echo "Traffic to v2: $weight%"
# メトリクスを確認してから次のステップへ(例: 5分待機)
sleep 300
done
# v1を完全に除外
echo "set server web_servers/web-v1 state maint" | socat stdio /var/run/haproxy/admin.sock
PromQLでエラー率が上昇したらv1に戻す自動ロールバックスクリプトと組み合わせると、ArgoCDのRollout・Flaggerと同等のProgressive Deliveryが実現できます。
Q. TraefikのMiddlewareでレートリミットとIP制限を設定する方法は?
A. TraefikのMiddlewareは宣言的に組み合わせられます。
# Traefikのミドルウェア設定(docker labels版)
# レートリミット: 1秒に100リクエストまで
- "traefik.http.middlewares.rate-limit.ratelimit.average=100"
- "traefik.http.middlewares.rate-limit.ratelimit.period=1s"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=200"
# IPホワイトリスト
- "traefik.http.middlewares.ip-whitelist.ipallowlist.sourcerange=10.0.0.0/8,192.168.0.0/16"
# Basic認証
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..."
# HTTPS強制リダイレクト
- "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
# セキュリティヘッダー
- "traefik.http.middlewares.security-headers.headers.browserxssfilter=true"
- "traefik.http.middlewares.security-headers.headers.contenttypenosniff=true"
- "traefik.http.middlewares.security-headers.headers.forcestsheader=true"
- "traefik.http.middlewares.security-headers.headers.stsseconds=63072000"
# APIルートに複数ミドルウェアをまとめて適用
- "traefik.http.routers.api.middlewares=rate-limit,ip-whitelist,security-headers"
Kubernetes環境ではTraefik Middleware CRD(カスタムリソース定義)として設定します。
Q. NginxをAPI Gatewayとして使い、OpenID ConnectでJWT検証を行う方法は?
A. nginx-auth-requestモジュールを使って認証サーバー(Keycloak/Authentik)にサブリクエストを送り、JWTを検証できます。より簡単な方法はngx_http_auth_jwt_moduleを使うことです。
# nginx.conf でJWT検証(nginx.orgビルドのcommercialモジュールまたはOpenResty)
# OpenRestyを使った方法:
location /api/ {
access_by_lua_block {
local jwt = require("resty.jwt")
local auth_header = ngx.req.get_headers()["Authorization"]
if not auth_header or not auth_header:match("Bearer ") then
ngx.status = 401
ngx.say('{"error": "missing token"}')
ngx.exit(401)
end
local token = auth_header:gsub("Bearer ", "")
local jwt_obj = jwt:verify("your-jwt-secret", token)
if not jwt_obj.verified then
ngx.status = 401
ngx.exit(401)
end
# JWTのクレームをバックエンドヘッダーに転送
ngx.req.set_header("X-User-Id", jwt_obj.payload.sub)
ngx.req.set_header("X-User-Role", jwt_obj.payload.role)
}
proxy_pass http://backend;
}
本番環境ではnginx-jwtモジュールよりもKeycloak/AuthentikをOIDC認証プロバイダーとして使い、NginxはJWT検証をAuthリクエスト先に委譲する方が安全です。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| 高トラフィックL4/L7・金融系 | HAProxy |
| Web+LB統合・静的ファイル配信 | Nginx |
| Docker/K8s自動化・Let's Encrypt | Traefik |
| KubernetesIngress | Nginx Ingress または Traefik |