104 lines
7.8 KiB
Markdown
104 lines
7.8 KiB
Markdown
# Шаг 1 — итоги: прототип окружения hpnn_v2
|
||
|
||
**Дата:** 2026-08-16
|
||
**Статус:** выполнено, стенд поднят и проверен (30 из 30 проверок)
|
||
**План:** [STEP1_IMPLEMENTATION_PLAN.md](STEP1_IMPLEMENTATION_PLAN.md)
|
||
|
||
## Что сделано
|
||
|
||
Собрано контейнерное окружение из трёх сетей и трёх контейнеров, на котором
|
||
работают обе подсистемы — маршрутизация и балансировка нагрузки. Всё
|
||
форвардинг-решение принимается в OpenFlow: сетевой стек ядра контейнера
|
||
транзитный трафик не обрабатывает.
|
||
|
||
- **Контейнер 1 (`hpnn-lb`)** — Open vSwitch с kernel datapath в собственном
|
||
netns, мост `br-lb` с тремя портами. Пайплайн из 42 правил и группы
|
||
балансировки рендерится скриптом из `topology.env` и заливается атомарным
|
||
бандлом.
|
||
- **Контейнеры 2 и 3 (`hpnn-be1`, `hpnn-be2`)** — идентичный web-сервис на Go,
|
||
каждый в своём приватном сегменте; отдаёт имя хоста, дату, время и адрес
|
||
клиента.
|
||
- **Сети** — публичный сегмент через macvlan поверх `enp3s0` (настоящий L2
|
||
клиентской сети) и два приватных bridge-сегмента.
|
||
- **Инструментарий** — `make up/down/flows/verify`, `lbctl` для осмотра
|
||
датапаса, `scripts/host-prereq.sh` для подготовки хоста.
|
||
|
||
## Результаты проверок
|
||
|
||
| Проверка | Результат |
|
||
|---|---|
|
||
| Kernel datapath OVS в netns контейнера | `system@ovs-system`, поддержка recirculation, ct_state_nat, ct_zone |
|
||
| macvlan-интерфейс как порт OVS | работает, `pub0` — ofport 1 |
|
||
| `selection_method=hash, fields(ip_src,tcp_src)` | принят OVS 3.1 |
|
||
| Балансировка 20 запросов с клиента | be1/be2 ≈ 10/10, счётчики обоих бакетов растут |
|
||
| Сохранение IP клиента | бэкенд видит `192.168.5.13` — DNAT без SNAT подтверждён |
|
||
| ARP- и ICMP-респондеры OVS | `ping` до узла и до VIP проходит |
|
||
| Маршрутизация между приватными сегментами | `be1 → be2` через таблицы 20/21 |
|
||
| Профиль A (§3.2 дизайна v1) | egress бэкенда наружу работает и на порту `p2` не появляется |
|
||
| `ofproto/trace` пути клиент → VIP | DNAT, `dec_ttl`, перепись MAC, выход в порт 2 |
|
||
|
||
## Отличия от плана
|
||
|
||
1. **Публичная сеть объявлена с подсетью `192.168.55.0/24`, а не
|
||
`192.168.5.0/24`.** Docker отказывается регистрировать пул, пересекающийся
|
||
с уже существующей macvlan-сетью соседнего стенда `router-functest`
|
||
(`Pool overlaps with other one on this address space`). Объявленная подсеть
|
||
нужна только Docker IPAM: адреса узла и VIP живут исключительно в правилах
|
||
OpenFlow, а macvlan включён в `enp3s0` и работает на реальном L2.
|
||
|
||
2. **Обратный путь занял таблицы 15 и 16 вместо 30 и 31.** `goto_table` в
|
||
OpenFlow разрешает переход только вперёд, поэтому таблицы обратного пути
|
||
обязаны стоять до общей маршрутизации (20).
|
||
|
||
3. **DNAT вынесен из бакетов группы в отдельную таблицу 11.** Бакет только
|
||
кладёт номер члена пула в `reg2` и делает `resubmit`. Так вся логика
|
||
трансляции лежит в одном месте и не зависит от того, какие действия
|
||
допустимы внутри бакета.
|
||
|
||
4. **Обучение MAC клиентов сужено** до трафика, адресованного стенду (VIP,
|
||
адрес узла, приватные сегменты). В первой редакции `learn` срабатывал на
|
||
любой IP-пакет с macvlan-порта и заносил в таблицу 21 весь
|
||
широковещательный шум сегмента — DHCP, mDNS, SSDP всех соседей по LAN.
|
||
|
||
5. **Проверка профиля A добавлена в `verify.sh`** — в плане она была только
|
||
ручной.
|
||
|
||
## Известные ограничения
|
||
|
||
Осознанные упрощения шага 1, каждое — задача следующих шагов:
|
||
|
||
- **Датапас stateful.** Обратную трансляцию выполняет `ct(nat)`, а не
|
||
stateless un-DNAT из §2 дизайна v1. Следствие: прямой и обратный трафик
|
||
сессии обязаны проходить через один узел, то есть Active/Active ECMP в такой
|
||
схеме работать не будет.
|
||
- **ICMP-ошибки не генерируются.** У чисто-OpenFlow узла нет стека, который бы
|
||
формировал `TTL exceeded` и `fragmentation needed`; PMTUD через стенд не
|
||
работает, `traceroute` не показывает узел.
|
||
- **Фрагменты IP не обрабатываются** — правила матчат L4-заголовок, которого
|
||
во втором и последующих фрагментах нет.
|
||
- **Один узел LB.** Ни BGP, ни BFD, ни ECMP-набора: FRR в стенде нет, место
|
||
под него (internal-порты с IP) на шаге 1 не занято, поскольку маршрутизация
|
||
выполняется целиком в OpenFlow.
|
||
- **Нет health-check.** Бэкенды считаются живыми всегда; отказ бэкенда не
|
||
выводит его из группы. У приложения есть `/healthz` как задел.
|
||
- **Пул и листенер статические** — заданы в `topology.env`, control plane и
|
||
OVSDB-схемы из §6 дизайна v1 нет.
|
||
- **MAC бэкендов прописаны статически.** ARP-резолвер next-hop отсутствует;
|
||
MAC зафиксированы в `docker-compose.yml`.
|
||
- **Только TCP и только IPv4.** UDP- и L3-листенеров нет.
|
||
|
||
## Задел на шаг 2
|
||
|
||
1. Заменить `ct(nat)` на stateless DNAT/un-DNAT с таблицей слотов и
|
||
`multipath(symmetric_l4)` — это спайк S0 из §12 дизайна v1 и предпосылка
|
||
для Active/Active.
|
||
2. Проверить детерминизм выбора бэкенда: один и тот же 5-tuple должен давать
|
||
один и тот же слот на разных узлах и между перезапусками
|
||
(`ofproto/trace` по корпусу синтетических кортежей).
|
||
3. Подсистема health-check: пробы с уникального адреса узла, вывод члена из
|
||
пула, перерасчёт таблицы слотов.
|
||
4. Control plane: модель `Load_Balancer → Listener → Pool → Member` в OVSDB
|
||
вместо `topology.env`, агент-рендерер пайплайна.
|
||
5. ICMP-транслятор в userspace (packet-in) — для PMTUD и корректных
|
||
ICMP-ошибок от имени VIP.
|