Реализует 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
178 lines
5.0 KiB
YAML
178 lines
5.0 KiB
YAML
name: poc-frr-anycast
|
|
|
|
networks:
|
|
# Note: /29 rather than /30 — Docker's bridge driver always claims the first
|
|
# usable address of a subnet as the network gateway (even with internal:
|
|
# true), so the actual /30 peering addresses (.1/.2, matching hld.md) need
|
|
# room alongside it; the gateway is pushed to .6, which nothing else uses.
|
|
link-a1-b1:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.0.1.0/29, gateway: 10.0.1.6}]
|
|
link-a1-b2:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.0.2.0/29, gateway: 10.0.2.6}]
|
|
link-a2-b1:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.0.3.0/29, gateway: 10.0.3.6}]
|
|
link-a2-b2:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.0.4.0/29, gateway: 10.0.4.6}]
|
|
link-a3-b1:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.0.5.0/29, gateway: 10.0.5.6}]
|
|
link-a3-b2:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.0.6.0/29, gateway: 10.0.6.6}]
|
|
net-b1-clients:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.100.1.0/24, gateway: 10.100.1.254}]
|
|
net-b2-clients:
|
|
driver: bridge
|
|
internal: true
|
|
ipam:
|
|
config: [{subnet: 10.100.2.0/24, gateway: 10.100.2.254}]
|
|
|
|
x-frr-a: &frr-a
|
|
image: frrouting/frr:latest
|
|
cap_add: [NET_ADMIN, NET_RAW, SYS_ADMIN]
|
|
sysctls:
|
|
net.ipv4.ip_forward: 1
|
|
entrypoint: ["/sbin/tini", "--", "/entrypoints/a-entrypoint.sh"]
|
|
|
|
x-frr-b: &frr-b
|
|
image: frrouting/frr:latest
|
|
cap_add: [NET_ADMIN, NET_RAW, SYS_ADMIN]
|
|
sysctls:
|
|
net.ipv4.ip_forward: 1
|
|
# default policy (0) hashes ECMP nexthop on src/dst IP only, ignoring L4
|
|
# ports - with a single client IP that pins every flow to the same A-node.
|
|
# Policy 1 adds L4 ports to the hash, matching the 5-tuple ECMP behavior
|
|
# described in hld.md.
|
|
net.ipv4.fib_multipath_hash_policy: 1
|
|
entrypoint: ["/sbin/tini", "--", "/entrypoints/b-entrypoint.sh"]
|
|
|
|
x-client: &client
|
|
image: nicolaka/netshoot
|
|
cap_add: [NET_ADMIN]
|
|
entrypoint: ["/entrypoints/client-entrypoint.sh"]
|
|
|
|
services:
|
|
# --- Site A: AS 65001, anycast 10.200.200.1/32 on dummy0 ---
|
|
a1:
|
|
<<: *frr-a
|
|
hostname: a1
|
|
volumes:
|
|
- ./frr/a1:/etc/frr
|
|
- ./entrypoints/a-entrypoint.sh:/entrypoints/a-entrypoint.sh:ro
|
|
networks:
|
|
link-a1-b1: {ipv4_address: 10.0.1.1}
|
|
link-a1-b2: {ipv4_address: 10.0.2.1}
|
|
|
|
a2:
|
|
<<: *frr-a
|
|
hostname: a2
|
|
volumes:
|
|
- ./frr/a2:/etc/frr
|
|
- ./entrypoints/a-entrypoint.sh:/entrypoints/a-entrypoint.sh:ro
|
|
networks:
|
|
link-a2-b1: {ipv4_address: 10.0.3.1}
|
|
link-a2-b2: {ipv4_address: 10.0.4.1}
|
|
|
|
a3:
|
|
<<: *frr-a
|
|
hostname: a3
|
|
volumes:
|
|
- ./frr/a3:/etc/frr
|
|
- ./entrypoints/a-entrypoint.sh:/entrypoints/a-entrypoint.sh:ro
|
|
networks:
|
|
link-a3-b1: {ipv4_address: 10.0.5.1}
|
|
link-a3-b2: {ipv4_address: 10.0.6.1}
|
|
|
|
# --- Site B: AS 65002 / 65003, client networks ---
|
|
b1:
|
|
<<: *frr-b
|
|
hostname: b1
|
|
volumes:
|
|
- ./frr/b1:/etc/frr
|
|
- ./entrypoints/b-entrypoint.sh:/entrypoints/b-entrypoint.sh:ro
|
|
networks:
|
|
link-a1-b1: {ipv4_address: 10.0.1.2}
|
|
link-a2-b1: {ipv4_address: 10.0.3.2}
|
|
link-a3-b1: {ipv4_address: 10.0.5.2}
|
|
net-b1-clients: {ipv4_address: 10.100.1.1}
|
|
|
|
b2:
|
|
<<: *frr-b
|
|
hostname: b2
|
|
volumes:
|
|
- ./frr/b2:/etc/frr
|
|
- ./entrypoints/b-entrypoint.sh:/entrypoints/b-entrypoint.sh:ro
|
|
networks:
|
|
link-a1-b2: {ipv4_address: 10.0.2.2}
|
|
link-a2-b2: {ipv4_address: 10.0.4.2}
|
|
link-a3-b2: {ipv4_address: 10.0.6.2}
|
|
net-b2-clients: {ipv4_address: 10.100.2.1}
|
|
|
|
# --- Клиенты площадки B (доверенная сеть) ---
|
|
c1:
|
|
<<: *client
|
|
hostname: c1
|
|
environment: {GATEWAY: 10.100.1.1}
|
|
volumes: ["./entrypoints/client-entrypoint.sh:/entrypoints/client-entrypoint.sh:ro"]
|
|
networks:
|
|
net-b1-clients: {ipv4_address: 10.100.1.11}
|
|
|
|
c2:
|
|
<<: *client
|
|
hostname: c2
|
|
environment: {GATEWAY: 10.100.1.1}
|
|
volumes: ["./entrypoints/client-entrypoint.sh:/entrypoints/client-entrypoint.sh:ro"]
|
|
networks:
|
|
net-b1-clients: {ipv4_address: 10.100.1.12}
|
|
|
|
c3:
|
|
<<: *client
|
|
hostname: c3
|
|
environment: {GATEWAY: 10.100.1.1}
|
|
volumes: ["./entrypoints/client-entrypoint.sh:/entrypoints/client-entrypoint.sh:ro"]
|
|
networks:
|
|
net-b1-clients: {ipv4_address: 10.100.1.13}
|
|
|
|
c4:
|
|
<<: *client
|
|
hostname: c4
|
|
environment: {GATEWAY: 10.100.2.1}
|
|
volumes: ["./entrypoints/client-entrypoint.sh:/entrypoints/client-entrypoint.sh:ro"]
|
|
networks:
|
|
net-b2-clients: {ipv4_address: 10.100.2.14}
|
|
|
|
c5:
|
|
<<: *client
|
|
hostname: c5
|
|
environment: {GATEWAY: 10.100.2.1}
|
|
volumes: ["./entrypoints/client-entrypoint.sh:/entrypoints/client-entrypoint.sh:ro"]
|
|
networks:
|
|
net-b2-clients: {ipv4_address: 10.100.2.15}
|
|
|
|
c6:
|
|
<<: *client
|
|
hostname: c6
|
|
environment: {GATEWAY: 10.100.2.1}
|
|
volumes: ["./entrypoints/client-entrypoint.sh:/entrypoints/client-entrypoint.sh:ro"]
|
|
networks:
|
|
net-b2-clients: {ipv4_address: 10.100.2.16}
|