KSMの実行可否
仮想化ホスト側で使用しているKSMだが、仮想化ゲスト側で使うべきなのかはいまいち確証が持てなかった。
が、今日KSMの起動用Systemd Unitを見直していたら下記の記述があった。
ConditionVirtualization=no
これは仮想化環境と言う事が検出されたら実行しないと言う事らしいので、SUSEの見解としては仮想化環境では使わないことを想定していると考えられる。
とりあえずホスト側でのみ実行中。
しかし、本当にsystemd多機能だな…
Intel SpeedShift
と言う訳で、Linuxが対応していなくて動いていないと思っていたIntel SpeedShiftはちゃんと動いていたっぽい。
【笠原一輝のユビキタス情報局】Skylakeの“SpeedShift”でPステートの消費電力削減を実現 ~Windows 10とSkylakeでさらなる長時間バッテリ駆動が可能に - PC Watch
ソフト制御の代わりに、ダイ内のコントローラ(PCU)が負荷状態を監視して制御する。
有効になっているかは起動時のメッセージで判別可能。
koke@koke-vm-server:~> dmesg | grep pstate
[ 3.831554] intel_pstate: Intel P-state driver initializing
[ 3.831855] intel_pstate: HWP enabled
HWPというのが、HardWare controlled P-Stateの略で、P-stateがハードウェアによってコントロールされていることを示している。
cpupower monitorで見るとC10(ほとんどの部分の電源まで遮断)まで落ちているので、ちゃんと動作している様子。
VM起動監視サービス
仮想化ホスト側の監視スクリプトを整理した。
pingによる生存確認とか、systemd-notifyによる起動完了通知なども入れて、タイミング調整のためにそこら中に入れていたsleepはほとんど居なくなった。
systemd timerを使えば無限ループじゃなくてone shotの塊として書くこともできそうだけど、とりあえず完成。
監視部本体
#!/bin/bash # Must be root if test "`/usr/bin/id -u`" != 0 ; then echo "$0: You must be root to run this script" >& 2 exit 1 fi # Must be give domain name & address [ ${#} -ne 2 ] && exit 1 POLLING_SLEEPTIME=120 source /usr/local/sbin/vm-boot-halt #echo $1 #echo $2 domain=${1} address=${2} exit_service () { wait_halt_vm ${domain} ${address} force_halt_vm ${domain} ${address} } trap "exit_service" EXIT exit_service #terminate existing VMs while true do # domain address wait_boot_vm ${domain} ${address} systemd-notify --ready sleep $POLLING_SLEEPTIME done
共通部分(関数定義)
#!/bin/bash BOOT_TIMEOUT_COUNT=300 #same as sec HALT_TIMEOUT_COUNT=300 #same as sec #N_("no state"), #N_("running"), #N_("idle"), #N_("paused"), #N_("in shutdown"), #N_("shut off"), #N_("crashed"), #N_("pmsuspended") export LANG=C boot_vm () { state=`virsh domstate ${1}` rc=${?} [ ${rc} -ne 0 ] && exit ${rc} case ${state} in "no state") echo "no state" rc=1;; "running") rc=0;; "idle") rc=0;; "paused") virsh resume ${1} rc=${?};; "in shutdown") rc=0;; "shut off") virsh start ${1} rc=${?};; "crashed") virsh reset ${1} rc=${?};; "pmsuspended") virsh dompmwakeup ${1} rc=${?};; *) echo "illegal state" rc=1 esac [ ${rc} -ne 0 ] && exit ${rc} } wait_boot_vm() { flag=1 for i in `seq 0 ${BOOT_TIMEOUT_COUNT}` do boot_vm ${1} ping -c 1 ${2} > /dev/null rc=${?} if [ ${rc} -eq 0 ]; then flag=0 #echo "booted" break fi done [ ${flag} -ne 0 ] && exit ${flag} } halt_vm () { state=`virsh domstate ${1}` rc=${?} [ ${rc} -ne 0 ] && exit ${rc} case ${state} in "no state") echo "no state" rc=1;; "running") virsh shutdown ${1} rc=${?};; "idle") virsh shutdown ${1} rc=${?};; "paused") virsh resume ${1} rc=${?} virsh shutdown ${1} rc=${rc}+${?};; "in shutdown") rc=0;; "shut off") rc=0;; "crashed") virsh destroy ${1} rc=${?};; "pmsuspended") virsh dompmwakeup ${1} rc=${?} virsh shutdown ${1} rc=${rc}+${?};; *) echo "illegal state" rc=1 esac [ ${rc} -ne 0 ] && exit ${rc} } force_halt_vm () { state=`virsh domstate ${1}` rc=${?} [ ${rc} -ne 0 ] && exit ${rc} case ${state} in "no state") echo "no state" rc=1;; "running") virsh destroy ${1} rc=${?};; "idle") virsh destroy ${1} rc=${?};; "paused") virsh resume ${1} rc=${?} virsh destroy ${1} rc=${rc}+${?};; "in shutdown") virsh destroy ${1} rc=${?};; "shut off") echo "no destroy" rc=0;; "crashed") virsh destroy ${1} rc=${?};; "pmsuspended") virsh dompmwakeup ${1} rc=${?} virsh destroy ${1} rc=${rc}+${?};; *) echo "illegal state" rc=1 esac [ ${rc} -ne 0 ] && exit ${rc} } wait_halt_vm() { flag=1 for i in `seq 0 ${HALT_TIMEOUT_COUNT}` do halt_vm ${1} ping -c 1 ${2} > /dev/null rc=${?} if [ ${rc} -ne 0 ]; then flag=0 echo "safe halted" break fi sleep 1 done [ ${flag} -ne 0 ] && exit ${flag} }
本体のバリエーションが1つのみになったので、分ける必要はなかった気もする。
最後にsystemd unit
[Unit] Description=KVM SUSE Tumbleweed ssh server startup After=network.target libvirt-guests.service libvirtd.service vm-router.service Requires=network.target libvirt-guests.service libvirtd.service [Service] ExecStart=/usr/local/sbin/vm-heartbeat-service tw-ssh-server 192.168.1.200 ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure Type=notify [Install] WantedBy=multi-user.target
Typeをnotifyにして依存関係待ち合わせをsystemdに解決させるようにした。
仮想化サーバーで自分で作った部分はここだけなので、新規構築用の備忘録。
tuned停止
有効にしていたtunedデーモンだが、結局停止した。
virtual-hostが継承しているthroughput-performanceはCPUクロック下限を最大周波数にする(min_perf_pct=100)オプションが付いていて、DVFSが利かなくなる。
スループット最大化が目的なので、やってることは正しいのだがそこまで必要ないので無効化。
というか、cpu governorの設定にintel_pstateドライバだと使えないconservativeとか書いてあったり、rhel6と書いてあったり微妙に古い?
無効化した後、カーネルのデフォルト設定にしたらDVFSが有効になってちゃんと制御されている模様。
OPNsenseでDynamic DNS
自宅サーバーのDynamic DNSにieserver.netを使わせていただいているが、NECのルーターを使っていた時にルーターで設定できなかった(対応サービスに存在しなかった)ので、クライアントのWindows上でDiCEを使っていた。
Windows10でも特に問題なく動いていたが、Windows機の電源が切れているときにIPアドレスが変わると繋がらなくなるのは流石にアレなので、仮想化ルーターに合わせて仮想化ルーター側に移動した。
OPNsenseもieserverのGnuDIPには対応していないっぽいので、別の方法を検討した。
便利ツールのページにperlスクリプトがあるので、これを適当な仮想マシンでCronで動かせばいいか…と思っていたが、よくよく見るとほとんどはIPアドレスの変化を監視する部分で、DNSエントリの更新はwget1コマンドでできるっぽい。
以下に処理部分を引用。
$STATUS = `wget -q -O - '$DDNS_UPDATE?username=$ACCOUNT&domain=$DOMAIN&password=$PASSWORD&updatehost=1'`;
どうも、このURLにアクセスするとアクセス元のIPアドレスを新しいアドレスとして認識するという仕組みらしい。
OPNsenseのDynamic DNSにはCustomというタイプがあり、これは特定のインターフェースを監視して、IPアドレスが変化したら指定されたURLにアクセスするという動作をするので、上記のURLを指定してやればよい。
しばらく使ってみたが、再起動時でIPアドレスが変化したときなども追従するので大丈夫だと判断した。
本当は上記でもやっているように戻り値をチェックするべきだとは思う。
OPNsense+virtio
pfSenseの時から、"仮想化したLinuxでNICにvirtioを選ぶと通信が失敗する"、"iTunesの通信がよく失敗する"、"添付ファイル付きメールが送れない"、”Windows Updateがたまに失敗する"、"内側(dmz)側のルーターのネットワーク経由のアップデートができない"など微妙にイラっと来る問題が発生していた。
それぞれ毎回起こるわけでもなかったり、代替手段で何とかなったりしていたので、真剣に追わず、"仮想化モニタ側の問題で、今にアップデートで直るだろう"と思っていた。
本日、予期せず原因が見つかって直せたのでメモ。
OPNsenseのドキュメントを読んでいたら、仮想化環境にインストールした時の設定方法が書いてあった。
Virtual & Cloud based Installation — OPNsense documentation
まず、General TipsとしてネットワークアダプタのすべてのハードウェアオフロードオプションはOFFにせよと書いてあり、Xen上だがChecksum Offloadを無効化しないとNATに問題が出るとあった。
もしかして…と思い、標準で無効化されているTSOとLROに加え、CRCも無効化したのち、ルーターを再起動したところ上記の問題が直った。
完全に仮想化モニタ側だと思い込んでいて、ルーター側をあまり疑わなかったのが失敗だったかもしれない。
pfSenseでもほぼ同じことが起きており、ベースも同じFreeBSDなのでおそらく同じ原因だと思われる。
とりあえず、全仮想マシンのNICをvirtioに変更し、動作することを確認した。
virtioは準仮想化と呼ばれるもので、実ハードのエミュレーションの代わりに専用のドライバ+ハイパーバイザ側の対応によって都合のいいインターフェースを作る仕組み。
特権/非特権間のコンテキストスイッチとデータのコピーが減るので処理が軽くなるという仕組みらしい。
virtio: Linux の I/O 仮想化フレームワーク
今までもストレージデバイスにはvirtioを使っていたが、今回NICも置き換えた。
性能などは測っていないが、同じ条件で仮想化モニタのメモリ使用量が気持ち減った。
しばらく様子を見る。