Files
loadtest/History/2026-07-11-bugreport-kubevip.md
2026-07-11 10:59:44 +04:00

94 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Bug Report: kube-vip / ingress — TCP stall 51s
## ROOT CAUSE + FIX
**Причина:** `externalTrafficPolicy: Cluster` на LoadBalancer-сервисе `shturval-ingress-controller-controller`.
С `Cluster` (дефолт) kube-vip/Cilium форвардит трафик на ЛЮБУЮ ноду, даже без локального ingress-пода. При cross-node форвардинге возникает TCP stall 51с.
**Исправление:**
```bash
kubectl patch svc -n ingress shturval-ingress-controller-controller \
-p '{"spec":{"externalTrafficPolicy":"Local"}}'
```
С `Local` трафик идёт только на ноды с локальными ingress-подами → TCP stall исчезает.
**Подтверждение:** 5/5 FAST (2 MB WebSocket через VIP) после применения `Local`.
## Детали (архив)
## Контакты
- Проект: `loadtest` (9039a501-df2c-4b85-b049-9cd4f77e6ac0)
- Домен: `loadtest.pythonk8s.dev.nubes.ru`
- VIP: `185.247.187.151`
## Симптом
Любой трафик извне через VIP с объёмом данных > ~50 KB испытывает **51-секундную паузу** в ~80% соединений. Оставшиеся ~20% проходят мгновенно.
## Что проверено
### Исключено (НЕ является причиной)
| Компонент | Что проверяли | Результат |
|---|---|---|
| **Код приложения** | Минимальный Flask (13 строк) — идентичный результат | Не приложение |
| **WebSocket vs HTTP** | Оба протокола — одинаковая пауза | Не протокол |
| **nginx ingress** | keepalive=0, scale до 4 реплик, buffering on/off — без изменений | Не nginx |
| **Cilium** | hostNetwork на поде (обходит Geneve) — без изменений | Не Cilium |
| **Node placement** | nodeSelector, podAntiAffinity — без изменений | Не расположение подов |
| **ModSecurity** | 1 MB файл проходит мгновенно (WAF не блокирует) | Не WAF |
| **Размер данных** | 2 MB и 4 MB — одинаковая пауза 51с | Не размер |
| **Версия Python/Flask** | Минимальный под с чистым Flask — то же самое | Не версии |
### Изолировано (ГДЕ проблема)
| Источник | Цель | Результат |
|---|---|---|
| pod внутри кластера | ingress pod IP (та же нода) | **5/5 FAST** ✅ |
| pod внутри кластера | ingress pod IP (другая нода) | **5/5 FAST** ✅ |
| pod внутри кластера | ClusterIP сервис (без ingress) | **3/3 FAST** ✅ |
| SSH-хост (5.172.178.213) | VIP (185.247.187.151) | **2/5 FAST, 3/5 SLOW** ❌ |
| Внешняя машина (интернет) | VIP | **~15% FAST, ~85% SLOW** ❌ |
**Вывод: проблема между внешним клиентом и ingress-подом, при проходе через kube-vip / VIP.**
## Детали воспроизведения
### Тест изнутри кластера (ВСЕГДА быстро):
```python
# Из пода pythonk8s → ingress pod (172.16.1.51:443, SSL)
# 5/5 FAST (~0.5s для 2 MB)
```
### Тест снаружи (СЛУЧАЙНАЯ пауза 51с):
```python
# С внешней машины → VIP (185.247.187.151:443, SSL)
# 2/10 FAST (~0.5s), 8/10 SLOW (~51s для 2 MB)
```
### Характер паузы:
- 51 секунда КОНСТАНТНА (не зависит от размера: 2 MB и 4 MB — одинаково)
- Задержка в фазе `send()` — клиент блокируется при отправке данных (TCP backpressure)
- Внутри кластера kube-vip форвардит трафик на ingress-под; когда клиент снаружи — kube-vip/ARP создаёт TCP stall
## Конфигурация kube-vip
```yaml
Режим: ARP
vip_leaderelection: false
Поды kube-vip: на всех 4 нодах
Ingress-поды: 2 реплики (на control-plane + worker)
```
## Ожидаемое поведение
Загрузка файлов 3-5 MB через WebSocket или HTTP POST должна происходить за 1-2 секунды (как это работает изнутри кластера).
## Запрос
1. Проверить конфигурацию kube-vip — почему ARP-трафик к VIP вызывает TCP stall для полезной нагрузки >50 KB
2. Проверить нет ли rate-limiting на уровне сети между внешним миром и VIP
3. Рассмотреть возможность переключения kube-vip в режим BGP вместо ARP