前回の続きです。
前回はネットワーク周りの設定を何もせずにKVM仮想マシンを作成しました。
この状態だと、ゲストOSはネットワーク的に孤立した状態となっていて外部と通信できません。
そこで今回はこのマシンからホストOSを通して外部に通信できるようにしていきます。
現在の設定内容の確認
まずはホストマシン、ゲストマシンそれぞれ現在どのようになっているかを確認しておきましょう。
ほぼろの環境では下記のようになっていました。
$ 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 04:01:4c:ce:86:01 brd ff:ff:ff:ff:ff:ff
inet 128.199.93.213/18 brd 128.199.127.255 scope global eth0
valid_lft forever preferred_lft forever
inet 10.15.0.5/16 brd 10.15.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::601:4cff:fece:8601/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 04:01:4c:ce:86:02 brd ff:ff:ff:ff:ff:ff
4: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 52:54:00:ab:1b:1d brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
5: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 500
link/ether 52:54:00:ab:1b:1d brd ff:ff:ff:ff:ff:ff
6: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN qlen 500
link/ether fe:54:00:f7:83:82 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fef7:8382/64 scope link
valid_lft forever preferred_lft forever
1.はローカルループバックですね。きっとここを見てる方では見たことのないひとはいないはず。
2.はグローバルIPが割り当てられていて、外の世界とつながっているNICです。(VPSなのでこれも仮想NICのはずです)
3.は...何用でしょうか。わかる人いたら教えてくださいw
4.〜6.に関してはKVMを入れたことによるものなので、まずは下記コマンドの出力から見ていきましょう。
$ brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.525400ab1b1d yes virbr0-nic
vnet0
これを見るとわかる通り、4.のvirbr0は仮想ブリッジで、libvirtdが自動で作成したものです。
この仮想ブリッジにvirbr0-nicというインターフェースとvnet0というインターフェースが接続されています。
vnet0がKVMゲストマシンのNICと繋がっているtapデバイスと呼ばれるものです。
つぎにゲストマシンの確認です。
まだネットワークの設定をしていないので、シリアルコンソール接続します。
$ sudo virsh console centos7
[sudo] password for rhoboro:
Connected to domain centos7
Escape character is ^]
CentOS Linux 7 (Core)
Kernel 3.10.0-327.el7.x86_64 on an x86_64
[root@localhost ~]# 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 52:54:00:f7:83:82 brd ff:ff:ff:ff:ff:ff
どこにもつながっていないeth0がありますね。
一応ホストマシン側でも仮想マシン定義ファイルの内容を確認。
$ sudo virsh edit centos7
~省略~
<interface type='network'>
<mac address='52:54:00:f7:83:82'/>
<source network='default'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
~省略~
今回試すネットワーク構成
仮想マシンを外部と通信できるようにするには基本的に下記の2つの方法があるようです。
- ホストマシンのiptablesのIPマスカレード機能を使い、物理NICに来たパケットを仮想マシンのNICが接続された仮想ブリッジに転送する(NAT)
- libvirtインストール時に自動作成される仮想ブリッジvirbr0はこのためにある。
- 外からゲストマシンにはアクセスできない。ホスト<=>ゲスト間の通信は可能。
- 仮想マシンのNICが接続された仮想ブリッジを作成し、仮想ブリッジと物理NICを直接接続する
- ホストマシンと同じネットワークに属することになるので、外からもゲストマシンにアクセス可能。
今回は1.の方法を試します。
本当は2.の方法を試したかったのですが、いま利用しているDigitalOceanのDropletには静的なグローバルIPが1つだけ割り当てられている状況なため、
おそらく2.の方法はIPアドレスを割り振ってもらえないはず。
やっぱリアルマシンのLinuxが欲しいな...
(コレ、いま書きながら気付きました。実際に試す前に気づけただけでもよしとしましょうw)
実際に試してみる
さきほど記載した通り、libvirtdはデフォルトで仮想ブリッジvirbr0
を自動で作成しています。
今回はこの仮想ブリッジを使い、
KVMゲストマシンのNIC => vnet0 => virbr0 => ホストマシンのNIC => 外の世界
という流れで外部へ通信ができるようにします。
何はともあれ、実際に試してみるのが早いと思いますので、何も考えずにまずは下記のコマンドを実行してみてさい。
$ sudo virsh attach-interface centos7 network default
たったこの1行だけでKVMゲストマシンから外部へ通信ができるようになるはずです。
気になる方はゲストマシンにログインしてping
でも飛ばしてみましょう。
先ほどまでと違い、相手さえいれば届くはずです。
ざっくり解説
まずは、default
とは何か、を見ていきましょう。
# virsh
Welcome to virsh, the virtualization interactive terminal.
Type: 'help' for help with commands
'quit' to quit
virsh # net-list
Name State Autostart Persistent
----------------------------------------------------------
default active yes yes
virsh # net-dumpxml default
<network connections='2'>
<name>default</name>
<uuid>49067ae7-e979-4a08-b702-f95d1287febb</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:ab:1b:1d'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
慣れるまではこれを見てもわからないことだらけだと思いますが、default
とはKVMが作成した仮想ネットワークの名前です。
具体的には、nat
で実NICにフォワードされている、192.168.122.0/24
のネットワークで、仮想ブリッジvirbr0
が接続されています。
また、このネットワークはdhcpによりIPアドレスを割り当てていきます。(dnsmasqというDNSサーバーが動いています)
先ほどのコマンドsudo virsh attach-interface centos7 network default
はこのネットワークと接続するための仮想インターフェースをゲストマシンにアタッチするためのコマンドでした。
実際、ゲストマシンでip a
コマンドを試してみるとensX
というインターフェースが追加されており、192.168.122.X
のIPアドレスが割り当てられていることがわかると思います。
さて、これで外部と通信できるようになりましたが、せっかくなので次回はもう少しKVM、libvirtでのネットワーク周りについて見ていこうと思います。
ということで、先ほど追加したインターフェースはip a
で調べたMACアドレスをコピーして、
$ sudo virsh detach-interface centos7 --mac XX:XX:XX:XX:XX:XX
で削除しておきましょう(笑
まとめ
ネットワークは私自身もまだ勉強中なため難しいところが多く感じてしまいます。
ただ、一度理解してしまうと最初に考えていたものほど難しくなく、「なんだ、こんなことだったのか」と納得できる部分も多いです。
実際、この記事ではあまり触れられていないのですが、この記事を書くことでブリッジに関する理解は確実に深まりました。
次回は定義ファイルのXMLを編集しながらネットワーク周りをもう少し弄ろうと思います(笑