BGP(Border Gateway Protocol)とは自律システム(AS:autonomous system)間で、経路情報を交換するために設計されたルーティングプロトコルです。
(Wikipediaより https://ja.wikipedia.org/wiki/Border_Gateway_Protocol)
さらに引用ですが、
自律システム(AS)間のルーティングを行うExterior Gateway Protocol(EGP)の通信プロトコルである。
BGPはIPネットワークか自律システム(AS)間の到達性を示すプレフィックス(prefix)のルーティングテーブルを維持することでルーティングを行う。BGPはパスベクトル型ルーティングプロトコル(英語版)に分類され、技術的なメトリックは使用しないが、ネットワークの細かい規則や方針に従ってルーティングを行う。BGPはクラスレスドメイン間ルーティング(CIDR)をサポートし、経路集約を行うことでルーティングテーブルのサイズを削減することができる。
とあります。
コンテナ間が増えるとルーティングも複雑になりパフォーマンスも悪くなります。これをeBPFベースのカーネルモードを使ったCiliumで効率よく運用するために、BGPというのものが使われるようです。
Ciliumの事例をいろいろ調べていたところBGPというキーワードをみつけ掘り下げていくと、isovalent labsに動作テストができる環境があることがわかり、そこでCilium上のBGPを試してみました。
参考)
https://nicovibert.com/2022/07/21/bgp-with-cilium/
https://isovalent.com/resource-library/labs/
https://isovalent.com/labs/bgp-on-cilium/
手順は下記動画にあります。
おおまかな流れは以下です。
1)Kindを使ったclusterの作成
2) Containerlabを使った仮想ルータの構築
3) CiliumBGPPeeringPolicyの適用
https://isovalent.com/labs/bgp-on-cilium/より
2) のルータを構築した時点で、router0とRack0のToR、router0とRack1のToRとのBGPのルーティングがされ、2) のポリシーを適用した時点で、rack0,1内のToRとnode間のBGPルーティングが完了します。
仮想ルータの構築
※FRR(Free Range Routing) オープンソースのルーティングソフトウェアで、OSPFやBGPなど様々なプロトコルをサポートしているLinuxなどで動作するソフトウェア (https://zenn.dev/bells17/scraps/238c522e2f7c9b#comment-6e9bc72cfe8c0c より引用)
Ciliumポリシーの適用
kubectl apply -f cilium-bgp-peering-policies.yaml
ポリシーの適用前後のルーティング情報の差異と導通テストです。
vtyshというのは、ネットワーク制御をするcliツールで、CISCOのルータのものと似ているそうです。(昔使っていました。)
RfxRcdで受信できていることが確認できます。
もっとわかりやすくpingでテストです。
このnetshootというのは、トラブルシューティングでよくつかわれるようで、コマンドが豊富です。(default name space)
その他コンテナの状態を表示しました。
これらを参考に、次は自前の環境でテストしてみたいと思います。
今回初物が多く、とくにContainerlabは驚きました。ルータについて他にもいろいろ調べましたが規制製品のソフトバージョンもあるようですね。結局ルータもLinuxなのでコンテナ環境で動かすのも納得がいきます。(ハードシンセサイザに対するソフトシンセみたいなイメージをもちました)
Ciliumにかかわる必要なノウハウは、eBPFというLinuxカーネルのコードを使った領域から、データセンターのインフラ構築の領域まで、幅が広いことを改めて実感しました。(ルーティングに関するテストをするには様々なネットワークを構築する必要があり)
最後に、yamlファイルを引用します。ここにある情報で完結したい部分は、Labを参考ください。
cluster.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
kind: Cluster name: clab-bgp-cplane-demo apiVersion: kind.x-k8s.io/v1alpha4 networking: disableDefaultCNI: true podSubnet: "10.1.0.0/16" nodes: - role: control-plane kubeadmConfigPatches: - | kind: InitConfiguration nodeRegistration: kubeletExtraArgs: node-ip: "10.0.1.2" node-labels: "rack=rack0" - role: worker kubeadmConfigPatches: - | kind: JoinConfiguration nodeRegistration: kubeletExtraArgs: node-ip: "10.0.2.2" node-labels: "rack=rack0" - role: worker kubeadmConfigPatches: - | kind: JoinConfiguration nodeRegistration: kubeletExtraArgs: node-ip: "10.0.3.2" node-labels: "rack=rack1" - role: worker kubeadmConfigPatches: - | kind: JoinConfiguration nodeRegistration: kubeletExtraArgs: node-ip: "10.0.4.2" node-labels: "rack=rack1" containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"] endpoint = ["http://kind-registry:5000"] |
topo.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
name: bgp-cplane-demo topology: kinds: linux: cmd: bash nodes: router0: kind: linux image: frrouting/frr:v8.2.2 labels: app: frr exec: # NAT everything in here to go outside of the lab - iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # Loopback IP (IP address of the router itself) - ip addr add 10.0.0.0/32 dev lo # Terminate rest of the 10.0.0.0/8 in here - ip route add blackhole 10.0.0.0/8 # Boiler plate to make FRR work - touch /etc/frr/vtysh.conf - sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons - /usr/lib/frr/frrinit.sh start # FRR configuration - >- vtysh -c 'conf t' -c 'frr defaults datacenter' -c 'router bgp 65000' -c ' bgp router-id 10.0.0.0' -c ' no bgp ebgp-requires-policy' -c ' neighbor ROUTERS peer-group' -c ' neighbor ROUTERS remote-as external' -c ' neighbor ROUTERS default-originate' -c ' neighbor net0 interface peer-group ROUTERS' -c ' neighbor net1 interface peer-group ROUTERS' -c ' address-family ipv4 unicast' -c ' redistribute connected' -c ' exit-address-family' -c '!' tor0: kind: linux image: frrouting/frr:v8.2.2 labels: app: frr exec: - ip link del eth0 - ip addr add 10.0.0.1/32 dev lo - ip addr add 10.0.1.1/24 dev net1 - ip addr add 10.0.2.1/24 dev net2 - touch /etc/frr/vtysh.conf - sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons - /usr/lib/frr/frrinit.sh start - >- vtysh -c 'conf t' -c 'frr defaults datacenter' -c 'router bgp 65010' -c ' bgp router-id 10.0.0.1' -c ' no bgp ebgp-requires-policy' -c ' neighbor ROUTERS peer-group' -c ' neighbor ROUTERS remote-as external' -c ' neighbor SERVERS peer-group' -c ' neighbor SERVERS remote-as internal' -c ' neighbor net0 interface peer-group ROUTERS' -c ' neighbor 10.0.1.2 peer-group SERVERS' -c ' neighbor 10.0.2.2 peer-group SERVERS' -c ' address-family ipv4 unicast' -c ' redistribute connected' -c ' exit-address-family' -c '!' tor1: kind: linux image: frrouting/frr:v8.2.2 labels: app: frr exec: - ip link del eth0 - ip addr add 10.0.0.2/32 dev lo - ip addr add 10.0.3.1/24 dev net1 - ip addr add 10.0.4.1/24 dev net2 - touch /etc/frr/vtysh.conf - sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons - /usr/lib/frr/frrinit.sh start - >- vtysh -c 'conf t' -c 'frr defaults datacenter' -c 'router bgp 65011' -c ' bgp router-id 10.0.0.2' -c ' bgp bestpath as-path multipath-relax' -c ' no bgp ebgp-requires-policy' -c ' neighbor ROUTERS peer-group' -c ' neighbor ROUTERS remote-as external' -c ' neighbor SERVERS peer-group' -c ' neighbor SERVERS remote-as internal' -c ' neighbor net0 interface peer-group ROUTERS' -c ' neighbor 10.0.3.2 peer-group SERVERS' -c ' neighbor 10.0.4.2 peer-group SERVERS' -c ' address-family ipv4 unicast' -c ' redistribute connected' -c ' exit-address-family' -c '!' server0: kind: linux image: nicolaka/netshoot:latest network-mode: container:control-plane exec: # Cilium currently doesn't support BGP Unnumbered - ip addr add 10.0.1.2/24 dev net0 # Cilium currently doesn't support importing routes - ip route replace default via 10.0.1.1 server1: kind: linux image: nicolaka/netshoot:latest network-mode: container:worker exec: - ip addr add 10.0.2.2/24 dev net0 - ip route replace default via 10.0.2.1 server2: kind: linux image: nicolaka/netshoot:latest network-mode: container:worker2 exec: - ip addr add 10.0.3.2/24 dev net0 - ip route replace default via 10.0.3.1 server3: kind: linux image: nicolaka/netshoot:latest network-mode: container:worker3 exec: - ip addr add 10.0.4.2/24 dev net0 - ip route replace default via 10.0.4.1 links: - endpoints: ["router0:net0", "tor0:net0"] - endpoints: ["router0:net1", "tor1:net0"] - endpoints: ["tor0:net1", "server0:net0"] - endpoints: ["tor0:net2", "server1:net0"] - endpoints: ["tor1:net1", "server2:net0"] - endpoints: ["tor1:net2", "server3:net0"] |
cilium-bgp-peering-policies.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
--- apiVersion: "cilium.io/v2alpha1" kind: CiliumBGPPeeringPolicy metadata: name: rack0 spec: nodeSelector: matchLabels: rack: rack0 virtualRouters: - localASN: 65010 exportPodCIDR: true neighbors: - peerAddress: "10.0.0.1/32" peerASN: 65010 --- apiVersion: "cilium.io/v2alpha1" kind: CiliumBGPPeeringPolicy metadata: name: rack1 spec: nodeSelector: matchLabels: rack: rack1 virtualRouters: - localASN: 65011 exportPodCIDR: true neighbors: - peerAddress: "10.0.0.2/32" peerASN: 65011 |