nabeo がピーしているブログ (仮)

どーも、nabeop です

GoBGP で受け取った経路を Quagga (zebra) でカーネル経路に落とし込む

vagrant で k8s クラスタを作った記録では以下のように書いていました。

gobgpd と quagga を使った BGP ルータの構築も https://github.com/nabeo/vagrant-k8s-metallb で構築していますが、ここでは詳しくは触れません。

ということで、今回は gobgpd で受けた BGP 経路を Quagga で kernel の経路表に落とし込んで別サブネットに存在しているクライアントが k8 で構築しているサービスにアクセスできるようにしている部分の解説をしようと思います。Quagga でも BGP を受けれることは承知していますが、GoBGP を使ってみたかったのでこんな構成にしています。

まず、gobgpd は BGP を喋ってくれますが、受けっとった経路を OS の経路表に落とし込んではくれません。このため、BGP 広報の内容にしたがってパケットを転送したい場合はなんらかの手段をつかって OS の経路表に反映させる必要があります。gobgpd のドキュメントでは Quagga もしくは FRRouting に含まれている zebra を使う方法が紹介されています。

[zebra]
  [zebra.config]
    enabled = true
    url = "unix:/var/run/quagga/zserv.api"
    redistribute-route-type-list = ["connect"]
    version = 2

つまり、gobgpd が unix domain socket を使って zebra の API とお話しているようです。2600/tcp 経由でも通信できるようですが、今回のユースケースでは unix domain socket で十分です。

Quagga (zebra) 側の設定は zebra が動けばいいので、以下のような必要最小限の設定しか入れていません。

hostname Router
password zebra
enable password zebra

また、今回は metallb からの経路広報では EXTERNAL-IP への経路は next hop が複数、つまり Equal Cost Multi Path (ECMP) で聞こえています。

zebra から ECMP な経路を受けるには上記のドキュメントのとおり、gobgpd 側に ECMP な経路が聞こえてくることを教えてあげる必要があります。このような時は以下のような設定を追加しておきます。

[global.use-multiple-paths.config]
  enabled = true

このような仕込みを入れておいて、zebra と gobgpd を立ち上げておけば、gobpd で受け取った BGP 経路が zebra によって以下のようにカーネルの経路表に書かれるようになります。

172.17.254.1 proto zebra metric 20
        nexthop via 172.17.0.22 dev enp0s8 weight 1
        nexthop via 172.17.0.21 dev enp0s8 weight 1
        nexthop via 172.17.0.23 dev enp0s8 weight 1

あとは、お約束としてカーネルパラメータでパケットの転送を有効にしてあげればお手軽なルータとして使うことができます。この辺りも ansible playbook にしています。