DEV Community

Cover image for Entendendo o consumo de memória do Gitaly e Kernel no Kubernetes
Camila
Camila

Posted on

Entendendo o consumo de memória do Gitaly e Kernel no Kubernetes

Durante uma madrugada, comecei a receber alertas do Gitaly, o mesmo estava com picos de uso de memória que não eram liberados automaticamente após Backup diário.

Esse artigo se trata de um GitLab self hosted no EKS e o comportamento de alguns componentes do gitlab no Kubernetes.

Se você também roda GitLab em Kubernetes, vale entender o que realmente acontece — e por que o Cgroup v2 é a solução definitiva pra esse tipo de problema.

GITALY

O Gitaly é o componente do GitLab responsável por todas as operações Git, como clone, push, pull, merge, diff e blame. Ele isola o armazenamento dos repositórios da aplicação web e se comunica com os demais serviços via gRPC, otimizando a performance e o controle de concorrência.

┌─────────────────────┐
│ GitLab Webservice   │
│              │
└──────────┬──────────┘
           │ gRPC
           ↓
┌─────────────────────┐
│ Gitaly              │
│ - Git operations    │
│ - Repository access │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│ Persistent Volume   │
│ /home/git/repos     │
└─────────────────────┘
Enter fullscreen mode Exit fullscreen mode

GITLAB TOOLBOX BACKUP

É um componente do Gitlab usado para realizar backups em ambientes Kubernetes (especificamente deployado usando helm charts). É um pod/container que contém ferramentas e scripts para executar operações de backup e restore do Gitlab. E quando ele aciona o Gitaly? durante o Backup dos repositórios.

  1. -Conecta ao Gitaly via gRPC
  2. -Solicita backup de cada repositório
  3. -Recebe bundles Git do Gitaly
  4. -Processa e comprime os dados
  5. -Envia para algum object storage (S3, GCS, etc)

Durante a execução do cronjob gitlab-toolbox-backup na madrugada, observei um uso elevado de memória no pod do Gitaly. Esse consumo é causado pelo comportamento padrão do kernel Linux, que utiliza a RAM como cache de arquivos lidos do disco (page cache).

Em ambientes Kubernetes, esse comportamento pode gerar problemas de alocação de recursos, pois o kernel é compartilhado entre todos os pods do node.

Sintomas:

Alto uso de memória

Alto uso de memória

Alto uso de memória

Implicações críticas:

  1. O kernel é único para todo o node
  2. O Page Cache é global e compartilhado
  3. CgroupsV1 apenas limitam quanto cada container pode usar
  4. ** O kernel não sabe o que é um "pod" ou "container" então se o Node tiver muita memória o Kernel vai considerar que tem memória disponível mesmo o pod estourando, pedindo pra morrer. **
┌─────────────────────────────────────────────────┐
│                     NODE       
│                                                 │
│  ┌──────────────────────────────────────────┐   │
│  │         KERNEL LINUX (único)             │   │
│  │  - Gerencia TODA a RAM do node           │   │
│  │  - Page Cache é COMPARTILHADO            │   │
│  │  - Não sabe o que é "pod"                │   │
│  └──────────────────────────────────────────┘   │
│                                                 │
│  ┌────────────┐  ┌────────────┐  ┌──────────┐   │
│  │  Pod A     │  │  Pod B     │  │  Pod C   │   │
│  │  (Gitaly)  │  │  (Redis)   │  │  (Web)   │   │
│  │            │  │            │  │          │   │
│  │  Vê:       │  │  Vê:       │  │  Vê:     │   │
│  │  Limit:8GB │  │  Limit:4GB │  │ Limit:2GB│   │
│  └────────────┘  └────────────┘  └──────────┘   │
│                                                 │
│  RAM Total: 32GB                                │
│  Cache Total: 20GB (visível para TODOS)         │
└─────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Obs: Page Cache é a RAM usada pelo kernel para cachear arquivos do disco.

Fluxo de Backup

O que acontece?

Durante o backup (1h):

  1. Gitaly lê centenas de repositórios Git
  2. Kernel cacheia tudo: "Vou guardar esses arquivos .git na RAM"
  3. Backup termina: Processo Gitaly volta ao normal (195MB)
  4. Kernel não limpa: Cache fica marcado como "active_file" = 35.6GB
  5. Kubernetes vê: Pod usando 37GB → perigo de OOM!

Por que não limpa automaticamente?

O cache está marcado como "active" (não "inactive"), então o kernel pensa:

"Esses arquivos foram usados recentemente"
"Provavelmente vão ser usados de novo em breve"
"Vou manter eles na RAM"
Mas como é um backup que roda 1x por dia, esses arquivos não vão ser usados de novo até amanhã!

Possíveis soluções estudadas:

Opção Esforço Benefício Recomendação
Migrar para cgroup v2 Alto (reboot nodes) Solução definitiva A melhor opção
CronJob privilegiado Baixo (15min) Resolve o problema se estiver com pressa
DaemonSet monitor Médio (1h) Automático Opcional
Aumentar limite Baixo Paliativo Só em emergência

Como podemos ver existem paliativos, porém a melhor opção a longo prazo é Cgroup V2. Só tem um pouco de complexidade para aplicar, mas mesmo assim se destaca pelos benefícios.

Dados do Cgroup V1 atual:

cache: 38829035520           # 36.2 GB !!!!!
rss: 204779520               # 195 MB
inactive_file: 568246272     # 542 MB
active_file: 38260654080     # 35.6 GB !!!!!


**35.6GB de `active_file`** = arquivos em cache ativo (page cache)!

Breakdown:
- Processo Gitaly (RSS): 195 MB
- Cache de arquivos ativos: 35.6 GB  ← AQUI!
- Cache de arquivos inativos: 542 MB
- Total cache: 36.2 GB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total do pod: ~37 GB
Enter fullscreen mode Exit fullscreen mode

Cgroup V2

Cgroup V2 tem um recurso chamado PSI que detecta quando há "pressão" de memória:

# cgroup v2 expõe:
/sys/fs/cgroup/memory.pressure
# Conteúdo:
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0
Enter fullscreen mode Exit fullscreen mode

Quando há pressão, o kernel automaticamente libera cache mesmo que seja "active"!

Cgroup v2 é a segunda geração do sistema de control groups do kernel Linux, com melhorias significativas sobre o v1, atualmente o EKS do Gitlab está com Cgroup V1.

Cgroup v1 tem múltiplas hierarquias independentes (memory, cpu, io), causando inconsistências. Cgroup v2 usa uma única árvore:

Bom, é isso... tive a oportunidade de estudar sobre essa semana e quis compartilhar o conhecimento.

Docs: backup-restore
Kernel Tuning and Optimization for Kubernetes: A Guide
Linux Kernel Version Requirements

Top comments (0)