Kubernetes conntrack Vyčerpanie: Tichý Zabijak Paketov
Conntrack vycerpanie je klasika, ktora aj tak prekvapi timy vo velkom scale. “Naše DNS lookupy náhodne zlyhávajú.” “Služby timeout-ujú ale pody sú healthy.” “Funguje lokálne ale padá v K8s.” Tieto symptómy často ukazujú na jedného vinníka: vyčerpanie conntrack tabuľky.
Testované na: EKS 1.28, GKE 1.27, Linux kernel 5.15, Calico CNI
Čo je conntrack?
Základy Connection Tracking
Linux connection tracking (conntrack) mapuje:
Source IP:Port ←→ Destination IP:Port ←→ State
Účel: Umožniť NAT, firewally a stateful filtrovanie paketov
Každé spojenie cez kube-proxy používa conntrack záznam:
Pod A (10.1.1.5:45678) → Service (10.96.0.10:80) → Pod B (10.1.2.3:8080)
↓
conntrack záznam sleduje toto mapovanie
Prečo Kubernetes je Conntrack-Heavy
Jeden HTTP request v Kubernetes:
1. DNS lookup do CoreDNS
Pod → kube-dns Service → CoreDNS Pod (conntrack záznam #1)
2. Service volanie
Pod → Service ClusterIP → Backend Pod (conntrack záznam #2)
3. Ak backend volá databázu
Backend → DB Service → DB Pod (conntrack záznam #3)
4. Externé API volanie (cez NAT Gateway)
Pod → NAT → External IP (conntrack záznam #4)
Výsledok: Jeden user request = 4+ conntrack záznamy
Pri 10,000 RPS: 40,000+ záznamy konštantne rotujúce
Problém
Default Limity
# Skontroluj aktuálne conntrack nastavenia
cat /proc/sys/net/netfilter/nf_conntrack_max
# Default: 131072 (128K záznamy)
cat /proc/sys/net/netfilter/nf_conntrack_count
# Aktuálne záznamy v použití
# Keď count sa blíži k max:
# - Nové spojenia sa ticho zahadzujú
# - DNS lookupy timeout-ujú (UDP)
# - TCP spojenia visia
Symptómy
Symptóm 1: DNS timeouty
- DNS je väčšinou UDP; aj \"connectionless\" traffic vytvára conntrack stav (kvôli kube-proxy NAT)
- Vysoký UDP QPS rýchlo rotuje záznamy
- DNS zlyhania kaskádujú do všetkých služieb
Symptóm 2: Náhodné zlyhania spojení
- Niektoré requesty uspejú, niektoré zlyhajú
- Žiaden vzor v logoch
- Pody hlásia healthy
Symptóm 3: Vysoké latency spiky
- Setup spojenia trvá dlhšie
- Existujúce spojenia ovplyvnené GC
Kernel log (dmesg):
nf_conntrack: table full, dropping packet
Súvisiaci failure mode: kube-proxy conntrack cleanup stormy (vysoke RSS/CPU)
Conntrack vycerpanie je o zahadzovani paketov, ked je tabulka plna. Ale existuje aj iny conntrack-typ vypadku, ktory vyzera uplne inak:
- kube-proxy RSS zrazu vystreli na viac GB
- kube-proxy CPU skoci hore
- casto to koreluje s update-mi Podov/Services, ktore maju UDP port (CoreDNS byva klasicky trigger)
- conntrack tabulka nemusi byt “plna” - je len dost velka na to, aby “scan celej tabulky” bol brutalne drahy
Toto sa pekne ukazalo v Kubernetes issue #129982 (kube-proxy v1.32): zmeny Podov/Services s UDP portom spustali full conntrack cleanup, ktory prechadzal celu tabulku a palil pamat/CPU.
Co robim v praxi:
-
Potvrd, ze to je kube-proxy (nie workload)
kubectl -n kube-system top pods -l k8s-app=kube-proxy -
Skontroluj conntrack pressure na node
cat /proc/sys/net/netfilter/nf_conntrack_{count,max} -
Upgradni na release, kde su fixy
V tomto type incidentu su relevantne najma tieto mergnute fixy:
- Kubernetes PR #130032: “Conntrack memory leak fix”
- Kubernetes PR #130484: “conntrack reconciler must check the dst port”
Fix bol backportnuty do Kubernetes 1.32 patch vetvy a klasicka rada plati stale: bud na najnovsom patch release pre svoju branch. Toto by som netunil okolo sysctl-ami, ak vies upgradovat/backportnut - failure mode je algoritmicky.
Ak si zaseknuty na provider builde, ktory laguje za upstreamom, v issue sa spominal aj workaround: zvysit
--iptables-min-sync-period, aby sa sync path nespustal tak casto. Nefixne to root cause, ale vie to znizit blast radius, kym sa dostanes na verziu s fixom.
Ak trafis toto, zvysok clanku (limity, timeouts, NodeLocal DNSCache) stale pomoze, lebo mensia/stabilnejsia conntrack tabulka znamena mensiu cenu. Ale realny fix je upgrade kube-proxy/Kubernetes na verziu s opravami v reconcileri.
Diagnostika
Skontroluj Stav Node
# SSH na node alebo použi kubectl debug
kubectl debug node/my-node -it --image=busybox
# Vnútri debug kontajnera:
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# Skontroluj dropy
dmesg | grep conntrack
# Hľadaj: "table full, dropping packet"
# Rozdelenie spojení podľa stavu
cat /proc/net/nf_conntrack | awk '{print $4}' | sort | uniq -c | sort -rn
# 45000 TIME_WAIT
# 38000 ESTABLISHED
# 12000 SYN_SENT
# 5000 FIN_WAIT
Prometheus Metriky
# Node exporter poskytuje tieto:
# Aktuálne conntrack záznamy
node_nf_conntrack_entries
# Maximum povolené
node_nf_conntrack_entries_limit
# Percentuálne využitie (kritická metrika)
node_nf_conntrack_entries / node_nf_conntrack_entries_limit
# Rýchlosť nových spojení
rate(node_nf_conntrack_entries[5m])
Analýza High-Traffic Služieb
# Nájdi služby generujúce najviac spojení
kubectl get endpoints -A -o json | jq '
.items[] |
select(.subsets != null) |
{
namespace: .metadata.namespace,
name: .metadata.name,
endpoints: [.subsets[].addresses // [] | length] | add
}' | sort -k3 -rn
# Skontroluj krátkodobé spojenia (HTTP bez keepalive)
# Tieto rotujú conntrack záznamy najrýchlejšie
Riešenia
1. Zvýš Conntrack Limity
# DaemonSet na tuning sysctl na všetkých nodoch
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: sysctl-tuner
namespace: kube-system
spec:
selector:
matchLabels:
app: sysctl-tuner
template:
metadata:
labels:
app: sysctl-tuner
spec:
hostPID: true
hostNetwork: true
initContainers:
- name: sysctl
image: busybox
securityContext:
privileged: true
command:
- sh
- -c
- |
sysctl -w net.netfilter.nf_conntrack_max=1048576
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=86400
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
sysctl -w net.core.somaxconn=65535
containers:
- name: pause
image: k8s.gcr.io/pause:3.9
Cloud-Špecifická Konfigurácia
# EKS: Použi launch template s user data
#!/bin/bash
echo "net.netfilter.nf_conntrack_max=1048576" >> /etc/sysctl.conf
echo "net.netfilter.nf_conntrack_tcp_timeout_time_wait=30" >> /etc/sysctl.conf
sysctl -p
# GKE: Použi node pool config
gcloud container node-pools create high-conntrack \
--cluster=my-cluster \
--node-config='linuxNodeConfig:
sysctls:
net.netfilter.nf_conntrack_max: "1048576"'
# AKS: Použi custom node config
az aks nodepool add \
--cluster-name my-cluster \
--name highconn \
--linux-os-config linuxOsConfig.json
# linuxOsConfig.json:
{
"sysctls": {
"netNetfilterNfConntrackMax": 1048576
}
}
2. Zníž Conntrack Využitie
# Použi headless služby kde možné
# Žiadny conntrack potrebný pre priame pod-to-pod
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
clusterIP: None # Headless - žiadny NAT, žiadny conntrack
selector:
app: my-app
---
# Povoľ HTTP keepalive pre zníženie churn spojení
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx.conf: |
upstream backend {
server backend:8080;
keepalive 100; # Znovupoužitie spojení
}
server {
location / {
proxy_http_version 1.1;
proxy_set_header Connection ""; # Povoľ keepalive
proxy_pass http://backend;
}
}
3. Tuning Timeout Hodnôt
# Default timeouty sú príliš dlhé pre efemérny traffic
# Zníž TIME_WAIT záznamy:
# Pred: TIME_WAIT spojenia držané 120 sekúnd
# Po: Uvoľnené za 30 sekúnd
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
# Uzavri mŕtve spojenia rýchlejšie
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_close_wait=15
# Plný timeout tuning pre vysoký traffic:
net.netfilter.nf_conntrack_tcp_timeout_syn_sent=30
net.netfilter.nf_conntrack_tcp_timeout_syn_recv=30
net.netfilter.nf_conntrack_tcp_timeout_established=86400
net.netfilter.nf_conntrack_tcp_timeout_fin_wait=15
net.netfilter.nf_conntrack_tcp_timeout_close_wait=15
net.netfilter.nf_conntrack_tcp_timeout_last_ack=15
net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
net.netfilter.nf_conntrack_tcp_timeout_close=10
net.netfilter.nf_conntrack_udp_timeout=30
net.netfilter.nf_conntrack_udp_timeout_stream=60
4. IPVS Mód (Alternatíva k iptables)
# IPVS používa menej conntrack pre služby
# ConfigMap pre kube-proxy
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-proxy
namespace: kube-system
data:
config.conf: |
mode: "ipvs"
ipvs:
scheduler: "rr"
strictARP: true
# IPVS výhody:
# - Lepší výkon v škále (O(1) vs O(n) pre iptables)
# - Efektívnejšie využitie conntrack
# - Vstavané algoritmy load balancingu
Monitoring
Alert Rules
groups:
- name: conntrack
rules:
- alert: ConntrackTabulkaSkoro Plna
expr: |
node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.75
for: 5m
labels:
severity: warning
annotations:
summary: "Conntrack tabuľka na {{ $value | humanizePercentage }}"
description: "Node {{ $labels.instance }} conntrack využitie vysoké"
- alert: ConntrackTabulkaKriticka
expr: |
node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.9
for: 2m
labels:
severity: critical
annotations:
summary: "Conntrack tabuľka na {{ $value | humanizePercentage }}"
description: "Packet dropy hrozia na {{ $labels.instance }}"
- alert: ConntrackZaznamyRastuRychlo
expr: |
rate(node_nf_conntrack_entries[5m]) > 1000
for: 10m
labels:
severity: warning
annotations:
summary: "Conntrack rastie rýchlosťou {{ $value }}/sec"
description: "Možný connection leak alebo traffic spike"
Grafana Dashboard
# Panel 1: Conntrack využitie per node
node_nf_conntrack_entries / node_nf_conntrack_entries_limit
# Panel 2: Záznamy v čase
node_nf_conntrack_entries
# Panel 3: Rýchlosť zmeny
rate(node_nf_conntrack_entries[1m])
# Panel 4: Rezerva
node_nf_conntrack_entries_limit - node_nf_conntrack_entries
DNS-Špecifické Problémy
NodeLocal DNS Cache
# NodeLocal DNSCache znižuje conntrack tlak
# DNS queries zostávajú na node, žiadny conntrack potrebný
# Nainštaluj NodeLocal DNSCache
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
# Výhody:
# - DNS queries neprechádzajú sieťou
# - Žiadne conntrack záznamy pre DNS
# - Znížená záťaž na CoreDNS
CoreDNS Conntrack Bypass
# CoreDNS môže použiť TCP pre zníženie UDP conntrack problémov
# ConfigMap pre CoreDNS
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
forward . /etc/resolv.conf {
prefer_udp
max_concurrent 1000
}
cache 30
}
Checklist
## Conntrack Vyčerpanie Prevencia
### Monitoring
- [ ] Alert na conntrack využitie > 75%
- [ ] Dashboard ukazujúci conntrack záznamy per node
- [ ] Monitoruj rýchlosť spojení (záznamy/sec)
### Tuning
- [ ] Zvýš nf_conntrack_max (1M+ pre vysoký traffic)
- [ ] Zníž TIME_WAIT timeout (30s)
- [ ] Zváž IPVS mód pre kube-proxy
### Architektúra
- [ ] Použi headless služby kde možné
- [ ] Povoľ HTTP keepalive medzi službami
- [ ] Deploy NodeLocal DNS Cache
- [ ] Použi connection pools v aplikáciách
### Investigácia
- [ ] Skontroluj dmesg pre "table full" správy
- [ ] Analyzuj distribúciu conntrack stavov
- [ ] Identifikuj high-connection služby
Záver
Conntrack vyčerpanie je tichý zabijak v Kubernetes:
- Default 128K limit je príliš nízky pre produkciu
- DNS a krátkodobé spojenia plnia tabuľku rýchlo
- Monitoruj
nf_conntrack_entriesskôr než nastanú problémy - Zvýš limity + zníž timeouty pre okamžitú úľavu
Skontroluj svoje nody teraz - dropy možno už prebiehajú.
Súvisiace články
- CoreDNS vs NodeLocal DNS Cache - DNS optimalizácia
- Kubernetes Cross-Zone Traffic - Sieťové náklady
Súvisiace články
Kubernetes Ghost Connections: Zastarané Conntrack DNAT Záznamy
Service vracia zlé pod IP po škálovaní. Príčina: Linux conntrack drží DNAT záznamy dlhšie ako existujú pody, smeruje traffic na zmazané endpointy.
Ghost Pod: Prečo váš Service stále posiela traffic na mŕtve endpointy
Náhodné ECONNRESET na niektorých nodoch. Endpointy vyzerajú správne. Vinník: conntrack NAT záznamy držia dlhodobé spojenia pripnuté k podom, ktoré už neexistujú.
Pakety prichadzaju ale aplikacia timeoutuje: rp_filter pasca v Kubernetes
tcpdump ukazuje pakety ktore prichadzaju, ale aplikacia nic nevidi. Vinik: Linux reverse path filtering ticho zahadzuje pakety predtym nez dosiahnu iptables, sposobene asymetrickym routovanim.
Kubernetes Headless Service DNS: Zastarané Záznamy Po Zmazaní Podu
Requesty idú na neexistujúce pody. Príčina: headless service DNS záznamy pretrvávajú v klient DNS cache po zmazaní podov, pred propagáciou endpoints update.
Citujte tento článok
Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.