インフラストラクチャ¶
KanjiIQはHetzner上のセルフホストKubernetesクラスターで動作し、IngressにTraefik、自動TLSにcert-managerを使用しています。
ホスティング:Hetzner専用サーバー¶
本番環境全体が単一のHetzner専用サーバーで動作しています:
- Kubernetesディストリビューション:k3s(軽量、単一バイナリのKubernetes)
- OS:Linux
- ネットワーキング:Cloudflare DNS付きパブリックIPv4
なぜHetznerなのか?¶
- 予測可能な月額料金(リクエスト単位や時間単位の課金なし)
- ヨーロッパのデータセンター(GDPRフレンドリー)
- 優れたコストパフォーマンス
- k3sインストールのためのフルルートアクセス
Kubernetes:k3s¶
k3sは、以下をバンドルした軽量でCNCF認定のKubernetesディストリビューションです:
- コンテナランタイム:containerd
- Ingressコントローラー:Traefik(プリインストール)
- サービスロードバランサー:Klipper
- ストレージ:Local path provisioner
- DNS:CoreDNS
k3sはマルチコンポーネントのkubeadmセットアップの代わりに、単一バイナリ(約100MB)でKubernetesを動作させます。標準のKubernetes APIと完全に互換性があり、すべてのkubectlコマンドとマニフェストが同様に動作します。
Ingress:Traefik¶
Traefikはクラスターのingressコントローラーとして以下を処理します:
- TLS終端:すべてのドメインの自動HTTPS
- ルーティング:サービスへのホストベースルーティング(kanjiiq.com → frontend、api.kanjiiq.com → backend)
- レート制限:CRDミドルウェアによるIPごとのリクエストスロットリング
- セキュリティヘッダー:ミドルウェアチェーンによるHSTS、X-Frame-Options、CSP
ミドルウェア設定¶
# Public traffic: rate limit + security headers
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: public-security-chain
spec:
chain:
middlewares:
- name: rate-limit # 100 req/min, burst 50
- name: security-headers # HSTS, X-Frame-Options, etc.
# Admin traffic: stricter rate limit + auth
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: admin-security-chain
spec:
chain:
middlewares:
- name: api-rate-limit # 50 req/min, burst 25
- name: security-headers
- name: admin-auth
TLS:cert-manager + Let's Encrypt¶
自動TLS証明書管理:
graph LR
I[Ingress with<br/>cert-manager annotation] --> CM[cert-manager]
CM --> LE[Let's Encrypt<br/>ACME challenge]
LE --> C[TLS Certificate]
C --> S[Kubernetes Secret]
S --> T[Traefik uses cert<br/>for HTTPS]
- ClusterIssuer:
letsencrypt-prod(クラスター全体の認証局) - チャレンジタイプ:Traefik経由のHTTP-01
- 更新:有効期限前に自動更新
- ストレージ:証明書はKubernetes Secretとして保存
Ingressリソースは単一のアノテーションで証明書をリクエストします:
DNS:Cloudflare¶
ドメインDNSはCloudflareで管理されています:
- Aレコード:HetznerサーバーIPを指定
- プロキシ:オプションのCloudflare CDN/WAFレイヤー
- CF-IPCountryヘッダー:IPデータベースなしでバックエンドがジオロケーションに使用
コンテナレジストリ:Forgejo¶
DockerイメージはForgejo Container Registry(<registry>)に保存されています:
- ソースコードと同じ場所に配置(単一プラットフォーム)
- Kubernetesでイメージプルシークレットを設定(
forgejo-registry) - タグ:各ビルドで
:latest+:COMMIT_SHA - 外部レジストリへの依存なし(Docker Hub、GHCRなど)
リソース割り当て¶
| コンポーネント | CPUリクエスト | CPU上限 | メモリリクエスト | メモリ上限 |
|---|---|---|---|---|
| Backend | 250m | 500m | 256Mi | 512Mi |
| Frontend | 100m | 200m | 128Mi | 256Mi |
| PostgreSQL | 250m | 500m | 256Mi | 512Mi |
| Docs | 10m | 100m | 32Mi | 64Mi |