コンテンツにスキップ

スケーリング戦略

KanjiIQは、現在の単一ノードデプロイメントから、トラフィックの増加に伴いマルチノード・マルチリージョンアーキテクチャにスケールできるよう設計されています。

現在の状態

指標
クラスターノード数 1(Hetzner専用サーバー)
アプリケーションレプリカ数 2
データベース 単一PostgreSQLインスタンス
トラフィック処理 IPごと最大約100リクエスト/分(レート制限あり)

これにより現在のトラフィックを快適に処理できます。以下のセクションでは、需要増加に伴うスケーリングパスを説明します。

Horizontal Pod Autoscaling(HPA)

最初のスケーリングステップは、負荷に基づいてレプリカ数を自動調整するHPAの追加です:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: jlpt-kanji-hpa
  namespace: jlpt-kanji
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: jlpt-kanji
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

要件:Metrics Serverのインストールが必要(k3sにはデフォルトで含まれています)。

影響:アプリケーションはCPU/メモリ負荷に基づいて2〜10レプリカ間で自動スケールし、コード変更は不要です。

マルチノードクラスター

単一ノードがリソース上限に達した場合、k3sクラスターにワーカーノードを追加します:

# On the new worker node
curl -sfL https://get.k3s.io | K3S_URL=https://master:6443 \
  K3S_TOKEN=<node-token> sh -

Kubernetesは利用可能なすべてのノードにPodを自動的にスケジュールします。アプリケーションは既にステートレスであるため、変更は不要です。

Node Affinity(オプション)

Podの配置を制御するには:

spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          podAffinityTerm:
            labelSelector:
              matchLabels:
                app: jlpt-kanji
            topologyKey: kubernetes.io/hostname

これによりレプリカが異なるノードに分散され、耐障害性が向上します。

データベースのスケーリング

接続プーリング

PgBouncerをサイドカーコンテナとして追加し、データベース接続をプールします:

containers:
  - name: pgbouncer
    image: edoburu/pgbouncer
    ports:
      - containerPort: 6432
    env:
      - name: DATABASE_URL
        valueFrom:
          secretKeyRef:
            name: jlpt-kanji-secrets
            key: database-url

バックエンドはPostgreSQLに直接接続する代わりにPgBouncerの:6432に接続し、接続オーバーヘッドを削減します。

リードレプリカ

読み取り負荷の高いワークロード(フラッシュカードクエリ)には、PostgreSQLストリーミングレプリケーションを追加します:

  1. プライマリインスタンスが書き込みを処理(学習セッション、クイズ結果)
  2. リードレプリカが読み取りを処理(漢字/語彙クエリ)
  3. バックエンドが操作タイプに基づいてクエリをルーティング

マネージドデータベース

最もシンプルなデータベーススケーリングパスは、マネージドサービスへの移行です:

  • AWS RDS:マルチAZ、自動バックアップ、リードレプリカ
  • GCP Cloud SQL:HA構成、自動フェイルオーバー
  • Hetzner Managed PostgreSQL:利用可能になり次第

移行の詳細は移植性を参照してください。

CDNレイヤー

グローバルパフォーマンスのために、静的フロントエンドアセットをCDN経由で配信できます:

graph LR
    U[User] --> CF[Cloudflare CDN]
    CF -->|Cache HIT| U
    CF -->|Cache MISS| N[Nginx Frontend]
    N --> CF

Flutter Webフロントエンドは静的ファイル(JS、CSS、画像)を生成するため、これらはCDNの理想的な候補です:

  • キャッシュポリシー:ハッシュ付きアセットに1年、index.htmlにはキャッシュなし
  • グローバルPoP:最寄りのエッジロケーションからコンテンツを配信
  • DDoS防御:CDNが大量攻撃を吸収

Cloudflare DNSは既に配置されています — プロキシモードを有効にするとCDNレイヤーが活性化します。

スケーリングロードマップ

トラフィックレベル インフラストラクチャ 主な変更点
現在(低) 1ノード、2レプリカ、単一PG 変更不要
成長中(中) 1ノード、HPA(2〜10レプリカ) HPAマニフェストの追加
2〜3ノード、HPA、PgBouncer ワーカーノード追加 + 接続プーリング
非常に高い マルチノード、マネージドDB、CDN DBをRDS/Cloud SQLに移行、CDN有効化
グローバル マルチリージョンクラスター、リードレプリカ 大幅なアーキテクチャ進化

各ステップはインクリメンタルで、書き換えは不要です。アプリケーションコードはすべてのスケーリングレベルで変更なしのままです。