デスクトップに再現する従来型ストレージ
はじめに
以下の記事の構築編です。
Windowsデスクトップ上 (VirtualBox) に従来型ストレージを構築していきます。
GCP編、AWS編の記事は以下にあります。
クラウドに再現する従来型ストレージ【GCP構築編】
クラウドに再現する従来型ストレージ【AWS構築編】
構成概要
以下のような構成で「star0001」というストレージを構築していきます。
スター?
中身が見えるストレージを目標に
see‐through array (シースルー アレイ)
という名前をつけました。
中心的な役割を果たすinitスクリプト名はSTARorbit (star orbit、星の軌道) です。
ソフトウェアはdnf (yumの後継パッケージ管理コマンド) で入手できる一般的なLinuxソフトウェアと100行未満の自前スクリプト (STARorbit) 1個から構成されます。
ストレージの構築
VirtualBox (バージョン6.1.50と7.0.142024.2.20追加
で動作確認) が既に使える状態からの手順です。
コマンド操作はコピー&ペーストができますので実際の手数はそれほど多くありません。
筆者のマシン環境は以下の通りです。
- Surface Pro 3
- Windows 10 Pro (64ビット)
- Intel Core i5-4300U CPU 1.90GHz 2コア 4スレッド
- 8GB RAM
1. コントローラ作成 (新規仮想マシン2台)
以下設定にて新規仮想マシンを1台作成します (2台目は後で複製します)。
項目 | 設定値 | 備考 |
---|---|---|
名前[1] | star0001-ctl1 | |
OSイメージ | Rocky-8.9-x86_64-minimal.iso | Download Rocky |
タイプ / バージョン | Linux / Red Hat (64-bit) | |
メモリーサイズ | 1,536MB | |
仮想ハードディスク | 10GB | |
プロセッサー | 2 CPU | |
ネットワーク - アダプター1 | ブリッジアダプターまたはNAT2024.2.20追加
|
準仮想化ネットワーク |
ネットワーク - アダプター2 | 内部ネットワーク | 準仮想化ネットワーク |
ブリッジアダプターを使わない構成 (アダプター1にNATを選択) の場合
ブリッジアダプターはVirtualBoxホストマシンと同じネットワークセグメントのIPアドレスを割り当てますが、都合が悪い場合 (典型例はVirtualBoxホストマシンが社内ネットワークに接続するPCの場合) はアダプター1にNATを選択し、以下の通りポートフォワーディングを設定します。
名前 | プロトコル | ホストポート | ゲストポート |
---|---|---|---|
SSH | TCP | 10022 | 22 |
ゲストマシンへの接続はlocalhostのホストポート (10022) を指定します。
仮想マシンを起動し、OSをインストールします (詳細な手順は省略)。
-
English (United States)
-
KeyboardにJapaneseを追加、
^
でEnglish (US)より優先 (Japaneseを一番上に) -
Time & DateはAsia / Tokyo
-
User Creationでrockyユーザ作成 (パスワードは任意のもの)
-
Make this user administrator
にチェックを入れます
-
-
Software SelectionはMinimal Installを指定
-
Network & Host NameではEthernet (enp0s3)のIPv6を無効化してからONにします
- Configure - IPv6 SettingsからMethodをDisabledにしてSaveします
- OFF → ONにします (IPアドレスが設定されConnectedになる)
-
Installation DestinationはCustom指定で非LVM構成にします
- Storage ConfigurationをCustomにしてDoneします
- LVMをStandard Partitionに変更、
Click here to create them automatically.
をクリック - 再度DoneするとSUMMARY OF CHANGESが出るのでAccept Changesをクリック
-
INSTALLATION SUMMARYが以下になっていることを確認し、Begin Installationをクリック
OSインストールの完了後、SSHから[2][3]rockyユーザログイン、sudo su -
コマンドでrootユーザにスイッチしてパッケージをアップデート、仮想マシンをシャットダウンします。
dnf update -y
sleep 30 && shutdown -h now
VirtualBoxマネージャー画面から作成したstar0001-ctl1を複製します。
電源オフ状態のstar0001-ctl1を右クリックしてクローン
します。
項目 | 設定値 |
---|---|
名前 | star0001-ctl2 |
MACアドレスのポリシー | すべてのネットワークアダプターでMACアドレスを生成 |
クローンのタイプ | すべてをクローン |
後でサーバ (作成するストレージを利用する) を立てる際にも使うので名前をinstance-1に指定してもう1台複製します。
ブリッジアダプターを使わない構成 (アダプター1にNATを選択) の場合
ポートフォワーディングの設定をホストポートが重複しないように変更します。
以下のようにstar0001-ctl2は20000番台、instance-1は30000番台とするとわかりやすいです。
star0001-ctl2
設定
名前 | プロトコル | ホストポート | ゲストポート |
---|---|---|---|
SSH | TCP | 20022 | 22 |
instance-1
設定 (SSHに加えHTTPが必要)
名前 | プロトコル | ホストポート | ゲストポート |
---|---|---|---|
SSH | TCP | 30022 | 22 |
HTTP | TCP | 30080 | 80 |
2. 共有ディスク作成・割り当て
VirtualBoxマネージャー画面のファイル
から仮想メディアマネージャー
を開いて仮想ハードディスクを2つ作成します。
項目 | 設定値 | 備考 |
---|---|---|
ファイルタイプ | VDI | |
可変 or 固定 | 固定サイズ | 可変では共有可能にできない |
ファイルの場所 | VirtualBox VMs\star0001\star0001-disk-1.vdi | 2つ目はstar0001-disk-2.vdi |
サイズ | 4GB |
作成したらタイプを通常から共有可能に変更します。
2台のコントローラ (star0001-ctl1、star0001-ctl2) に作成した共有ディスクを割り当てます。
コントローラ SATA
配下に追加します。
3-1. コントローラホスト名設定
2台のコントローラを起動し、SSHからrockyユーザログイン、sudo su -
コマンドでrootユーザにスイッチしてホスト名を設定します。
hostnamectl set-hostname "star0001-ctl1" # 任意の名前を指定する場合は書換え必要
exec bash # プロンプトにホスト名反映
hostnamectl set-hostname "star0001-ctl2" # 任意の名前を指定する場合は書換え必要
exec bash # プロンプトにホスト名反映
3-2. コントローラ共通設定 (両コントローラに実施)
コントローラ1,2で以下のコマンドを実行し、ネットワーク設定を行います。
## 変数設定
ARRAY_NAME="star0001" # 任意の筐体名を指定可
NODE1_ADDR="172.16.0.1" # 任意のアドレスを指定可 (コントローラ1)
NODE2_ADDR="172.16.0.2" # 任意のアドレスを指定可 (コントローラ2)
CIDR="24" # 任意のアドレスを指定可
## hosts設定
grep -qF "$ARRAY_NAME" /etc/hosts || {
NODE_BASENAME="$(uname -n | sed 's/\(.\+\).$/\1/g')"
echo $NODE1_ADDR ${NODE_BASENAME}1 >> /etc/hosts
echo $NODE2_ADDR ${NODE_BASENAME}2 >> /etc/hosts
}
## ネットワーク設定
NODE_ADDR=$(getent ahostsv4 $(uname -n) | head -1 | awk '{ print $1 }')
nmcli c mod enp0s8 ipv4.method manual ipv4.addresses ${NODE_ADDR}/${CIDR} \
ipv6.method disabled connection.autoconnect yes 802-3-ethernet.mtu 9000
nmcli c up enp0s8 ; nmcli c
コントローラ1,2で以下のコマンドを実行し、ソフトウェアインストール・設定を行います。
## パッケージインストール、アップデート
dnf -y install pcs pacemaker targetcli iscsi-initiator-utils \
sysstat vsftpd lvm2 rsyslog jq --enablerepo=ha
dnf update -y
## selinux無効 (2024.4.21追加)
grubby --update-kernel ALL --args selinux=0
## サービス起動設定
systemctl start vsftpd # ftpはSSH設定まで利用、enableしない
systemctl enable --now pcsd iscsid
systemctl disable --now target iscsi-onboot iscsi
systemctl --no-pager status pcsd iscsid target iscsi-onboot iscsi vsftpd
## firewall設定
firewall-cmd --permanent --add-service=high-availability
firewall-cmd --permanent --add-port=3260/tcp # iscsi target
firewall-cmd --reload
firewall-cmd --add-service=ftp # ftpはSSH設定まで利用、--permanentしない
## ユーザ、パスワード設定
echo hacluster | passwd --stdin hacluster
useradd -u 1979 alien && echo alien | passwd --stdin alien
## SSHサーバ設定 (rootログインを許可、rootのパスワードログインは不要)
sed -i 's/^PermitRootLogin no/PermitRootLogin yes/g' /etc/ssh/sshd_config
systemctl restart sshd
## LVM環境設定
FILTER='a|scsi-SATA_VBOX_.*|'
grep -qF "$FILTER" /etc/lvm/lvm.conf || {
sed -Ei -e 's/# system_id_source = "none"/system_id_source = "uname"/' \
-e "/# Run vgscan aft.+cache/a \ filter = [ \"$FILTER\", \"r|.*|\" ]" \
/etc/lvm/lvm.conf ; }
# STANDBYに見えるiSCSIデバイス拒否、failoverにてSTANDBY->ACTIVE昇格後に
# 不通のiSCSIデバイスを走査してSTARpool活性T.O.から切替失敗するのを防ぐ
echo '(=・ω・)ノ ぃょぅ'
コントローラ1,2で以下のコマンドを実行し、iSCSI target起動スクリプトの設定を行います。
## ファイル配置
cat << "__EOF__" > /etc/init.d/STARorbit # 2024.4.21コード修正
#!/bin/bash
# chkconfig: 345 99 1
# description: STAR iSCSI target control script
NODE_BASENAME="$(uname -n | sed 's/\(.\+\).$/\1/g')"
NODE_NUM="$(uname -n | sed 's/.\+\(.\)$/\1/g')"
PARTNER_NODE="${NODE_BASENAME}$(( 3 - $NODE_NUM ))"
test -f /etc/star/config && . /etc/star/config
is_active_node() { pcs resource status STARpool | egrep -q "Started +$(uname -n)"; }
start_as_active() {
iscsiadm -m node --logout
cp /etc/target/{saveconfig.json.active,saveconfig.json}
sed -i -e "s/node._tg_pt_gp/node${NODE_NUM}_tg_pt_gp/g" \
-e "s/\"tg_pt_gp_id\": [12]/\"tg_pt_gp_id\": ${NODE_NUM}/g" \
/etc/target/saveconfig.json
systemctl restart target
ssh -n -o ConnectTimeout=10 $PARTNER_NODE "/etc/init.d/STARorbit start" &
}
start_as_standby() {
for I in $(seq 120); do
is_active_node && break
# This function may run for up to 10 minutes, with the possibility of
# parallel switching to ACTIVE. If it detects ACTIVE, it exits.
pcs resource status STARorbit | egrep -q "Started +${PARTNER_NODE}" || \
{ sleep 5 ; continue ; }
iscsiadm -m discovery -t sendtargets -p $PARTNER_NODE
iscsiadm -m node --login
for ISCSI_HOST in $(ls -1 /sys/class/iscsi_host) ; do
echo '- - -' > /sys/class/scsi_host/$ISCSI_HOST/scan ; done
sleep 5 ; lsscsi | fgrep -q -e STAR-LUN -e STAR-HD140283 || continue
cp /etc/target/{saveconfig.json.standby,saveconfig.json}
sed -i -e "s/node._tg_pt_gp/node${NODE_NUM}_tg_pt_gp/g" \
-e "s/\"tg_pt_gp_id\": [12]/\"tg_pt_gp_id\": ${NODE_NUM}/g" \
/etc/target/saveconfig.json
if type jq >/dev/null 2>&1; then
jq '(.storage_objects[].alua_tpgs[] | select(.name | test("node._tg_pt_gp"))
| .alua_access_type) |=1' /etc/target/saveconfig.json \
| jq "(.storage_objects[].alua_tpgs[]
| select(.name | test(\"node._tg_pt_gp\")) | .alua_access_state) \
|=${STANDBY_NON_OPTIMIZED:-0}" > /etc/target/saveconfig.json.$$ \
&& mv /etc/target/{saveconfig.json.$$,saveconfig.json}; fi
systemctl start target
break
done
}
stop_as_active() {
ssh -n -o ConnectTimeout=10 $PARTNER_NODE "/etc/init.d/STARorbit stop"
systemctl stop target
}
stop_as_standby() { systemctl stop target ; }
start() {
echo -n "Starting STAR iSCSI target:"
is_active_node && start_as_active
is_active_node || start_as_standby
return 0
}
stop() {
echo -n "Stopping STAR iSCSI target:"
systemctl is-active target || return 0
is_active_node && stop_as_active
is_active_node || stop_as_standby
return 0
}
status() {
is_active_node || return 3
# STANDBY returns 'stopped' to avoid 2-nodes-active detection by Pacemaker.
systemctl status target
}
case $1 in
start) start ;;
stop) stop ;;
status) status ;;
esac
__EOF__
## パーミッション設定
chmod 755 /etc/init.d/STARorbit
## rc.local有効化と追記
grep -qF '/etc/init.d/STARorbit' /etc/rc.d/rc.local \
|| { echo "/etc/init.d/STARorbit start" >> /etc/rc.d/rc.local ; }
chmod 755 /etc/rc.d/rc.local
echo 'ヽ(^O^)ノ いらっしゃいませー'
4. SSH公開鍵認証設定
コントローラ1,2の順に以下のコマンドを実行し、SSHの公開鍵認証設定を実施します。
NODE_BASENAME="$(uname -n | sed 's/\(.\+\).$/\1/g')"
NODE_NUM="$(uname -n | sed 's/.\+\(.\)$/\1/g')"
PARTNER_NODE="${NODE_BASENAME}$(( 3 - $NODE_NUM ))"
test -f /root/.ssh/id_rsa || {
if [ $NODE_NUM -eq 1 ]; then
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa # 公開鍵作成 (両ノード共通)
## 鍵転送 (コントローラ2に向けて)
curl -T "/root/.ssh/{id_rsa.pub,id_rsa}" -u alien:alien ftp://${PARTNER_NODE}/
# コントローラ2を再起動した場合にはvsftpdが起動していません
# 先に`systemctl start vsftpd ; firewall-cmd --add-service=ftp`が必要です
else
## 鍵配置 (コントローラ1から転送されたもの)
test -d /root/.ssh || { mkdir /root/.ssh ; chmod 700 /root/.ssh ; }
mv /home/alien/{id_rsa.pub,id_rsa} /root/.ssh
chown root:root /root/.ssh/{id_rsa.pub,id_rsa}
chmod 600 /root/.ssh/id_rsa
fi
cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys # ログイン許可
echo '( ´ー`)フゥー...'
}
コントローラ1,2で以下のコマンドを実行し、SSH動作確認をします。
ssh -n -o StrictHostKeyChecking=no $PARTNER_NODE "date ; uname -n"
# 表示例 (初回は`Warning: Permanently added ...`が出ます):
# Sun Oct 15 12:37:27 JST 2023
# star0001-ctl2
echo '∩( ・ω・)∩'
5. ストレージプール、LUN作成
コントローラ1 (star0001-ctl1) にログイン、sudo su -
コマンドでrootユーザになります。
コントローラ1で以下のコマンドを実行し、ストレージプール、LUN作成を実施します。
POOL_NAME="STARpool"
DIR="/etc/star" ; mkdir -p $DIR
LUN_SIZE="1024M"
NODE_NUM="$(uname -n | sed 's/.\+\(.\)$/\1/g')"
if [ $NODE_NUM -eq 1 ]; then
vgs -q "$POOL_NAME" || {
## ストレージプール (Volume Group) 作成
for disk in $(pvs --all | grep -v '\-part[1-9]' | awk '/dev/{ print $1 }'); do
pvcreate $disk ; done
vgcreate --setautoactivation n $POOL_NAME $(pvs | awk '/dev/{ print $1 }')
vgs -o+systemid ; pvs --all
lvcreate -n HD140283 -l 1 $POOL_NAME
# Pacemakerで制御するにあたりLogical Volumeが0個になる状況を避けるため
## LUN (Logical Volume) 作成
for I in $(seq 0 5); do
LUN_NAME="LUN${I}" ; LUN_WWN="$(uuidgen)"
lvcreate -n $LUN_NAME -L $LUN_SIZE $POOL_NAME
echo "$LUN_NAME $LUN_WWN $LUN_SIZE" >> $DIR/lunlist
done
}
echo '>゜)))彡 サカナ'
else
echo '(#゚Д゚) ゴルァ!!' # 誤ってコントローラ2で実行した場合
fi
6. iSCSIターゲット設定
コントローラ1 (star0001-ctl1) にログイン、sudo su -
コマンドでrootユーザになります。
コントローラ1で以下のコマンドを実行し、iSCSIターゲット設定を実施します。
## 変数設定
ARRAY_NAME="star0001" # 任意の筐体名を指定可
DIR="/etc/star"
ARRAY_VERSION="0.5"
STANDBY_NON_OPTIMIZED=0
NUM_HOSTS=2
NODE_BASENAME="$(uname -n | sed 's/\(.\+\).$/\1/g')"
NODE_NUM="$(uname -n | sed 's/.\+\(.\)$/\1/g')"
PARTNER_NODE="${NODE_BASENAME}$(( 3 - $NODE_NUM ))"
if [ $NODE_NUM -eq 1 ]; then
test -f /etc/target/saveconfig.json.active || {
## 筐体情報作成
echo $ARRAY_NAME > $DIR/starname
echo $ARRAY_VERSION > $DIR/version
echo "STANDBY_NON_OPTIMIZED=${STANDBY_NON_OPTIMIZED}" > $DIR/config
## iSCSIターゲット設定 (ACTIVEコントローラ用)
ARRAY_IQN=iqn.2023-09.test.use.only:${ARRAY_NAME}-target
targetcli /iscsi create $ARRAY_IQN
while read LUN_INFO ; do
LUN_NAME="$(echo $LUN_INFO | awk '{ print $1 }')"
LUN_WWN="$(echo $LUN_INFO | awk '{ print $2 }')"
targetcli /backstores/block create name=STAR-${LUN_NAME} \
dev=/dev/STARpool/$LUN_NAME wwn=${LUN_WWN}
targetcli /backstores/block/STAR-${LUN_NAME}/alua \
create node${NODE_NUM}_tg_pt_gp ${NODE_NUM}
targetcli /iscsi/$ARRAY_IQN/tpg1/luns create /backstores/block/STAR-${LUN_NAME}
done < $DIR/lunlist
for lunN in \
$(targetcli ls /iscsi/$ARRAY_IQN/tpg1/luns 1 | awk '/STAR/{ print $2 }') ; do
targetcli /iscsi/$ARRAY_IQN/tpg1/luns/$lunN \
set alua alua_tg_pt_gp_name=node${NODE_NUM}_tg_pt_gp ; done
for I in $(seq $NUM_HOSTS); do
HOST_NAME="Host_${I}"
HOST_IQN="iqn.2023-09.com.example:host${I}-initiator"
echo "$HOST_NAME $HOST_IQN LUN0,LUN1,LUN2,LUN3,LUN4,LUN5" >> $DIR/hostlist
targetcli /iscsi/$ARRAY_IQN/tpg1/acls create $HOST_IQN
done
targetcli /iscsi/$ARRAY_IQN/tpg1/acls \
create iqn.2023-09.test.use.only:${ARRAY_NAME}-initiator
targetcli saveconfig /etc/target/saveconfig.json.active
## コントローラ2に構成情報を転送
ssh -n $PARTNER_NODE "mkdir -p $DIR"
scp $DIR/* ${PARTNER_NODE}:${DIR}
scp /etc/target/saveconfig.json.active ${PARTNER_NODE}:/etc/target
## iSCSIイニシエータ設定 (コントローラ間iSCSIアクセス用)
echo InitiatorName=iqn.2023-09.test.use.only:${ARRAY_NAME}-initiator \
> /etc/iscsi/initiatorname.iscsi
systemctl restart iscsid
}
echo '▼・ェ・▼'
else
echo '(#゚Д゚) ゴルァ!!' # 誤ってコントローラ2で実行した場合
fi
コントローラ2 (star0001-ctl2) にログイン、sudo su -
コマンドでrootユーザになります。
コントローラ2で以下のコマンドを実行し、iSCSIターゲット設定を実施します。
DIR="/etc/star"
ARRAY_NAME=$(cat $DIR/starname)
NODE_BASENAME="$(uname -n | sed 's/\(.\+\).$/\1/g')"
NODE_NUM="$(uname -n | sed 's/.\+\(.\)$/\1/g')"
PARTNER_NODE="${NODE_BASENAME}$(( 3 - $NODE_NUM ))"
if [ $NODE_NUM -eq 2 ]; then
test -f /etc/target/saveconfig.json.standby || {
## iSCSIイニシエータ設定 (コントローラ間iSCSIアクセス用)
echo InitiatorName=iqn.2023-09.test.use.only:${ARRAY_NAME}-initiator \
> /etc/iscsi/initiatorname.iscsi
systemctl restart iscsid
## LUN認識
iscsiadm -m discovery -t sendtargets -p $PARTNER_NODE
iscsiadm -m node -o show ; iscsiadm -m node --login
iscsiadm -m session -o show
sleep 10 ; lsscsi
## iSCSIターゲット設定 (STANDBYコントローラ用)
ARRAY_IQN=iqn.2023-09.test.use.only:${ARRAY_NAME}-target
targetcli /iscsi create $ARRAY_IQN
while read LUN_INFO ; do
LUN_NAME="$(echo $LUN_INFO | awk '{ print $1 }')"
LUN_WWN="$(echo $LUN_INFO | awk '{ print $2 }')"
targetcli /backstores/block create name=STAR-${LUN_NAME} \
dev=/dev/disk/by-id/scsi-36001405$(echo ${LUN_WWN//-/} | cut -c 1-25) \
wwn=${LUN_WWN}
targetcli /backstores/block/STAR-${LUN_NAME}/alua \
create node${NODE_NUM}_tg_pt_gp ${NODE_NUM}
targetcli /iscsi/$ARRAY_IQN/tpg1/luns create /backstores/block/STAR-${LUN_NAME}
done < $DIR/lunlist
for lunN in \
$(targetcli ls /iscsi/$ARRAY_IQN/tpg1/luns 1 | awk '/STAR/{ print $2 }') ; do
targetcli /iscsi/$ARRAY_IQN/tpg1/luns/$lunN \
set alua alua_tg_pt_gp_name=node${NODE_NUM}_tg_pt_gp ; done
for HOST_IQN in $(cat $DIR/hostlist | awk '{ print $2 }'); do
targetcli /iscsi/$ARRAY_IQN/tpg1/acls create $HOST_IQN ; done
targetcli saveconfig /etc/target/saveconfig.json.standby
## コントローラ1に構成情報を転送
scp /etc/target/saveconfig.json.standby ${PARTNER_NODE}:/etc/target
}
echo '( ゚Д゚).。oO(もうひと息)'
else
echo '(#゚Д゚) ゴルァ!!' # 誤ってコントローラ1で実行した場合
fi
7. クラスタ構築
コントローラ1 (star0001-ctl1) にログイン、sudo su -
コマンドでrootユーザになります。
コントローラ1で以下のコマンドを実行し、クラスタ構築を実施します。
DIR="/etc/star"
ARRAY_NAME=$(cat $DIR/starname)
POOL_NAME="STARpool"
NODE_NAME=`uname -n`
NODE_BASENAME="$(uname -n | sed 's/\(.\+\).$/\1/g')"
NODE_NUM="$(uname -n | sed 's/.\+\(.\)$/\1/g')"
PARTNER_NODE="${NODE_BASENAME}$(( 3 - $NODE_NUM ))"
if [ $NODE_NUM -eq 1 ]; then
## クラスタ作成
NODE_ADDR=`getent ahostsv4 ${NODE_NAME} | head -1 | awk '{ print $1 }'`
PARTNER_ADDR=`getent ahostsv4 ${PARTNER_NODE} | head -1 | awk '{ print $1 }'`
pcs host auth ${NODE_NAME} addr=${NODE_ADDR} ${PARTNER_NODE} \
addr=${PARTNER_ADDR} -u hacluster -p hacluster
pcs cluster setup ${ARRAY_NAME} ${NODE_NAME} addr=${NODE_ADDR} \
${PARTNER_NODE} addr=${PARTNER_ADDR}
## クラスタ起動
pcs cluster start --all ; pcs cluster enable --all
pcs cluster status ; pcs status corosync
## STONITH無効化 (スプリットブレインでデータ破壊の可能性!!実験用のため)
pcs property set stonith-enabled=false no-quorum-policy=ignore
pcs property
## リソース作成
pcs resource create ${POOL_NAME} ocf:heartbeat:LVM-activate \
vgname=${POOL_NAME} vg_access_mode=system_id --group star_group
pcs resource create STARorbit lsb:STARorbit --group star_group \
op monitor enabled=false force-reload timeout=60 restart timeout=60 \
start timeout=60 stop timeout=60
sleep 60 ; pcs status
echo 'キタ━(゚∀゚)━!!'
else
echo '(#゚Д゚) ゴルァ!!' # 誤ってコントローラ2で実行した場合
fi
8. 1台ずつコントローラリブート (クラスタ動作確認)
コントローラ2→コントローラ1の順で1台ずつリブートします。
1台リブートしたらpcs status
コマンドの出力のNode Listが2台ともOnlineになるまで待ってから2台目をリブートします。
Node List:
* Online: [ star0001-ctl1 ]
* OFFLINE: [ star0001-ctl2 ]
Node List:
* Online: [ star0001-ctl1 star0001-ctl2 ]
サーバの構築
1. サーバ作成
instance-1として複製済のものをそのまま使うので作成は不要です。
2. サーバ設定
instance-1を起動し、SSHからrockyユーザログイン、sudo su -コマンドでrootユーザになります。
以下のコマンドを実行し、ネットワーク設定を行います。
## 変数設定
ARRAY_NAME="star0001" # star0001でない場合は書換え必要
NODE1_NAME="${ARRAY_NAME}-ctl1" # ctl1でない場合は書換え必要
NODE2_NAME="${ARRAY_NAME}-ctl2" # ctl2でない場合は書換え必要
NODE1_ADDR="172.16.0.1" # コントローラ1のアドレスを指定
NODE2_ADDR="172.16.0.2" # コントローラ2のアドレスを指定
SERVER_NAME="instance-1" # 任意のサーバ名を指定可
SERVER_ADDR="172.16.0.3" # 任意のアドレスを指定可
CIDR="24" # 任意のアドレスを指定可
## hosts設定
grep -qF "$ARRAY_NAME" /etc/hosts || {
echo $NODE1_ADDR $NODE1_NAME >> /etc/hosts
echo $NODE2_ADDR $NODE2_NAME >> /etc/hosts
}
## ネットワーク設定
nmcli c mod enp0s8 ipv4.method manual ipv4.addresses ${SERVER_ADDR}/${CIDR} \
ipv6.method disabled connection.autoconnect yes 802-3-ethernet.mtu 9000
nmcli c up enp0s8 ; nmcli c
## ホスト名設定
hostnamectl set-hostname $SERVER_NAME
exec bash # プロンプトにホスト名反映
echo '_〆(・_・。)^ カキカキ'
以下のコマンドを実行し、ソフトウェアインストール・設定を行います。
## 変数設定
ARRAY_NAME="star0001" # star0001でない場合は書換え必要
NODE1_NAME="${ARRAY_NAME}-ctl1" # ctl1でない場合は書換え必要
NODE2_NAME="${ARRAY_NAME}-ctl2" # ctl2でない場合は書換え必要
## タイムゾーン設定
timedatectl set-timezone Asia/Tokyo ; timedatectl
## パッケージインストール、アップデート
dnf -y install iscsi-initiator-utils device-mapper-multipath sysstat rsyslog
# minimalではsyslogが入らない
yum update -y
## selinux無効 (2024.4.21追加)
grubby --update-kernel ALL --args selinux=0
## iSCSIイニシエータ設定
echo InitiatorName=iqn.2023-09.com.example:host1-initiator \
> /etc/iscsi/initiatorname.iscsi
## multipath設定
mpathconf --enable --user_friendly_names y
cat << "__EOF__" >> /etc/multipath.conf
devices {
device {
vendor "LIO-ORG"
product "STAR-.+"
path_grouping_policy "group_by_prio"
path_selector "round-robin 0"
hardware_handler "1 alua"
prio "alua"
failback "immediate"
no_path_retry 10
detect_prio no
max_sectors_kb 256
}
}
__EOF__
systemctl restart multipathd
## ディスク認識
iscsiadm -m discovery -t sendtargets -p $NODE1_NAME
iscsiadm -m discovery -t sendtargets -p $NODE2_NAME
iscsiadm -m node -o show ; iscsiadm -m node --login
iscsiadm -m session -o show
sleep 10 ; lsscsi ; ll /dev/sd* /dev/disk/by-id
## マルチパス確認
multipath -ll
echo 'キタ━━(゚∀゚)━( ゚∀)━( ゚)━( )━( )━(・ )━(∀・ )━(・∀・)━イイ!!!!'
この段階で1度サーバリブートします。
ここまででサーバにストレージが見えましたので、ファイルシステムを作成する、読み書きをするなど試行することができます。
3. サーバ追加設定 (性能情報取得インターバル変更とWeb表示)
サーバにログイン、sudo su -
コマンドでrootユーザになります。
以下のコマンドを実行し、ブラウザからsarグラフが見えるように設定します。
## パッケージインストール
dnf -y install httpd expect firewalld
## digest認証設定
cat << "__EOF__" > /etc/httpd/conf.d/digest.conf
<Directory "/var/www/html/">
AuthType Digest
AuthName "milky way"
AUthUserFile "/etc/httpd/.htdigest"
Require valid-user
</Directory>
__EOF__
M=$(date '+%m') ; D=$(date '+%d')
X=$([ $((D % 2)) -eq 1 ] && echo "-" || echo "=") # 奇数日なら"-"、偶数日なら"="
expect -c "
spawn htdigest -c /etc/httpd/.htdigest \"milky way\" perfweb
expect \"New password:\"
send -- \"${M}Kinp@kU${D}${X}\n\"
expect \"Re-type new password:\"
send -- \"${M}Kinp@kU${D}${X}\n\"
wait"
systemctl enable --now httpd # apache起動
## sar記録インターバル変更 (30秒)
DIR="/etc/systemd/system/sysstat-collect.timer.d/"
mkdir -p $DIR
cat << "__EOF__" > $DIR/override.conf
[Timer]
OnCalendar=*:00/1
__EOF__
DIR="/etc/systemd/system/sysstat-collect.service.d/"
mkdir -p $DIR
cat << "__EOF__" > $DIR/override.conf
[Service]
Type=oneshot
User=root
ExecStart=/usr/lib64/sa/sa1 30 2
__EOF__
systemctl enable --now sysstat
systemctl daemon-reload
sleep 90 # データ生成待ち
## sarデータWeb化スクリプト配置・設定
cat << "__EOF__" > /usr/bin/perfweb
#!/bin/bash
DIR="/var/www/html"
METRIC=("disk" "cpu" "net")
OPTION=("-d -p" "-P ALL" "-n DEV")
INTERVAL=1
CMD="nice -n 10 sadf -Tg -O showinfo"
ENDTIME="$(date '+%H:%M')"
PREVDAY="$(date '+%d' -d '-1 day')"
sleep 3 ; cd $DIR || exit 1
draw_graph() {
STARTTIME="$(date -d "-${1} minutes" '+%H:%M')"
SADIR="/var/log/sa"
[ $2 -lt 30 ] && SADIR="/var/log/sa.short.5"
[ $2 -lt 5 ] && SADIR="/var/log/sa.short.1"
for I in $(seq 0 $(( ${#METRIC[@]} - 1 ))); do
if [ ${STARTTIME:0:2} -gt ${ENDTIME:0:2} ]; then
$CMD -s $STARTTIME -- ${OPTION[$I]} $2 $SADIR/sa$PREVDAY \
> ${METRIC[$I]}.${1}m.1.svg.$$
sleep $INTERVAL
$CMD -e $ENDTIME -- ${OPTION[$I]} $2 $SADIR > ${METRIC[$I]}.${1}m.2.svg.$$
rm -f ${METRIC[$I]}.${1}m.svg
else
$CMD -s $STARTTIME -e $ENDTIME -- ${OPTION[$I]} $2 $SADIR \
> ${METRIC[$I]}.${1}m.svg.$$
rm -f ${METRIC[$I]}.${1}m.{1,2}.svg
fi
rename .$$ '' *.svg.$$
sleep $INTERVAL
done
}
draw_graph 1 1 ; draw_graph 5 5 ; draw_graph 15 5 ; draw_graph 30 5
draw_graph 60 30 ; draw_graph 180 30 ; draw_graph 360 60
cat << _eof_ > index.html.$$
<html lang=en><title>$(uname -n) - perfweb</title><body>
<h2 style="background:#88ee88;padding:5px">$(uname -n)</h2>
<h2>Performance Statistics Graphs</h2>
<table border=1 cellpadding=3>
_eof_
for I in $(seq 0 $(( ${#METRIC[@]} - 1 ))); do
echo '<td>'
for SVG in $(ls -1 ${METRIC[$I]}.*.svg | sort -t . -k 1,1 -k 2n); do
echo "<a href=${SVG} target=_blank>${SVG}</a><br>" ; done
echo '</td>'
done >> index.html.$$
echo "</table><br>Last Updated on $(date)</body></html>" >> index.html.$$
mv index.html.$$ index.html
exit 0
__EOF__
chmod 700 /usr/bin/perfweb
mkdir /var/log/sa.short.{1,5} # 1秒、5秒間隔のsar取得ディレクトリ作成
## cronに1秒、5秒間隔のsar取得とsarデータWeb化スクリプト登録
cat << "__EOF__" > /var/spool/cron/root
MAILTO=""
S1=/var/log/sa.short.1
S5=/var/log/sa.short.5
* * * * * cd $S1 && sar -o sa$(date +\%d\%H\%M) 1 60 >/dev/null
* * * * * cd $S1 && ln -sf sa$(date +\%d\%H\%M -d '-1 min') sa$(date +\%d)
* * * * * cd $S5 && sar -o sa$(date +\%d\%H00) 5 12 >/dev/null
* * * * * cd $S5 && ln -s sa$(date +\%d\%H00) sa$(date +\%d) 2>/dev/null
* 1-23 * * * cd $S5 && sar -o sa$(date +\%d\%H30 -d '-30 min') 5 12 >/dev/null
0,30 1-23 * * * cd $S5 && ln -sf sa$(date +\%d\%H\%M -d '-30 min') sa$(date +\%d)
* * * * * find $S1 $S5 -xtype l -delete -o -type f -name 'sa*' -mmin +30 -delete
* * * * * /usr/bin/perfweb
__EOF__
chmod 600 /var/spool/cron/root
systemctl reload crond
sleep 90 # データ生成待ち
## firewalld起動・設定
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
echo -e "Username: perfweb\nPassword: ${M}Kinp@kU${D}${X}"
echo '(。・ω・)ノ゙ ありがとう'
enp0s3のアドレスにブラウザで接続 (http://アドレス
) [4]します。
認証ダイアログが出るのでユーザ名とパスワードを入力してログインします。
- ユーザ名は
perfweb
です - パスワードは
3. サーバ追加設定
を実施した日付によって変化します- パスワードは
2桁月
+Kinp@kU
+2桁日
+-
または=
です-
Kinp@kU
は「金箔」のローマ字を一部変更、末尾は奇数日が-
で偶数日が=
です - 例えば2月29日の場合には
02Kinp@kU29-
、2月28日の場合には02Kinp@kU28=
です
-
- パスワードは
ログインすると、sarをSVG形式にグラフ化したファイルへのリンクページが表示されます。
クリックするとグラフ化されたsarが表示されます[5]。
例えば以下のグラフ (disk.15m.svg) はI/O負荷を入れながら動かしたものです。
サーバから見たI/O状況 (mpathf)
170 IOPS程度しか出ないのはTTLがクラウド環境に比べ大きい[6]ことが影響しているようです。
クラウド環境とのTTL差異
VirtualBox環境は以下の通り、クラウド環境 (後述) のTTLに比べると大きいです。
[root@instance-1 ~]# ping -c 60 star0001-ctl1
PING star0001-ctl1 (172.16.0.1) 56(84) bytes of data.
64 bytes from star0001-ctl1 (172.16.0.1): icmp_seq=1 ttl=64 time=3.78 ms
64 bytes from star0001-ctl1 (172.16.0.1): icmp_seq=2 ttl=64 time=2.71 ms
(省略)
64 bytes from star0001-ctl1 (172.16.0.1): icmp_seq=60 ttl=64 time=3.36 ms
--- star0001-ctl1 ping statistics ---
60 packets transmitted, 60 received, 0% packet loss, time 59475ms
rtt min/avg/max/mdev = 0.972/2.007/7.301/1.138 ms
[root@instance-1 ~]#
クラウド (GCP) 環境では以下の通り、非常にTTLは小さいです。
[root@instance-1 ~]# ping -c 60 star0001-ctl1
PING star0001-ctl1.us-XXXXX (10.128.0.27) 56(84) bytes of data.
64 bytes from star0001-ctl1.us-XXXXX (10.128.0.27): icmp_seq=1 ttl=64 time=0.773 ms
64 bytes from star0001-ctl1.us-XXXXX (10.128.0.27): icmp_seq=2 ttl=64 time=0.247 ms
(省略)
64 bytes from star0001-ctl1.us-XXXXX (10.128.0.27): icmp_seq=60 ttl=64 time=0.247 ms
--- star0001-ctl1.us-XXXXX ping statistics ---
60 packets transmitted, 60 received, 0% packet loss, time 60427ms
rtt min/avg/max/mdev = 0.216/0.262/0.773/0.070 ms
[root@instance-1 ~]#
I/O負荷は以下コマンドで入れています。
while :
do
dd if=/dev/zero of=/dev/mapper/mpathf bs=8192 oflag=direct
done
あとがき
今回作成したストレージを初期構成から変更するツールの導入は別記事を参照下さい。通常ストレージ製品には固有のコマンドやWebツールが提供されており、それらを利用して変更をします。
また、このストレージはRAIDを構成していませんが、LVMでのRAIDやmdadm (ソフトウェアRAID) をPacemakerで管理することでこれも実現できると思います (未検証)。
-
名前は任意のものでも構いませんが末尾は1台目「1」、2台目「2」とする必要があり、また、末尾の直前までは2台で全く同じである必要があります ↩︎
-
SSHログインのためのIPアドレスはVirtualBoxウィンドウから一度ログインして
ip addr show
コマンドで確認します (enp0s3デバイス) ↩︎ -
ブリッジアダプターを使わない構成 (アダプター1にNATを選択) の場合のゲストマシンへの接続はlocalhostのポートフォワーディング設定したホストポート (例:10022) を指定します ↩︎
-
ブリッジアダプターを使わない構成 (アダプター1にNATを選択) の場合は
http://localhost:30080
を指定します ↩︎ -
日付をまたぐ期間は日付をまたぐ前後の2つのファイルが生成されます、例えば0時20分時点での
*.30m.svg
は前日分*.30m.1.svg
、当日分*.30m.2.svg
が生成されます ↩︎ -
Windows上のVirualBoxにおける一般的な特性ではなく、筆者のマシン環境 (
VirtualBox 6.1.50
) における結果です ↩︎
Discussion