スケーリング戦略¶
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ストリーミングレプリケーションを追加します:
- プライマリインスタンスが書き込みを処理(学習セッション、クイズ結果)
- リードレプリカが読み取りを処理(漢字/語彙クエリ)
- バックエンドが操作タイプに基づいてクエリをルーティング
マネージドデータベース¶
最もシンプルなデータベーススケーリングパスは、マネージドサービスへの移行です:
- 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有効化 |
| グローバル | マルチリージョンクラスター、リードレプリカ | 大幅なアーキテクチャ進化 |
各ステップはインクリメンタルで、書き換えは不要です。アプリケーションコードはすべてのスケーリングレベルで変更なしのままです。