Saltar a contenido

Infraestructura

KanjiIQ se ejecuta en un clúster de Kubernetes autoalojado en Hetzner, usando Traefik para ingress y cert-manager para TLS automático.

Alojamiento: Servidor dedicado Hetzner

Todo el entorno de producción se ejecuta en un único servidor dedicado de Hetzner:

  • Distribución de Kubernetes: k3s (Kubernetes ligero, binario único)
  • SO: Linux
  • Red: IPv4 pública con Cloudflare DNS

¿Por qué Hetzner?

  • Precios mensuales predecibles (sin cargos por solicitud o por hora)
  • Centros de datos en Europa (compatible con GDPR)
  • Excelente relación precio-rendimiento
  • Acceso root completo para la instalación de k3s

Kubernetes: k3s

k3s es una distribución de Kubernetes ligera y certificada por CNCF que incluye:

  • Runtime de contenedores: containerd
  • Controlador de ingress: Traefik (preinstalado)
  • Balanceador de carga de servicios: Klipper
  • Almacenamiento: Local path provisioner
  • DNS: CoreDNS

k3s ejecuta Kubernetes con un solo binario (~100MB) en lugar de la configuración multi-componente de kubeadm. Es totalmente compatible con las APIs estándar de Kubernetes — todos los comandos de kubectl y los manifiestos funcionan de forma idéntica.

Ingress: Traefik

Traefik sirve como el controlador de ingress del clúster, gestionando:

  • Terminación TLS: HTTPS automático para todos los dominios
  • Enrutamiento: Enrutamiento basado en host hacia servicios (kanjiiq.com -> frontend, api.kanjiiq.com -> backend)
  • Limitación de velocidad: Throttling de solicitudes por IP mediante CRD middlewares
  • Cabeceras de seguridad: HSTS, X-Frame-Options, CSP mediante cadena de middleware

Configuración de middleware

# 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

Gestión automática de certificados 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 (autoridad de certificación a nivel de clúster)
  • Tipo de desafío: HTTP-01 vía Traefik
  • Renovación: Automática antes del vencimiento
  • Almacenamiento: Certificados almacenados como Kubernetes Secrets

Los recursos Ingress solicitan certificados con una sola anotación:

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

DNS: Cloudflare

El DNS del dominio se gestiona a través de Cloudflare:

  • Registros A: Apuntan a la IP del servidor Hetzner
  • Proxied: Capa opcional de CDN/WAF de Cloudflare
  • Cabecera CF-IPCountry: Utilizada por el backend para geolocalización sin bases de datos de IP

Registro de contenedores: Forgejo

Las imágenes Docker se almacenan en el Forgejo Container Registry en <registry>:

  • Co-ubicado con el código fuente (plataforma única)
  • Secretos de pull de imágenes configurados en Kubernetes (forgejo-registry)
  • Etiquetas: :latest + :COMMIT_SHA para cada compilación
  • Sin dependencias de registros externos (Docker Hub, GHCR, etc.)

Asignación de recursos

Componente CPU solicitada Límite CPU Memoria solicitada Límite memoria
Backend 250m 500m 256Mi 512Mi
Frontend 100m 200m 128Mi 256Mi
PostgreSQL 250m 500m 256Mi 512Mi
Docs 10m 100m 32Mi 64Mi