2017年3月7日火曜日

実はちょっと問題が

今のウチの構成は、KVMホストとして使っている物理マシンが2台ある。
Intel NUCを使った弁当箱サイズのaquariusと、いわゆる自作マシンのミドルタワーサイズのsagittariusだ。

このマシンにUbuntu16.04を導入し、iSCSIイニシエータ、OpenvSwitch、KVM等を導入して運用している。

で、このマシン、実はシャットダウンやリブートで詰まる事象が起きている。
ファイルシステムアンマウント・ボリュームディアクティベートあたりで発生しているようで、多分「gfs2マウントについて(その1:自動マウント)」辺りと似たような問題だと睨んでいる。

ただ、仮想マシンではなく物理マシンのため、今までは見て見ぬふりをしていた。
再起動を伴う設定変更・確認は、物理マシンを相手にする場合は、物理マシンの直ぐ側にいないとリスキーなので。

ただ、仮想マシンでiSCSIが利用できることも確認できたので、仮想マシンで現象の再現、対応方法の確立をしようと思う。

とりあえず、gemini/cancer上でKVMを動かしたいので、一旦停止してgemini/cancerのCPU定義と割当メモリを変更する。
まずは停止。
(gemini) $ sudo shutdown -h now
(cancer) $ sudo shutdown -h now

停止しているのを確認して、両仮想マシンを編集。
(sagittarius) $ virsh list --all
(sagittarius) $ virsh edit gemini
(sagittarius) $ virsh edit cancer
gemini/cancerともに同じ修正を施す。
--ココから
4~5行目付近
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
↓(割当サイズを4GBにする)
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>

17~18行目付近
<cpu mode='custom' match='exact'>
<model fallback='allow'>core2duo</model>
↓(CPUモデルをhost-modelに)
<cpu mode='host-model'>
<model fallback='allow'/>
--ココまで

ココまで出来たらgemini/cancerともに起動する。
(sagittarius) $ virsh start gemini
(sagittarius) $ virsh start cancer

後は、過去の内容を参照しながら作り込んでいく。(とりあえずgeminiに対してのみ更新。)
ざっとコマンド羅列。
(gemini) $ sudo apt-get update
(gemini) $ sudo apt-get install qemu-kvm
(gemini) $ sudo shutdown -r now

(gemini) $ grep kvm /etc/group
(gemini) $ id
(gemini) $ sudo adduser (自分のユーザ名) kvm
(gemini) $ grep kvm /etc/group
(一旦exitで抜けて、再度ログイン)
(gemini) $ id

(gemini) $ lsmod | grep kvm

(gemini) $ sudo apt-get install virtinst
(gemini) $ sudo apt-get install libosinfo-bin

再ログイン
(gemini) $ virsh list --all
(gemini) $ sudo apt-get install virt-manager
(gemini) $ sudo apt-get install fonts-ipafont

(gemini) $ sudo apt-get install openvswitch-switch
(gemini) $ sudo ovs-vsctl show
(gemini) $ sudo ovs-vsctl list-br
(gemini) $ sudo ovs-vsctl add-br br-external
(gemini) $ sudo ovs-vsctl show
(gemini) $ sudo ovs-vsctl list-br

(gemini) $ sudo vi /etc/network/interfaces.d/0110.ens3
ファイルの新規作成
--ココから--
auto ens3
allow-br-external
iface ens3 inet manual
ovs_bridge br-external
ovs_type OVSPort
--ココまで--

(gemini) $ sudo vi /etc/network/interfaces.d/0010.br-external
ファイルの新規作成
--ココから--
auto br-external
allow-ovs br-external
iface br-external inet static
address 192.168.55.136
network 192.168.55.0
netmask 255.255.255.0
broadcast 192.168.55.255
gateway 192.168.55.1
ovs_type OVSBridge
ovs_ports ens3

dns-nameservers 192.168.55.1
--ココまで--

--2017/04/14追記
ネットワークセッションが切れてしまうので、コンソールで作業しよう。
(gemini) $ sudo ifdown ens3
(gemini) $ sudo rm /etc/network/interfaces.d/ens3
(gemini) $ sudo ovs-vsctl add-port br-external ens3
(gemini) $ sudo ovs-vsctl show
(gemini) $ sudo ifup ens3
(gemini) $ sudo ifup br-external
--2017/04/14追記ココまで

--2017/04/20追記
このまま再起動させると、 OpenvSwitch/corosync/dlm/lvm2-cluster-activation の起動関連が上手く行かず、ハングしてしまう。
  1. OpenvSwitchが完全に起動
  2. corosync起動
  3. dlm起動
  4. lvm2-cluster-activation起動
の順で起動して欲しいのだが、OpenvSwitchの起動処理が完全に終わる前にcorosyncが起動してしまい、その後の起動処理が不安定になってしまう。

そのため、起動順の制御と、OpenvSwitchの起動時に、少しsleepを置くことにする。
(gemini) $ cd /lib/systemd/system
(gemini) $ sudo cp -pi corosync.service corosync.service.orig
(gemini) $ sudo cp -pi openvswitch-switch.service openvswitch-switch.service.orig

(gemini) $ sudo vi corosync.service
--ココから
Requires=network-online.target
After=network-online.target
(前提条件に openvswitch-switch.service を追加する)
Requires=network-online.target openvswitch-switch.service
After=network-online.target openvswitch-switch.service
--ココまで

(gemini) $ sudo vi openvswitch-switch.service
--ココから
ExecStart=/bin/true
(何も実行しない処理を、6秒待機に変更する)
ExecStart=/bin/sleep 6
--ココまで

変更内容を取り込む。
(gemini) $ sudo systemctl daemon-reload
(gemini) $ cd
--2017/04/20追記ココまで

(gemini) $ sudo shutdown -r now
(gemini) $ ip address show
(gemini) $ dig www.blogger.com
(gemini) $ sudo ovs-vsctl show

(gemini) $ virsh net-list --all
(gemini) $ vi ovsbridge.xml
ファイルの新規作成
--ここから
<network>
<name>ovsbridge</name>
<forward mode='bridge'/>
<bridge name='br-external'/>
<virtualport type='openvswitch'/>
</network>
--ここまで
(gemini) $ virsh net-define ovsbridge.xml
(gemini) $ virsh net-list --all

(gemini) $ virsh net-autostart ovsbridge
(gemini) $ virsh net-list --all

(gemini) $ virsh net-start ovsbridge
(gemini) $ virsh net-list --all

(gemini) $ sudo apt-get install ovmf
-------------------------------------------------------------
がーっと作ってしまったが、iSCSIのボリューム以外はだいたいホストOSと同じになったはず。
この状態で再起動が上手くいくか確認。
(gemini) $ sudo shutdown -r now
特に問題無さそうだ。

iSCSIストレージ装置で、新しくiSCSIターゲットを作成、100GBのLUNを新たに繋いで、geminiにのみ接続させておく。
/dev/sdb として認識された。

そのディスクを、ホストOSと同じように領域確保&ファイルシステム作成する。
(gemini) $ sudo parted /dev/sdb print
(gemini) $ sudo parted /dev/sdb mklabel gpt
(gemini) $ sudo parted /dev/sdb mkpart primary ext4 0% 100%
(gemini) $ sudo parted /dev/sdb toggle 1 lvm
(gemini) $ sudo parted /dev/sdb print

(gemini) $ sudo pvcreate /dev/sdb1
(gemini) $ sudo vgcreate vg-kvm /dev/sdb1
(gemini) $ sudo vgchange -c n vg-kvm
(gemini) $ sudo vgdisplay -v vg-kvm

(gemini) $ sudo lvcreate -L 32M -n lv-etc-libvirt vg-kvm
(gemini) $ sudo lvcreate -L 50G -n lv-var-lib-libvirt vg-kvm
(gemini) $ sudo lvcreate -L 2G -n lv-var-log-libvirt vg-kvm

(gemini) $ sudo mkfs.ext4 /dev/vg-kvm/lv-etc-libvirt
(gemini) $ sudo mkfs.ext4 /dev/vg-kvm/lv-var-lib-libvirt
(gemini) $ sudo mkfs.ext4 /dev/vg-kvm/lv-var-log-libvirt

続いて、中身のコピー。
(gemini) $ sudo mkdir /tmp/libvirt

(gemini) $ sudo mount /dev/vg-kvm/lv-etc-libvirt /tmp/libvirt
(gemini) $ df /tmp/libvirt
(gemini) $ sudo -i
(gemini) # cd /etc
(gemini) # tar cSf - libvirt | ( cd /tmp ; tar xSf - )
(gemini) # ls -l /tmp/libvirt
(gemini) # ls -ld /tmp/libvirt /etc/libvirt
(gemini) # exit
(gemini) $ sudo umount /tmp/libvirt
(gemini) $ sudo rm -rf /etc/libvirt
(gemini) $ sudo mkdir /etc/libvirt
(gemini) $ sudo mount /dev/vg-kvm/lv-etc-libvirt /etc/libvirt
(gemini) $ df /etc/libvirt

(gemini) $ sudo mount /dev/vg-kvm/lv-var-lib-libvirt /tmp/libvirt
(gemini) $ df /tmp/libvirt
(gemini) $ sudo -i
(gemini) # cd /var/lib
(gemini) # tar cSf - libvirt | ( cd /tmp ; tar xSf - )
(gemini) # ls -l /tmp/libvirt
(gemini) # ls -ld /tmp/libvirt /var/lib/libvirt
(gemini) # exit
(gemini) $ sudo umount /tmp/libvirt
(gemini) $ sudo rm -rf /var/lib/libvirt
(gemini) $ sudo mkdir /var/lib/libvirt
(gemini) $ sudo mount /dev/vg-kvm/lv-var-lib-libvirt /var/lib/libvirt
(gemini) $ df /var/lib/libvirt

(gemini) $ sudo mount /dev/vg-kvm/lv-var-log-libvirt /tmp/libvirt
(gemini) $ df /tmp/libvirt
(gemini) $ sudo -i
(gemini) # cd /var/log
(gemini) # tar cSf - libvirt | ( cd /tmp ; tar xSf - )
(gemini) # ls -l /tmp/libvirt
(gemini) # ls -ld /tmp/libvirt /var/log/libvirt
(gemini) # exit
(gemini) $ sudo umount /tmp/libvirt
(gemini) $ sudo rm -rf /var/log/libvirt
(gemini) $ sudo mkdir /var/log/libvirt
(gemini) $ sudo mount /dev/vg-kvm/lv-var-log-libvirt /var/log/libvirt
(gemini) $ df /var/log/libvirt

(gemini) $ sudo rmdir /tmp/libvirt

fstabを更新
(gemini) $ sudo vi /etc/fstab
以下の行を追加
--ココから
/dev/mapper/vg--kvm-lv--etc--libvirt /etc/libvirt ext4 _netdev 0 0
/dev/mapper/vg--kvm-lv--var--lib--libvirt /var/lib/libvirt ext4 _netdev 0 0
/dev/mapper/vg--kvm-lv--var--log--libvirt /var/log/libvirt ext4 _netdev 0 0
--ココまで

(gemini) $ sudo umount /etc/libvirt
(gemini) $ sudo umount /var/log/libvirt
(gemini) $ sudo umount /var/lib/libvirt
(gemini) $ sudo mount -a
(gemini) $ df

自動アクティベート対象にする。
(gemini) $ sudo vi /etc/lvm/lvm.conf
--ココから
1156行目付近
auto_activation_volume_list = [ "gemini-vg" ]
↓項目追加
auto_activation_volume_list = [ "gemini-vg", "vg-kvm" ]
--ココまで

もう1つ、KVMホストは実はcifsマウントもしている。
(OSのisoメディアを配置するディスクはcifsにした。これなら別のWindowsマシンからも利用が可能だからだ。)
cifsマウント用のパッケージの導入
(gemini) $ sudo apt-get install cifs-utils

そのマウントポイントを作成する。
(gemini) $ sudo mkdir /mnt/iso-os

fstabに追記する。
(gemini) $ sudo vi /etc/fstab
以下の行を追記
--ココから
//(cifsのIPアドレス)/(cifsのディレクトリ) /mnt/iso-os cifs guest,_netdev 0 0
--ココまで

マウント確認
(gemini) $ sudo mount /mnt/iso-os
(gemini) $ df /mnt/iso-os
(gemini) $ sudo umount /mnt/iso-os

再起動してマウント状態の確認
(gemini) $ sudo shutdown -r now
(gemini) $ df

これでgeminiは、KVMホストのaquarius/sagittariusとほぼ同じ環境になったはずだ。

あれ…何度再起動しかけても、KVMホストマシンで発生している現象が起きない…な…。

そういえば、ココでnetworking.serviceを無効にしてたんだった。
それも適用してみよう。
(gemini) $ sudo systemctl stop networking.service
(gemini) $ sudo systemctl is-active networking.service
(gemini) $ sudo systemctl disable networking.service
(gemini) $ sudo systemctl is-enabled networking.service

--2017/04/20追記--
そもそも、 networking.service が failed になる理由だけど…。
今回、 OpenvSwitch で br-external という仮想スイッチ(仮想デバイス)を作成している。物理デバイスは存在しないデバイスだ。
networking.service は、 /etc/network/interfaces と /etc/network/interfaces.d/* で auto に指定されているデバイスは起動時に有効にしようとするが、 br-external は物理デバイスが無いため、 networking.service では有効に出来ない。(openvswitch-nonetwork.service にて有効にされる。)
networking.service が failed になる理由は、起動時に br-external を有効化しようとしてコケるからだ。

というわけで、 br-external は networking.service からは有効化されないように設定しよう。
(gemini) $ sudo cp -pi /etc/default/networking /etc/default/netwoking.orig
(gemini) $ sudo vi /etc/default/networking
--ココから
8行目付近
#EXCLUDE_INTERFACES=
↓(br-externalを指定)
EXCLUDE_INTERFACES=br-external
--ココまで

(gemini) $ sudo systemctl daemon-reload

networking.service は有効化しておこう。
(gemini) $ sudo systemctl enable networking.service
(gemini) $ sudo systemctl is-enabled networking.service

これで、再起動しても networking.service が failed になることは無いはずだ。
--2017/04/20追記ココまで--
--2017/04/20削除ココから--
これで再起動してみると…。再現した!というか、状況はもっと悪くて、vg-kvmがアクティベートされてない!?

なるほど、networking.serviceを無効にしたら停止や再起動で刺さったような状態になるのか…。
実際にaquariusで停止を実行しようとすると、cifsアンマウントやiSCSI領域のアンマウント前にOpenvSwitchが停止しているように見える。
cifsやiSCSIは、OpenvSwitchのネットワークを経由して接続している。これらの停止前にOpenvSwitchが停止してはマズいのだ。

しかし、networking.serviceを有効にすると、systemctlでFaild:1unitsになってしまう。
これはこれで問題だ。
どうすりゃいいんだろうか。

gfs2マウントについて(その1:自動マウント)」辺りと同じように、x-systemd.requiresを設定して対応するのではないだろうか?

ちょっと長いのと、調査に時間がかかるので、ここで一旦記事を切ろう。
--2017/04/20削除ココまで--

0 件のコメント:

コメントを投稿