コンテンツにスキップ

Kubernetesマニフェスト

すべてのKubernetesリソースはk8s/ディレクトリに定義され、番号順に適用されます。

マニフェスト概要

ファイル リソース 用途
00-namespace.yaml Namespace jlpt-kanji namespaceを作成
01-secrets.yaml Secret データベースURL、JWTシークレット、OpenAIキー
02-postgres-pvc.yaml PersistentVolumeClaim PostgreSQL用10Giストレージ
03-postgres-deployment.yaml Deployment + Service PostgreSQL 15データベース
04-libretranslate-deployment.yaml Deployment + Service セルフホスト翻訳(オプション)
05-deployment.yaml Deployment メインアプリ(frontend + backendコンテナ)
06-service.yaml Service (x2) Frontend (:80)およびBackend (:8080)サービス
07-ingress.yaml Ingress jlpt.iqquest.appのTraefikルーティング
08-security-middlewares.yaml Middleware (CRD) レート制限とセキュリティヘッダー
ingress-kanjiiq.yaml Ingress kanjiiq.comドメインのルーティング
ingress-docs.yaml Ingress docs.kanjiiq.appのルーティング
docs-deployment.yaml Deployment ドキュメントサイト
docs-service.yaml Service ドキュメントサービス

初回デプロイメント

マニフェストを順番に適用します:

# Create namespace and secrets
kubectl apply -f k8s/00-namespace.yaml
kubectl apply -f k8s/01-secrets.yaml

# Database
kubectl apply -f k8s/02-postgres-pvc.yaml
kubectl apply -f k8s/03-postgres-deployment.yaml

# Application
kubectl apply -f k8s/05-deployment.yaml
kubectl apply -f k8s/06-service.yaml

# Networking
kubectl apply -f k8s/07-ingress.yaml
kubectl apply -f k8s/08-security-middlewares.yaml
kubectl apply -f k8s/ingress-kanjiiq.yaml

Namespace:jlpt-kanji

すべてのリソースは単一のnamespaceに存在します:

apiVersion: v1
kind: Namespace
metadata:
  name: jlpt-kanji

これにより以下が提供されます:

  • 他のワークロードからのリソース分離
  • スコープ付きRBAC(必要に応じて)
  • 簡単なクリーンアップ(kubectl delete namespace jlpt-kanji
  • リソースクォータの適用(必要に応じて)

シークレット管理

機密値はKubernetes Secret(Gitにコミットされない)に保存されます:

apiVersion: v1
kind: Secret
metadata:
  name: jlpt-kanji-secrets
  namespace: jlpt-kanji
type: Opaque
stringData:
  database-url: "postgresql://user:pass@jlpt-postgres:5432/jlpt_flashcard"
  jwt-secret: "random-secret-string"
  openai-api-key: "sk-..."

リポジトリ内の01-secrets.yamlテンプレートです — 実際の値はサーバー上で手動適用されます。

Pod設計

メインアプリケーションPodは2つのコンテナを並行して実行します:

spec:
  replicas: 2
  template:
    spec:
      imagePullSecrets:
        - name: forgejo-registry
      containers:
        - name: backend
          image: <registry>/jlpt-kanji-backend:latest
          ports:
            - containerPort: 8080
          resources:
            requests: { memory: "256Mi", cpu: "250m" }
            limits: { memory: "512Mi", cpu: "500m" }

        - name: frontend
          image: <registry>/jlpt-kanji-frontend:latest
          ports:
            - containerPort: 80
          resources:
            requests: { memory: "128Mi", cpu: "100m" }
            limits: { memory: "256Mi", cpu: "200m" }

ヘルスチェック

両コンテナにはlivenessプローブとreadinessプローブがあります:

  • Liveness:コンテナが応答しなくなった場合に再起動(10秒ごと、3回の失敗)
  • Readiness:準備完了までServiceエンドポイントからPodを除外(5秒ごと、2回の失敗)

セキュリティコンテキスト

すべてのコンテナは非root(UID 1000)で実行されます:

securityContext:
  runAsUser: 1000
  runAsGroup: 1000
  runAsNonRoot: true

サービス

2つのClusterIPサービスがPodのコンテナをクラスターに公開します:

# Frontend service (port 80 → 80)
name: jlpt-kanji-frontend
ports:
  - port: 80
    targetPort: 80

# Backend service (port 80 → 8080)
name: jlpt-kanji-backend
ports:
  - port: 80
    targetPort: 8080

バックエンドサービスは外部ポート80を内部ポート8080にマッピングするため、Traefikはすべてのサービスに同じポートでルーティングします。

Ingress

Traefik経由のホストベースルーティング:

spec:
  ingressClassName: traefik
  tls:
    - hosts:
        - kanjiiq.com
        - api.kanjiiq.com
        - admin.kanjiiq.com
      secretName: kanjiiq-tls
  rules:
    - host: kanjiiq.com       → jlpt-kanji-frontend:80
    - host: api.kanjiiq.com   → jlpt-kanji-backend:80
    - host: admin.kanjiiq.com → jlpt-kanji-backend:80

Ingressが作成されると、TLS証明書はcert-managerによって自動的にプロビジョニングされます。