From dab1a72e1c329831647727546397da8d14a3ca28 Mon Sep 17 00:00:00 2001 From: chemavx Date: Sat, 25 Jul 2026 15:17:14 +0000 Subject: [PATCH] backup-system: --b2-hard-delete + exporter de uso real de B2 B2 tiene el mismo fallo que la papelera de MEGA con otro nombre: al borrar/espejar no elimina, oculta la version vieja y la sigue facturando. Las versiones ocultas llegaron al ~88% del tramo gratis de 10GB el 2026-07-25 (8.78 GiB facturados vs 1.75 GiB visibles). - --b2-hard-delete en el sync de crown-jewels y en el delete de reddit-intel - mega-quota-exporter ahora tambien exporta b2_visible/billed/hidden_bytes Co-Authored-By: Claude Opus 4.8 --- backup-system/configmap-backup-scripts.yaml | 7 ++- backup-system/mega-quota-exporter.yaml | 69 ++++++++++++++++++--- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/backup-system/configmap-backup-scripts.yaml b/backup-system/configmap-backup-scripts.yaml index 23bc749..c6ce10d 100644 --- a/backup-system/configmap-backup-scripts.yaml +++ b/backup-system/configmap-backup-scripts.yaml @@ -267,7 +267,11 @@ data: N=$(ls -1 "$KEEP" | wc -l) log "Sync de $N artefactos crown-jewels a B2..." # -L: resuelve los symlinks; sync = espejo → la retención remota (2/servicio) es automática + # --b2-hard-delete: sin esto B2 no borra al espejar, OCULTA la versión vieja y + # la sigue facturando (mismo patrón que la papelera de MEGA). Sin el flag las + # versiones ocultas llegaron al ~88% del tramo gratis de 10GB el 2026-07-25. rclone sync "$KEEP" b2:chemavx-k3s-backups/crown-jewels/ -L \ + --b2-hard-delete \ --config /rclone/rclone.conf --log-level INFO --stats 60s rm -rf "$KEEP" log "B2 crown-jewels completado ($N artefactos)." @@ -292,7 +296,8 @@ data: rclone delete mega:k3s-backups/reddit-intel/ --min-age 8d --mega-hard-delete --config /rclone/rclone.conf log "Subiendo a B2 (crown jewels, retención 3 días)..." rclone copy "$F" b2:chemavx-k3s-backups/reddit-intel/ --config /rclone/rclone.conf --log-level INFO - rclone delete b2:chemavx-k3s-backups/reddit-intel/ --min-age 3d --config /rclone/rclone.conf + # --b2-hard-delete: ver nota en b2-crown-jewels.sh (B2 oculta y factura, no borra). + rclone delete b2:chemavx-k3s-backups/reddit-intel/ --min-age 3d --b2-hard-delete --config /rclone/rclone.conf rm -f "$F" log "reddit-intel OK" verify.sh: | diff --git a/backup-system/mega-quota-exporter.yaml b/backup-system/mega-quota-exporter.yaml index cef7e32..ba32d35 100644 --- a/backup-system/mega-quota-exporter.yaml +++ b/backup-system/mega-quota-exporter.yaml @@ -1,4 +1,4 @@ -# Exporter de la cuota de MEGA. +# Exporter de la cuota de los dos offsites: MEGA y B2. # # Contexto: el 2026-07-25 la papelera de MEGA (que cuenta cuota) llenó los 20GB # de la cuenta y tumbó rclone-mega-backup y reddit-intel-backup con "Request @@ -9,6 +9,11 @@ # mega_trash_bytes = usado - visible: es la métrica que habría cazado aquello. # Con --mega-hard-delete en las rotaciones debería quedarse cerca de 0; si # vuelve a crecer, es que algún borrado se está yendo a la papelera otra vez. +# +# B2 tiene el MISMO fallo con otro nombre: al borrar/espejar no elimina, OCULTA +# la versión vieja y la sigue facturando. El mismo día las versiones ocultas de +# B2 estaban al ~88% del tramo gratis de 10GB. b2_hidden_bytes = todas las +# versiones - visible: con --b2-hard-delete en los scripts debería quedar en ~0. --- apiVersion: v1 kind: ConfigMap @@ -19,25 +24,29 @@ data: export.sh: | #!/bin/sh # Imagen BusyBox (rclone) — sin GNU-ismos. + # Exporta la cuota de MEGA (papelera) y el uso REAL de B2 (versiones ocultas). set -u CONF=/rclone/rclone.conf OUT=/metrics/metrics INTERVAL="${INTERVAL:-900}" + B2_REMOTE="b2:chemavx-k3s-backups/" # Extrae el entero que sigue a "clave". Hay que anclar en la clave y no # limpiar la línea entera: `rclone size --json` saca {"count":N,"bytes":M} # en una sola línea y un sed global concatenaría los dos números. num() { sed -n 's/.*"'"$1"'"[^0-9]*\([0-9][0-9]*\).*/\1/p' "$2" 2>/dev/null | head -1; } - # Últimos valores buenos: si un scrape falla preferimos republicarlos con - # success=0 antes que dejar la serie en NoData y disparar un falso positivo. + # Últimos valores buenos por proveedor: si un scrape falla preferimos + # republicarlos con success=0 antes que dejar la serie en NoData (falso positivo). L_TOTAL=""; L_USED=""; L_FREE=""; L_VB=""; L_VC="" + LB_VIS=""; LB_ALL=""; LB_OBJ="" while true; do - OK=1 - rclone about mega: --json --config "$CONF" > /tmp/about.json 2>/tmp/about.err || OK=0 - rclone size mega: --json --config "$CONF" > /tmp/size.json 2>/tmp/size.err || OK=0 + # --- MEGA (about da la cuota; la papelera = usado - visible) --- + MOK=1 + rclone about mega: --json --config "$CONF" > /tmp/about.json 2>/tmp/about.err || MOK=0 + rclone size mega: --json --config "$CONF" > /tmp/size.json 2>/tmp/size.err || MOK=0 TOTAL=$(num total /tmp/about.json) USED=$(num used /tmp/about.json) @@ -46,19 +55,42 @@ data: VC=$(num count /tmp/size.json) for v in "$TOTAL" "$USED" "$FREE" "$VB" "$VC"; do - [ -n "$v" ] || OK=0 + [ -n "$v" ] || MOK=0 done - if [ "$OK" = "1" ]; then + if [ "$MOK" = "1" ]; then L_TOTAL="$TOTAL"; L_USED="$USED"; L_FREE="$FREE"; L_VB="$VB"; L_VC="$VC" else - echo "[$(date '+%Y-%m-%d %H:%M:%S')] scrape fallido: $(cat /tmp/about.err /tmp/size.err 2>/dev/null | tr '\n' ' ')" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] MEGA scrape fallido: $(cat /tmp/about.err /tmp/size.err 2>/dev/null | tr '\n' ' ')" + fi + + # --- B2 (sin about: el tramo gratis no lo reporta. Medimos visible vs + # TODAS las versiones, que es lo que B2 factura de verdad) --- + BOK=1 + rclone size "$B2_REMOTE" --json --config "$CONF" > /tmp/b2vis.json 2>/tmp/b2vis.err || BOK=0 + rclone size "$B2_REMOTE" --b2-versions --json --config "$CONF" > /tmp/b2all.json 2>/tmp/b2all.err || BOK=0 + + BVIS=$(num bytes /tmp/b2vis.json) + BALL=$(num bytes /tmp/b2all.json) + BOBJ=$(num count /tmp/b2vis.json) + + for v in "$BVIS" "$BALL" "$BOBJ"; do + [ -n "$v" ] || BOK=0 + done + + if [ "$BOK" = "1" ]; then + LB_VIS="$BVIS"; LB_ALL="$BALL"; LB_OBJ="$BOBJ" + else + echo "[$(date '+%Y-%m-%d %H:%M:%S')] B2 scrape fallido: $(cat /tmp/b2vis.err /tmp/b2all.err 2>/dev/null | tr '\n' ' ')" fi { echo "# HELP mega_quota_scrape_success 1 si el ultimo sondeo a MEGA funciono." echo "# TYPE mega_quota_scrape_success gauge" - echo "mega_quota_scrape_success $OK" + echo "mega_quota_scrape_success $MOK" + echo "# HELP b2_scrape_success 1 si el ultimo sondeo a B2 funciono." + echo "# TYPE b2_scrape_success gauge" + echo "b2_scrape_success $BOK" echo "# HELP mega_quota_last_scrape_timestamp_seconds Momento del ultimo sondeo." echo "# TYPE mega_quota_last_scrape_timestamp_seconds gauge" echo "mega_quota_last_scrape_timestamp_seconds $(date +%s)" @@ -85,6 +117,23 @@ data: echo "# TYPE mega_trash_bytes gauge" echo "mega_trash_bytes $TRASH" fi + + if [ -n "$LB_ALL" ]; then + BHID=$((LB_ALL - LB_VIS)) + [ "$BHID" -lt 0 ] && BHID=0 + echo "# HELP b2_visible_bytes Tamano de los ficheros visibles en B2." + echo "# TYPE b2_visible_bytes gauge" + echo "b2_visible_bytes $LB_VIS" + echo "# HELP b2_billed_bytes Tamano real facturado por B2 (todas las versiones)." + echo "# TYPE b2_billed_bytes gauge" + echo "b2_billed_bytes $LB_ALL" + echo "# HELP b2_hidden_bytes Versiones ocultas/antiguas (facturado - visible)." + echo "# TYPE b2_hidden_bytes gauge" + echo "b2_hidden_bytes $BHID" + echo "# HELP b2_visible_objects Numero de ficheros visibles en B2." + echo "# TYPE b2_visible_objects gauge" + echo "b2_visible_objects $LB_OBJ" + fi } > "${OUT}.tmp" && mv "${OUT}.tmp" "$OUT" sleep "$INTERVAL"