1 はじめに
bondingの仕組みを調べるための環境を構築します。
本記事では環境構築のみ。
図1のKVMホスト環境に仮想ブリッジ(br1)を作成し、
仮想マシン(vm3,vm4)のNICを仮想ブリッジ(br1)に接続します。
最終的に図2の環境を作成します。図中の[]
内はデバイス名を表します。
+----- vm3 -----+ +----- vm4 -----+
| | | |
| | | |
| | | |
| | | |
| | | |
+--- [eth0]-----+ +--- [eth0] ----+
| .10 | .20
| |
| 192.168.122.0/24 |
| |
+--- [vnet0] ---------------- virbr0 ---------------- [vnet1] ---+
| |
| |
+------------------------- [virbr0-nic] -------------------------+
VM3とVM4のNICは、10.0.0.0/8
のネットワークに所属するように作成します。
VM3のbond0は10.0.0.30
、VM4のeth1は10.0.0.40
に設定します。
10.0.0.0/8
+----- vm3 -----+ +-- br1 --+ +----- vm4 -----+
| | | | | |
| .30 | | | | |
| +---+ | | | | |
| | b | | | | | |
| | o |[eth1] --- [vnet2] | .40| |
| | n | | | [vent4] --- [eth1] |
| | d |[eth2] --- [vnet3] | | |
| | 0 | | | | | |
| +---+ | | | | |
| | | | | |
+--- [eth0]-----+ +---------+ +--- [eth0] ----+
| .10 | .20
| |
| 192.168.122.0/24 |
| |
+--- [vnet0] ---------------- virbr0 ---------------- [vnet1] ---+
| |
| |
+------------------------- [virbr0-nic] -------------------------+
2 環境
VMware Workstation 15 Playerで作成した仮想マシンを使用しました。
仮想マシンの中に仮想マシンを作る、いわゆるNested VMを使って、環境を構築しました。
Nested VMの作り方は、ここ(Nested VMの作り方)を参照してください。
なお、KVMホスト、および仮想マシン(VM3,VM4)のOS版数は以下のとおりです。
[root@kvm ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@kvm ~]# uname -r
3.10.0-957.el7.x86_64
KVMホストのvirshコマンドの版数は以下のとおりです。
[root@kvm ~]# virsh -v
4.5.0
3 環境作成手順
NICが壊れているかどうかの判定方法として、以下の2つがあります。
仮想化マシンのNICを使用するので、ここでは、ARP監視を使用してみます。
・MII監視
・ARP監視
3.1 KVMホストで実施する手順
3.1.1 仮想ブリッジの作成
KVMホスト仮想にブリッジ(br1)を作成します。
[root@kvm ~]# ip l add br1 type bridge
仮想ブリッジの状態を確認します。状態がDOWNしていることがわかります。
[root@kvm ~]# ip l show dev br1
12: br1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ce:67:a9:62:c9:7d brd ff:ff:ff:ff:ff:ff
仮想ブリッジの状態をUPにします。
[root@kvm ~]# ip l set dev br1 up
仮想ブリッジの状態を確認します。状態がUPしていることがわかります。
[root@kvm ~]# ip l show dev br1
12: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/ether ce:67:a9:62:c9:7d brd ff:ff:ff:ff:ff:ff
3.1.2 VM3のNIC追加
仮想マシンが実行中のとき、VM3とVM4にNICを追加します。
VM3,VM4ともに実行中であることがわかります。
なお、virshコマンドの使い方は、ここ(virshコマンドの使い方)を参照してください。
[root@kvm ~]# virsh list
Id 名前 状態
----------------------------------------------------
1 vm3 実行中
2 vm4 実行中
VM3にNICを2つ追加します。
[root@kvm ~]# virsh attach-interface --type bridge --source br1 --model virtio vm3
インターフェースが正常に接続できました
[root@kvm ~]# virsh attach-interface --type bridge --source br1 --model virtio vm3
インターフェースが正常に接続できました
[root@kvm ~]# virsh domiflist vm3
インターフェース 種類 ソース モデル MAC
-------------------------------------------------------
vnet0 network default virtio 52:54:00:5e:65:7a
vnet2 bridge br1 virtio 52:54:00:b3:86:d2
vnet3 bridge br1 virtio 52:54:00:fb:90:fb
3.1.3 VM4のNIC追加
VM4にNICを追加します。
[root@kvm ~]# virsh attach-interface --type bridge --source br1 --model virtio vm4
インターフェースが正常に接続できました
仮想ブリッジのvnet4にVM4のNIC(52:54:00:33:a0:fc
)が追加されたことがわかります。
[root@kvm ~]# virsh domiflist vm4
インターフェース 種類 ソース モデル MAC
-------------------------------------------------------
vnet1 network default virtio 52:54:00:35:03:3f
vnet4 bridge br1 virtio 52:54:00:33:a0:fc
3.2 ゲストで実施する手順
3.2.1 VM4で実施する手順
NetworkManagerが動作していると、設定したIPアドレスが消えてしまい、
上手く動作しないので、NetworkManagerを停止します。
[root@vm4 ~]# systemctl stop NetworkManager
追加したNICにIPアドレスを設定します。
[root@vm4 ~]# ip addr add 10.0.0.40/8 dev eth1
3.2.2 VM3で実施する手順
NetworkManagerが動作していると、設定したIPアドレスが消えてしまい、
上手く動作しないので、NetworkManagerを停止します。
[root@vm3 ~]# systemctl stop NetworkManager
bondingデバイスを作成します。
[root@vm3 ~]# ip l add bond0 type bond
bondingのモードは、active-backup
に設定します。
また、リンク状態(UP/DOWN)の監視方法は、ARPを使います。
[root@vm3 ~]# ip link set bond0 type bond arp_interval 1000 arp_ip_target 10.0.0.40 mode active-backup
[root@vm3 ~]# ip l set eth1 down
[root@vm3 ~]# ip link set eth1 master bond0
[root@vm3 ~]# ip l set eth2 down
[root@vm3 ~]# ip link set eth2 master bond0
bondingデバイスにIPアドレス(10.0.0.30
)を設定します。
[root@vm3 ~]# ip addr add 10.0.0.30/8 dev bond0
bondingデバイスをUPすると、
ARPパケットがVM4(eth1)に1秒間隔で送信されるようになります。
[root@vm3 ~]# ip link set bond0 up
4 設定の確認方法
activeのデバイスを確認します。
現在は、eth1がactiveであることがわかります。
eth1のリンク断を検出すると、activeなデバイスがeth2に切り替わります。
[root@vm3 ~]# cat /sys/class/net/bond0/bonding/active_slave
eth1
ARP監視の間隔を確認します。
ARPパケットが1000(ms)間隔で送信される設定になっていることがわかります。
[root@vm3 ~]# cat /sys/class/net/bond0/bonding/arp_interval
1000
ARPターゲットを確認します。
ARPパケットは、10.0.0.40
に対して送信されることがわかります。
[root@vm3 ~]# cat /sys/class/net/bond0/bonding/arp_ip_target
10.0.0.40
5 動作確認
5.1 ARP監視の動作確認
VM3のbond0をUPすると、VM3からVM4に対して、ARPパケットが1秒間隔で送信されます。
なお、tsharkコマンドの使い方はここ(tsharkコマンドの使い方)を参照してください。
[root@vm4 ~]# tshark -i eth1 -Y 'arp.opcode==1 or arp.opcode==2' -n
Running as user "root" and group "root". This could be dangerous.
Capturing on 'eth1'
1 0.000000000 52:54:00:b3:86:d2 -> ff:ff:ff:ff:ff:ff ARP 42 Who has 10.0.0.40? Tell 10.0.0.30
2 0.000081854 52:54:00:33:a0:fc -> 52:54:00:b3:86:d2 ARP 42 10.0.0.40 is at 52:54:00:33:a0:fc
5 1.001786653 52:54:00:b3:86:d2 -> ff:ff:ff:ff:ff:ff ARP 42 Who has 10.0.0.40? Tell 10.0.0.30
6 1.001811054 52:54:00:33:a0:fc -> 52:54:00:b3:86:d2 ARP 42 10.0.0.40 is at 52:54:00:33:a0:fc
9 2.003887200 52:54:00:b3:86:d2 -> ff:ff:ff:ff:ff:ff ARP 42 Who has 10.0.0.40? Tell 10.0.0.30
10 2.003908729 52:54:00:33:a0:fc -> 52:54:00:b3:86:d2 ARP 42 10.0.0.40 is at 52:54:00:33:a0:fc
-snip-
5.2 active/backupの動作確認
ping実行中、仮想ブリッジのデバイス(vnet2またはvnet3)をダウンします。
デバイスをダウンすると、activeのデバイスが切り替わることを確認してみます。
VM3(bond0)からVM4(eth1)に対してpingを実行します。
なお、pingコマンドの使い方は、ここ(pingコマンドの使い方)を参照してください。
[root@vm3 ~]# ping -I bond0 -D 10.0.0.40
activeのデバイスを確認します。eth1がactiveであることがわかります。
[root@vm3 ~]# cat /sys/class/net/bond0/bonding/active_slave
eth1
このとき、VM3のeth1が接続している仮想ブリッジのvent2デバイスをダウンします。
[root@kvm ~]# ip l set vnet2 down
activeのデバイスを確認します。
activeのデバイスがeth1からeth2に切り替わったことがわかります。
[root@vm3 ~]# cat /sys/class/net/bond0/bonding/active_slave
eth2
デバイスがeth1からeth2に切り替わるさい、シーケンス番号31,32,33,34の
ICMPパケットがロストしていることがわかります。
パケットロストの時間としては約5秒であることがわかります。
[root@vm3 ~]# ping -I bond0 -D 10.0.0.40
-snip-
[1575039704.503299] 64 bytes from 10.0.0.40: icmp_seq=27 ttl=64 time=0.531 ms
[1575039705.503227] 64 bytes from 10.0.0.40: icmp_seq=28 ttl=64 time=0.449 ms
[1575039706.503992] 64 bytes from 10.0.0.40: icmp_seq=29 ttl=64 time=0.566 ms
[1575039707.504498] 64 bytes from 10.0.0.40: icmp_seq=30 ttl=64 time=0.479 ms
[1575039712.507103] 64 bytes from 10.0.0.40: icmp_seq=35 ttl=64 time=0.598 ms
[1575039713.507608] 64 bytes from 10.0.0.40: icmp_seq=36 ttl=64 time=0.804 ms
[1575039714.508439] 64 bytes from 10.0.0.40: icmp_seq=37 ttl=64 time=0.615 ms
5.3 SystemTapによる動作確認
activeなデバイスが切り替わったときの様子をsystemtapを使って確認してみます。
なお、SystemTapの使い方は、ここ(SystemTapの使い方)を参照してください。
[root@vm3 stap]# cat ping.stp
# !/usr/bin/stap
function is_skb_conn(skb)
{
iphdr = __get_skb_iphdr(skb)
daddr = format_ipaddr(__ip_skb_daddr(iphdr), AF_INET())
saddr = format_ipaddr(__ip_skb_saddr(iphdr), AF_INET())
if((saddr=="10.0.0.30") || (saddr=="10.0.0.40")){
return 1
}
}
probe kernel.function("__dev_queue_xmit@net/core/dev.c")
{
if(is_skb_conn($skb)) {
net_device = @cast($skb, "struct sk_buff", "kernel<linux/skbuff.h>")->dev
dev_name = @cast(net_device, "struct net_device", "kernel<linux/netdevice.h>")->name
printf("pp=%s,dev_name=%s\n", pp(), kernel_string(dev_name))
}
}
systemtapを実行します。
[root@vm3 stap]# stap -v ping.stp
VM3からVM4に対してpingを実行します。
[root@vm3 ~]# ping -I bond0 -D 10.0.0.40
このとき、VM3のeth1が接続している仮想ブリッジのvent2デバイスをダウンします。
[root@kvm ~]# ip l set vnet2 down
systemtapの実行結果から、activeなデバイスがeth1からeth2に切り替わったことがわかります。
また、ICMPパケットはbond0を通過したあと、eth1(またはeth2)を通過していることがわかります。
[root@vm3 stap]# stap -v ping.stp
-snip-
pp=kernel.function("__dev_queue_xmit@net/core/dev.c:3416"),dev_name=bond0
pp=kernel.function("__dev_queue_xmit@net/core/dev.c:3416"),dev_name=eth1
pp=kernel.function("__dev_queue_xmit@net/core/dev.c:3416"),dev_name=bond0
pp=kernel.function("__dev_queue_xmit@net/core/dev.c:3416"),dev_name=eth2
Z 参考情報
10.6. IP コマンドを使用したボンドおよびブリッジ上での VLAN の使用
7.6. チャンネルボンディングの使用
[root@vm3 ~]# ip link set bond0 type bond miimon 100 mode active-backup