2019年6月14日金曜日

ストレージプールのStart/Stopをリソース化

前回、gfs2マウントまでリソース化して、これで環境が整ったかと思ったんだけど、別の問題が発生した。
kvm/libvirt で default という名前がつけられたストレージプールが空っぽになってしまっている、という状態だ。
default というストレージプール、実際のパスは /var/lib/libvirt/images になっている。

そもそも、 /var/lib/libvirt 自体が外部ディスクで、今回の一連の作業でこの領域のマウント自体をクラスタ制御にした。

考えてみたら当たり前で、/var/lib/libvirt のマウントより先に、kvm/libvirt が起動する。kvm/libvirt では default ストレージプールは自動起動になっているため、/var/lib/libvirt がマウントされる前に default ストレージプールが起動してきて、中身が空っぽの /var/lib/libvirt/images を見て、空のストレージプールとして定義された、というわけだ。
(ウチの環境では、/var/lib/libvirt のマウント前に、/var/lib/libvirt/images というディレクトリが存在している。もし存在して無ければ、 default プールの自動起動に失敗し、default プールが停止していると思う。)

ストレージプールを start する作業を gfs2 ファイルシステムマウントの後に、stop する作業を gfs2 ファイルシステムマウントの前に実行する必要がある。

gfs2 マウントがクラスタリソースなので、ストレージプールの stop/start もクラスタリソースとして定義してしまうのがスマートだろう。

ということで、ストレージプールの start/stop をするリソースエージェントを探したのだが…見つからない。存在していないようだ。

ということは、リソースエージェントを自作する必要があるということだ。
面倒だが、この辺を参考に作っていくことにしよう。

まずは、リソースエージェントを配置するパス。
/usr/lib/ocf/resource.d/プロジェクト名/ に配置することになるらしい。他の環境と被って欲しくないので、プロジェクト名は kvmcluster にしよう。
$ sudo mkdir /usr/lib/ocf/resource.d/kvmcluster

そして、とりあえず以下のようにファイルを作成してみる。
$ sudo vi /usr/lib/ocf/resource.d/kvmcluster/virt-pool
-----ココから
#!/bin/bash
#
#   Resource Agent for libvirt storage pool resources.
#
#   License:      GNU General Public License (GPL)
#   Original
#
# Initialization:
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
virt_pool_meta_data() {
cat <<EOF
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="virt-pool">
  <version>0.1</version>
  <longdesc lang="en">
This is a resource agent to start / stop libvirt storage-pool.
  </longdesc>
  <shortdesc lang="en">start / stop storage-pool</shortdesc>
  <parameters>
    <parameter name="poolname" unique="0" required="1">
      <longdesc lang="en">
      Name of Storage pool
      </longdesc>
      <shortdesc lang="en">Pool Name</shortdesc>
      <content type="string"/>
    </parameter>
  </parameters>
  <actions>
    <action name="start"        timeout="20" />
    <action name="stop"         timeout="20" />
    <action name="monitor"      timeout="20"
                                interval="10" depth="0" />
    <action name="meta-data"    timeout="5" />
    <action name="validate-all"   timeout="20" />
  </actions>
</resource-agent>
EOF
}
virt_pool_usage() {
    return $OCF_SUCCESS
}
virt_pool_validate_all() {
    #check_binary virsh
    ocf_run -q virsh pool-info $OCF_RESKEY_poolname
    case "$?" in
        0)
            rc=$OCF_SUCCESS
            ocf_log debug "poolname is OK"
            ;;
        1)
            rc=$OCF_ERR_CONFIGURED
            ocf_log err "No pool"
            ;;
    esac
}
virt_pool_monitor() {
    local rc
    # 設定が不正な場合は即終了する
    virt_pool_validate_all || exit $?
    virsh pool-info $OCF_RESKEY_poolname | grep State: | grep running > /dev/null 2>&1
    # 0: pool-start済
    # 1: pool-stop済
    # それ以外: エラー
    case "$?" in
        0)
            rc=$OCF_SUCCESS
            ocf_log debug "Resource is running"
            ;;
        1)
            rc=$OCF_NOT_RUNNING
            ocf_log debug "Resource is not running"
            ;;
        *)
            ocf_log err "Resource has failed"
            exit $OCF_ERR_GENERIC
    esac
    return $rc
}
virt_pool_stop() {
    ocf_run -q virsh pool-destroy $OCF_RESKEY_poolname
    return $OCF_SUCCESS
}
virt_pool_start() {
    ocf_run -q virsh pool-start $OCF_RESKEY_poolname
    return $OCF_SUCCESS
}
case $__OCF_ACTION in
meta-data)      virt_pool_meta_data
                exit $OCF_SUCCESS
                ;;
usage|help)     virt_pool_usage
                exit $OCF_SUCCESS
                ;;
esac
virt_pool_validate_all || exit $?
case $__OCF_ACTION in
start)          virt_pool_start;;
stop)           virt_pool_stop;;
status|monitor) virt_pool_monitor;;
validate-all)   virt_pool_validate_all;;
*)              virt_pool_usage
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
esac
rc=$?
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION returned $rc"
exit $rc
-----ココまで
必要最小限の機能だけ盛り込んだ。
エラーハンドリング等、甘い部分もあるが、とりあえずの実装なので良しとする。
正規のリソースエージェントがリリースされたら、それに移行すればいい。

作成したらパーミッション変更。
$ sudo chmod 755 /usr/lib/ocf/resource.d/kvmcluster/virt-pool

テスターがあるので実行してみる。
テストの時、実際にプールのStart/Stopが行われるので、default プールは止めておく。
また、合わせて default プールの自動起動も止めておく。(sagittarius/aquarius 両方やっておくのを忘れないように)
$ virsh pool-destroy default
$ virsh pool-autostart default --disable
$ virsh pool-list --all

そしたらテスター実行
$ sudo ocf-tester -n ocf:kvmcluster:virt-pool -o poolname=default /usr/lib/ocf/resource.d/kvmcluster/virt-pool
最後に
/usr/lib/ocf/resource.d/kvmcluster/virt-pool passed all tests
と出てきたらなんとか成功だ。
もしダメだったら、詳細表示状態でテスターを実行してみよう。もしかしたら何が悪いか分かるかも。
$ sudo ocf-tester -v -n ocf:kvmcluster:virt-pool -o poolname=default /usr/lib/ocf/resource.d/kvmcluster/virt-pool

さて、このリソースエージェントを使って、defaultプールの start/stop を作るのだが…認識されているかな?
$ sudo pcs resource list
どうやら出てきたようだ。

詳細は?
$ sudo pcs resource describe ocf:kvmcluster:virt-pool
出た。

じゃぁコレを使ってリソースを作ってみよう。
$ sudo pcs resource create pool-default ocf:kvmcluster:virt-pool \
  poolname=default \
  --clone \
  --disabled

$ sudo pcs resource show
pool-default-clone が定義されたはずだ。
ただ、今はまだ disabled のはず。

$ sudo pcs resource show pool-default-clone
詳細も見える。

リソースの前後関係・起動ノード関係を設定しておく。
$ sudo pcs constraint show --full
$ sudo pcs constraint order start shared-pool-clone then pool-default-clone
$ sudo pcs constraint colocation add pool-default-clone with shared-pool-clone
$ sudo pcs constraint show --full

設定できたらリソースを有効化してみよう。
$ virsh pool-list --all
$ sudo pcs status
$ sudo pcs resource enable pool-default
$ sudo pcs status
$ virsh pool-list --all
無事に defaultプール が起動してきたはず。
念のために中身も見てみよう。
$ virsh vol-list default
中身も見れる。

shared-pool-clone が落ちれば、pool-default-clone も落ちるはず。
$ sudo pcs status
$ sudo pcs resource disable shared-pool-clone
$ sudo pcs status
落ちた。
$ sudo pcs resource enable shared-pool-clone
$ sudo pcs status
上がった。

OS再起動等して、リソースが起動、プールが起動するところも確認しておこう。

問題が無ければ、このあたりで一度システムバックアップを取得しておこう。
1台ずつ、クラスタを停止してからバックアップを取るように。
$ sudo pcs cluster stop aquarius --force
$ sudo pcs status
(ここでaquariusをバックアップ)
$ sudo pcs cluster start aquarius
$ sudo pcs status
$ sudo pcs cluster stop sagittarius --force
$ sudo pcs status
(ここでsagittariusをバックアップ)
$ sudo pcs cluster start sagittarius
$ sudo pcs status

ふぅ。これでなんとかなったか?
あと少し、整理・調整したいので、もう少し続ける。

0 件のコメント:

コメントを投稿