Estrategias de escalado¶
KanjiIQ está diseñado para escalar desde su despliegue actual de un solo nodo hasta una arquitectura multi-nodo y multi-región a medida que crece el tráfico.
Estado actual¶
| Métrica | Valor |
|---|---|
| Nodos del clúster | 1 (dedicado Hetzner) |
| Réplicas de aplicación | 2 |
| Base de datos | Instancia única de PostgreSQL |
| Manejo de tráfico | ~100 req/min por IP (con límite de velocidad) |
Esto maneja el tráfico actual cómodamente. Las secciones siguientes describen la ruta de escalado a medida que aumenta la demanda.
Horizontal Pod Autoscaling (HPA)¶
El primer paso de escalado es añadir HPA para ajustar automáticamente el número de réplicas según la carga:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: jlpt-kanji-hpa
namespace: jlpt-kanji
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: jlpt-kanji
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
Requisitos: Metrics Server debe estar instalado (incluido en k3s por defecto).
Impacto: La aplicación escala automáticamente entre 2-10 réplicas según la presión de CPU/memoria, sin cambios de código.
Clúster multi-nodo¶
Cuando un solo nodo alcanza los límites de recursos, se añaden nodos worker al clúster k3s:
# On the new worker node
curl -sfL https://get.k3s.io | K3S_URL=https://master:6443 \
K3S_TOKEN=<node-token> sh -
Kubernetes programa automáticamente los pods en todos los nodos disponibles. La aplicación no requiere cambios — ya es sin estado.
Afinidad de nodo (opcional)¶
Para controlar la ubicación de los pods:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: jlpt-kanji
topologyKey: kubernetes.io/hostname
Esto distribuye las réplicas en diferentes nodos para mejor tolerancia a fallos.
Escalado de base de datos¶
Connection pooling¶
Añadir PgBouncer como contenedor sidecar para agrupar conexiones de base de datos:
containers:
- name: pgbouncer
image: edoburu/pgbouncer
ports:
- containerPort: 6432
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: jlpt-kanji-secrets
key: database-url
El backend se conecta a PgBouncer en :6432 en lugar de directamente a PostgreSQL, reduciendo la sobrecarga de conexiones.
Réplicas de lectura¶
Para cargas de trabajo con muchas lecturas (consultas de tarjetas), añadir replicación por streaming de PostgreSQL:
- La instancia primaria gestiona las escrituras (sesiones de estudio, resultados de cuestionarios)
- Las réplicas de lectura gestionan las lecturas (consultas de kanji/vocabulario)
- El backend enruta las consultas según el tipo de operación
Base de datos gestionada¶
La ruta más simple de escalado de base de datos es migrar a un servicio gestionado:
- AWS RDS: Multi-AZ, respaldos automatizados, réplicas de lectura
- GCP Cloud SQL: Configuración HA, failover automático
- Hetzner Managed PostgreSQL: Cuando esté disponible
Consulta Portabilidad para detalles de migración.
Capa CDN¶
Los assets estáticos del frontend pueden servirse a través de un CDN para rendimiento global:
graph LR
U[User] --> CF[Cloudflare CDN]
CF -->|Cache HIT| U
CF -->|Cache MISS| N[Nginx Frontend]
N --> CF
Dado que el frontend Flutter Web produce archivos estáticos (JS, CSS, imágenes), estos son candidatos ideales para CDN:
- Política de caché: 1 año para assets con hash, sin caché para
index.html - PoPs globales: Contenido servido desde la ubicación edge más cercana
- Protección DDoS: El CDN absorbe ataques volumétricos
Cloudflare DNS ya está configurado — activar el modo proxy habilita la capa CDN.
Hoja de ruta de escalado¶
| Nivel de tráfico | Infraestructura | Cambios clave |
|---|---|---|
| Actual (bajo) | 1 nodo, 2 réplicas, PG único | Ninguno necesario |
| Creciente (moderado) | 1 nodo, HPA (2-10 réplicas) | Añadir manifiesto HPA |
| Alto | 2-3 nodos, HPA, PgBouncer | Añadir nodos worker + connection pooling |
| Muy alto | Multi-nodo, BD gestionada, CDN | Migrar BD a RDS/Cloud SQL, habilitar CDN |
| Global | Clústeres multi-región, réplicas de lectura | Evolución significativa de la arquitectura |
Cada paso es incremental — no se requieren reescrituras. El código de la aplicación permanece sin cambios en todos los niveles de escalado.