FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

VyOSとDockerで仮想ルータをつくってみる。

こんにちは。 株式会社FLINTERSの阿部です。10周年記念として133日間ブログリレー122日目の投稿です。

1. きっかけ

FLINTERSに転職して、インフラまわりをやることになりました。 業務上はAWSやGoogle Cloudといったクラウド環境なのですが、ネットワークの基礎とかをちゃんと押さえるためにも、これは10年前に挫折したねすぺにリベンジすべきか...?と重い腰を9mm Parabellum Bulletほどあげました。
久々にぱらぱらと参考書とか見てみて、やっぱり実機やってないとわからんなーとなり、ローカルで気軽にネットワークで遊べるものを探してたら見つけたのが、今回のVyOSです。 VyOSはOSSの仮想ネットワークツールのようです。

2. つくったもの

GitHub - abejjj/vyos_tutorial にあげています。

3. やってみよう〜

VyOSをDockerでたちあげ、双方のルータ配下にあるサブネットワーク間でpingが通るところを目指します。 図はこんなかんじです。

vyos-tutorial01

この図でいう、debian-a-1からdebian-b-1へpingを飛ばして、応答が返れば成功です。

3-1. Dockerイメージのビルド

以下を参考にして、手順を上記Githubの build/build_docker_image.sh にまとめました。 ざっくりの流れとしては、VyOSが公開しているISOビルド用ツールを使ってISOファイルを吐き出して、そのISOとその中にあるSquashFSを展開し、最終的にそれをDockerイメージとしてimportしています。

3-2. docker composeから起動

ビルド毎にイメージ名を識別するのと、GOSU関係の環境変数が必要な都合上、簡単なシェルスクリプトにしています。 ここでの学びは、docker-composeのnetworksは、一つのサービスに対して複数指定できるんだー、ってことです。 (これできなかったらルータたてられない)

3-3. 初期状態の確認

起動直後のネットワークまわりの状態を確認しておきます。

(vrouterA)

vyos@vyos:~$ show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
eth0             192.168.21.3/28                   u/u  
eth1             192.168.100.3/28                  u/u  

vyos@vyos:~$show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup

K>* 0.0.0.0/0 [0/0] via 192.168.21.1, eth0, 00:03:25
C>* 192.168.21.0/28 is directly connected, eth0, 00:03:25
C>* 192.168.100.0/28 is directly connected, eth1, 00:03:25

(vrouterB)

vyos@vyos:~$ show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
eth0             192.168.22.3/28                   u/u  
eth1             192.168.100.2/28                  u/u  
lo               127.0.0.1/8                       u/u

vyos@vyos:~$ show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup

K>* 0.0.0.0/0 [0/0] via 192.168.22.1, eth0, 00:05:52
C>* 192.168.22.0/28 is directly connected, eth0, 00:05:52
C>* 192.168.100.0/28 is directly connected, eth1, 00:05:52

3-4. デフォルトゲートウェイの変更

疎通したいdebian側ですが、起動直後の状態だと、デフォルトゲートウェイがDockerのホストに向いてるため、 この先なにやっても通らなくなっています。。 なので、デフォルトゲートウェイを今回作ったVyOSのルータに向けるように変更します。 なお、docker-compose.ymlで以下のオプションを指定しないとそもそも変更ができません。。(これで時間が溶けました)

cap_add:
    - NET_ADMIN

かつこれは起動時のオプションらしいので、Dockerfileでビルド中によしなにやることができなかったです、、(もっといい方法しりたい

(debian-a-1)

root@debian-a-1:/# ip route
default via 192.168.21.1 dev eth0 
192.168.21.0/28 dev eth0 proto kernel scope link src 192.168.21.2 

root@debian-a-1:/# ip route add 192.168.21.1 via 192.168.21.1
root@debian-a-1:/# ip route del default via 192.168.21.1
root@debian-a-1:/# ip route add default via 192.168.21.3

root@debian-a-1:/#  ip route
default via 192.168.21.3 dev eth0 
192.168.21.0/28 dev eth0 proto kernel scope link src 192.168.21.2 
192.168.21.1 via 192.168.21.1 dev eth0 

(debian-b-1)

root@debian-b-1:/# ip route
default via 192.168.22.1 dev eth0 
192.168.22.0/28 dev eth0 proto kernel scope link src 192.168.22.2

root@debian-b-1:/# ip route add 192.168.22.1 via 192.168.22.1
root@debian-b-1:/# ip route del default via 192.168.22.1
root@debian-b-1:/# ip route add default via 192.168.22.3

root@debian-b-1:/# ip route
default via 192.168.22.3 dev eth0 
192.168.22.0/28 dev eth0 proto kernel scope link src 192.168.22.2 
192.168.22.1 via 192.168.22.1 dev eth0 

ping打ってこのままだと通らないことを確認します。

root@debian-a-1:/# ping -c 4 192.168.22.2
PING 192.168.22.2 (192.168.22.2) 56(84) bytes of data.

--- 192.168.22.2 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3064ms

root@debian-b-1:/# ping -c 4 192.168.21.2
PING 192.168.21.2 (192.168.21.2) 56(84) bytes of data.

--- 192.168.21.2 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3060ms

3-5. ルーティングの設定

通るように設定していきます。 今回は単純にstaticで(このサブネットだったらこっちだよー)設定します。

routerA/往路

$ configure
$ set protocols static route 192.168.22.0/28 next-hop 192.168.100.2
$ commit
$ save
$ exit
#設定の反映を確認
$ show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup

K>* 0.0.0.0/0 [0/0] via 192.168.21.1, eth0, 00:33:18
C>* 192.168.21.0/28 is directly connected, eth0, 00:33:18
S>* 192.168.22.0/28 [1/0] via 192.168.100.2, eth1, weight 1, 00:00:09 ★ココ
C>* 192.168.100.0/28 is directly connected, eth1, 00:33:18

routerB/復路

$ configure
$ set protocols static route 192.168.21.0/28 next-hop 192.168.100.3
$ commit
$ save
$ exit
#設定の反映を確認
$ show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup

K>* 0.0.0.0/0 [0/0] via 192.168.22.1, eth0, 00:35:36
S>* 192.168.21.0/28 [1/0] via 192.168.100.3, eth1, weight 1, 00:00:27
C>* 192.168.22.0/28 is directly connected, eth0, 00:35:36
C>* 192.168.100.0/28 is directly connected, eth1, 00:35:36

3-6. ping通るかな

通りましたーーーー!!!

root@debian-a-1:/# ping -c 4 192.168.22.2
PING 192.168.22.2 (192.168.22.2) 56(84) bytes of data.
64 bytes from 192.168.22.2: icmp_seq=1 ttl=62 time=0.157 ms
64 bytes from 192.168.22.2: icmp_seq=2 ttl=62 time=0.169 ms
64 bytes from 192.168.22.2: icmp_seq=3 ttl=62 time=0.168 ms
64 bytes from 192.168.22.2: icmp_seq=4 ttl=62 time=0.169 ms

--- 192.168.22.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3068ms
rtt min/avg/max/mdev = 0.157/0.165/0.169/0.005 ms

おわりに

VyOS自体よりもDockerのネットワーク設定まわりでのハマりどころが多くて泣きそうでしたが、ひとまずそれらしく動いてよかったです。
変なところあればコメントください。
ねすぺがんばります〜

参考

公式サイトの他、以下を参考にさせて頂きました。
感謝です。