ページ

2014-07-06

VyOS と L2TPv3 でハイパーバイザ内部ネットワーク同士をブリッジ接続する

前回ようやく仮想マシン(VM)達を移設するためのPCの準備ができたのだけど、移設する元のPCには、内部のみのネットワーク(VirtualBoxで言うところのHost-Only Network)があり、そこにいくつかVMがぶら下がっているので、これらも移行しないといけない。

一気に移せば何の問題もないのだけど、徐々に移そうとすると、内部のみのネットワークなので、旧ハイパーバイザに残ったVMと新ハイパーバイザに移し終わったVMで通信ができなくなってしまう。

どうしたらいけるかなと考えた結果、「イーサネットフレームを中継するVMを用意すればよくね?」ということで、それを可能にするL2TPv3と、L2TPv3を簡単に使えそうなVyOS (Vyattaのfork)を使って試してみた。

今回の話を図にすると、以下のとおり。

環境 / 利用ソフトウェア

  • 仮想マシンハイパーバイザ 2台。
  • VyOS v1.1 Helium (開発版なので注意:今回はVyOS-virt-livecd-1407022200-7e8544a-i386.isoを利用)

設定方法

VyOS インストール

まず、それぞれのハイパーバイザにVyOS をインストールする必要があるが、これはISOイメージでブートしてvyos / vyosでログイン、install imageと打てば指示に従うだけでOK。

こちらのブログが絵が張ってあってわかりやすそうなので参考に→『Vyatta』からフォークした『VyOS』をインストールしてみた | 俺的備忘録 〜なんかいろいろ〜

あとはホストとしての設定をする必要があるが、とりあえずこんな感じだけやればSSHでログインできる(ブリッジするだけのホストとして考えているので、インターネットに出していくのは想定していない)。
$ configure
# set interfaces ethernet ethX address '192.168.XXX.YYY/24'  (あとで出てくるので値は省略)
# set system host-name vybridge1    (あるいはvybridge2)
# set service ssh port 22
# commit
# save
以下、saveは省略するが、適宜保存する。

vybridge1の設定

まずeth0インタフェースにIPアドレスを振る。

$ configure
# set interfaces ethernet eth0 address '192.168.100.241/24'

次に「l2tpeth0」インタフェースを構成する。トンネルID/セッションIDは好きに決めてOK.
# set interfaces l2tpv3 l2tpeth0 
# set interfaces l2tpv3 l2tpeth0 local-ip 192.168.100.241
# set interfaces l2tpv3 l2tpeth0 remote-ip 192.168.100.242
# set interfaces l2tpv3 l2tpeth0 tunnel-id 41
# set interfaces l2tpv3 l2tpeth0 peer-tunnel-id 42
# set interfaces l2tpv3 l2tpeth0 session-id 1
# set interfaces l2tpv3 l2tpeth0 peer-session-id 2
# set interfaces l2tpv3 l2tpeth0 source-port 5000
# set interfaces l2tpv3 l2tpeth0 destination-port 5001

いったん適用して様子を見る。
# commit
# exit
$ show interfaces l2tpv3 detail
l2tpeth0:  mtu 1488 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet6 XXXX::XXXX:XXXX:XXXX:XXXX/64 scope link
       valid_lft forever preferred_lft forever

    RX:  bytes    packets     errors    dropped    overrun      mcast
             0          0          0          0          0          0
    TX:  bytes    packets     errors    dropped    carrier collisions
           738          7          0          0          0          0
l2tpeth0ができていることを確認する。

br0を構成し、eth1とブリッジする。
$ configure
# set interfaces bridge br0
# set interfaces ethernet eth1 bridge-group bridge br0
# set interfaces l2tpv3 l2tpeth0 bridge-group bridge br0
# commit
# exit
$ show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
br0              -                                 u/u
eth0             192.168.100.241/24                u/u
eth1             -                                 u/u
l2tpeth0         -                                 u/u
lo               127.0.0.1/8                       u/u
                 ::1/128
$ show bridge br0
bridge name     bridge id               STP enabled     interfaces
br0             0000.xxxxxxxxxxxx       no              eth1
                                                        l2tpeth0
br0ができていて、eth1とl2tpeth0が入っていることがわかる。
なお、eth1にはIPを振っていない。

これで、vybridge1の準備は終了。

vybridge2の設定

vybridge2の設定もほぼ同様。

$ configure
# set interfaces ethernet eth0 address '192.168.100.242/24'

vybridge2の「l2tpeth0」インタフェースには、基本的にはvyatta1と対照にする。
# set interfaces l2tpv3 l2tpeth0 
# set interfaces l2tpv3 l2tpeth0 local-ip 192.168.100.242
# set interfaces l2tpv3 l2tpeth0 remote-ip 192.168.100.241
# set interfaces l2tpv3 l2tpeth0 tunnel-id 42
# set interfaces l2tpv3 l2tpeth0 peer-tunnel-id 41
# set interfaces l2tpv3 l2tpeth0 session-id 2
# set interfaces l2tpv3 l2tpeth0 peer-session-id 1
# set interfaces l2tpv3 l2tpeth0 source-port 5001
# set interfaces l2tpv3 l2tpeth0 destination-port 5000

br0を構成し、eth1とブリッジする。
$ configure
# set interfaces bridge br0
# set interfaces ethernet eth1 bridge-group bridge br0
# set interfaces l2tpv3 l2tpeth0 bridge-group bridge br0
# commit

これでおしまい。あとは、新ハイパーバイザのVMから、旧ハイパーバイザのVMに通信してみて通信できればOK。

備考

実際のところ、今回の要件では一気に移行すればいいだけだったので、こんなことは必要ない。必要な場合であっても、Production環境でこのような使い方をするのであれば、L2VPNはオーバーヘッドが大きいのでパフォーマンスの検証をすべきと思う。(そもそも今のところVyOSの開発版についている機能のようなので、安定版では使えないのだけど)

なお、今回の構成では暗号化はされないので、もし必要ならIPSecの上に乗せるなど、別途考える必要がある。

しかしながら、かなりお手軽にL2ブリッジを構成できるので覚えておいて損はないと思う。

参考



2014-07-03

KVMの仮想マシンをWebブラウザから管理する

自分用にLinux KVM (Kernel-based Virtual Machine) で検証用他の仮想マシン達を立てている。その仮想マシンの管理に、今まではvirshコマンドと仮想マシンマネージャー (virt-manager)を使っていたが、各VMの画面が見たいとなると、VNCでXにログインして... という感じで煩わしかった。そこで、ハイパーバイザとなるPCのリプレースを契機に、Web管理ツールのWebVirtMgrを使って、Webブラウザから管理できるようにしてみた。

こんな感じの画面がWebブラウザから使えるようになる。


環境/前提

  • Ubuntu 14.04 Server
  • libvirtでKVMの仮想マシンを起動できる状態
    • (BIOS設定他+apt-get install qemu-kvm libvirt-bin的な状態)

Web側の設定


WebVirtMgrはPython + Djangoで書かれたWebアプリケーションなので、それが動くようにする。基本的には、https://github.com/retspen/webvirtmgr/wiki/Install-WebVirtMgr に書かれている手順の通り。このページには、RedHat/CentOS/Debianなんかのときの方法も書いてある。

Python他のインストール

apt-getで入れる。

$ sudo apt-get install git python-pip python-libvirt python-libxml2 novnc supervisor nginx 

アプリケーションのダウンロードと設定

gitで落としてきて、いくつか設定する。
$ git clone git://github.com/retspen/webvirtmgr.git
$ cd webvirtmgr

ここで本来の手順は「sudo pip install -r requirements.txt」なのだけど、パッケージ管理されないファイルが増えてしまう。requirements.txtを見ると、書いてあるライブラリがUbuntu 14.04のバージョン的にいけそうだったのでパッケージで入れることにした。
$ sudo apt-get install python-django gunicorn python-lockfile

スクリプトで初期設定をする。
$ ./manage.py syncdb
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'ユーザ名'): 
Email address: user@example.org
Password: パスワード
Password (again): パスワード
Superuser created successfully.
$ ./manage.py collectstatic

ディレクトリをまるっと移動する。
$ sudo mkdir /var/www
$ cd ..
$ sudo mv webvirtmgr /var/www/
$ sudo chown -R www-data:www-data /var/www/webvirtmgr

バックグラウンド起動の設定

バックグラウンドで起動するようにsupervisorを設定する。
/etc/supervisor/conf.d/webvirtmgr.confに以下の内容を書く。
[program:webvirtmgr]
command=/usr/bin/python /var/www/webvirtmgr/manage.py run_gunicorn -c /var/www/webvirtmgr/conf/gunicorn.conf.py
directory=/var/www/webvirtmgr
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/webvirtmgr.log
redirect_stderr=true
user=www-data

supervisorのリスタート(これで8000/tcpで立ち上がる)
$ sudo service supervisor restart 

フロントのWebサーバの設定

フロントに立つnginxを設定する。プロキシしているだけなので、Apacheでもいいと思うが、サンプルがこうなっているのでそうした。

/etc/nginx/sites-available/webvirtmgrに以下を記述する。
server {
    listen 8008 default_server;

    server_name $hostname;
    #access_log /var/log/nginx/webvirtmgr_access_log; 

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-Proto $remote_addr;
    }
}

$ sudo ln -s /etc/nginx/sites-available/webvirtmgr /etc/nginx/sites-enabled/webvirtmgr
$ service nginx restart 

これで http://hostname:8008/ にアクセスすると画面が見えるようになる。

novncの設定

ブラウザからコンソールを使うためのnovncの設定。この設定ファイルもwebvirtmgrに入っているので、使うだけでOK.

$ cd /var/www/webvirtmgr
$ sudo cp conf/initd/webvirtmgr-novnc-ubuntu /etc/init.d/webvirtmgr-novnc
$ sudo service webvirtmgr-novnc start
$ sudo update-rc.d webvirtmgr-novnc defaults

(コメントにnova-novncproxyとか書いてあったのでOpenStack Novaから持ってきたのであろう...)

libvirtの設定

WebVirtMgrはlibvirtdにTCP接続するので、その設定をする(なので、ハイパーバイザは別ホストでもOK)
ここの設定は https://www.webvirtmgr.net/docs/ を参考にした(証明書切れてる...)。

/etc/default/libvirt-binのlibvirtd_optsの行に-lを足して、tcpでlistenするようにする。
libvirtd_opts="-d -l"

/etc/libvirt/libvirtd.conf を以下のように編集する。今回はハイパーバイザが同一ホストなので127.0.0.1でlistenさせる。
listen_tls = 0
listen_tcp = 1
listen_addr = "127.0.0.1"

libvirt用のパスワードを設定する。
$ sudo apt-get install sasl2-bin
$ sudo saslpasswd2 -a libvirt ユーザ名
Password: 
Again (for verification): 
$ sudo sasldblistusers2 -f /etc/libvirt/passwd.db 
ユーザ名@ホスト名: userPassword

libvirtdを再起動する。
$ service libvirt-bin restart

以下のようにして接続できることを確認する。

$ virsh -c qemu+tcp://127.0.0.1/system nodeinfo
Please enter your authentication name: ユーザ名@ホスト名
Please enter your password: 
CPU model:           x86_64
CPU(s):              8
CPU frequency:       800 MHz
CPU socket(s):       1
Core(s) per socket:  4
Thread(s) per core:  2
NUMA cell(s):        1
Memory size:         16318576 KiB

Web画面にログインしての設定

http://hostname:8008/ にアクセスすると、ログイン画面が表示されるので、最初の「syncdb」を実行したときのユーザ/パスワードでログインする。

あとは画面ベースなので詳細は省略するが、以下のように設定すれば使えるようになる。

  • Servers List画面で127.0.0.1を追加する。
  • Storage Pools画面で、仮想マシン用のディレクトリorLVMプールとISOを配置するディレクトリを追加する。
  • Networks画面でネットワークを追加する。
  • Instances画面でインスタンスを追加する。

感想

OpenStackをこのようにVMを管理するために使おうと検証してみたのだけど、LVMのストレージやOpen vSwitchのブリッジを自前でIDを振って管理したりしていて、トラブルがあったときに追いづらくなるデメリットのほうが大きそうだったのでやめた。一方で、このWebVirtMgrはlibvirtやLVMをそのまま見せる設計思想なので、何かあったときにも追いやすく、1台~数台の管理ならかなり向いていそうだった。

2014-07-01

GPT パーティションテーブルを別のディスクにコピーする

sdaからsdbにパーティションテーブルをコピーするには、sgdiskを使うのが簡単。コマンドを先に書くとこう。不用意に実行するとさっくり壊れるので注意。
# sgdisk -R=/dev/sdb /dev/sda
# sgdisk -G /dev/sdb
sgdisk --backup sda.table /dev/sdaとかしておいたほうが安心かも?
参考: http://askubuntu.com/questions/57908/how-can-i-quickly-copy-a-gpt-partition-scheme-from-one-hard-drive-to-another

sgdiskがないとき

GPT版のfdiskであるところのgdiskをインストールする。
# apt-get install gdisk
cfdisk, sfdiskがあるように、cgdisk, sgdiskも入ってくる。ただし、コマンドラインオプションは違うので注意。
正直デフォルトで入っていて欲しい...

コマンドの説明

前提として、こんなディスクが二つあるとする。
$ sudo sgdisk -p /dev/sda
Disk /dev/sda: 16777216 sectors, 8.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 1519615B-B82D-4CA6-9849-28F3198A90E7
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 16777182
Partitions will be aligned on 2048-sector boundaries
Total free space is 3102653 sectors (1.5 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            4095   1024.0 KiB  EF02
   2            4096        13676543   6.5 GiB     FD00

$ sudo sgdisk -p /dev/sdb
Creating new GPT entries.
Disk /dev/sdb: 16777216 sectors, 8.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 65906D3D-B672-4373-AB55-F0C473EC52ED
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 16777182
Partitions will be aligned on 2048-sector boundaries
Total free space is 16777149 sectors (8.0 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name

ここで以下を実行することでパーティションテーブルをコピーできる。
$ sudo sgdisk -R=/dev/sdb /dev/sda
The operation has completed successfully.

これだけでコピーされているのだが、ディスクとパーティションに振られた固有IDまでコピーされてしまっている。

以下はディスク本体と2番目のパーティションの状態。
$ sudo sgdisk /dev/sda -p -i 2
Disk /dev/sda: 16777216 sectors, 8.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 1519615B-B82D-4CA6-9849-28F3198A90E7
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 16777182
Partitions will be aligned on 2048-sector boundaries
Total free space is 3102653 sectors (1.5 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            4095   1024.0 KiB  EF02
   2            4096        13676543   6.5 GiB     FD00
Partition GUID code: A19D880F-05FC-4D3B-A006-743F0F84911E (Linux RAID)
Partition unique GUID: CEA27178-6FB4-4358-B921-C75352CE33D7
First sector: 4096 (at 2.0 MiB)
Last sector: 13676543 (at 6.5 GiB)
Partition size: 13672448 sectors (6.5 GiB)
Attribute flags: 0000000000000000
Partition name: ''

$ sudo sgdisk /dev/sdb -p -i 2
Disk /dev/sdb: 16777216 sectors, 8.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 1519615B-B82D-4CA6-9849-28F3198A90E7 ←同じ
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 16777182
Partitions will be aligned on 2048-sector boundaries
Total free space is 3102653 sectors (1.5 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            4095   1024.0 KiB  EF02
   2            4096        13676543   6.5 GiB     FD00
Partition GUID code: A19D880F-05FC-4D3B-A006-743F0F84911E (Linux RAID)
Partition unique GUID: CEA27178-6FB4-4358-B921-C75352CE33D7 ←同じ
First sector: 4096 (at 2.0 MiB)
Last sector: 13676543 (at 6.5 GiB)
Partition size: 13672448 sectors (6.5 GiB)
Attribute flags: 0000000000000000
Partition name: ''

そこで、sgdisk -Gで振りなおす。

$ sgdisk -G /dev/sdb

そうすると、IDが新しくなっていることがわかる。
$ sudo sgdisk /dev/sdb -p -i 2
Disk /dev/sdb: 16777216 sectors, 8.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): CCC50747-7D41-4662-9FFE-93E7EE7644A3 ←変わっている
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 16777182
Partitions will be aligned on 2048-sector boundaries
Total free space is 3102653 sectors (1.5 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            4095   1024.0 KiB  EF02
   2            4096        13676543   6.5 GiB     FD00
Partition GUID code: A19D880F-05FC-4D3B-A006-743F0F84911E (Linux RAID)
Partition unique GUID: 29394950-7433-4913-8BA9-64E36B979394 ←変わっている
First sector: 4096 (at 2.0 MiB)
Last sector: 13676543 (at 6.5 GiB)
Partition size: 13672448 sectors (6.5 GiB)
Attribute flags: 0000000000000000
Partition name: ''