実践LESSON 04

この教材で学ぶこと L4/L7、Nginx、リバースプロキシの使い分けを学びます。

ロードバランサーとプロキシ — Nginx・L4/L7 LB

前提知識: Web 3層構造の概要。本教材ではLBの仕組みと AWS・自前LBの使い分けを扱います。


1. ロードバランサーの役割と種類

L4(トランスポート層)ロードバランサー:
  対象: IP + TCP/UDP ポート
  仕組: パケットの転送先IPを書き換える(NAT)
  特徴: 高速・HTTP の中身は見ない
  用途: MySQL Proxy・FTP・ゲームサーバー

L7(アプリケーション層)ロードバランサー:
  対象: HTTP ヘッダー・パス・Cookie・ホスト名
  仕組: HTTPをパースしてルーティング
  特徴: 柔軟なルーティング・TLS終端・リクエストの書き換え可能
  用途: 通常のWebサービス

AWS における対応:
  L4 → NLB(Network Load Balancer)
  L7 → ALB(Application Load Balancer)

2. ALB(Application Load Balancer)の設計

構成例:
  インターネット
       ↓
  [ALB] (ap-northeast-1a / 1c にまたがる)
       ↓ パスベースルーティング
  /api/*  → Target Group A (ECS API サービス)
  /admin/* → Target Group B (EC2 管理画面) ← IP制限
  /*      → Target Group C (CloudFront/S3 の前の静的サイト)
# ALB のリスナールール(Terraform)
resource "aws_lb_listener_rule" "api" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 10

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.api.arn
  }

  condition {
    path_pattern {
      values = ["/api/*"]
    }
  }
}

resource "aws_lb_listener_rule" "admin_ip_restriction" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 5

  action {
    type = "fixed-response"
    fixed_response {
      content_type = "text/plain"
      message_body = "Forbidden"
      status_code  = "403"
    }
  }

  condition {
    path_pattern {
      values = ["/admin/*"]
    }
  }
  condition {
    not {
      source_ip {
        values = ["203.0.113.0/24"]  # 会社のIPのみ許可
      }
    }
  }
}

3. Nginx — リバースプロキシとして使う

# /etc/nginx/conf.d/myapp.conf

# アップストリーム定義(バックエンドのプール)
upstream app_backend {
    least_conn;  # 最小接続数に振り分け(デフォルトは round-robin)

    server 10.0.1.10:8080 weight=3;  # 重み付き(3:1の割合)
    server 10.0.1.11:8080 weight=1;
    
    # ヘルスチェック(NGINX Plus のみ / OSS は passive のみ)
    keepalive 32;  # コネクションプール(バックエンドへの接続を再利用)
}

server {
    listen 80;
    server_name api.mycompany.com;
    
    # HTTP → HTTPS リダイレクト
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name api.mycompany.com;

    ssl_certificate     /etc/letsencrypt/live/api.mycompany.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.mycompany.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;

    # リクエストボディのサイズ制限
    client_max_body_size 10m;

    # タイムアウト設定
    proxy_connect_timeout 10s;
    proxy_read_timeout    60s;
    proxy_send_timeout    60s;

    location /api/ {
        proxy_pass http://app_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;
    }

    # 静的ファイルは Nginx から直接配信
    location /static/ {
        alias /var/www/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

4. レート制限(Nginx)

# レート制限の設定(DDoS 対策・API 保護)
http {
    # ゾーン定義(IPアドレスベース、10MBのメモリ = 約16万IPを管理可能)
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_req_zone $http_x_api_key     zone=key_limit:10m rate=100r/s;

    server {
        location /api/ {
            # burst=20: 一時的に20リクエストのバーストを許可
            # nodelay: バーストは即時処理(キューに入れない)
            limit_req zone=api_limit burst=20 nodelay;
            limit_req_status 429;  # 超過時は 429 Too Many Requests
        }
    }
}

5. ALB vs NLB vs Nginx の使い分け

AWS ALB:
  ✅ パスベース・ホストベースのルーティング
  ✅ ECS/EKS との統合(ターゲットグループのヘルスチェック)
  ✅ WAF との統合
  ✅ マネージド(管理不要)
  → 通常の Web サービスはこれ一択

AWS NLB:
  ✅ 超低レイテンシ(L4で高速)
  ✅ 静的 IP(固定IPが必要なときに使う)
  ✅ TCP/UDP(非HTTP プロトコル)
  → WebSocket 大規模・ゲーム・IoT

自前 Nginx:
  ✅ 細かいカスタマイズ(Lua スクリプト等)
  ✅ オンプレ環境
  ✅ ALB の前段に置いて特殊なリクエスト変換
  → マネージドで対応できない要件のみ

🔗 次のステップ