OpenStack環境で特定の仮想マシンが疎通できない場合のトラブルシュート
2016年 12月 19日

コントローラノードで実行 xxxx@controller
コンピュートノードで実行 xxxx@compute
クライアントPCで実行 xxxx@client※今回はUbuntuDesktopがインストールされたPCですが、OpenStackのコマンドが叩ければどこでもOKOpenStack上でのアカウントは2つ一般ユーザー demo@xxxx
管理者 admin@xxxxOS上のアカウントはroot不要のコマンドもありますが、説明簡略化のため全てrootで作業します。管理者 root@xxxx上記を組み合わせて表記します。ターミナルエミュレータの画面を4つ開き、demo@client
admin@client
root@controller
root@compute ※どこのcompute nodeかは後述とご用意頂くと幸せになれそうです。今回検証に用いたクライアントのバージョンは下記の通りです。バージョンが違う場合、特にメジャーバージョンが違う場合は意図した戻り値にならない場合が有りますので、ご了承ください。さて、トラブルのお題は「Instance Connectivity」です。何かしらの原因で仮想マシンへの疎通が取れない。という想定で、あくまで仮想マシン自体は正常に起動しているのが前提になります。まず、そもそもネットワーク周りがどんな仕組みになっているのか?を理解する必要があるのは言うまでもありません。コンピュートホスト上に起動した仮想マシンから、実際に物理インターフェイスにたどり着くまで、下記のような流れとなります。
- Tap interface
- Linux bridge
- Veth pair
- OVS integration bridge
- OVS patch ports
- OVS provider bridge
- Physical interface
ですので、これらの情報を調べる所から始めます。まず、調査対象のインスタンスIDを取得します。(ここでは調査対象のホスト名を「test-instance-2016」としています。)[demo@client]~$ openstack server list --column ID --column Name --format value | grep test-instance-2016
5e007107-ca0f-452c-8217-48658279dbef test-instance-2016これで、インスタンスIDがわかりましたので、今度はどこのコンピュートホストで動いているかを確認します。[admin@client]~$ openstack server show 5e007107-ca0f-452c-8217-48658279dbef --column name --column OS-EXT-SRV-ATTR:host
+----------------------+--------------------------+
| Field | Value |
+----------------------+--------------------------+
| OS-EXT-SRV-ATTR:host | compute03 |
| name | test-instance-2016 |
+----------------------+--------------------------+どこのcompute nodeで動いているかを示す「OS-EXT-SRV-ATTR:host」というカラムは、管理者権限でのみ参照可能ですので、ご注意ください。これで、compute03 というコンピュートノードで動いていることがわかりました。もちろんGUIで確認してもOKです。次に、取得したインスタンスIDからポートのIDを取得します。[demo@client]~$ neutron port-list --device_id 5e007107-ca0f-452c-8217-48658279dbef --fields id --format value
6047ba5c-9e0f-4d49-ac10-ae35957a24e3先ほど確認したコンピュートノードにログインし、上記の戻り値の最初の8文字を使って、この仮想マシンに関連するポートの情報を取得します。[root@compute] ip a | egrep "tap|qbr|qvb|qvo" | grep 6047ba5c
117: qbr6047ba5c-9e: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP
118: qvo6047ba5c-9e@qvb6047ba5c-9e: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master ovs-system state UP qlen 1000
119: qvb6047ba5c-9e@qvo6047ba5c-9e: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master qbr6047ba5c-9e state UP qlen 1000
120: tap6047ba5c-9e: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast master qbr6047ba5c-9e state UNKNOWN qlen 500各ポートの名称はそれぞれTap interface は、tap...Linux bridge は、qbr...Veth pair は、qvb... と qvo...となります。これらの情報とOVS Integration Bridge、OVS Provider Bridge、物理インターフェイスの情報ををまとめると下記のようになります。
Tap interface tap6047ba5c-9e Linux bridge qbr6047ba5c-9e Veth pair qvb6047ba5c-9e / qvo6047ba5c-9e OVS integration bridge br-int OVS patch ports int-br-ex / phy-br-ex OVS provider bridge br-ex Physical interface bond0 これで調査に必要な下調べが完了。ではここから実際に調査を開始します。まず最初に、DHCPで正常にIPアドレスが取れているかをチェックします。当該コンピュートノードで上記のTap Interfaceを指定して、tcpdumpを実行した状態で、当該仮想マシンを再起動してみます。この際、Soft Rebootしてしまうと、一旦Tap Interface自体を作り直されてしまい、tcpdumpが終了してしまいますので、GUIのConsoleから"Send CtrlAltDel" が手っ取り早いかと思います。下記のようにDHCPのRequest/Replyのやり取りが出力されていれば、IPアドレスの取得は問題ないかと思います。何も出力されない場合は、DHCP周りに何か問題がある可能性が高いです。[root@compute] tcpdump -eni tap6047ba5c-9e port bootpc or port bootps
tcpdump: WARNING: tap6047ba5c-9e: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap6047ba5c-9e, link-type EN10MB (Ethernet), capture size 65535 bytes
18:33:16.815223 fa:16:3e:86:2d:7f > fa:16:3e:27:05:29, ethertype IPv4 (0x0800), length 342: 10.114.0.68.bootpc > 10.114.0.20.bootps: BOOTP/DHCP, Request from fa:16:3e:86:2d:7f, length 300
18:33:24.194755 fa:16:3e:86:2d:7f > Broadcast, ethertype IPv4 (0x0800), length 342: 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from fa:16:3e:86:2d:7f, length 300
18:33:24.195924 fa:16:3e:27:05:29 > fa:16:3e:86:2d:7f, ethertype IPv4 (0x0800), length 372: 10.114.0.20.bootps > 10.114.0.68.bootpc: BOOTP/DHCP, Reply, length 330
18:33:24.196206 fa:16:3e:86:2d:7f > Broadcast, ethertype IPv4 (0x0800), length 342: 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from fa:16:3e:86:2d:7f, length 300
18:33:24.196211 fa:16:3e:12:ff:3d > fa:16:3e:86:2d:7f, ethertype IPv4 (0x0800), length 372: 10.114.0.21.bootps > 10.114.0.68.bootpc: BOOTP/DHCP, Reply, length 330
18:33:24.196271 fa:16:3e:24:83:a7 > fa:16:3e:86:2d:7f, ethertype IPv4 (0x0800), length 372: 10.114.0.22.bootps > 10.114.0.68.bootpc: BOOTP/DHCP, Reply, length 330
18:33:24.196971 fa:16:3e:27:05:29 > fa:16:3e:86:2d:7f, ethertype IPv4 (0x0800), length 390: 10.114.0.20.bootps > 10.114.0.68.bootpc: BOOTP/DHCP, Reply, length 348このように、問題の仮想マシンに紐付けられてるTap Interfaceを直接指定してtcpdumpをすることで、他の仮想マシンのトラフィックに邪魔されること無く調査ができます。もしDHCP周りがおかしいなと思った場合は、まずは下記点を確認します。[admin@client]~$ neutron agent-list | grep DHCP
| 4e2e7d4d-f993-4191-8d79-a8d55fa5c21f | DHCP agent | controller01 | :-) | True | neutron-dhcp-agent |
| f44e4362-8017-4bc8-9666-e33ab2fe7556 | DHCP agent | controller03 | :-) | True | neutron-dhcp-agent |
| f55d3a06-b85f-4b08-9b30-c482e5e96381 | DHCP agent | controller02 | :-) | True | neutron-dhcp-agent |ニッコリと笑顔が並んでればOKです。次にdnsmasqプロセスが稼働しているか確認します。[root@controller] ps aux | grep dnsmasq
nobody 2115 0.0 0.0 30692 1536 ? S 11月07 0:14 /usr/sbin/dnsmasq --no-resolv --keep-in-foreground --no-hosts --bind-interfaces --pid-file=/run/sendsigs.omit.d/network-manager.dnsmasq.pid --listen-address=127.0.1.1 --conf-file=/var/run/NetworkManager/dnsmasq.conf --cache-size=0 --proxy-dnssec --enable-dbus=org.freedesktop.NetworkManager.dnsmasq --conf-dir=/etc/NetworkManager/dnsmasq.dどちらかもしくは両方とも意図した結果でない場合は、下記コマンドでneutron-dhcp-agentを再起動します。[admin@client]~$ openstack-service restart neutron-dhcp-agent
その後、再度上記の確認を行います。当然ながら、そもそもneutron-dhcp-agentが上がってなければにっちもさっちも行かないですし、そもそもすべての仮想マシンで疎通が取れないかと思います。この辺の原因は基本的なセットアップの問題の可能性が高いので、ここでは割愛します。今回はあくまで、「なんでオマエだけ疎通しないんだよっ!」っていう、こたつの上のみかんを窓に向かって投げたくなるシチュエーションです。(※弊社オフィスの机がこたつなわけではありません)Agentが正常であることがわかりましたので、さらに下記点を確認してみます。仮想マシンのネットワークを調べます。(ここではsrv_networkという変数に入れておきます)[demo@client]~$ srv_network=`openstack server show test-instance-2016 --column addresses --format value | cut -d= -f 1`
取得したネットワークの名前からIDを調べます。(同様にnet_id)[demo@client]~$ net_id=`openstack network show $srv_network --column id --format value`
同様にサブネットのIDを調べます。(同様にsubnet)[demo@client]~$ subnet=`openstack network show $srv_network --column subnets --format value`
同様に当該サブネットに関連するDHCPのポート一覧を取得します。(同様にport_list)[demo@client]~$ port_list=(`openstack port list --device-owner network:dhcp --format value --column ID --column 'Fixed IP Addresses' | grep $subnet | awk '{print $1}'`)
それぞれのポートのnetwork_idが一致していることを確認します。[demo@client]~$ for p in ${port_list[@]};do
openstack port show $p --column network_id --format value
done | sort | uniq
15548108-b67e-42c6-bc36-b076d0898c94ここで複数のIDが出力される場合は一致していません。コントローラノードで上記network_idからDHCP Agent IDを確認。[root@controller] ip netns | grep 15548108-b67e-42c6-bc36-b076d0898c94
qdhcp-15548108-b67e-42c6-bc36-b076d0898c94上記network_idの先頭に「qdhcp-」というプレフィックスが付与されたDHCP Agentがいることがわかります。上記DHCP Agent IDはネームスペースになっているので、コントローラノードで上記IDを指定して、インターフェイス情報を確認します。[root@controller] ip netns exec qdhcp-15548108-b67e-42c6-bc36-b076d0898c94 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
32: tap89fa4ae5-9f: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UNKNOWN
link/ether fa:16:3e:27:05:29 brd ff:ff:ff:ff:ff:ff
inet 10.114.0.20/24 brd 10.114.0.255 scope global tap89fa4ae5-9f
valid_lft forever preferred_lft forever
inet 169.254.169.254/16 brd 169.254.255.255 scope global tap89fa4ae5-9f
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe27:529/64 scope link
valid_lft forever preferred_lft forever上記のTap interfaceと前述のDHCP Agent IDを組み合わせて、再度tcpdumpを実行してDHCP関連の出力がされるか確認します。前回同様、GUIのConsoleから"Send CtrlAltDel" が手っ取り早いかと思います。[root@controller] ip netns exec qdhcp-15548108-b67e-42c6-bc36-b076d0898c94 tcpdump -leni tap89fa4ae5-9f port bootpc or port bootps
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap89fa4ae5-9f, link-type EN10MB (Ethernet), capture size 65535 bytes
17:50:33.626407 fa:16:3e:86:2d:7f > fa:16:3e:12:ff:3d, ethertype IPv4 (0x0800), length 342: 10.114.0.68.bootpc > 10.114.0.21.bootps: BOOTP/DHCP, Request from fa:16:3e:86:2d:7f, length 300
17:50:41.204057 fa:16:3e:86:2d:7f > Broadcast, ethertype IPv4 (0x0800), length 342: 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from fa:16:3e:86:2d:7f, length 300
17:50:41.204840 fa:16:3e:27:05:29 > fa:16:3e:86:2d:7f, ethertype IPv4 (0x0800), length 372: 10.114.0.20.bootps > 10.114.0.68.bootpc: BOOTP/DHCP, Reply, length 330
17:50:41.205466 fa:16:3e:86:2d:7f > Broadcast, ethertype IPv4 (0x0800), length 342: 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from fa:16:3e:86:2d:7f, length 300
17:50:41.206198 fa:16:3e:27:05:29 > fa:16:3e:86:2d:7f, ethertype IPv4 (0x0800), length 390: 10.114.0.20.bootps > 10.114.0.68.bootpc: BOOTP/DHCP, Reply, length 348今回想定している「仮想マシンは起動しているのに疎通できない」という場合、DHCP周りでうまくIPアドレスが取れないということが多いため、上記手順で切り分けができるかと思います。長くなってしまったので、仮にDHCP周りに問題があると判断したあとの対処法に関しては、別の機会にご紹介できればと思います。明日は、伊藤さんのAndroidTVの話です。 家にテレビないですけど楽しみです。エンジニア募集エキサイトではエンジニアとして一緒に働いてくださる方を新卒採用と中途採用で募集しています。詳しくはこちら↓
をご覧ください。