Files
drhider/docs/INGRESS-SOLUTIONS.md
T
2026-07-13 11:55:36 +04:00

4.8 KiB
Raw Blame History

Варианты решения ingress replicas + TCP stall

Дата: 2026-07-13
Источники: Sonnet analysis, Opus analysis
Связано: KUBEVIP-EXTERNAL-TRAFFIC-POLICY.md


Ключевой вывод (оба согласны)

Проблемы две независимые, решать по отдельности:

  1. TCP stall 51с — PMTU Blackhole на Geneve-туннеле, а не свойство Cluster-политики. Local лечит как побочный эффект (убирает cross-node).
  2. Сброс репликkubectl scale обходит Helm, поэтому реконсиляция откатывает.

⚠️ Важно (Opus): kubectl scale вы обходите Helm, поэтому и сбрасывается. Любое итоговое решение должно быть в values чарта, а не через kubectl.


Варианты

1. DaemonSet (рекомендуется)

Одно изменение в Helm values:

controller:
  kind: DaemonSet
  # replicaCount игнорируется
  • Автоматически 1 под/ноду
  • Helm не ломает
  • Стандарт для bare-metal / kube-vip
  • Не требует менять сетевую конфигурацию

2. Починить MTU (убрать stall в корне)

51с — это классический Path MTU Discovery Blackhole. Geneve: MTU 1500 → ~1450.

Диагностика:

ip link show | grep -E "cilium|genev"
iptables -t mangle -L FORWARD -n -v | grep TCPMSS

Исправление:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Если stall устранён → можно вернуть externalTrafficPolicy: Cluster и replicaCount 2.

3. Cilium DSR (Direct Server Return)

Ответный трафик идёт напрямую от пода к клиенту, без cross-node SNAT.

# cilium-config (требует kube-proxy replacement = strict)
loadBalancer:
  mode: dsr
kubeProxyReplacement: strict
  • Долго, меняет всю сетевую конфигурацию

4. replicaCount: 4 + podAntiAffinity

Если Штурвал не даёт сменить kind на DaemonSet:

controller:
  replicaCount: 4
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels:
              app.kubernetes.io/name: ingress-nginx
          topologyKey: kubernetes.io/hostname
  • Гарантирует 1 под/ноду
  • Helm values зафиксированы, не сбрасывается

Рекомендуемый путь (Sonnet + Opus)

Приоритет Действие Эффект
🟢 Сразу controller.kind: DaemonSet в Helm values Убирает костыль с репликами навсегда
🟡 Параллельно Диагностика MTU + MSS clamping Устраняет stall в корне
🔵 Потом Если MTU починен — вернуть Cluster Можно уйти от Local и требования под/ноду

Как передать девопсу (Opus)

Для чарта shturval-ingress-controller-2.12.1:

# Вариант A: DaemonSet
helm upgrade -n ingress shturval-ingress-controller <чарт> \
  --set controller.kind=DaemonSet

# Вариант B: replicaCount + antiAffinity (если DaemonSet недоступен)
helm upgrade -n ingress shturval-ingress-controller <чарт> \
  --set controller.replicaCount=4 \
  --set controller.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].labelSelector.matchLabels.app\.kubernetes\.io/name=ingress-nginx \
  --set controller.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].topologyKey=kubernetes.io/hostname

Либо через Штурвал UI — изменить replicaCount: 4 в настройках чарта.

Диагностика MTU (Opus)

# реальный MTU туннеля
ip link show | grep -E "cilium|genev"

# есть ли MSS clamping
iptables -t mangle -L FORWARD -n -v | grep MSS

Варианты фикса:

  • MSS clamping: iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
  • Cilium DSR: loadBalancer.mode: dsr + kubeProxyReplacement: strict
  • Выставить MTU в Cilium под физическую сеть (Geneve overhead ~50 байт)

Текущий статус

externalTrafficPolicy: Local — не сбрасывается.
replicas: 4 — ручной scale, периодически сбрасывается Helm на 2.