Добавлена локальная локальная балансировка

This commit is contained in:
ayurishchev committed 2026-08-17 16:59:16 +03:00
1 parent afd4f057be
commit d80a6c44b0
17 files changed
+1628 -369

No files matched your search

+150 -2
View File
@@ -8,6 +8,10 @@
нужен, чтобы увидеть поведение стенда своими глазами и понять, что означает
каждый результат.
Что происходит с пакетом на каждом шаге — в документах по потокам данных:
[публичная балансировка](PUBLIC_LB_DATAFLOW.md) для блоков A–C и E–I,
[приватная балансировка](PRIVATE_LB_DATAFLOW.md) для блока J.
## Обозначения
| Метка | Где выполнять |
@@ -26,8 +30,9 @@ cd /opt/lvraid/claude/hpnn_v2
make up
```
Ожидается: пять контейнеров в состоянии `healthy` и таблица состояния пула,
где все четыре члена `up` и у каждого по 256 слотов.
Ожидается: семь контейнеров и таблица состояния пула, где все четыре члена
`up` и у каждого по 256 слотов. `make up` сам вызывает `make attach` —
подключение ВМ приватных сегментов к мосту.
**Шаг 0.2 [Х]** — убедиться, что всё запустилось:
@@ -42,9 +47,20 @@ hpnn-be1 Up ... (healthy)
hpnn-be2 Up ... (healthy)
hpnn-be3 Up ... (healthy)
hpnn-be4 Up ... (healthy)
hpnn-cli2 Up ...
hpnn-cli3 Up ...
hpnn-lb Up ... (healthy)
```
Проверьте, что ВМ сегментов подключены к мосту:
```bash
make ports
```
Ожидается 11 портов: `pub0`, `p2`, `p3`, `hcif-p2`, `hcif-p3`, `be1`, `be3`,
`cli2`, `be2`, `be4`, `cli3`. Если портов ВМ нет — `make attach`.
Если `hpnn-lb` в состоянии `Restarting` — смотрите `docker compose logs
lb-router` и раздел «Диагностика» в конце документа.
@@ -538,6 +554,118 @@ make enable M=be2
---
## Блок J. Листенер в приватном сегменте
Главное шага 3: клиент стоит в одном сегменте с бэкендами, и его исходный адрес
на бэкенде сохраняется. Все шаги выполняются на хосте — клиентом служит
контейнер `cli2`.
**Шаг J.1 [Х]** — убедиться, что в ОС клиента ничего не настроено:
```bash
docker compose exec cli2 ip route
```
Ожидается ровно одна строка — connected-маршрут `10.20.0.0/24 dev eth0`. Ни
default, ни маршрута на VIP: адрес листенера находится в подсети клиента.
**Шаг J.2 [Х]** — доступность VIP сегмента:
```bash
docker compose exec cli2 ping -c2 10.20.0.100
```
**Шаг J.3 [Х]** — запрос к сервису через балансировщик:
```bash
docker compose exec cli2 curl -s http://10.20.0.100/
```
Ожидается строка вида:
```
backend=be1 time=... client=10.20.0.10:46064 served=10.20.0.2:8080 req=1
```
Здесь два ключевых поля: `client` — исходный адрес клиента (SNAT не
выполняется), `served` — адрес и порт бэкенда, то есть листенер принял на 80 и
оттранслировал на 8080.
**Шаг J.4 [Х]** — распределение по пулу:
```bash
docker compose exec cli2 sh -c 'for i in $(seq 24); do curl -s http://10.20.0.100/; done' \
| sort | uniq -c -w 12
```
Ожидается: встречаются все четыре бэкенда. `be1` и `be3` — соседи клиента по
сегменту (коммутируемый путь), `be2` и `be4` — из другого сегмента
(маршрутизируемый).
**Шаг J.5 [Х]** — увидеть разницу путей по TTL. В одном терминале:
```bash
docker compose exec lb-router tcpdump -ni cli2 -v \
'tcp and src host 10.20.0.100 and tcp[tcpflags] & tcp-syn != 0'
```
Во втором — десяток запросов из шага J.3.
Ожидается: у ответов **ttl 64** и **ttl 63**. Первые пришли от `be1`/`be3` —
для них балансировщик не был L3-хопом, он лишь подменил MAC и оттранслировал
адрес. Вторые — от `be2`/`be4` через маршрутизацию, с уменьшением TTL.
**Шаг J.6 [Х]** — путь пакета по таблицам:
```bash
make trace SRC=10.20.0.10 SPORT=40000 SEG=p2
```
Ожидается цепочка `0 → 1 → 10 → 11 → 12`, затем после `ct(...nat(dst=...))` —
`Resuming from table 25` и вывод в порт члена. В `Final flow` видно, что
`nw_src` остался клиентским, а `nw_ttl` **не уменьшен**.
**Шаг J.7 [Х]** — внутрисегментный трафик не блокирован:
```bash
docker compose exec cli2 curl -s http://10.20.0.2:8080/ # клиент к бэкенду напрямую
docker compose exec be1 curl -s http://10.20.0.3:8080/ # бэкенд к бэкенду
docker compose exec be1 ping -c2 10.20.0.254 # шлюз Docker
```
Ожидается: все три работают. Балансировщик коммутирует этот трафик, не
транслируя его.
**Шаг J.8 [Х]** — таблица коммутации:
```bash
make fdb
```
Ожидается: по строке на каждую ВМ сегмента с её MAC и портом, счётчики растут.
**Шаг J.9 [Х]** — выключить листенер в одном сегменте:
```bash
sed -i 's/^PRIV_LISTENERS=.*/PRIV_LISTENERS="p2"/' lb/topology.env
docker compose cp lb/topology.env lb-router:/opt/lb/topology.env
docker compose exec lb-router /opt/lb/apply.sh
docker compose exec cli3 curl -s --max-time 4 http://10.30.0.100/ # таймаут
docker compose exec cli3 curl -s http://10.30.0.2:8080/ # связность цела
docker compose exec cli2 curl -s http://10.20.0.100/ # второй сегмент работает
```
Вернуть обратно:
```bash
sed -i 's/^PRIV_LISTENERS=.*/PRIV_LISTENERS="p2 p3"/' lb/topology.env
docker compose cp lb/topology.env lb-router:/opt/lb/topology.env
docker compose exec lb-router /opt/lb/apply.sh
```
---
## Итоговый чек-лист
| # | Проверка | Результат |
@@ -560,6 +688,12 @@ make enable M=be2
| G | При пустом пуле трафик отбрасывается, счётчик растёт | ☐ |
| H | `make flows` и перезапуск не ломают раскладку | ☐ |
| I | Установленная сессия переживает дренаж | ☐ |
| J | В ОС клиента сегмента нет ни одного маршрута | ☐ |
| J | Бэкенд видит исходный IP клиента-соседа | ☐ |
| J | Листенер 80 транслирует на порт бэкенда 8080 | ☐ |
| J | Ответ от соседа по сегменту приходит с неуменьшенным TTL | ☐ |
| J | Трафик между ВМ сегмента не блокирован | ☐ |
| J | `PRIV_LISTENERS` выключает листенер, не трогая связность | ☐ |
---
@@ -686,6 +820,8 @@ DNAT. Сравнение показателей двух путей даёт ц
| Ключ хэша (алгоритм балансировки) | `lb/pipeline.sh`, таблица 10 | `make flows` |
| Число слотов, basis хэша | `lb/topology.env`: `SLOTS`, `POOL_ID` | пересборка образа |
| Состав пула на лету | — | `make drain` / `make enable` |
| Приватные листенеры (какие сегменты) | `lb/topology.env`, `PRIV_LISTENERS` | `make flows` после копирования файла |
| Адрес приватного VIP | `lb/topology.env`, `P2_VIP` / `P3_VIP` | то же |
«Пересборка образа» — это:
@@ -829,6 +965,18 @@ SLOTS=1024 # гранулярность весов
## Диагностика
**Клиент сегмента не получает ответ от приватного VIP, или ответ приходит не
от VIP.**
Первая гипотеза — ВМ не подключены к мосту: `make ports` должен показывать
порты `be1`, `be3`, `cli2`, `be2`, `be4`, `cli3`. Вручную созданные veth
исчезают вместе с контейнером, поэтому после `docker compose restart be1` или
пересоздания любого контейнера сегмента нужен `make attach`.
Если порты на месте — смотрите `make fdb` (выучен ли MAC клиента) и счётчики
таблицы 24 (`docker compose exec lb-router lbctl flows 24`): именно она снимает
трансляцию с ответа бэкенда соседу.
**Контейнер `hpnn-lb` перезапускается.**
```bash