Zum Inhalt

Infrastruktur

KanjiIQ läuft auf einem selbst gehosteten Kubernetes-Cluster auf Hetzner, mit Traefik für Ingress und cert-manager für automatisches TLS.

Hosting: Hetzner Dedicated Server

Die gesamte Produktionsumgebung läuft auf einem einzelnen Hetzner Dedicated Server:

  • Kubernetes-Distribution: k3s (leichtgewichtiges, einzelbinäres Kubernetes)
  • Betriebssystem: Linux
  • Netzwerk: Öffentliche IPv4 mit Cloudflare DNS

Warum Hetzner?

  • Vorhersehbare monatliche Preise (keine Kosten pro Anfrage oder pro Stunde)
  • Europäische Rechenzentrumsstandorte (GDPR-freundlich)
  • Ausgezeichnetes Preis-Leistungs-Verhältnis
  • Voller Root-Zugang für k3s-Installation

Kubernetes: k3s

k3s ist eine leichtgewichtige, CNCF-zertifizierte Kubernetes-Distribution, die Folgendes bündelt:

  • Container-Runtime: containerd
  • Ingress Controller: Traefik (vorinstalliert)
  • Service Load Balancer: Klipper
  • Speicher: Local Path Provisioner
  • DNS: CoreDNS

k3s führt Kubernetes mit einer einzelnen Binary (~100MB) aus, anstelle des Multi-Komponenten-kubeadm-Setups. Es ist vollständig kompatibel mit Standard-Kubernetes-APIs — alle kubectl-Befehle und Manifeste funktionieren identisch.

Ingress: Traefik

Traefik dient als Ingress Controller des Clusters und übernimmt:

  • TLS-Terminierung: Automatisches HTTPS für alle Domains
  • Routing: Host-basiertes Routing zu Services (kanjiiq.com → Frontend, api.kanjiiq.com → Backend)
  • Ratenbegrenzung: IP-basierte Anfragedrosselung über CRD-Middlewares
  • Sicherheitsheader: HSTS, X-Frame-Options, CSP über Middleware-Kette

Middleware-Konfiguration

# 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

Automatische TLS-Zertifikatsverwaltung:

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 (clusterweite Zertifizierungsstelle)
  • Challenge-Typ: HTTP-01 über Traefik
  • Erneuerung: Automatisch vor Ablauf
  • Speicherung: Zertifikate als Kubernetes Secrets gespeichert

Ingress-Ressourcen fordern Zertifikate mit einer einzigen Annotation an:

annotations:
  cert-manager.io/cluster-issuer: letsencrypt-prod

DNS: Cloudflare

Domain-DNS wird über Cloudflare verwaltet:

  • A-Records: Verweisen auf die Hetzner-Server-IP
  • Proxied: Optionale Cloudflare CDN/WAF-Schicht
  • CF-IPCountry-Header: Vom Backend für Geolokalisierung ohne IP-Datenbanken verwendet

Container Registry: Forgejo

Docker-Images werden in der Forgejo Container Registry unter <registry> gespeichert:

  • Am selben Standort wie der Quellcode (einzelne Plattform)
  • Image-Pull-Secrets in Kubernetes konfiguriert (forgejo-registry)
  • Tags: :latest + :COMMIT_SHA für jeden Build
  • Keine externen Registry-Abhängigkeiten (Docker Hub, GHCR, etc.)

Ressourcenzuteilung

Komponente CPU-Anfrage CPU-Limit Speicher-Anfrage Speicher-Limit
Backend 250m 500m 256Mi 512Mi
Frontend 100m 200m 128Mi 256Mi
PostgreSQL 250m 500m 256Mi 512Mi
Docs 10m 100m 32Mi 64Mi