3 台の KVM ホストのローカル ディスクで GlusterFS(レプリカ 3)を作り、その上でエンジンを仮想マシンとして動かす HCI(ハイパーコンバージド)構成の構築手順です。公式の手順どおり、Cockpit の Gluster ウィザードと Hosted Engine ウィザードで構築します。
Oracle のドキュメントでは、GlusterFS を使う HCI 構成は Oracle Linux 8 のホストでのみ利用でき、手順の順番は「GlusterFS → セルフホステッド エンジン → 残りの KVM ホスト」です。この検証では、現行のパッケージの組み合わせで公式手順どおりに進めると 3 か所で失敗しました。回避策を各手順の中に書いています。
この記事の前提
参照した公式ドキュメント
- Hyperconverged Infrastructure Deployment Using GlusterFS Storage(Oracle Linux Virtualization Manager Getting Started)
- Configure KVM Hosts for Gluster(同上)
- Deploy GlusterFS Storage Using Cockpit(同上)
- Deploy the Self-Hosted Engine(同上)
構成
| 項目 | 内容 |
|---|---|
| KVM ホスト | doc-olvm1〜3.olvmdoc.lab(192.168.1.142〜144)。Oracle Linux 8.10、4 vCPU、メモリー 20 GB |
| ディスク | sda 60 GB(OS)、sdb 200 GB(Gluster 用。パーティションなし) |
| 管理ネットワーク | ens18(ovirtmgmt)192.168.1.0/24 |
| ストレージ ネットワーク | bond0(ens21+ens22、active-backup)10.20.83.0/24。Gluster の通信とライブ マイグレーションに使います |
| Gluster 用のホスト名 | doc-olvm1〜3-gl.olvmdoc.lab(bond0 の IP アドレス) |
| セルフホステッド エンジン | doc-olvm-he.olvmdoc.lab(192.168.1.145)、4 vCPU、メモリー 8 GB |
| Gluster ボリューム | engine(エンジン用)、data(仮想マシン用)。どちらもレプリカ 3(3 台目はアービター) |
| 名前解決 | 全ホストとエンジンの /etc/hosts に、管理用と Gluster 用の FQDN を登録 |
| パッケージ | ovirt-engine-appliance-4.5-20260211、gluster-ansible-roles-1.0.5-28、ovirt-ansible-collection-3.2.0-1.29 |
アービターは、ファイルのメタデータだけを持つブリックです。3 台目にはデータの実体を置かないので、ディスクの容量を節約しながら、2 台の複製で起きるスプリット ブレイン(どちらが正しいか分からなくなる状態)を防げます。
ホストの準備(全ホスト)
各ホストで root で実行します。
(1) OLVM のリポジトリを有効にし、UEK の追加モジュールを入れて OS を最新にします。
dnf install oracle-ovirt-release-45-el8
dnf install kernel-uek-modules-extra
dnf update -y
(2) ストレージ ネットワークのボンドを作り、再起動します。
nmcli con add type bond con-name bond0 ifname bond0 bond.options mode=active-backup,miimon=100 ipv4.method manual ipv4.addresses 10.20.83.142/24 ipv6.method disabled
nmcli con add type ethernet con-name bond0-ens21 ifname ens21 master bond0
nmcli con add type ethernet con-name bond0-ens22 ifname ens22 master bond0
reboot
IP アドレスはホストごとに 10.20.83.142〜144 にします。
(3) Cockpit と Gluster のパッケージを入れ、Cockpit を有効にします。
dnf install cockpit-ovirt-dashboard ovirt-host vdsm-gluster
systemctl enable --now cockpit.socket
firewall-cmd --permanent --add-service cockpit
firewall-cmd --reload
(4) Gluster 用のディスク(sdb)にパーティションや LVM がないことを確認します。
lsblk /dev/sdb
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdb 8:16 0 200G 0 disk
展開ホストの準備(doc-olvm1)
(1) SSH の鍵を作り、自分自身とほかのホストに公開鍵を登録します。Gluster のウィザードは管理用と Gluster 用の両方のホスト名で SSH 接続するので、両方の名前で一度接続して known_hosts に登録しておきます。
ssh-keygen
ssh-copy-id doc-olvm1.olvmdoc.lab
ssh-copy-id doc-olvm2.olvmdoc.lab
ssh-copy-id doc-olvm3.olvmdoc.lab
ssh doc-olvm1-gl.olvmdoc.lab hostname # 2・3 も同様に。-gl の名前でも接続して確認
ln $HOME/.ssh/known_hosts $HOME/.known_hosts
(2) エンジンのアプライアンスと Gluster の Ansible ロールを入れます。
dnf install ovirt-engine-appliance gluster-ansible-roles
(3) 【回避策 1】json_query フィルターを追加します。OLVM の ovirt-ansible-collection(3.2.0-1.29)は jmespath を使わないように json_query フィルターを削除していますが、gluster-ansible-infra は ovirt.ovirt.json_query を使っているため、このままでは Gluster の展開が「Could not load “ovirt.ovirt.json_query”」で失敗します。
dnf install python3.11-jmespath
ln -s /usr/lib/python3.11/site-packages/jmespath /usr/lib/python3.12/site-packages/jmespath
cat > /usr/share/ansible/collections/ansible_collections/ovirt/ovirt/plugins/filter/json_query.py <<'EOF'
from ansible.errors import AnsibleError, AnsibleFilterError
try:
import jmespath
HAS_LIB = True
except ImportError:
HAS_LIB = False
def json_query(data, expr):
if not HAS_LIB:
raise AnsibleError('You need to install "jmespath" prior to running json_query filter')
try:
return jmespath.search(expr, data)
except jmespath.exceptions.JMESPathError as e:
raise AnsibleFilterError('JMESPathError in json_query filter plugin:\n%s' % e)
class FilterModule(object):
def filters(self):
return {'json_query': json_query}
EOF

上の画面は、回避策を入れずに展開して失敗したときのものです。失敗した場合は、回避策を入れてから [Redeploy] をクリックし、Review の画面に戻ったら、もう一度 [Deploy] をクリックします。
(4) 【回避策 2】エンジンのリポジトリ パッケージ名を変えます。現在のアプライアンス(20260211)の中身は Oracle Linux 9 ですが、展開の処理は oracle-ovirt-release-45-el8 を固定でインストールしようとして「No package oracle-ovirt-release-45-el8 available」で失敗します。ロールの既定値で el9 版を指定します。
sed -i 's|^he_oracle_ovirt_release_rpm_url: .*|he_oracle_ovirt_release_rpm_url: oracle-ovirt-release-45-el9|' \
/usr/share/ansible/collections/ansible_collections/ovirt/ovirt/roles/hosted_engine_setup/defaults/main.yml
(5) 【回避策 3】ホスト追加の競合を避けます。展開処理の「Add host」は、要求を投げた直後に認証トークンを失効させます。このため、処理の遅い環境では要求がエンジンに届く前にトークンが無効になり、エンジン側で「USER_IS_NOT_LOGGED_IN」となってホストが追加されません。その後の「Wait for the host to be up」は 20 分待ってから失敗します。/usr/share/ansible/collections/ansible_collections/ovirt/ovirt/roles/hosted_engine_setup/tasks/bootstrap_local_vm/05_add_host.yml の「Add host」タスク(async: 1、poll: 0)の直後に、30 秒待つタスクを追加します。
- name: Wait for the add host request to reach the engine (workaround)
ansible.builtin.pause:
seconds: 30
GlusterFS の展開(Cockpit)
(1) ブラウザーで https://doc-olvm1.olvmdoc.lab:9090 を開き、root でログインします。[Virtualization] → [Hosted Manager] を開き、[Hyperconverged] の [Start] をクリックします。

(2) [Run Gluster Wizard] をクリックします。

(3) [Hosts] で、各ホストの Gluster 用(Storage Network)と管理用(Public Network)の FQDN を入力し、[Next] をクリックします。

| 項目 | 説明 | 設定値 |
|---|---|---|
| Use same hostname for Storage and Public Network | ストレージと管理で同じネットワークを使う場合にオン | オフ(ストレージは bond0 に分ける) |
| Host1〜3 の上段(Storage Network FQDN) | Gluster の通信に使う名前 | doc-olvm1〜3-gl.olvmdoc.lab |
| Host1〜3 の下段(Public Network FQDN) | 管理用の名前 | doc-olvm1〜3.olvmdoc.lab |
(4) [Packages] は何も入力せずに [Next] をクリックします。

(5) [Volumes] で engine と data を残し(vmstore は右のごみ箱で削除)、両方の [Arbiter] をオンにして [Next] をクリックします。最初のボリューム(engine)がエンジン用になります。

(6) [Bricks] で [Raid Type] を JBOD にし、[Blacklist Gluster Devices] がオンであることを確認します。[Select Host] でホストを切り替えながら、各ホストの LV のサイズを入力します。

| 項目 | 説明 | 設定値 |
|---|---|---|
| Raid Type | ディスクの RAID 構成(ストライプの揃え方が変わる) | JBOD |
| Blacklist Gluster Devices | Gluster のディスクを dm-multipath の対象から外す | オン |
| engine の LV Size | engine ブリックのサイズ(シック プロビジョニング) | 100 GB(3 台目のアービターは自動で 20 GB) |
| data の LV Size | data ブリックのサイズ(シン プール上) | 80 GB(既定の 500 GB はディスクに入らないので変更) |
(7) [Review] で生成された Ansible のインベントリ(/etc/ansible/hc_wizard_inventory.yml)を確認し、[Deploy] をクリックします。

(8) 「Successfully deployed Gluster」と表示されれば完了です。この環境では約 5 分かかりました。[Continue to Hosted Engine Deployment] をクリックします。

ホストで確認すると、2 つのボリュームがレプリカ 3(2+アービター 1)で作られています。
gluster volume info data | grep -E "Type|Number of Bricks|Brick[0-9]"
Type: Replicate
Number of Bricks: 1 x (2 + 1) = 3
Brick1: doc-olvm1-gl.olvmdoc.lab:/gluster_bricks/data/data
Brick2: doc-olvm2-gl.olvmdoc.lab:/gluster_bricks/data/data
Brick3: doc-olvm3-gl.olvmdoc.lab:/gluster_bricks/data/data (arbiter)
セルフホステッド エンジンの展開
(1) [VM] でエンジンの仮想マシンの設定を入力します。

| 項目 | 説明 | 設定値 |
|---|---|---|
| Engine VM FQDN | エンジンの FQDN(ホストの FQDN とは別) | doc-olvm-he.olvmdoc.lab |
| Network Configuration | IP アドレスの設定方法 | Static |
| VM IP Address | エンジンの IP アドレスとプレフィックス長 | 192.168.1.145 / 24 |
| Gateway Address/DNS Servers | ゲートウェイと DNS | 192.168.1.1 |
| Bridge Interface | 管理ブリッジ(ovirtmgmt)を作る NIC | ens18 |
| Root Password | エンジン VM の root のパスワード | 任意 |
| Number of Virtual CPUs/Memory Size (MiB) | エンジン VM の CPU とメモリー | 4/8192(既定は 16384) |
プレフィックス長の欄の「24」は入力例(プレースホルダー)で、空のままだと「Required field」になります。数字を入力してください。
(2) [Advanced] を開き、設定を確認します。

| 項目 | 説明 | 設定値 |
|---|---|---|
| Edit Hosts File | エンジン VM とホストの /etc/hosts に互いの名前を追加する | オン |
| Network Test | ネットワークの確認方法(DNS・Ping・TCP・None) | Ping(この環境は DNS に登録していないため) |
(3) [Engine] で管理者(admin@internal)のパスワードを入力し、[Next] をクリックします。

(4) 設定を確認して [Prepare VM] をクリックします。ホストの中に一時的なエンジン VM(HostedEngineLocal)が作られ、エンジンがインストールされます。

【回避策 4】アプライアンス(Oracle Linux 9)の sshd は、cloud-init の設定では root のパスワード ログインが許可されず(sshd_config.d 側の設定が優先されるため)、展開処理が「Wait for the local VM」で最大 1 時間待ち続けます。この検証では、HostedEngineLocal のシリアル コンソール(ホストで
virsh console HostedEngineLocal)に root でログインし、次のコマンドで許可しました。
>
echo "PermitRootLogin yes" > /etc/ssh/sshd_config.d/00-permitrootlogin.conf; systemctl restart sshd
(5) 「Execution completed successfully」と表示されたら [Next] をクリックします。この環境では約 30 分かかりました。

(6) [Storage] には Gluster の engine ボリュームが自動で入力されています。[Advanced] の [Disk Size] はエンジン VM のディスクのサイズです。[Next] をクリックします。

| 項目 | 説明 | 設定値 |
|---|---|---|
| Storage Type | エンジン VM のディスクを置くストレージ | Gluster |
| Storage Connection | ボリュームの接続先 | doc-olvm1-gl.olvmdoc.lab:/engine |
| Mount Options | 1 台目に接続できないときに使うサーバー | backup-volfile-servers=doc-olvm2-gl.olvmdoc.lab:doc-olvm3-gl.olvmdoc.lab |
| Disk Size (GiB) | エンジン VM のディスク | 58(既定) |
(7) [Finish Deployment] をクリックします。エンジン VM が Gluster のボリュームに移されて起動します。

(8) 「Hosted engine deployment complete!」と表示されれば完了です。この環境では約 15 分かかりました。

(9) [Close] をクリックすると、Hosted Manager の画面にエンジンの状態が表示されます。

ホストでも状態を確認できます。
hosted-engine --vm-status
Hostname : doc-olvm1.olvmdoc.lab
Engine status : {"vm": "up", "health": "good", "detail": "Up"}
Score : 3400
残りのホストの追加
(1) エンジン VM の /etc/hosts に、残りのホストの名前を追加します(DNS がない場合)。
cat >> /etc/hosts <<'EOF'
192.168.1.143 doc-olvm2.olvmdoc.lab doc-olvm2
192.168.1.144 doc-olvm3.olvmdoc.lab doc-olvm3
EOF
(2) ブラウザーで https://doc-olvm-he.olvmdoc.lab/ovirt-engine/webadmin/ を開き、ユーザー名 admin、プロファイル internal でサインインします。

セルフホステッド エンジンでは、スタンドアロンのエンジンと違い、シングル サインオンに Keycloak を使わない従来の画面になりました。
(3) ダッシュボードでは、ホスト 1 台、データ ストレージ ドメイン 2 つ(hosted_storage と data)、Gluster ボリューム 2 つが登録されています。data ボリュームのストレージ ドメインも自動で作られています。

(4) [Compute] → [Hosts] で [New] をクリックし、[General] にホストの情報を入力します。

(5) [Hosted Engine] で [Deploy] を選び、[OK] をクリックします。電源管理の確認が出たら [OK] をクリックします。

| 項目 | 説明 | 設定値 |
|---|---|---|
| Choose hosted engine deployment action | Deploy にすると、ホストにエンジン VM の HA エージェントを入れ、エンジン VM を動かせるホストにする | Deploy |
doc-olvm3 も同じように追加します。REST API で追加する場合は、deploy_hosted_engine=true を付けます。
curl -k -u 'admin@internal:<パスワード>' -H 'Content-Type: application/xml' \
-X POST 'https://doc-olvm-he.olvmdoc.lab/ovirt-engine/api/hosts?deploy_hosted_engine=true' \
-d '<host><name>doc-olvm3.olvmdoc.lab</name><address>doc-olvm3.olvmdoc.lab</address><root_password>...</root_password><cluster><name>Default</name></cluster></host>'
(6) 3 台が Up になり、HE を動かせるホストには王冠のアイコンが表示されます。

ストレージ ネットワークの設定
Gluster の通信とライブ マイグレーションを、冗長化した bond0 に通します。
(1) 論理ネットワーク gluster([VM network] はオフ)を作り、クラスタの [Manage Networks] で [Migration Network] と [Gluster Network] の役割を付けます。手順はネットワークの設定手順と同じです。

(2) 各ホストの [Network Interfaces] → [Setup Host Networks] で、gluster を bond0 にドラッグして割り当てます。bond0 はホストの準備で作ったものが、そのまま表示されます。

(3) gluster の鉛筆アイコンをクリックし、[Boot Protocol] を Static にして、bond0 の IP アドレス(10.20.83.142〜144)を入力します。[OK] を 2 回クリックします。

役割を付けたネットワークを後から割り当てても、作成済みの Gluster ボリュームのブリックは、作成時に指定した -gl の名前(bond0 の IP アドレス)のまま通信します。この役割は、エンジンから新しくブリックやボリュームを作るときに使うアドレスを決めるものです。