Zum Inhalt

Kubernetes-Manifeste

Alle Kubernetes-Ressourcen sind im k8s/-Verzeichnis definiert und werden in nummerierter Reihenfolge angewendet.

Manifestübersicht

Datei Ressource Zweck
00-namespace.yaml Namespace Erstellt den jlpt-kanji-Namespace
01-secrets.yaml Secret Datenbank-URL, JWT-Secret, OpenAI-Schlüssel
02-postgres-pvc.yaml PersistentVolumeClaim 10Gi Speicher für PostgreSQL
03-postgres-deployment.yaml Deployment + Service PostgreSQL 15 Datenbank
04-libretranslate-deployment.yaml Deployment + Service Selbst gehostete Übersetzung (optional)
05-deployment.yaml Deployment Hauptanwendung (Frontend + Backend Container)
06-service.yaml Service (x2) Frontend (:80) und Backend (:8080) Services
07-ingress.yaml Ingress Traefik-Routing für jlpt.iqquest.app
08-security-middlewares.yaml Middleware (CRD) Ratenbegrenzung und Sicherheitsheader
ingress-kanjiiq.yaml Ingress Routing für kanjiiq.com-Domains
ingress-docs.yaml Ingress Routing für docs.kanjiiq.app
docs-deployment.yaml Deployment Dokumentationsseite
docs-service.yaml Service Dokumentations-Service

Erstmalige Bereitstellung

Manifeste in Reihenfolge anwenden:

# 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

Alle Ressourcen befinden sich in einem einzelnen Namespace:

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

Dies bietet:

  • Ressourcenisolierung von anderen Workloads
  • Eingeschränkte RBAC (bei Bedarf)
  • Einfache Bereinigung (kubectl delete namespace jlpt-kanji)
  • Durchsetzung von Ressourcenkontingenten (bei Bedarf)

Secrets-Verwaltung

Sensible Werte werden in Kubernetes Secrets gespeichert (nicht in Git eingecheckt):

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-..."

Die 01-secrets.yaml im Repository ist eine Vorlage — die tatsächlichen Werte werden manuell auf dem Server angewendet.

Pod-Design

Der Hauptanwendungs-Pod führt zwei Container nebeneinander aus:

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" }

Gesundheitsprüfungen

Beide Container haben Liveness- und Readiness-Probes:

  • Liveness: Startet den Container neu, wenn er nicht mehr reagiert (alle 10s, 3 Fehlschläge)
  • Readiness: Entfernt den Pod aus den Service-Endpunkten, bis er bereit ist (alle 5s, 2 Fehlschläge)

Sicherheitskontext

Alle Container laufen als Non-Root (UID 1000):

securityContext:
  runAsUser: 1000
  runAsGroup: 1000
  runAsNonRoot: true

Services

Zwei ClusterIP-Services stellen die Container des Pods dem Cluster zur Verfügung:

# 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

Der Backend-Service bildet den externen Port 80 auf den internen Port 8080 ab, sodass Traefik alle Services auf demselben Port ansteuert.

Ingress

Host-basiertes Routing über 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

TLS-Zertifikate werden automatisch von cert-manager bereitgestellt, wenn der Ingress erstellt wird.