# 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:de3b2e34 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