loki : les morceaux sont lies, pas copies ; chunks/index reste copie
Copier 6 550 morceaux arretait Loki 13 s au site ; les lier prend 40 ms. Ils sont adresses par leur contenu ; chunks/index loge delete_requests.gz, qui se reecrit, et reste vraiment copie. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3e2846cc5f
commit
9a4b63544e
4 changed files with 86 additions and 17 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
|
@ -1,5 +1,30 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-10-07 (109) — Les morceaux de Loki sont liés, pas copiés ; sa base de suppressions, si
|
||||
|
||||
**94 preuves.** Au site, la copie à froid arrêtait Loki **13 s**, pour copier 6 550 petits
|
||||
fichiers. Ses morceaux de journal sont adressés par leur contenu : un nom décodé donne
|
||||
`1a0d123a4e8:1a0d1918235:6b5feaac` (début, fin, somme de contrôle). Ils ne bougent donc
|
||||
jamais, et les lier prend **40 ms** (mesuré sur `site-mon-01`).
|
||||
|
||||
### Le fichier qui bougeait parmi les morceaux
|
||||
|
||||
Un contrôle d'immuabilité, refait avec `stat` (le `find` de la machine ne connaît pas `%W` :
|
||||
le premier passage ne mesurait rien), a trouvé **un fichier sur 6 550** modifié après sa
|
||||
naissance : `chunks/index/delete_requests/delete_requests.gz`, né le 2026-09-12 et réécrit le
|
||||
2026-10-07. Ce n'est pas un morceau : c'est la base des demandes de suppression du compacteur,
|
||||
rangée dans le même stockage objet. Lier tout `chunks/` aurait laissé la sauvegarde changer
|
||||
avec elle.
|
||||
|
||||
**Fait** : `setops-copie-a-froid` accepte `--lier REL` (lier tout un sous-dossier) et
|
||||
`--copier REL` (y copier vraiment ce qui bouge). Loki : `--lier chunks --copier chunks/index`.
|
||||
|
||||
**Éprouvé** : `test_restauration.py` ; morceau lié (même inode), `chunks/index` copié (autre
|
||||
inode), une réécriture après la copie ne touche pas la sauvegarde. Témoin : sans `--copier`,
|
||||
les deux derniers échouent. `shellcheck` propre. `make verifier` conforme, **94/94**.
|
||||
|
||||
**Pas encore déployé** : la durée réelle se mesurera au prochain dépôt.
|
||||
|
||||
## 2026-10-07 (108) — Le site recevait encore la sauvegarde d'avant le 2026-09-30
|
||||
|
||||
**94 preuves.** Déployer la copie à froid de Prometheus et Loki au site (`site-mon-01`) a
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ client_backup_catalogue:
|
|||
/usr/local/sbin/setops-copie-a-froid
|
||||
{{ serveur_loki_service | default('loki') }}
|
||||
{{ serveur_loki_chemin | default('/var/lib/loki') }}
|
||||
{{ client_backup_staging }}/loki/donnees
|
||||
{{ client_backup_staging }}/loki/donnees --lier chunks --copier chunks/index
|
||||
chemins: ["{{ client_backup_staging }}/loki"]
|
||||
serveur_icinga:
|
||||
# L'AC D'ICINGA FAIT L'IDENTITE DE SA BASE (2026-10-07). Icinga 2 derive l'environnement
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
# Géré par Set-OPS (rôle client_backup). Ne pas éditer à la main.
|
||||
#
|
||||
# setops-copie-a-froid SERVICE SOURCE DESTINATION [--blocs-immuables]
|
||||
# setops-copie-a-froid SERVICE SOURCE DESTINATION [--blocs-immuables] [--lier REL]... [--copier REL]...
|
||||
#
|
||||
# Copie COHERENTE d'une base qui ecrit en continu (Prometheus, Loki) : le service est
|
||||
# arrete le temps de la copie, puis redemarre — QUOI QU'IL ARRIVE a la copie, et seulement
|
||||
|
|
@ -17,12 +17,28 @@
|
|||
# les blocs de Prometheus, que rien ne reecrit apres leur fermeture. On les recopie par
|
||||
# LIENS DURS — instantane, sans place — et le reste (WAL, `chunks_head`) par une vraie
|
||||
# copie. Si la destination est sur un autre systeme de fichiers, on copie tout.
|
||||
#
|
||||
# `--lier REL` lie tout un sous-dossier ; `--copier REL` y copie vraiment un sous-dossier qui,
|
||||
# lui, bouge (2026-10-07). Pour Loki : `--lier chunks --copier chunks/index`. Ses morceaux sont
|
||||
# adresses par leur contenu (`debut:fin:somme`, decode sur site-mon-01) et ne bougent jamais ;
|
||||
# mais `chunks/index/` loge aussi `delete_requests.gz`, la base du compacteur, mesuree
|
||||
# reecrite trois semaines apres sa naissance. La lier, c'etait laisser la sauvegarde changer
|
||||
# avec elle. Copier 6 550 morceaux arretait Loki 13 s ; les lier prend 40 ms.
|
||||
set -euo pipefail
|
||||
|
||||
service="${1:?service}"
|
||||
source="${2:?source}"
|
||||
dest="${3:?destination}"
|
||||
blocs="${4:-}"
|
||||
shift 3
|
||||
blocs="" lier=() copier=()
|
||||
while (( $# )); do
|
||||
case "$1" in
|
||||
--blocs-immuables) blocs=1; shift ;;
|
||||
--lier) lier+=("$2"); shift 2 ;;
|
||||
--copier) copier+=("$2"); shift 2 ;;
|
||||
*) echo "copie a froid : option inconnue : $1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -d "${source}" ]] || { echo "copie a froid : ${source} n'existe pas — rien a copier." >&2; exit 0; }
|
||||
|
||||
|
|
@ -38,20 +54,26 @@ debut=$(date +%s%N)
|
|||
if (( actif )); then systemctl stop "${service}"; fi
|
||||
trap relancer EXIT
|
||||
|
||||
if [[ "${blocs}" == "--blocs-immuables" ]]; then
|
||||
mkdir -p "${tmp}"
|
||||
for e in "${source}"/* "${source}"/.[!.]*; do
|
||||
[[ -e "${e}" ]] || continue
|
||||
n="$(basename "${e}")"
|
||||
if [[ -d "${e}" && ${#n} -eq 26 && "${n}" == 01* ]]; then
|
||||
cp -al "${e}" "${tmp}/${n}" 2>/dev/null || cp -a "${e}" "${tmp}/${n}"
|
||||
else
|
||||
cp -a "${e}" "${tmp}/${n}"
|
||||
fi
|
||||
done
|
||||
else
|
||||
cp -a "${source}" "${tmp}"
|
||||
fi
|
||||
lie() { cp -al "$1" "$2" 2>/dev/null || { rm -rf "$2"; cp -a "$1" "$2"; }; }
|
||||
mkdir -p "${tmp}"
|
||||
for e in "${source}"/* "${source}"/.[!.]*; do
|
||||
[[ -e "${e}" ]] || continue
|
||||
n="$(basename "${e}")"
|
||||
if [[ -n "${blocs}" && -d "${e}" && ${#n} -eq 26 && "${n}" == 01* ]] \
|
||||
|| [[ " ${lier[*]:-} " == *" ${n} "* ]]; then
|
||||
lie "${e}" "${tmp}/${n}"
|
||||
else
|
||||
cp -a "${e}" "${tmp}/${n}"
|
||||
fi
|
||||
done
|
||||
# Ce qui bouge, a l'interieur d'un dossier lie : remplace par une vraie copie.
|
||||
for c in "${copier[@]:+${copier[@]}}"; do
|
||||
if [[ -e "${source}/${c}" ]]; then
|
||||
rm -rf "${tmp:?}/${c}"
|
||||
mkdir -p "$(dirname "${tmp}/${c}")"
|
||||
cp -a "${source}/${c}" "${tmp}/${c}"
|
||||
fi
|
||||
done
|
||||
|
||||
trap - EXIT
|
||||
relancer
|
||||
|
|
|
|||
|
|
@ -395,6 +395,28 @@ exit 0
|
|||
verifier(r.returncode == 0 and "stop prometheus" not in appels and "start prometheus" not in appels,
|
||||
"un service inactif n'est ni arrete ni relance")
|
||||
|
||||
# LOKI (2026-10-07) : les morceaux sont lies, `chunks/index/` copie. Il loge la base
|
||||
# du compacteur (`delete_requests.gz`), qui se reecrit : liee, la sauvegarde
|
||||
# changerait avec elle.
|
||||
loki, prep = d / "loki", d / "prep" / "donnees"
|
||||
(loki / "chunks" / "fake").mkdir(parents=True)
|
||||
(loki / "chunks" / "fake" / "MWEw").write_text("morceau")
|
||||
(loki / "chunks" / "index" / "delete_requests").mkdir(parents=True)
|
||||
(loki / "chunks" / "index" / "delete_requests" / "delete_requests.gz").write_text("v1")
|
||||
(loki / "wal").mkdir()
|
||||
(loki / "wal" / "00000001").write_text("wal")
|
||||
r = subprocess.run(["bash", str(outil), "loki", str(loki), str(prep), "--lier", "chunks",
|
||||
"--copier", "chunks/index"], env=env, capture_output=True, text=True)
|
||||
verifier(r.returncode == 0 and (prep / "chunks" / "fake" / "MWEw").stat().st_ino
|
||||
== (loki / "chunks" / "fake" / "MWEw").stat().st_ino,
|
||||
f"Loki : un morceau est lie (meme inode) ({r.stderr.strip()[-120:]})")
|
||||
base = loki / "chunks" / "index" / "delete_requests" / "delete_requests.gz"
|
||||
copie = prep / "chunks" / "index" / "delete_requests" / "delete_requests.gz"
|
||||
verifier(copie.exists() and copie.stat().st_ino != base.stat().st_ino,
|
||||
"Loki : chunks/index est vraiment copie (un autre inode)")
|
||||
base.write_text("v2") # le compacteur reecrit sa base sur place
|
||||
verifier(copie.read_text() == "v1", "une reecriture apres la copie ne change pas la sauvegarde")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
couverture()
|
||||
|
|
|
|||
Loading…
Reference in a new issue