drumato.com

about
contacts
免責事項
ライセンス
記事一覧
日記一覧
ENGLISH
simpleなiBGP route-reflectorをFRRでやってみる

simpleなiBGP route-reflectorをFRRでやってみる

bgpfrr

こんにちは.
せっかく こんな記事 を書いたのだから,
ここに書いてあることを一つずつ消化しようかなー,と思ったり.

ということで,iBGP route-reflectorを触ってみます.
まずはfullmeshをやってconfig mgmtの大変さを経験したあと,
route-reflector導入 -> RR clusterに拡張,の流れです.
今回使用するconfigは こちら に置いてあります.

iBGP full meshについておさらい

まず前提として,iBGP messageはeBGPと異なり1より大きいTTL(64とか255)でやり取りされます.
つまり,いくつかのnodeを経由するようなpeer establishmentが可能です.
そして,BGP split horizonにより,iBGP peerから受け取った経路は他のiBGP peerに広報しません.
以上のことから,
一般的にiBGP speakerはfull meshにpeerを貼ることが想定されています.
ここらへんの話のconceptは こちら を読むと理解できます.

余談ですが,split horizonでloopを回避する,という概念はRIPとかにもあるものだと思います.
そこらへんの話は 3分間ルーティング 基礎講座 がとても参考になりましたので紹介します.

このとき,iBGP speakerの数が増えるにつれてpeerの組み合わせが膨大になります.
具体的には,iBGP speakerの数を S としたとき,
peerの数は S * (S - 1) / 2 となります.

これは管理が大変になりますし,performance上の問題も出てくるかもしれません.
ということで,いくつかの手法のうちどれかを適用してこれを回避します.
そのうち最も一般的(だと思われる)手法がroute-reflectorです.

とはいえ本当に大変なのかよくわからないと思うので,
まずはfull meshから試してみましょう.
適当にtinet specを用意します.
tinetについての紹介はここでは省略します.
ちゃんと使い方を解説する記事を上げると思います.
tinet specについてはrepoを御覧ください.
ここでは write mem の内容のうち,
R0のものを取り上げます.
広報するnetworkは適当にしておきます.

通常,iBGPやOSPFで扱うinterfaceはloopback interfaceです.
これはloopback interfaceにdownしないという特徴があり,
iBGP sessionを落とさずに運用できるという利点があります.
FRRでは neighbor PEER update-source <IFNAME|ADDRESS> のようにして使えます.
本記事ではこの設定は使わないですが,
実際にiBGPで遊ぶときはこれを設定すると良いでしょう.

1frr version 8.0 2frr defaults traditional 3hostname R0 4log syslog informational 5no ipv6 forwarding 6service integrated-vtysh-config 7! 8interface net0 9 ip address 10.0.1.100/24 10! 11interface net1 12 ip address 10.0.2.1/24 13! 14router bgp 100 15 bgp router-id 10.0.1.100 16 neighbor 10.0.1.101 remote-as 100 17 neighbor 10.0.1.102 remote-as 100 18 neighbor 10.0.1.103 remote-as 100 19 neighbor 10.0.1.104 remote-as 100 20 neighbor 10.0.1.105 remote-as 100 21 ! 22 address-family ipv4 unicast 23 network 10.0.2.0/24 24 exit-address-family 25! 26line vty 27!

configだけ見てもよくわからないかもしれないので,
network topologyの図を用意しました.

fullmesh

1tinet upconf -c spec | sudo sh -x 2tinet test -c spec | sudo sh -x

のようにしてcontainerを起動,test commandを実行できます.
repositoryにはribの内容とかをdumpしておいたので,よかったら御覧ください.
実際にinterfaceにpacketが着弾しているのを確認しましょう.

1$ docker exec -it R0 tcpdump -nni net0 -w /tinet/r0-net0.pcap # 別のshellで実行 2$ tinet test -c spec.yaml | sudo sh -x

tinetではcontainerの /tinet にhostの /tmp/tinet をmountしているので,
かんたんにpcap fileを共有したりできます. 便利.

r0-net0

良さそうですね.

route-reflector

6台構成でも実感できるぐらい管理が大変なので,
route-reflectorを使ってかんたんにしたいと思います.
ospfとか使ってもうちょっと実践的なnetworkにしても良かったんですが,とりあえず.
こちら にすべてのconfigとかがおいてあります.

まずはrouter-reflectorとして動作する RR0 のconfigを見てみましょう.

1interface net0 2 ip address 10.0.1.99/24 3! 4router bgp 100 5 bgp router-id 10.0.1.99 6 neighbor 10.0.1.100 remote-as 100 7 neighbor 10.0.1.101 remote-as 100 8 neighbor 10.0.1.102 remote-as 100 9 neighbor 10.0.1.103 remote-as 100 10 neighbor 10.0.1.104 remote-as 100 11 neighbor 10.0.1.105 remote-as 100 12 ! 13 address-family ipv4 unicast 14 neighbor 10.0.1.100 route-reflector-client 15 neighbor 10.0.1.101 route-reflector-client 16 neighbor 10.0.1.102 route-reflector-client 17 neighbor 10.0.1.103 route-reflector-client 18 neighbor 10.0.1.104 route-reflector-client 19 neighbor 10.0.1.105 route-reflector-client 20 exit-address-family 21!

route-reflectorはすべてのpeerを礼儀正しく作って,
誰に対しても経路を届けられるようにします.
star topologyを組む感覚ですね.

すると, R0 のconfigは以下のようにスッキリします.

1interface net0 2 ip address 10.0.1.100/24 3! 4interface net1 5 ip address 10.0.2.1/24 6! 7router bgp 100 8 bgp router-id 10.0.1.100 9 neighbor 10.0.1.99 remote-as 100 10 ! 11 address-family ipv4 unicast 12 network 10.0.2.0/24 13 exit-address-family 14!

route-reflector cluster

ところで,このroute-reflector1台に対してどんどんspeakerを接続していくのは得策ではありません.
このroute-reflectorの障害によって全体に影響が及んでしまいますし,
結局route-reflectorが持つconfigが肥大化してしまいます.

ということで,これを回避する方法として,route-reflectorのclusterを組む,というものがあります.
大まかには,次のような感覚です.

  • route-reflectorが管理するiBGP speakerの集合をclusterとします
  • clusterに責任を持つroute-reflectorをn台構成で管理します
    • rr同士はcluster-idで相互に識別しpeerを組み,loopは防がれます

ということで,最後にclusterを作ってみます.
今回はsubnetを分けたりせず単純に2冗長の構成とするだけですが,
subnetを分けて,管理する経路やpeerをそれぞれ分けて,という感じに構成することも可能です.
具体的には,
clusterごとにn台のrrを運用して,
clusterのrrごとにpeerを組めば良いと思います.
今回はそこまでの体力がなかった...

ここでは RR0 のconfigを紹介します.
RR1 でも同じcluster-idを指定するのがpointです.
すべてのconfigはこちら に.

1interface net0 2 ip address 10.0.1.91/24 3! 4router bgp 100 5 bgp router-id 10.0.1.91 6 bgp cluster-id 10.0.1.90 7 neighbor 10.0.1.92 remote-as 100 8 neighbor 10.0.1.100 remote-as 100 9 neighbor 10.0.1.101 remote-as 100 10 neighbor 10.0.1.102 remote-as 100 11 neighbor 10.0.1.103 remote-as 100 12 neighbor 10.0.1.104 remote-as 100 13 neighbor 10.0.1.105 remote-as 100 14 ! 15 address-family ipv4 unicast 16 neighbor 10.0.1.92 route-reflector-client 17 neighbor 10.0.1.100 route-reflector-client 18 neighbor 10.0.1.101 route-reflector-client 19 neighbor 10.0.1.102 route-reflector-client 20 neighbor 10.0.1.103 route-reflector-client 21 neighbor 10.0.1.104 route-reflector-client 22 neighbor 10.0.1.105 route-reflector-client 23 exit-address-family 24! 25line vty 26!
  • rrを2台ともstopして, R5clear bgp ipv4 unicast * すると C0 へのreachabilityが失われる
  • どちらか1台stopして clear bgp ipv4 unicast * しても経路をもらえる

というのを確認してみましょう.

rr-cluster1
rr-cluster2

おぉー,うまくできていますね.
CLUSTER_LIST path attributeについてはまた別途記事を上げるかもしれません.
上げないかもしれません.

おわりに

今回はiBGP full meshからやり始めて,
simple route-reflectorと,これまたsimpleなrr clusterを組んでみました.
個人的に一番勉強になったのはroute-reflectorではなく,
loopback interfaceの使われ方でした.