diff --git a/reddit-intel/PROMOTION.md b/reddit-intel/PROMOTION.md deleted file mode 100644 index a20a75f..0000000 --- a/reddit-intel/PROMOTION.md +++ /dev/null @@ -1,61 +0,0 @@ -# reddit-intel — promoción de docker compose (n97) a k3s - -Estado: **INACTIVO**. Los manifiestos de este directorio existen solo en git; -el app-of-apps `k8s-manifests` no es recursivo, así que ArgoCD no los -sincroniza. La app corre en docker compose en chemavx-n97 -(`/opt/reddit-intel`, semana de calibración desde 2026-07-06). - -## Checklist de activación (en este orden) - -1. **Imagen en el registro.** Primer build manual, o `workflow_dispatch` del - workflow "Build reddit-intel image" en el repo - `git.chemavx.xyz/chemavx/reddit-intel` (requiere secrets `CI_TOKEN` y - `TELEGRAM_BOT_TOKEN` configurados en ese repo). El workflow actualiza el - tag de `deployment.yaml` aquí; si el build es manual, sustituir el - placeholder `:00000000` a mano por el sha8 real. - -2. **Secrets en Infisical** (proyecto "homelab", env `prod`, path - `/reddit-intel`) — mismos valores que el `.env` del compose: - `reddit-client-id`, `reddit-client-secret`, `llm-api-key`, - `dashboard-auth-token`, `telegram-bot-token`, `telegram-chat-id` - (los dos de telegram pueden ir vacíos). - -3. **Congelar el compose y copiar la BD al PVC:** - ```bash - # en n97 - cd /opt/reddit-intel && docker compose down # para la app (checkpoint WAL limpio) - /opt/reddit-intel/scripts/backup.sh # backup final pre-migración - - # activar la app (crea PVCs y arranca el pod con BD vacía) - kubectl apply -f reddit-intel/argocd-app.yaml - kubectl -n reddit-intel rollout status deploy/reddit-intel - - # parar el pod y volcar la BD del host al PVC - kubectl -n reddit-intel scale deploy/reddit-intel --replicas=0 - kubectl -n reddit-intel run pvc-loader --image=busybox --restart=Never \ - --overrides='{"spec":{"nodeSelector":{"kubernetes.io/hostname":"chemavx-n97"},"containers":[{"name":"pvc-loader","image":"busybox","command":["sleep","600"],"volumeMounts":[{"name":"data","mountPath":"/data"}]}],"volumes":[{"name":"data","persistentVolumeClaim":{"claimName":"reddit-intel-data"}}]}}' - kubectl -n reddit-intel wait --for=condition=Ready pod/pvc-loader - kubectl -n reddit-intel cp /opt/reddit-intel/data/reddit-intel.db pvc-loader:/data/reddit-intel.db - kubectl -n reddit-intel delete pod pvc-loader - kubectl -n reddit-intel scale deploy/reddit-intel --replicas=1 - ``` - (El `docker compose down` previo garantiza que no hay `-wal`/`-shm` - pendientes: basta copiar el `.db`.) - -4. **Verificar:** `kubectl -n reddit-intel logs deploy/reddit-intel` debe - mostrar `scheduler_start jobs=monitor,detector,analyzer,karma,learning`; - el dashboard responde vía `svc/reddit-intel` (port-forward o el ingress - que se decida — pendiente de elegir exposición). - -5. **Desmantelar la fase compose:** quitar la línea del crontab de chemavx en - n97 (el CronJob `reddit-intel-db-backup` de aquí la reemplaza) y archivar - `/opt/reddit-intel` cuando la semana de convivencia confirme que todo va bien. - -## Notas - -- El CronJob de backup (`backup-cronjob.yaml`) replica el patrón researchowl: - `sqlite3 .backup` + `integrity_check` + retención 7, contra el PVC. -- Un solo replica siempre (`strategy: Recreate`): SQLite WAL + APScheduler - in-process no admiten dos pods. -- El namespace `reddit-intel` ya existe en el clúster (creado durante la - preparación); `CreateNamespace=true` lo cubre igualmente. diff --git a/reddit-intel/argocd-app.yaml b/reddit-intel/argocd-app.yaml deleted file mode 100644 index 5311494..0000000 --- a/reddit-intel/argocd-app.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# INACTIVO hasta la promoción: el app-of-apps k8s-manifests NO es recursivo, -# así que este fichero solo existe en git — nadie lo aplica automáticamente. -# La activación es manual: ver PROMOTION.md en este directorio. -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: reddit-intel - namespace: argocd - annotations: - notifications.argoproj.io/subscribe.on-sync-failed.telegram: "5138407666" - notifications.argoproj.io/subscribe.on-health-degraded.telegram: "5138407666" -spec: - project: default - source: - repoURL: https://git.chemavx.xyz/chemavx/k8s-manifests - targetRevision: HEAD - path: reddit-intel - destination: - server: https://kubernetes.default.svc - namespace: reddit-intel - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/reddit-intel/backup-cronjob.yaml b/reddit-intel/backup-cronjob.yaml deleted file mode 100644 index 08e197d..0000000 --- a/reddit-intel/backup-cronjob.yaml +++ /dev/null @@ -1,80 +0,0 @@ ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - annotations: - # Never let ArgoCD prune this PVC: it holds the DB backups. - argocd.argoproj.io/sync-options: Prune=false - name: reddit-intel-backups - namespace: reddit-intel -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - ---- -apiVersion: batch/v1 -kind: CronJob -metadata: - name: reddit-intel-db-backup - namespace: reddit-intel - labels: - app: reddit-intel -spec: - schedule: "0 3 * * *" - timeZone: "Europe/Madrid" - concurrencyPolicy: Forbid - successfulJobsHistoryLimit: 3 - failedJobsHistoryLimit: 3 - jobTemplate: - spec: - backoffLimit: 2 - activeDeadlineSeconds: 600 - template: - metadata: - labels: - app: reddit-intel-db-backup - spec: - restartPolicy: Never - containers: - - name: backup - image: keinos/sqlite3:latest - command: - - /bin/sh - - -c - - | - set -eu - STAMP=$(date +%Y%m%d) - DEST="/backups/reddit-intel-${STAMP}.db" - echo "Backing up /data/reddit-intel.db -> ${DEST}" - sqlite3 -cmd ".timeout 30000" /data/reddit-intel.db ".backup '${DEST}'" - RESULT=$(sqlite3 "${DEST}" "PRAGMA integrity_check;") - if [ "${RESULT}" != "ok" ]; then - echo "Integrity check FAILED: ${RESULT}" - rm -f "${DEST}" - exit 1 - fi - echo "Integrity check ok" - # Retention: keep the 7 most recent backups - for f in $(ls -1t /backups/reddit-intel-*.db | tail -n +8); do - echo "Pruning old backup ${f}" - rm -f "${f}" - done - ls -lh /backups/ - volumeMounts: - # NOT readOnly: the source DB runs in WAL mode and sqlite readers - # must be able to touch the -shm/-wal sidecar files. The job only - # ever reads the DB (.backup); it never modifies application data. - - name: data - mountPath: /data - - name: backups - mountPath: /backups - volumes: - - name: data - persistentVolumeClaim: - claimName: reddit-intel-data - - name: backups - persistentVolumeClaim: - claimName: reddit-intel-backups diff --git a/reddit-intel/deployment.yaml b/reddit-intel/deployment.yaml deleted file mode 100644 index a7fb7d1..0000000 --- a/reddit-intel/deployment.yaml +++ /dev/null @@ -1,124 +0,0 @@ ---- -apiVersion: v1 -kind: Namespace -metadata: - name: reddit-intel - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - annotations: - # Never let ArgoCD prune this PVC: it holds the SQLite DB. - argocd.argoproj.io/sync-options: Prune=false - name: reddit-intel-data - namespace: reddit-intel -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: reddit-intel - namespace: reddit-intel - labels: - app: reddit-intel -spec: - replicas: 1 - # Single-replica app on a RWO local-path SQLite DB (WAL) with an in-process - # APScheduler: Recreate avoids two pods briefly sharing /data/reddit-intel.db. - strategy: - type: Recreate - selector: - matchLabels: - app: reddit-intel - template: - metadata: - labels: - app: reddit-intel - spec: - containers: - - name: reddit-intel - # Placeholder tag: el workflow manual (repo reddit-intel) lo sustituye - # por el sha8 real en cada build. Ver PROMOTION.md. - image: git.chemavx.xyz/chemavx/reddit-intel:00000000 - imagePullPolicy: Always - ports: - - containerPort: 8080 - env: - - name: DB_PATH - value: "/data/reddit-intel.db" - - name: REDDIT_USERNAME - value: "ExclusionZoneUAP" - - name: REDDIT_USER_AGENT - value: "linux:reddit-intel:v1.0 (by /u/ExclusionZoneUAP)" - - name: LLM_PROVIDER - value: "anthropic" - - name: LLM_MODEL_SCORING - value: "claude-haiku-4-5" - - name: LLM_MODEL_DRAFTING - value: "claude-sonnet-5" - - name: DAILY_LLM_BUDGET - value: "60" - - name: REDDIT_CLIENT_ID - valueFrom: - secretKeyRef: - name: reddit-intel-secrets - key: reddit-client-id - - name: REDDIT_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: reddit-intel-secrets - key: reddit-client-secret - - name: LLM_API_KEY - valueFrom: - secretKeyRef: - name: reddit-intel-secrets - key: llm-api-key - - name: DASHBOARD_AUTH_TOKEN - valueFrom: - secretKeyRef: - name: reddit-intel-secrets - key: dashboard-auth-token - - name: TELEGRAM_BOT_TOKEN - valueFrom: - secretKeyRef: - name: reddit-intel-secrets - key: telegram-bot-token - - name: TELEGRAM_CHAT_ID - valueFrom: - secretKeyRef: - name: reddit-intel-secrets - key: telegram-chat-id - volumeMounts: - - name: data - mountPath: /data - readinessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 10 - livenessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 20 - periodSeconds: 60 - resources: - requests: - memory: "128Mi" - cpu: "50m" - limits: - memory: "512Mi" - cpu: "500m" - volumes: - - name: data - persistentVolumeClaim: - claimName: reddit-intel-data - imagePullSecrets: - - name: gitea-registry diff --git a/reddit-intel/infisical-gitea-registry.yaml b/reddit-intel/infisical-gitea-registry.yaml deleted file mode 100644 index b85ec59..0000000 --- a/reddit-intel/infisical-gitea-registry.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: secrets.infisical.com/v1beta1 -kind: InfisicalStaticSecret -metadata: - name: gitea-registry - namespace: reddit-intel -spec: - # References the SHARED auth layer in infisical-operator (cross-namespace). - infisicalAuthRef: - name: infisical-auth - namespace: infisical-operator - sources: - - projectId: 17e98e9d-70f5-43d1-8382-7da818dfcdd0 # project "homelab" - environmentSlug: prod - secretPath: /registry - syncOptions: - refreshInterval: 60s - targets: - - kind: Secret - name: gitea-registry - namespace: reddit-intel - creationPolicy: Owner - secretType: kubernetes.io/dockerconfigjson - template: - engineVersion: v1 - data: - # Reconstruct the docker pull-secret blob from the two discrete /registry fields. - .dockerconfigjson: '{"auths":{"git.chemavx.xyz":{"username":"{{ .GITEA_REGISTRY_USERNAME.Value }}","password":"{{ .GITEA_REGISTRY_TOKEN.Value }}","auth":"{{ printf "%s:%s" .GITEA_REGISTRY_USERNAME.Value .GITEA_REGISTRY_TOKEN.Value | encodeBase64 }}"}}}' diff --git a/reddit-intel/infisical-reddit-intel-secrets.yaml b/reddit-intel/infisical-reddit-intel-secrets.yaml deleted file mode 100644 index 6abe2a2..0000000 --- a/reddit-intel/infisical-reddit-intel-secrets.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: secrets.infisical.com/v1beta1 -kind: InfisicalStaticSecret -metadata: - name: reddit-intel-secrets - namespace: reddit-intel -spec: - # Shared, read-only machine identity (no write grant, no PushSecret). - # Source is the /reddit-intel folder. Expected keys (lowercase-hyphenated, - # straight passthrough to the deployment's secretKeyRef values): - # reddit-client-id, reddit-client-secret, llm-api-key, - # dashboard-auth-token, telegram-bot-token, telegram-chat-id - # telegram-* pueden crearse vacíos (las notificaciones son opcionales). - infisicalAuthRef: - name: infisical-auth - namespace: infisical-operator - sources: - - projectId: 17e98e9d-70f5-43d1-8382-7da818dfcdd0 # project "homelab" - environmentSlug: prod - secretPath: /reddit-intel - syncOptions: - refreshInterval: 60s - targets: - - kind: Secret - name: reddit-intel-secrets - namespace: reddit-intel - creationPolicy: Owner diff --git a/reddit-intel/service.yaml b/reddit-intel/service.yaml deleted file mode 100644 index 6abca2f..0000000 --- a/reddit-intel/service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: reddit-intel - namespace: reddit-intel - labels: - app: reddit-intel -spec: - selector: - app: reddit-intel - ports: - - name: http - port: 80 - targetPort: 8080