Files
k8s-manifests/roswell/deployment.yaml
T

134 lines
5.1 KiB
YAML

# Bot + scheduler en un pod (PLAN §Fase 6). Los secretos vienen de Infisical
# (carpeta /roswell del proyecto homelab) vía infisical-roswell-secrets.yaml.
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
# ArgoCD no debe podar este PVC: guarda la caché del modelo Whisper (~3GB)
# y los PDFs subidos por Telegram.
argocd.argoproj.io/sync-options: Prune=false
name: roswell-data
namespace: roswell
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: roswell
namespace: roswell
labels:
app: roswell
spec:
replicas: 1
# Dos pods haciendo polling del mismo token de Telegram entran en conflicto:
# Recreate garantiza que el viejo muere antes de arrancar el nuevo.
strategy:
type: Recreate
selector:
matchLabels:
app: roswell
template:
metadata:
labels:
app: roswell
spec:
containers:
- name: roswell
# Tag placeholder: el workflow de Gitea Actions lo sustituye por el
# sha8 real en cada build (ver .gitea/workflows/build.yml del repo).
image: git.chemavx.xyz/chemavx/roswell-corpus:e9476a63
imagePullPolicy: Always
env:
- name: TELEGRAM_BOT_TOKEN
valueFrom:
secretKeyRef:
name: roswell-secrets-infisical
key: telegram-bot-token
- name: TELEGRAM_ALLOWED_USERS
valueFrom:
secretKeyRef:
name: roswell-secrets-infisical
key: telegram-allowed-users
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
name: roswell-secrets-infisical
key: anthropic-api-key
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: roswell-secrets-infisical
key: database-url
- name: PODCASTINDEX_KEY
valueFrom:
secretKeyRef:
name: roswell-secrets-infisical
key: podcastindex-key
- name: PODCASTINDEX_SECRET
valueFrom:
secretKeyRef:
name: roswell-secrets-infisical
key: podcastindex-secret
- name: OLLAMA_URL
value: "http://ollama.ollama.svc.cluster.local:11434"
- name: SEARXNG_URL
value: "http://searxng-svc.researchowl.svc.cluster.local:8080"
- name: WHISPER_MODEL
value: "large-v3"
- name: WHISPER_DEVICE
value: "cpu"
- name: DATA_DIR
value: "/data"
# Régimen normal: entra ~1 episodio al día y el tope es de 5 por
# feed y pasada, así que revisar más a menudo solo sería bajarse el
# RSS de más. Se bajó a 3 del 2026-07-26 al 28 para drenar el
# atraso de 45 episodios que destapó el arreglo del tope por
# pasada (a 24 h el pod trabajaba 4 h y dormía 20, y el atraso
# tardaba 5 días en irse en vez de uno). Si vuelve a acumularse
# atraso, bájalo otra vez y súbelo al terminar.
- name: FEED_CHECK_HOURS
value: "24"
# Caché de modelos Whisper en el PVC: la descarga (~3GB) sobrevive
# a los redeploys.
- name: HF_HOME
value: "/data/hf-cache"
volumeMounts:
- name: data
mountPath: /data
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
# Whisper large-v3 INT8 en CPU. Este límite subió tres veces
# persiguiendo episodios cada vez más largos (4Gi del PLAN §10 →
# 6Gi tras el OOM del 2026-07-13 → 8Gi tras el del 2026-07-24,
# un episodio de 80 min), porque faster-whisper procesaba el
# fichero ENTERO de golpe al arrancar y el pico escalaba con la
# duración. Desde `_plan_windows` (roswell-corpus c869b61,
# 2026-07-26) el audio largo se transcribe en ventanas de ~20 min
# y el pico ya no depende de lo que dure el episodio: el mismo
# episodio de 113 min que tocaba el techo tres veces
# (memory.events max=3) pasó a max=0, con ~3,9Gi de anon.
# NO volver a subirlo sin comprobar antes que el troceado sigue
# activo: la línea "Audio de N min: X ventanas" en el log.
# Sin límite de CPU: la transcripción usa los cores libres.
memory: "8Gi"
# Nodo grande (16 cores / 29Gi): transcribe a ~1x tiempo real y comparte
# nodo con los PVC de datos y backups. El nodo pequeño (4 cores/12Gi)
# se saturaba con Whisper.
nodeSelector:
kubernetes.io/hostname: chemavx-k8
volumes:
- name: data
persistentVolumeClaim:
claimName: roswell-data
imagePullSecrets:
- name: gitea-registry