CommunityEscrita e Ediçãogithub.com

PixiBixi/claude-skills

Use ao revisar, escrever ou dimensionar uma implantação Thanos (valores Helm, manifests, flags de componentes, regras de alerta, config de cache) ou diagnosticar saturação do caminho de leitura do Thanos - store gateway gate fixo, consultas globais lentas, primeira consulta após idle infinito, Receive OOM, alertas do compactor que nunca ou sempre disparam, dimensionamento de cache para Redis, Memcached ou Dragonfly.

O que é claude-skills?

Esta skill fornece um conjunto abrangente de regras de campo e procedimentos de diagnóstico para engenheiros que gerenciam implantações Thanos em produção, especificamente para arquiteturas de locatário único atrás de um querier global no GKE. Baseada na experiência operacional de aproximadamente 20 stacks, a skill cobre desde a revisão de configurações de componentes (Querier, Store Gateway, Receive, Compactor) até a resolução de problemas de saturação do caminho de leitura. Ela enfatiza a verificação do invariante de concorrência (que envolve query frontend, querier e store gateway) para evitar que consultas saturem o gate, além de fornecer diretrizes detalhadas para dimensionamento de cache (Redis, Memcached, Dragonfly) com base no conjunto de trabalho real, não no uptime do pod. A skill também alerta sobre armadilhas comuns, como defaults inseguros para resposta parcial, conflitos de chave de cache em versões antigas do Thanos, e a necessidade de substituir alertas baseados em métricas do compactor em modo CronJob. Ela é compatível com ferramentas como Claude Code, Cursor, Codex e outros agentes de IA que precisam analisar configurações Thanos, oferecendo um formato de saída estruturado para relatar achados por gravidade.

Funciona com✓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 Escrita e Edição skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Revisando implantações Thanos

Regras de campo de ~20 stacks Thanos de locatário único atrás de um querier global no GKE (Thanos 0.42, caches 0.35+). Fonte da verdade, com números e raciocínio:

O conjunto completo de regras (R1-R102, flags, defaults, métricas, âncoras) está em references/rules.md. Leia a seção de cada componente que a alteração afeta antes de concluir.

Procedimento de revisão

  1. Anote a versão do Thanos (tag da imagem). Flags e defaults mudam: verifique cada flag contra ela (regra R92).
  2. Com um chart wrapper (bitnami thanos, um umbrella chart local, extraFlags/args escritos à mão), leia as flags nos manifests renderizados (helm template por stack), não nos valores: as camadas se sobrescrevem e algumas flags só existem em um template.
  3. Nomes específicos da implantação (os labels nos quais as stacks são podadas, labels de tenant, labels de cluster ou datacenter) vêm da própria configuração. Quando o diff não os mostrar, peça o repositório GitOps em vez de assumir um nome.
  4. Para cada componente presente, percorra sua checklist abaixo, depois sua seção em references/rules.md.
  5. Calcule o invariante de concorrência com os valores reais sempre que qualquer uma de suas 4 flags for definida ou deixada no padrão.
  6. Verifique as regras de alerta contra como o componente realmente executa (CronJob, spot, pods Pending).
  7. Reporte no formato de saída abaixo.

Checklist por componente

Invariante de concorrência (query frontend + querier + store gateway). --query-range.max-query-parallelism (padrão 14) x min(selectors, --query.max-concurrent-select) (padrão 4) deve permanecer abaixo de min(--store.grpc.series-max-concurrency, --query.max-concurrent) (ambos padrão 20). Os defaults já o quebram (56 vs 20). Uma vez que o paralelismo sozinho atinge o limite do gate, uma consulta satura o gate em cada stack. Um --query.max-concurrent-select elevado muito acima de 4 remove o limite: o multiplicador se torna a contagem bruta de seletores. Um gate dimensionado para limitar o RSS do store gateway (definido após OOMKills) é um limite de memória, mantenha-o. O invariante vincula consultas amplas: consultas medidas têm média de 1,5 seletores, e a saturação do gate veio de várias consultas concorrentes no shard de histórico, não de uma consulta ampla. Um querier global alcança queriers regionais através da StoreAPI, que ignora seus gates PromQL. Corrija ambos os multiplicadores juntos, frontend global incluído, calcule --query.max-concurrent em todo o pool de queriers, e comente cada multiplicador com o limite downstream que ele deve respeitar.

Querier.

  • Resposta parcial está ligada por padrão (--query.partial-response padrão é true): uma flag ausente não é um padrão seguro. Ela descarta stores que erram, não as lentas: --store.response-timeout padrão é 0ms (desabilitado), então uma store lenta falha toda a consulta em --query.timeout (padrão 2m) em vez de ser descartada.
  • Resposta parcial em um querier usado pelo ruler ou alerta pode silenciosamente perder alertas, e respostas parciais nunca são armazenadas em cache. Ative-a por solicitação apenas em datasources humanos do Grafana.
  • --selector-label nunca deve ser um padrão de template: uma stack ingerindo 2 valores do label retorna VAZIO para o segundo (perda silenciosa de dados). Opte por stack, label de valor único que as consultas realmente carregam. Verifique cada stack onde está definido contra o que essa stack realmente ingere.
  • --grpc-compression está obsoleto após v0.43.0. Seu substituto, client_config.compression por endpoint em --endpoint.sd-config, é ignorado a menos que esse endpoint também defina seu próprio tls_config (ex.: enabled: false): a flag global ainda vence caso contrário.

Store gateway.

  • Nunca aumente --store.grpc.series-max-concurrency para curar saturação: o gate enfileira, não recusa. Saturação aparece como timeouts, a maioria dos minutos está muito abaixo do limite, e aumentá-lo remove o único limite durante os picos. Encontre o cliente no log lento do query frontend.
  • --store.limits.request-series=2000000 é um valor copiado que nunca dispara (maior chamada medida: 200000 séries). Meça thanos_bucket_store_series_data_touched_bucket{data_type="series"} primeiro.
  • thanos_bucket_store_queries_dropped_total em 0 não prova nada: conta apenas limitadores que são 0 (desligados) por padrão.
  • Shards de tempo devem se sobrepor; limites --min-time/--max-time justapostos garantem uma janela cega quando uma réplica está faltando. --min-time é o limite mais antigo. Um --max-time positivo (ex.: 3h) não é limite superior: o shard atende até agora, sobrepondo Receive.
  • Sem emptyDir no disco de boot do nó: o download do index-header o satura (30 min de recuperação). PVC dedicado com IOPS/throughput provisionado; no Hyperdisk Balanced capacidade não compra desempenho.
  • --sync-block-duration abaixo do padrão de 15m custa muito pouco atrás de um bucket com cache (apenas chamadas iter dependem dele, ~1 USD/mês frota medida): não vale um rollout dedicado, corrija no próximo restart planejado.
  • Mantenha o lazy reader, nunca lazy index-header download (p99 ~224 s). No timeout de idle padrão de 5m a primeira consulta após cada lacuna paga um recarregamento completo; a flag oculta --store.index-header-lazy-reader-idle-timeout elevada para um dia útil (10h) reduziu o tempo de carga em 84% em uma stack, ao custo de memória residente. Flag oculta: verifique novamente na atualização.

Caches.

  • Bucket de cache compartilhado entre tenants no Thanos < v0.35.0: colisão de chaves, store gateway permanece Ready e não serve dados históricos. O prefix do Redis isola em qualquer versão. Um canário de locatário único não pode pegá-lo.
  • Cache de índice e bucket de cache no mesmo Redis: separe db (índice db: 1).
  • Não dimensione um cache compartilhado a partir de tamanhos de cache IN-MEMORY (eles medem uptime do pod). Dimensione no conjunto de trabalho sobre a janela TTL (P95 de uma subconsulta contínua >= 24 h com step explícito), dividido pela sobreposição medida entre réplicas de um shard, nunca pela contagem de pods. Réplicas carregam os mesmos blocos mas armazenam chunks diferentes: 2 réplicas mediram 1,4, não 2.
  • Subranges do bucket de cache vivem 24 h (chunk_subrange_ttl); expiration do Redis não os governa.
  • Arquivo de cache do query frontend é analisado estritamente: sem ttl, sem enabled_items, TTL é expiration sob config:. Chaves desconhecidas: o componente se recusa a iniciar.
  • Redis atrás de Sentinel: serviço Sentinel + master_name, senão escritas vão para o master antigo após failover.

Receive.

  • Permanece sob demanda com uma classe de prioridade dedicada: o único componente segurando dados ainda não enviados. Todo o resto vai para spot.
  • Dimensione o limite de memória no pico de séries ativas. head_series_limit só compensa em um Receive multi-tenant compartilhado ou com replicação: com uma réplica um 429 bloqueia cada escrita do tenant, um OOM custa apenas um restart e uma repetição WAL. É inerte sem um meta_monitoring_url acessível. Limites de solicitação retornam 413 (Prometheus descarta os dados), o limite de séries retorna 429 (repetido).
  • Hashring Ketama, não hashmod, quando o tamanho do pool mudar.
  • Limite o heap Go: GOMEMLIMIT do limite de memória do pod, ou --enable-auto-gomemlimit (desligado por padrão, 0.9 do limite do contêiner). Go define GOMAXPROCS a partir do cgroup desde 1.25, nunca GOMEMLIMIT. Um OOM no Receive significa uma repetição WAL antes de servir novamente.

Compactor.

  • Como CronJob: concurrencyPolicy: Forbid é obrigatório (2 compactors em um bucket corrompem blocos).
  • thanos_compact_todo_* gauges são registrados apenas com --wait: em modo CronJob um alerta sobre eles nunca dispara. O estoque ThanosCompactIsDown dispara 23 h/24. Substitua por regras de CronJob do kube-state-metrics e um proxy de backlog thanos_blocks_meta_synced do store gateway. Qualquer alerta em uma métrica do compactor (thanos_compact_group_compactions_failures_total...) nunca dispara em modo CronJob: nenhum alvo de scrape entre execuções.
  • Nunca uma regra de ciclo de vida do bucket ou classe de armazenamento de arquivamento em um bucket Thanos: apenas o compactor conhece as dependências de bloco; o loop de repetição multiplicou a conta da API em 10x a economia.
  • Níveis de retenção alinhados com o que os store gateways servem.

Transversal.

  • Todos os componentes de uma stack em uma zona: tráfego entre zonas é cobrado em cada seta do caminho de dados. Uma restrição de spread de zona em uma stack é um bug de custo, uma troca deliberada para afirmar o contrário.
  • Alerta de prontidão da store em StatefulSet desejado vs réplicas prontas com for: 30m: up == 0 nunca dispara para um pod Pending removido, e for: 5m pagina na recuperação normal de spot.

Diagnosticando saturação

Use procedimentos D1-D10 em references/rules.md. Núcleo do D1: in_flight = taxa de transferência x duração (lei de Little), medido por pod; duração geralmente domina (x190 vs x4.5 em campo). Leia painéis de gate com max_over_time(...[$__interval:1m]), latência em p999/p9999, tamanho da frota com count(group by (pod) (up == 1)).

Formato de saída

Achados classificados por gravidade: perda de dados ou resultados errados silenciosos, depois risco de parada (uma configuração com a qual o componente se recusa a iniciar conta aqui), depois custo, depois higiene. Cada achado:

  • campo ou flag, com a linha
  • o problema e sua consequência concreta
  • a correção, como o valor exato ou trecho
  • a URL da wiki com âncora, copiada de references/rules.md (IDs de regra são internos, deixe-os de fora)

Individual skills in this repo

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

Habilidades Relacionadas