Leak mémoire massif dans le Slab (kmalloc-1k) via eBPF probe

Posté par richard-marin le 21/03/2026
RÉSOLU

richard-marin

Membre depuis le 31/08/2019

hello. on déploie un nouvel agent d'observabilité basé sur ebpf (kprobes sur tcp_connect et tcp_close).

après 4h de run les nodes k8s saturent en ram. le plus bizarre c'est que l'usage rss de l'agent est stable.

c'est le slab kernel qui explose. kmalloc-1k prend des gigas.

Commentaires

lucy-mercier

Membre depuis le 30/05/2024

si c'est dans le slab c'est que ton code ebpf ou ton loader côté userland leak des objets kernel.

tu utilises quoi ? cilium/ebpf en go ou libbpf en c ?

richard-marin

Membre depuis le 31/08/2019

on est sur du go avec cilium/ebpf. on utilise des hash maps pour stocker le state des connexions entre le connect et le close.

alexandria30

Membre depuis le 05/10/2024

classique. tu dois avoir une map qui ne se vide jamais ou des fd de maps qui restent ouverts.

regarde le contenu de /proc/slabinfo ou utilise slabtop pour confirmer le kmalloc-1k.

richard-marin

Membre depuis le 31/08/2019

slabtop -o | head -n 10
 OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
2450321 2450100  99%    1.00K 153145       16      2.4G kmalloc-1k

2.4G de kmalloc-1k. c'est énorme pour des simples traces tcp.

lucy-mercier

Membre depuis le 30/05/2024

tes maps ebpf sont définies comment ? si c'est du BPF_MAP_TYPE_HASH sans taille max cohérente ou si tu oublies le delete...

fais un bpftool map dump id de ta map pour voir le nombre d'entrées.

richard-marin

Membre depuis le 31/08/2019

bpftool map show
15: hash  name tcp_stats  flags 0x0
	key 16B  value 1024B  max_entries 1000000  memlock 1048576000B

la value fait 1024 bytes (1k). ça matche parfaitement le slab kmalloc-1k.

alexandria30

Membre depuis le 05/10/2024

bingo. ton max_entries est à 1 million. le kernel pré-alloue pas forcément tout mais il garde les entrées tant que tu les vires pas.

si tu as beaucoup de connexions courtes et que tu loupes le tcp_close tu accumules à l'infini.

lucy-mercier

Membre depuis le 30/05/2024

pourquoi tu louperais le tcp_close ? kprobe sur tcp_close est assez fiable pourtant.

vérifie si tu as des erreurs de lecture dans /sys/kernel/debug/tracing/trace_pipe.

richard-marin

Membre depuis le 31/08/2019

j'ai rien dans trace_pipe. par contre je viens de voir un truc. on a des pods qui se font sigkill violemment.

si le pod meurt les connexions tcp sont fermées par le kernel mais est-ce que tcp_close est appelé de la même façon ?

alexandria30

Membre depuis le 05/10/2024

oui mais si ton agent ebpf tourne aussi dans un pod et qu'il redémarre il perd le lien avec les maps si elles sont épinglées (pinned) dans bpffs.

est-ce que tu réutilises la même map après restart sans la clean ?

richard-marin

Membre depuis le 31/08/2019

non on ne pin pas la map. par contre je viens de trouver le bug dans le code go.

sur tcp_close on tente de delete la key mais si la socket est dans un état particulier la key générée est légèrement différente de celle du connect.

// bug ici
err := bpfMaps.TcpStats.Delete(key)
if err != nil {
    // on ignorait l'erreur sans loguer
}

lucy-mercier

Membre depuis le 30/05/2024

aie. l'erreur silencieuse sur le delete d'une map ebpf c'est le meilleur moyen de leak le slab.

pour corriger ça proprement utilise plutôt une BPF_MAP_TYPE_LRU_HASH. comme ça quand c'est plein le kernel évince les plus vieux tout seul.

richard-marin

Membre depuis le 31/08/2019

je vais passer sur une LRU hash et fixer la génération de la key pour qu'elle soit consistante.

j'ai testé le patch sur un node : le kmalloc-1k reste stable à 50mb. plus d'explosion du slab.

alexandria30

Membre depuis le 05/10/2024

parfait. oublie pas de rajouter des métriques sur les échecs de delete dans ton agent go pour pas que ça revienne.

richard-marin

Membre depuis le 31/08/2019

c'est implémenté. déploiement en cours sur tout le cluster. merci les gars.

Laisser une réponse

Vous devez être connecté pour poster un message !

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire