CommunityRédaction et éditiongithub.com

PixiBixi/claude-skills

À utiliser lors de la révision, de l'écriture ou de l'estimation d'un déploiement Thanos (valeurs Helm, manifests, flags des composants, règles d'alerte, configuration du cache) ou du diagnostic de saturation du chemin de lecture Thanos – gate du store gateway bloquée, requêtes globales lentes, première requête après inactivité interminable, OOM de Receive, alertes du compactor qui ne se déclenchent jamais ou toujours, dimensionnement du cache pour Redis, Memcached ou Dragonfly.

Qu'est-ce que claude-skills ?

Cette compétence est conçue pour les ingénieurs DevOps et les opérateurs de stack Thanos qui gèrent des déploiements à grande échelle, en particulier ceux qui utilisent un querier global avec plusieurs stacks Thanos monolocataires. Elle fournit un ensemble complet de règles de terrain (R1-R102) couvrant l'architecture, la performance, les coûts (FinOps) et le dimensionnement du cache, dérivé de l'exploitation d'une vingtaine de stacks sur GKE. La compétence inclut une procédure de révision détaillée pour vérifier les déploiements, des check-lists par composant (store gateway, querier, caches, receive, compactor) avec des invariants de concurrence, des pièges courants (comme les collisions de clés de cache ou les alertes silencieuses), et des procédures de diagnostic pour la saturation (D1-D10). Elle est destinée à être utilisée avec des agents comme Claude Code, Cursor ou Codex pour automatiser l'analyse des configurations Thanos et prévenir les régressions coûteuses ou les pannes de données. Les règles sont référencées dans un fichier `references/rules.md` et chaque conclusion est associée à une URL de wiki pour une traçabilité complète.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/PixiBixi/claude-skills/tree/HEAD/plugins/wiki/skills/reviewing-thanos-deployments

Installed? Explore more Rédaction et édition skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Révision des déploiements Thanos

Règles de terrain issues de l'exploitation d'une vingtaine de stacks Thanos monolocataires derrière un querier global sur GKE (Thanos 0.42, caches 0.35+). Source de vérité, avec chiffres et raisonnement :

L'ensemble complet des règles (R1-R102, flags, valeurs par défaut, métriques, ancres) se trouve dans references/rules.md. Lisez la section de chaque composant que la modification touche avant de conclure.

Procédure de révision

  1. Notez la version de Thanos (tag de l'image). Les flags et leurs valeurs par défaut changent : vérifiez chaque flag par rapport à celle-ci (règle R92).
  2. Avec un chart wrapper (bitnami thanos, un chart umbrella local, extraFlags/args écrits à la main), lisez les flags sur les manifests rendus (helm template par stack), pas sur les valeurs : les couches se surchargent mutuellement et certains flags n'existent que dans un template.
  3. Les noms spécifiques au déploiement (les labels sur lesquels les stacks sont élaguées, les labels de locataire, les labels de cluster ou de datacenter) proviennent de la configuration elle-même. Lorsque le diff ne les montre pas, demandez le dépôt GitOps au lieu de supposer un nom.
  4. Pour chaque composant présent, parcourez sa check-list ci-dessous, puis sa section dans references/rules.md.
  5. Calculez l'invariant de concurrence avec les valeurs réelles chaque fois que l'un de ses 4 flags est défini ou laissé par défaut.
  6. Vérifiez les règles d'alerte en fonction de la façon dont le composant s'exécute réellement (CronJob, spot, pods Pending).
  7. Rapportez dans le format de sortie ci-dessous.

Check-list par composant

Invariant de concurrence (query frontend + querier + store gateway). --query-range.max-query-parallelism (par défaut 14) x min(selectors, --query.max-concurrent-select) (par défaut 4) doit rester inférieur à min(--store.grpc.series-max-concurrency, --query.max-concurrent) (tous deux par défaut 20). Les valeurs par défaut le brisent déjà (56 vs 20). Une fois que le parallélisme seul atteint le plafond de la gate, une seule requête sature la gate sur chaque stack. Un --query.max-concurrent-select élevé bien au-dessus de 4 supprime le plafond : le multiplicateur devient le nombre brut de selecteurs. Une gate dimensionnée pour limiter la RSS du store gateway (définie après des OOMKills) est une limite mémoire, conservez-la. L'invariant lie les requêtes larges : les requêtes mesurées ont en moyenne 1,5 selecteurs, et la saturation de la gate provenait de plusieurs requêtes concurrentes sur le shard historique, pas d'une seule requête large. Un querier global atteint les queriers régionaux via StoreAPI, ce qui contourne leurs gates PromQL. Corrigez les deux multiplicateurs ensemble, y compris le frontend global, calculez --query.max-concurrent sur l'ensemble du pool de queriers, et commentez chaque multiplicateur avec le plafond aval qu'il doit respecter.

Querier.

  • La réponse partielle est activée par défaut (--query.partial-response par défaut à true) : un flag absent n'est pas une valeur par défaut sûre. Elle supprime les stores qui génèrent une erreur, pas les lents : --store.response-timeout par défaut à 0ms (désactivé), donc un store lent fait échouer toute la requête à --query.timeout (par défaut 2m) au lieu d'être supprimé.
  • La réponse partielle sur un querier utilisé par le ruler ou l'alerting peut manquer silencieusement des alertes, et les réponses partielles ne sont jamais mises en cache. Activez-la par requête uniquement sur les sources de données Grafana humaines.
  • --selector-label ne doit jamais être une valeur par défaut de template : un stack ingérant 2 valeurs du label renvoie VIDE pour la seconde (perte de données silencieuse). Optez par stack, label à valeur unique que les requêtes portent réellement. Vérifiez chaque stack où il est défini par rapport à ce que ce stack ingère réellement.
  • --grpc-compression est déprécié après v0.43.0. Son remplacement, client_config.compression par endpoint dans --endpoint.sd-config, est ignoré à moins que cet endpoint ne définisse également son propre tls_config (par exemple enabled: false) : le flag global l'emporte sinon.

Store gateway.

  • N'augmentez jamais --store.grpc.series-max-concurrency pour guérir la saturation : la gate met en file d'attente, elle ne refuse pas. La saturation se manifeste par des timeouts, la plupart des minutes sont bien en dessous du plafond, et l'augmenter supprime la seule limite pendant les pics. Trouvez le client dans le journal lent du query frontend.
  • --store.limits.request-series=2000000 est une valeur copiée qui ne se déclenche jamais (plus grand appel mesuré : 200000 séries). Mesurez d'abord thanos_bucket_store_series_data_touched_bucket{data_type="series"}.
  • thanos_bucket_store_queries_dropped_total à 0 ne prouve rien : il ne compte que les limiteurs qui sont à 0 (désactivés) par défaut.
  • Les shards temporels doivent se chevaucher ; des bornes --min-time/--max-time jointes bout à bout garantissent une fenêtre aveugle lorsqu'un réplica est manquant. --min-time est la borne la plus ancienne. Un --max-time positif (par exemple 3h) n'est pas une borne supérieure : le shard sert jusqu'à maintenant, par-dessus Receive.
  • Pas de emptyDir sur le disque de démarrage du nœud : le téléchargement de l'index-header le sature (30 min de récupération). PVC dédié avec IOPS/débit provisionnés ; sur Hyperdisk Balanced, la capacité n'achète pas les performances.
  • --sync-block-duration en dessous de la valeur par défaut de 15m coûte à peine quelque chose derrière un bucket de mise en cache (seuls les appels iter en dépendent, ~1 USD/mois à l'échelle de la flotte mesuré) : ne vaut pas un déploiement dédié, corrigez-le au prochain redémarrage planifié.
  • Conservez le lazy reader, jamais de téléchargement lazy de l'index-header (p99 ~224 s). Avec le timeout d'inactivité par défaut de 5m, la première requête après chaque intervalle paie un rechargement complet ; le flag caché --store.index-header-lazy-reader-idle-timeout porté à une journée de travail (10h) a réduit le temps de chargement de 84 % sur un stack, au prix de la mémoire résidente. Flag caché : revérifiez lors de la mise à niveau.

Caches.

  • Bucket de mise en cache partagé entre locataires sur Thanos < v0.35.0 : collision de clés, le store gateway reste Ready et ne sert aucune donnée historique. Le prefix Redis isole sur n'importe quelle version. Un canary monolocataire ne peut pas le détecter.
  • Cache d'index et bucket de mise en cache sur le même Redis : séparez db (index db: 1).
  • Ne dimensionnez pas un cache partagé à partir des tailles de cache IN-MEMORY (elles mesurent la durée de vie du pod). Dimensionnez sur l'ensemble de travail sur la fenêtre TTL (P95 d'une sous-requête glissante >= 24 h avec pas explicite), divisé par le chevauchement mesuré entre les réplicas d'un shard, jamais par le nombre de pods. Les réplicas chargent les mêmes blocs mais mettent en cache des chunks différents : 2 réplicas mesurés à 1,4, pas 2.
  • Les sous-plages du bucket de mise en cache vivent 24 h (chunk_subrange_ttl) ; expiration de Redis ne les régit pas.
  • Le fichier de cache du query frontend est analysé strictement : pas de ttl, pas de enabled_items, le TTL est expiration sous config:. Clés inconnues : le composant refuse de démarrer.
  • Redis derrière Sentinel : service Sentinel + master_name, sinon les écritures vont vers l'ancien master après un basculement.

Receive.

  • Reste à la demande avec une classe de priorité dédiée : le seul composant contenant des données non encore téléversées. Tout le reste va sur spot.
  • Dimensionnez la limite mémoire sur le pic de séries actives. head_series_limit ne paie que dans un Receive partagé multi-locataire ou avec réplication : avec un réplica, un 429 bloque chaque écriture du locataire, un OOM ne coûte qu'un redémarrage et une relecture WAL. Il est inerte sans meta_monitoring_url joignable. Les limites de requête renvoient 413 (Prometheus abandonne les données), la limite de séries renvoie 429 (réessayé).
  • Anneau de hachage Ketama, pas hashmod, lorsque la taille du pool changera.
  • Bornez le heap Go : GOMEMLIMIT à partir de la limite mémoire du pod, ou --enable-auto-gomemlimit (désactivé par défaut, 0,9 de la limite du conteneur). Go définit GOMAXPROCS à partir du cgroup depuis la version 1.25, jamais GOMEMLIMIT. Un OOM de Receive signifie une relecture WAL avant de servir à nouveau.

Compactor.

  • En tant que CronJob : concurrencyPolicy: Forbid est obligatoire (2 compacteurs sur un même bucket corrompent les blocs).
  • Les jauges thanos_compact_todo_* ne sont enregistrées qu'avec --wait : en mode CronJob, une alerte sur elles ne se déclenche jamais. Le stock ThanosCompactIsDown se déclenche 23 h/24. Remplacez par des règles CronJob de kube-state-metrics et un proxy de backlog thanos_blocks_meta_synced du store gateway. Toute alerte sur une métrique du compactor (thanos_compact_group_compactions_failures_total...) ne se déclenche jamais en mode CronJob : pas de cible de scraping entre les exécutions.
  • Jamais de règle de cycle de vie du bucket ou de classe de stockage d'archive sur un bucket Thanos : seul le compactor connaît les dépendances des blocs ; la boucle de réessai a multiplié la facture API par 10 par rapport à l'économie.
  • Niveaux de rétention alignés sur ce que les store gateways servent.

Transversal.

  • Tous les composants d'un stack dans une seule zone : le trafic inter-zone est facturé sur chaque flèche du chemin de données. Une contrainte de répartition par zone sur un stack est un bug de coût, un compromis délibéré à indiquer autrement.
  • Alerte de disponibilité du store sur les réplicas desired vs ready du StatefulSet avec for: 30m : up == 0 ne se déclenche jamais pour un pod Pending évincé, et for: 5m page lors d'une récupération spot normale.

Diagnostic de saturation

Utilisez les procédures D1-D10 dans references/rules.md. Cœur de D1 : in_flight = throughput x duration (loi de Little), mesuré par pod ; la durée domine généralement (x190 vs x4.5 sur le terrain). Lisez les panneaux de gate avec max_over_time(...[$__interval:1m]), la latence à p999/p9999, la taille de la flotte avec count(group by (pod) (up == 1)).

Format de sortie

Résultats classés par sévérité : perte de données ou résultats erronés silencieux, puis risque de panne (une configuration avec laquelle le composant refuse de démarrer compte ici), puis coût, puis hygiène. Chaque résultat :

  • champ ou flag, avec la ligne
  • le problème et sa conséquence concrète
  • la correction, comme la valeur ou l'extrait exact
  • l'URL du wiki avec ancre, copiée depuis references/rules.md (les IDs de règle sont internes, laissez-les de côté)

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Skills associés