Manifiestos de Kubernetes¶
Todos los recursos de Kubernetes están definidos en el directorio k8s/ y se aplican en orden numérico.
Descripción general de manifiestos¶
| Archivo | Recurso | Propósito |
|---|---|---|
00-namespace.yaml |
Namespace | Crea el namespace jlpt-kanji |
01-secrets.yaml |
Secret | URL de base de datos, secreto JWT, clave OpenAI |
02-postgres-pvc.yaml |
PersistentVolumeClaim | Almacenamiento de 10Gi para PostgreSQL |
03-postgres-deployment.yaml |
Deployment + Service | Base de datos PostgreSQL 15 |
04-libretranslate-deployment.yaml |
Deployment + Service | Traducción autoalojada (opcional) |
05-deployment.yaml |
Deployment | Aplicación principal (contenedores frontend + backend) |
06-service.yaml |
Service (x2) | Servicios de Frontend (:80) y Backend (:8080) |
07-ingress.yaml |
Ingress | Enrutamiento Traefik para jlpt.iqquest.app |
08-security-middlewares.yaml |
Middleware (CRD) | Limitación de velocidad y cabeceras de seguridad |
ingress-kanjiiq.yaml |
Ingress | Enrutamiento para dominios kanjiiq.com |
ingress-docs.yaml |
Ingress | Enrutamiento para docs.kanjiiq.app |
docs-deployment.yaml |
Deployment | Sitio de documentación |
docs-service.yaml |
Service | Servicio de documentación |
Despliegue inicial¶
Aplica los manifiestos en orden:
# 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¶
Todos los recursos viven en un único namespace:
Esto proporciona:
- Aislamiento de recursos de otras cargas de trabajo
- RBAC con alcance (si es necesario)
- Limpieza fácil (
kubectl delete namespace jlpt-kanji) - Aplicación de cuotas de recursos (si es necesario)
Gestión de secretos¶
Los valores sensibles se almacenan en Kubernetes Secrets (no se suben a 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-..."
El 01-secrets.yaml en el repositorio es una plantilla — los valores reales se aplican manualmente en el servidor.
Diseño del pod¶
El pod principal de la aplicación ejecuta dos contenedores en paralelo:
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" }
Health checks¶
Ambos contenedores tienen sondas de liveness y readiness:
- Liveness: Reinicia el contenedor si deja de responder (cada 10s, 3 fallos)
- Readiness: Elimina el pod de los endpoints del Service hasta que esté listo (cada 5s, 2 fallos)
Contexto de seguridad¶
Todos los contenedores se ejecutan como non-root (UID 1000):
Servicios¶
Dos servicios ClusterIP exponen los contenedores del pod al clúster:
# 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
El servicio del backend mapea el puerto externo 80 al puerto interno 8080, para que Traefik enrute a todos los servicios en el mismo puerto.
Ingress¶
Enrutamiento basado en host mediante 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
Los certificados TLS son provisionados automáticamente por cert-manager cuando se crea el Ingress.