Späť na blog

kube-proxy Mikro-Výpadky: Problém xtables Lock Contencie

Najprv to vyzeralo ako packet loss, ale bol to iptables lock. “Deploymenty spôsobujú náhodné výpadky spojení ale všetko vyzerá zdravé.” Pridali sme viac replík aby sme zvládli záťaž—čo to zhoršilo. Skutočný vinník bol kube-proxy bojujúci o xtables lock počas endpoint churnu.

Prostredie: Kubernetes 1.27, kube-proxy iptables mode, 200+ služieb, častý HPA scaling

Problém

Symptómy

Vzor ktorý nás šialel:

1. Deploy novej verzie (alebo HPA škáluje)
2. 1-3 sekundy dropped connections
3. Žiadne reštarty podov, žiadny OOM, žiadne CPU špičky
4. Metriky neukazujú nič zlé
5. Stáva sa náhodne počas "busy" časov

Čo sme videli:
- Nové TCP spojenia zlyhajú s "connection refused"
- Existujúce spojenia sú v poriadku
- Trvá len 1-3 sekundy
- Viac replík = častejší výskyt

Prečo Štandardný Monitoring Toto Nezachytí

# Normálne metriky vyzerajú dobre
kubectl top nodes     # CPU: 40%, Memory: 60% - vyzerá dobre
kubectl top pods      # Všetky pody zdravé

# Ani kube-proxy metriky neukazujú problém jasne
curl localhost:10249/metrics | grep sync
# kubeproxy_sync_proxy_rules_duration_seconds - ukazuje priemer, nie špičky

# Lock kontencia sa deje na kernel úrovni, neviditeľná pre Kubernetes

Príčina

Ako Funguje iptables Mode

Normálny kube-proxy iptables sync:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  Endpoints  │────▶│  kube-proxy │────▶│  iptables   │
│   zmena     │     │  generuje   │     │  -restore   │
└─────────────┘     │  nové rules │     └─────────────┘
                    └─────────────┘           │

                                    ┌─────────────────┐
                                    │  xtables lock   │
                                    │  (kernel mutex) │
                                    └─────────────────┘

                                    Blokuje VŠETKY iptables
                                    operácie počas restore
                                    (môže trvať sekundy)

Problém Amplifikácie

Endpoint churn vytvára feedback loop:

1. Pod crashuje (CrashLoopBackOff)
   └─▶ Endpoint odstránený
        └─▶ kube-proxy syncuje rules (drží xtables lock)

2. HPA škáluje hore
   └─▶ Nové endpointy pridané
        └─▶ kube-proxy syncuje rules (drží xtables lock)

3. Rolling deployment
   └─▶ Staré pody terminujú, nové štartujú
        └─▶ Viaceré endpoint zmeny
             └─▶ Viaceré rule syncy v queue
                  └─▶ Lock držaný dlhšie

Kontra-intuitívna časť:
VIAC REPLÍK = VIAC ENDPOINT ZMIEN = VIAC LOCK CONTENCIE

"Škáluj hore pre záťaž" môže problém zhoršiť!

Meranie Lock Contencie

# Na node, trasuj xtables lock akvizíciu
sudo perf trace -e 'lock:*' -p $(pgrep kube-proxy) 2>&1 | head -100

# Alebo použi bpftrace na meranie lock hold time
sudo bpftrace -e '
  kprobe:xt_lock_table_lock { @start[tid] = nsecs; }
  kretprobe:xt_lock_table_unlock /@start[tid]/ {
    @lock_held_us = hist((nsecs - @start[tid]) / 1000);
    delete(@start[tid]);
  }
'

# Praktickejšie: time iptables-save počas syncu
time iptables-save > /dev/null
# Ak toto trvá >100ms počas "normálnych" časov, máš problém

Riešenie

Možnosť 1: Prepni na IPVS Mode

# kube-proxy ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
data:
  config.conf: |
    mode: "ipvs"
    ipvs:
      syncPeriod: "30s"
      minSyncPeriod: "5s"
      scheduler: "rr"

# IPVS používa iné kernel štruktúry, žiadny xtables lock
# Vyžaduje ipvs kernel moduly
# Over že IPVS moduly sú dostupné
lsmod | grep -E "ip_vs|nf_conntrack"

# Ak nie, načítaj ich
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack

Možnosť 2: Vylaď iptables Mode

# kube-proxy ConfigMap - zníž sync frekvenciu
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
data:
  config.conf: |
    mode: "iptables"
    iptables:
      syncPeriod: "60s"       # Zvýš z default 30s
      minSyncPeriod: "10s"    # Zvýš z default 1s
      masqueradeAll: false

Možnosť 3: Zníž Endpoint Churn

# Spomaľ HPA reakcie
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app
spec:
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300  # 5 min okno
      policies:
        - type: Percent
          value: 10                     # Len 10% naraz
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Percent
          value: 50                     # 50% naraz
          periodSeconds: 60
# Použi maxSurge/maxUnavailable na limitovanie deployment churnu
apiVersion: apps/v1
kind: Deployment
spec:
  strategy:
    rollingUpdate:
      maxSurge: 1          # Len 1 nový pod naraz
      maxUnavailable: 0    # Drž všetky staré pody kým nový nie je ready

Možnosť 4: nftables Mode (Kubernetes 1.29+)

# Ak bežíš K8s 1.29+ s kompatibilnými nodmi
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
data:
  config.conf: |
    mode: "nftables"
    nftables:
      syncPeriod: "30s"
      minSyncPeriod: "1s"

# nftables používa atomickú výmenu pravidiel, oveľa menej lock contencie

Monitoring

Detekcia Lock Contencie

# Prometheus alert pre sync duration špičky
groups:
  - name: kube-proxy
    rules:
      - alert: KubeProxySyncSlow
        expr: |
          histogram_quantile(0.99,
            rate(kubeproxy_sync_proxy_rules_duration_seconds_bucket[5m])
          ) > 1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "kube-proxy rule sync trvá >1s na {{ $labels.instance }}"

      - alert: KubeProxyEndpointChurn
        expr: |
          rate(kubeproxy_sync_proxy_rules_endpoint_changes_total[5m]) > 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Vysoký endpoint churn na {{ $labels.instance }}"

Custom Metrika pre xtables Lock

#!/bin/bash
# /etc/node_exporter/scripts/xtables_lock.sh
# Spusti ako textfile collector

# Zmeraj ako dlho trvá iptables-save (proxy pre lock contenciu)
start=$(date +%s.%N)
iptables-save > /dev/null 2>&1
end=$(date +%s.%N)
duration=$(echo "$end - $start" | bc)

echo "# HELP xtables_lock_duration_seconds Čas na získanie xtables lock"
echo "# TYPE xtables_lock_duration_seconds gauge"
echo "xtables_lock_duration_seconds $duration"

# Spočítaj pravidlá (viac pravidiel = dlhší lock hold)
rule_count=$(iptables-save | wc -l)
echo "# HELP iptables_rule_count Celkový počet iptables pravidiel"
echo "# TYPE iptables_rule_count gauge"
echo "iptables_rule_count $rule_count"

Debugging Playbook

#!/bin/bash
# kube-proxy-debug.sh

echo "=== Krok 1: Skontroluj kube-proxy mode ==="
kubectl get cm kube-proxy -n kube-system -o jsonpath='{.data.config\.conf}' | grep mode

echo "=== Krok 2: Spočítaj iptables pravidlá ==="
iptables-save | wc -l

echo "=== Krok 3: Zmeraj iptables-save ==="
time iptables-save > /dev/null

echo "=== Krok 4: Skontroluj počet endpointov ==="
kubectl get endpoints -A | wc -l

echo "=== Krok 5: Sleduj sync eventy ==="
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=50 | grep -i sync

echo "=== Krok 6: Skontroluj crashlooping pody (zdroj churnu) ==="
kubectl get pods -A | grep -E "(CrashLoop|Error)"

echo "=== Krok 7: Skontroluj HPA aktivitu ==="
kubectl get hpa -A

Reálne Čísla

Cluster s 200 službami, iptables mode:

Pred ladením:
- iptables pravidiel: 15,000+
- iptables-save čas: 800ms priemer, 3s špičky
- Endpoint zmeny: 50/min počas business hours
- Výpadky spojení: 5-10/hodinu

Po prepnutí na IPVS:
- iptables-save čas: 50ms (len non-kube pravidlá)
- Endpoint zmeny: rovnaké, ale žiadna lock kontencia
- Výpadky spojení: 0

Alternatíva - vyladený iptables:
- minSyncPeriod: 10s (bolo 1s)
- Kontrolované HPA správanie
- Výpadky spojení: <1/hodinu

Checklist

## kube-proxy Lock Contention

### Symptómy
- [ ] Náhodné 1-3s výpadky spojení
- [ ] Koreluje s deploymentami/škálovaním
- [ ] CPU/memory vyzerajú normálne
- [ ] Viac replík to zhoršilo

### Diagnostika
- [ ] Skontroluj kube-proxy mode (iptables?)
- [ ] Spočítaj iptables pravidlá (>10k je znepokojujúce)
- [ ] Zmeraj iptables-save (>500ms je zlé)
- [ ] Skontroluj endpoint churn rate
- [ ] Hľadaj crashlooping pody

### Riešenia
- [ ] Zváž IPVS mode
- [ ] Zvýš minSyncPeriod
- [ ] Vylaď HPA stabilization windows
- [ ] Kontroluj deployment surge/unavailable
- [ ] Zváž nftables mode (K8s 1.29+)

Záver

Kontra-intuitívna lekcia: pridávanie viac replík na zvládnutie záťaže môže zvýšiť endpoint churn a zhoršiť výpadky spojení. xtables lock je skrytý bottleneck ktorý štandardný Kubernetes monitoring neodhalí.

Kľúčové poznatky:

  1. iptables mode má inherentnú lock contenciu pri škále
  2. Viac endpointov = dlhší lock hold time = viac výpadkov
  3. IPVS mode sa problému úplne vyhýba
  4. Ak si viazaný na iptables, znižuj churn nie kapacitu

Súvisiace články

Súvisiace články

Citujte tento článok

Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.

Michal Drozd. "kube-proxy Mikro-Výpadky: Problém xtables Lock Contencie". https://www.michal-drozd.com/sk/blog/kube-proxy-xtables-zamok-kontencia/ (Publikované 4. novembra 2024).