Files
poc-frr-anycast/README.md
T
ayurishchevandClaude Sonnet 5 eaa577e6b7 Add FRR anycast lab: HLD, containerized topology, docs
Реализует HLD-дизайн (hld.md) в виде развёртываемого Docker Compose
окружения: 5 FRR-роутеров (A1-A3 anycast 10.200.200.1/32 на AS 65001,
B1/B2 на AS 65002/65003) + 6 клиентских контейнеров, ECMP-балансировка
трафика клиентов площадки B к anycast-адресу площадки A.

- docker-compose.yml, frr/*, entrypoints/* — топология и конфиги FRR
- scripts/verify.sh, scripts/traffic-test.sh — проверка BGP/ECMP и трафика
- hld.md — HLD-дизайн + Mermaid-диаграмма топологии
- README.md — запуск, структура, команды проверки на роутерах и клиентах
- docs/ — планы внедрения и summary по каждому изменению

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bc3HkMiDwooSyLBLoMKNyF
2026-09-03 12:52:44 +03:00

6.7 KiB
Raw Blame History

poc_frr_anycast

POC anycast-топологии на FRR: две площадки, eBGP full-mesh, ECMP-балансировка трафика клиентов площадки B к anycast-адресу площадки A.

  • Дизайн (HLD): hld.md (в т.ч. Mermaid-диаграмма топологии)
  • История изменений: docs/ — на каждое изменение отдельный план внедрения и summary.

Lab-окружение (Docker Compose)

Топология из hld.md поднимается локально в Docker Compose: 5 FRR-роутеров (a1/a2/a3 — площадка A, b1/b2 — площадка B) + 6 клиентских контейнеров площадки B. Каждый линк HLD — отдельная Docker-сеть с фиксированной адресацией, 1:1 соответствующая схеме из hld.md.

Детали архитектуры и обоснование решений: docs/2026-09-03-anycast-lab-plan.md, результаты — docs/2026-09-03-anycast-lab-summary.md.

Запуск

docker compose up -d      # поднять топологию (13 контейнеров)
./scripts/verify.sh       # проверить BGP-сессии и ECMP-маршрут до 10.200.200.1/32
./scripts/traffic-test.sh [client] [count]   # прогнать трафик к anycast, увидеть распределение по A1/A2/A3
docker compose down       # разобрать окружение

Пример: ./scripts/traffic-test.sh c1 30 — 30 запросов с клиента c1 (площадка B1) к anycast-адресу с варьированием src-port; ответ каждого anycast-узла (a1/a2/a3) содержит его hostname, что показывает распределение трафика.

Структура

hld.md                    HLD-дизайн топологии
docker-compose.yml         13 контейнеров, 8 сетей (1 на линк)
frr/{a1,a2,a3,b1,b2}/      конфиги FRR (daemons, frr.conf, vtysh.conf)
entrypoints/                создание dummy0 + anycast-responder (A), маршрут по умолчанию (клиенты)
scripts/                    verify.sh, traffic-test.sh
docs/                       план внедрения + summary по каждому изменению

Проверка окружения

Всё это уже автоматизировано в ./scripts/verify.sh (BGP + маршруты) и ./scripts/traffic-test.sh (трафик), но ниже — те же проверки вручную, командами на самих узлах.

На маршрутизаторах (vtysh)

Выполняются как docker compose exec -T <node> vtysh -c "<command>" или интерактивно: docker compose exec <node> vtysh.

Команда Где Что должно быть в норме
show bgp summary все 5 узлов все соседи в состоянии Established (число вместо Idle/Active в колонке State/PfxRcd) — 2 соседа на a1/a2/a3, 3 на b1/b2
show ip route 10.200.200.1/32 b1, b2 3 записи * <ip>, via ethN, weight 1 — ECMP-маршрут до anycast через a1/a2/a3
show bgp ipv4 unicast 10.200.200.1/32 b1, b2 тот же префикс в BGP-таблице, 3 валидных пути, Local AS 65001 у всех
show ip bgp neighbor <ip> advertised-routes a1/a2/a3 (<ip> — сосед в сторону B) среди анонсируемых — 10.200.200.1/32
show ip bgp neighbor <ip> advertised-routes b1, b2 (<ip> — сосед в сторону A) среди анонсируемых — 10.100.1.0/24 (b1) / 10.100.2.0/24 (b2)
show interface brief любой все интерфейсы up, IP соответствуют hld.md

Пример:

docker compose exec -T b1 vtysh -c "show bgp summary"
docker compose exec -T b1 vtysh -c "show ip route 10.200.200.1/32"
docker compose exec -T a1 vtysh -c "show ip bgp neighbor 10.0.1.2 advertised-routes"

На клиентах (площадка B, доверенная сеть)

Выполняются как docker compose exec -T <client> <command>, где <client> — один из c1…c6.

Команда Что должно быть в норме
ping -c 4 10.200.200.1 0% packet loss, ответы приходят с ttl=63 (1 транзитный хоп — B-роутер)
traceroute -n 10.200.200.1 2 хопа: локальный B-роутер (10.100.1.1 / 10.100.2.1), затем сразу 10.200.200.1
curl -s http://10.200.200.1/ в ответе — hostname одного из a1/a2/a3 (мини-HTTP на dummy0, см. entrypoints/a-entrypoint.sh)
серия curl с разным --local-port (см. scripts/traffic-test.sh) ответы приходят от разных anycast-узлов — подтверждает, что ECMP реально распределяет трафик по 5-tuple, а не всегда уходит в один и тот же узел

Пример:

docker compose exec -T c1 ping -c 4 10.200.200.1
docker compose exec -T c1 traceroute -n 10.200.200.1
docker compose exec -T c1 curl -s http://10.200.200.1/
./scripts/traffic-test.sh c1 30     # готовый прогон с разбивкой по узлам

Если curl/ping не проходят — сначала проверить BGP (show bgp summary на затронутых узлах), затем ECMP-маршрут (show ip route 10.200.200.1/32 на b1/b2).

Важные технические нюансы

  • Линки между A и B заведены как /29 (не /30, как в hld.md буквально) — Docker резервирует первый адрес подсети под gateway моста даже для internal: true-сетей, поэтому реальным peering-адресам (.1/.2, как в hld.md) нужно место рядом с ним. IP-адресация роутеров и логика BGP при этом полностью соответствуют hld.md.
  • ECMP-балансировка на b1/b2 требует net.ipv4.fib_multipath_hash_policy=1 (в docker-compose.yml) — по умолчанию (0) Linux хеширует next-hop только по src/dst IP, без учёта портов, из-за чего один клиент всегда попадал бы в один и тот же anycast-узел.