Files
loadtest/History/sonnet-question-kubevip-detailed.md
T
naeel 91d717585a
Deploy loadtest / validate (push) Waiting to run
fix: debug=False, force read body, bump 1.0.6→1.0.7
2026-07-10 22:59:56 +04:00

6.3 KiB
Raw Blame History

Sonnet: найти точку отказа внутри k8s — загрузка >48KB падает

КОНТЕКСТ

Сервис: Flask loadtest (замер скорости загрузки) на Shturval managed k8s. POST /upload с base64-телом >48KB случайно обрывается (TimeoutError на TCP-коннекте). Мелкие файлы — всегда 100%.

Требование: починить ВНУТРИ k8s. Без ВМ, без внешнего роутера, без ретраев/костылей.

ИНФРАСТРУКТУРА

Shturval 2.12.1, Cilium CNI, 4 ноды:
  - control-plane (10.10.102.2) — kube-vip ✅, ingress ❌
  - worker-6f74n  (10.10.102.3) — kube-vip ✅, ingress ❌
  - worker-bhbvs  (10.10.102.4) — kube-vip ✅, ingress ✅ (hostPort 443)
  - worker-v8zq4  (10.10.102.5) — kube-vip ✅, ingress ✅ (hostPort 443)

kube-vip: DaemonSet, ARP mode, vip_leaderelection=false, hostNetwork=true
  Все 4 ноды добавляют VIP 185.247.187.151 на интерфейс и шлют gratuitous ARP

nginx ingress: Deployment, 2 реплики, hostPort 443
  Service type LoadBalancer, external IP = 185.247.187.151
  Ингресс-аннотации: proxy-body-size=1024m, timeouts 120-600s, proxy-request-buffering=off

ModSecurity: OWASP CRS 4.10, SecRuleEngine DetectionOnly, SecRequestBodyNoFilesLimit=131072
Flask: dev-сервер (python app.py), порт 5000, НЕ Gunicorn

ВСЕ ТЕСТЫ

1. Базовые (изоляция компонентов)

# Источник Цель Размер Результат
1 Под pythonk8s свой localhost:5000 100KB base64 (136KB POST) 10/10, ~4ms
2 Под pythonk8s ingress ClusterIP:443 136KB POST 10/10, ~2ms
3 Под pythonk8s VIP 185.247.187.151:443 136KB POST 10/10, 1-6ms
4 Мы (интернет) VIP 185.247.187.151:443 136KB POST 3-5/10, TimeoutError
5 Мы (интернет) прямой IP ВМ 5.172.178.213:443 136KB POST 0 таймаутов, но "no file"
6 ВМ (10.10.102.21) VIP 185.247.187.151:443 136KB POST 1/10
7 ВМ worker node :443 любой ConnectionRefused

2. Бинарный поиск предела

Размер Результат (снаружи→VIP)
1-48 KB всегда
50 KB
52 KB
55-80 KB
100 KB иногда , иногда

Жёсткого предела НЕТ — случайность.

3. HTTP/1.1 keep-alive (одно соединение)

Тест Результат
10 запросов на одном TCP-соединении 8/10 (первые 2 таймаута при установке, остальные OK)

4. Rapid-fire vs delayed (проверка ARP-стабильности)

Rapid (без пауз): сначала 5 таймаутов, потом 3 OK подряд 10s пауза: снова миксуется

ЧТО ПРОБОВАЛИ (внутри k8s)

Действие Результат
proxy_request_buffering: off (ingress annotation) было 3/10 → стало 5/10
keep-alive: 10→75 (ingress ConfigMap) ухудшило 5→2/10, откачено
iptables TCPMSS --set-mss 1200-1360 на ноде 3-4/10, откачено
vip_leaderelection: true (kube-vip DS) 5→3/10, откачено
ingress replicaCount 2→3 (scale) 3/10, откачено
Dockerfile Gunicorn field_size бесполезно (Gunicorn не используется)
conntrack проверка чистый (54/262K), не проблема
ModSecurity DetectionOnly, не проблема

ЧТО НЕ ПРОБОВАЛИ

  • kube-vip BGP вместо ARP
  • NodePort/LoadBalancer вместо hostPort
  • Убрать kube-vip с нод без ingress (nodeSelector/taints)
  • Увеличить ARP-интервал в kube-vip
  • Включить strict ARP (kube-vip only on leader node)

КЛЮЧЕВОЙ ВЫВОД

Внутри k8s ВСЁ работает идеально (тесты 1-3). Снаружи — нет (тест 4). Разница: внешний роутер получает ARP от ВСЕХ 4 нод (kube-vip без лидера), включая 2 ноды БЕЗ ingress. Когда роутер выбирает MAC ноды без ingress → connection timeout.

KUBE-VIP КОНФИГУРАЦИЯ (полностью)

# DaemonSet: shturval-vip (namespace: kube-vip)
Image: r.shturval.tech/kube-vip:v1.0.0
hostNetwork: true
env:
  cp_enable: "false"
  enable_endpointslices: "true"
  enable_node_labeling: "true"
  lb_enable: "true"          # LoadBalancer включён
  lb_port: "6443"
  svc_election: "true"       # выборы для сервисов
  svc_enable: "true"
  vip_arp: "true"            # ARP-режим (не BGP)
  vip_interface: ""          # пусто = все интерфейсы
  vip_leaderelection: "false" # ВСЕ ноды анонсят VIP
  vip_leasename: "sht-uservip-cp-lock"
  vip_subnet: "32"
  vip_nodename: ""           # из spec.nodeName

# ShturvalServiceConfig: shturval-vip
spec:
  chart: shturval-vip
  version: 2.12.1
  mode: auto
  iscritical: true
  namespace: kube-vip

# Ingress Service (namespace: ingress)
type: LoadBalancer
externalTrafficPolicy: Cluster
status.loadBalancer.ingress.ip: 185.247.187.151
status.loadBalancer.ingress.ipMode: VIP
# Lease: kubevip-shturval-ingress-controller-controller (ingress ns)
holderIdentity: iot-naeel-workers-vqphm-v8zq4 (с 2026-04-20)

ВОПРОС

kube-vip v1.0.0 ARP mode, vip_leaderelection=false, DaemonSet на 4 нодах, ingress hostPort только на 2. Как заставить VIP 185.247.187.151 всегда вести на ноды с ingress?

  • vip_leaderelection: true не применился через DaemonSet (Shturval не подхватил customvalues)
  • svc_election: true уже есть — почему не работает?
  • Есть ли способ через customvalues в ShturvalServiceConfig правильно включить лидера?
  • Или нужен nodeSelector на DaemonSet чтобы kube-vip был только на нодах с ingress?