MINISFORUM UM580 ミニ PC 購入。

今まで購入した「NiPoGi GK3Pro ミニ PC」や「Beelink MINI S」は Intel の Atom 系の CPU だったのだけど、今度は AMD Ryzen7 の CPU 搭載ミニ PC を購入しました。

まぁ、AMD Ryzen7 搭載ミニ PC が欲しかった。と、いうのもあるのですが、一番は USB Type-C がついているモノが欲しくなった。と、いうのが大前提としてありました。モバイルサブディスプレーなどは HDMI ではなく USB Type-C のものがそれなりに存在しているし、そーいうのに接続できるミニ PC が欲しくなった。と、いうことですね。

 
amazon で購入しましたが、注文したのは 2024/12/29 で、正月休みにこれで遊べたら嬉しいなぁ。なんて思っていましたが、配達されたのが、明けた 2025/01/18 でした。あらま・・。
まぁ、このミニ PC は 2022 年に発売されたようで、今はもう売ってないみたいです。僕が買ったタイミングで、多分、既に在庫一斉セール状態だったのかもしれません。だって、以下のスペックなのに 40,154yen で、そこにポイント還元で 400 ポイントくらいもらったので、実質 30,000yen 台で購入することができました。

  • CPU: Ryzen 7 5800H (3 コア/16 スレッド)
  • Memory: 16GB (DDR4 SO-DIMM 8GBx2)
  • SSD: PCIe M.2 2280 SSD 512GB

 
多少古い製品で、既にディスコンとはいえ、新品でこのスペックであればサブ機として十分です。
届いた箱を早速開けました。中に入っていたのはこんな感じ。

写真中央のちょっと上の黒い個体が本体で、右の説明書の下にあるのが、100W の USB Type-C のアダプターです。 USB Type-C のポートが二つあり、一個はミニ PC 本体への電源供給。もう一個は他の機器の充電用。なのだと思い、試しましたが PC に電源供給して起動している最中にもう一個の USB-C ポートに接続したら、PC 本体の電源が落ちてしまいました(g_g)。ダメじゃん・・orz。

本体の下の袋にはいっているのが S-ATA コネクタです。マザーボードに接続してミニ PC 本体に S-ATA の 2.5 インチ SSD などを追加可能です。早速、余っていた SSD を中に入れました。

全体のスペック、筐体の雰囲気などはこんな感じです。

 
このミニ PC 使い方ですが、どうしよう・・。

以前購入した NiPoGi GK3Pro ミニ PC は Windows11 Pro がインストールされていて、かつ FreeBSD でデスクトップ環境もフルで KDE6+Plasma6 が入っているマルチブートな環境で利用していますが、メインでの利用は FreeBSDで、それを bhyve サーバとして、利用していて仮想マシンが 3 台動作しています。

今回購入したのは Windows11 Pro の専用機に使用かなぁ。と、なったのであります。

 
まぁ、中国産のミニ PC は基本 OS 再インストール必須なので、今回も全て削除してから Windows11 Pro を再インストール。アクティベーションキーは BIOS(UEFI) 中で持っているので、サクっと再インストールできました。また、 Atom 機とは違い使っているデバイスも AMD 系 PC の一般的なものなので、あちこちから拾ってくる手間いらずで嬉しいです。

探し回ったのは WiFi と Bluetooth のドライバくらいでしょうか。最近は AMD の CPU 搭載 PC は MediaTek のものを利用しているケースが多いので、それだけ拾ってきました。

普段は FreeBSD の pciconf -lv を貼り付けるのですが、今回は FreeBSD はインストールしないので「デバイスマネージャー」のキャプチャを貼り付けておきます;-)。

さてと。 Windows 専用マシンとして利用するのにどうしよう。などと思ったのですが Oracle VirtualBox をインストールして、そこに FreeBSD/amd64 14.2-RELEASE をインストールしてみたいと思います。

と、いうのも Oracle VirtualBox はバージョンが 7.1.6 になって、MS ゴシックのギザギザしたフォントが変更になり、ちゃんとアンチエイリアスが効いたフォントで表示されるようになりました。また、Qt5 から Qt6 にフレームワークが変更になり、ロゴのアイコンまで変更になり「お。なんか良い感じじゃーん。」となっているのであります。

 
では、ここから FreeBSD/amd64 14.2-RELEASE をインストールして、X まで動作させていきます。

1. VirtualBox 7.1.6 を拾ってきてインストール
2. VirtualBox 7.1.6 Extension Pack を拾ってきてインストール
3. FreeBSD の iso ファイルを拾ってくる
4. FreeBSD をインストール

 
端折りましたが、ここまで大丈夫でしょうかね。

で、今回は X まで動作させるので、当然 KDE6 をインストールします。
他のマシンで既に KDE6+Plasma6 が動作しているので、そのマシン上で以下のコマンドを実行すれば、pkg を生成してくれます。

# pkg create -n -g -o /usr/ports/packages/All -a

 
あとは今回 Virtialbox にインストールした FreeBSD 側で /usr/ports/packages/All を NFS マウントするなり /usr/ports/packages/All/* を scp で取ってくるなりして pkg add kde-6.2.5.24.12.2.pkg などすれば 一気にインストールされます。また、 xorg-7 や emacs-29.4 などを pkg add するのも良いでしょう。

と、いうか、僕の場合、メインの ports コンパイルマシンがあって、そこでコンパイルして pkg create して NFS サーバ上に置いて、他の FreeBSD は NFS マウントして pkg add しています。 FreeBSD サイトを利用した pkg install はほぼ利用していないです。 pkg install すると、僕の make config とは合わないので、あまり利用していません。

 
と、いうこどて、 Xorg をインストールして KDE6+Plasma6 までインストールが完了しました。と、いうことで Xorg を起動させましょう。

今回 VirtualBox で FreeBSD を動作させるには以下のサイトが参考になるかと思います。

https://docs.freebsd.org/en/books/handbook/virtualization/#virtualization-guest-virtualbox

 
virtualbox-ose-additions を emulators/virtualbox-ose-additions からインストールします。 Xorg 使う版をインストールします。その後、 /etc/rc.conf に以下の行を追加。

vboxguest_enable="YES"
vboxservice_enable="YES"

 
続いて /usr/local/etc/X11/xorg.conf.d/ 配下の xorg.conf の設定です。 今の Xorg は結構自動で設定認識して動作するので設定は不要かもしれないです。僕の場合の設定を記載します。

o. 00-module.conf

Section "Module"
    Load  "GLcore"
    Load  "drm"
    Load  "fb"
    Load  "vgahw"
    Load  "shadow"

    SubSection "extmod"
        Option      "omit xfree86-dga"
    EndSubSection
EndSection

Section "DRI"
    Group "video"
    Mode 0666
EndSection

Section "ServerFlags"
    Option      "StandbyTime" "3"
    Option      "SuspendTime" "5"
    Option      "OffTime"     "10"
    Option      "AIGLX"       "True"

#   Option      "AllowEmptyInput" "off"
#   Option      "AutoAddDevices"  "off"
EndSection

 

o. 10-monitor-screen.conf

Section "Monitor"
    Identifier     "Monitor0"
    VendorName     "Monitor Vendor"
    ModelName      "Monitor Model"
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Card0"
    Monitor        "Monitor0"
    DefaultDepth    24
    Option         "NvAGP"

    SubSection "Display"
        Viewport   0 0
        Depth     24
    EndSubSection
EndSection

 

o. 20-video.conf

Section "Device"
    Identifier "Card0"
    Driver "vboxvideo"
    VendorName "InnoTek Systemberatung GmbH"
    BoardName "VirtualBox Graphics Adapter"
EndSection

 

o. 50-keyboard.conf

Section "InputClass"
    Identifier      "AT Keyboard"
    MatchIsKeyboard "on"
#   Driver      "kbd"
    Driver      "evdev"
#   Option      "XkbRules"   "xorg"
    Option      "XkbRules"   "base"
    Option      "XkbModel"   "jp106"
    Option      "XkbLayout"  "jp"
#   Option      "XkbOptions" "ctrl:swapcaps"
EndSection

 

o. 60-mouse.conf

Section "InputDevice"
        Identifier      "Mouse0"
        Driver          "vboxmouse"
        Option          "Protocol"      "auto"
#       Option          "Device"        "/dev/sysmouse"
        Option          "Buttons"       "5"
        Option          "ZAxisMapping"  "5 4 6 7 8 9"
EndSection

 
Xorg でディスプレーを表示させたり、キーボードやマウスを認識させたり、マウスホイールを動作させたりするには VirtualBox 側の「設定」が重要になってきます。

必要な設定内容を抜き出しました。

  • 「システム」の「ポインティングデバイス」は[PS2 マウス]を選択
  • 「システム」の「EFIを有効化」にチェック
  • 「システム」の他の「拡張機能」も必要に応じてチェック
  • 「ディスプレイ」の「グラフィックコントラー」は[VBosSVGA]を選択
  • 上記の設定を有効にすることにより一番下に「無効な設定が見つかりました」となるがとりあえず無視して[OK]を押す
  • CPU やメモリ容量については自分の好みでチョイス

 
こんな感じで設定して、 FreeBSD を起動して Xorg を起動すると動作してくれると思います。

ただ、一点。マウスのホイール機能がいまいち怪しい動作です。どうやら VirtualBox の他の機能に食われているようです。

FreeBSD の画面のメニューから「入力」をクリックして「マウス統合」を無効にしてみてください。

「マウス統合」を無効にすると、FreeBSD のウィンドから他のウィンドに移動する際、左 Ctrl ボダンを押す必要があります。シームレスにマウスが動作しません。しかし、VirtualBox の FreeBSD ではホイール機能はちゃんと動作するようになりました。ただ、ダブルクリックしてコピーしようとしたとき、下にちょっとズレたり、あまり使い勝手が良くないような・・。

このあたり、趣味の世界で利用方法を選択してください。

 
今回、初めてコッテリと Windows 側で FreeBSD を設定してみました。普段は PC 買ったら即『マルチブート』が鉄則になっていたので、まぁ、ある意味良い体験でした。これで、Windows 上の VirtualBox で FreeBSD が動作することも確認できたし、まぁ良しとするですかねぇ。

ちなみに、今回購入したミニ PC で World of Warships なるゲームを試してみましたが 3 分に一回落ちるとか、結構悲惨。ファイナル・ファンタジーのベンチマークとか走らせたら 1920×1080 のフル HD で 2700 とか。ゲームにはちとつらいか・・。

FreeBSD に KDE6 が降ってきた。

kde.org から KDE6 がリリースされて、FreeBSD では長らくベータ版だったのですが、いよいよ 2025/2/3 に、ports-current に降ってきました。以前「FreeBSD に KDE5 が降ってきた。」と書いたのは 2018 年 5 月で、その間ずっと KDE5 と Plasma5 を使っていたのですが、今回、めでたくバージョンアップです。

今回は KDE5+Plasma5 から KDE6+Plasma6 へのバージョンアップ編として書いてみたいと思います。

KDE5 から KDE6 へのバージョンアップについては、以下の項目に付いて重点的に考慮しつつインストールしてみたいと思います。

  • QT5 との決別
  • fcitx は 4 系から fcitx5 へ移行
  • fcitx5 への移行に伴う mozc のバージョンアップ

内容が似ているようないないような雰囲気ですが、簡単に説明すると、そもそも KDE6+Plasma6 になると QT5 が不要になり、 KDE6+Plasma6 は QT6 へ移行していきます。また、QT5 と QT6 では qt アプリケーションの中でも同居できないモノがあり conflift が発生するので QT6 への移行は必須となります。

QT5 を使っているアプリケーションが色々あるよなぁ。と、思うのですが、上記でいうと mozc-tools が QT5 を利用しているので、これを QT6 を利用しているバージョンに移行する必要があります。するっていと、 fcitx は 4 系から fcitx5 へ移行。と、なります。

では実際にインストールしてみます。環境としましては、 FreeBSD/amd64 14.2-RELEASE において、現在、 KDE5+Plasma5 がインストールされている状態のところに ports から x11/kde をインストールするところから始めます。

次に fcitx5 をインストールして、最後に mozc をインストールして、環境を整えます。

 

1. kde6 のインストール
まず、その前に不要なものを削除しましょうか。

# pkg delete kde5-5.27.11.23.08.5_2
# pkg delete ja-fcitx-mozc-2.23.2815.102.01_25 ja-mozc-el-2.23.2815.102.01_25 ja-mozc-server-2.23.2815.102.01_25 ja-mozc-tool-2.23.2815.102.01_25
# pkg delete fcitx-qt5-1.2.7 zh-fcitx-4.2.9.9 zh-fcitx-configtool-0.4.9_2
# pkg delete sddm
# pkg autoremove
#
# pkg info | grep qt5- | awk '{print "pkg delete -fy " $1}' | sh -x
# pkg info | grep kf5- | awk '{print "pkg delete -fy " $1}' | sh -x
# pkg info | grep plasma5- | awk '{print "pkg delete -fy " $1}' | sh -x
#
# portmaster -a
#
# cd /usr/ports/x11/kde
# make install
# cd /usr/ports/x11/sddm
# make install
#

 
大体こんな感じでしょうか。そして、そのあと x11/kde をインストールします。
一点気をつけるのが x11/plasma6-plasma の make config のオプションです。

下の「Install Plasma 6 integration plugins for Qt5 applications」にチェックを付けてコンパイルすると、ドドドと QT5 関係のソフトウェアが入ってしまいます。なので、チェックは外したほうが良いです。
それにしても、ここからインストールされる qt アプリはどうして QT5 と QT6 で conflict を起こさないのだろう・・。不思議だ。

まぁ、速いマシンで約半日。と、いう感じでしょうか。

まっさらな状態から KDE6+Plasma6 をインストールするときは素直に下の二つの make install を叩けば良いでしょう。あ。その前に 既存のインストールされているものを portmaster -a で最新の状態にしておきましょう。

 
インストールが完了した KDE6 と、以前利用していた KDE5 との違いはあまり感じられません。まぁ、themes で色々カスタマイズしているしているので、それはそれで今まで利用していた自分の環境が引き継がれるかと思います。
ただ、QT5 から QT6 になった関係で themes やアイコンが引き継がれない場合があるので、その場合は「ソフトウェアセンター」から再インストールしましょう。

KDE6+Plasma6 になって一番変わったのは「設定」アプリでしょうか。左側の並び順がごそっと変わりました。一番上に[入力/出力デバイス]が来て、[接続されたデバイス]とか、[外観とスタイル]は結構下に移動しました。

あとは、現在動作確認中です。特に問題なく動作しています。

 

2. fcitx5 のインストール
次に日本語入力である fcitx5 をインストールします。 fcitx の 4 系は今までは ports では chinese/fcitx にありましたが fcitx5 では textproc/fcitx5 になります。 textproc/ の下に fcitx5 関連のものが色々入っているのでこちらをインストールします。

# cd /usr/ports/textproc/fcitx5
# make install
# cd ../fcitx5-qt
# make FLAVOR=qt6 install 
# cd ../fcitx5-gtk
# make install
# cd ../fcitx5-m17n
# make install

 
こんな感じで OK です。 fcitx5-qt は FLAVOR=qt6 を指定して QT6 対応のものを作成します。
fcitx5-gtk は Firefox や Thunderbird など GTK アプリで日本語入力をする場合に必須ですので、インストールします。 falkon などは QT6 アプリなので fcitx5-gtk は不要で日本語入力ができます。
GTK アプリで日本語入力する場合は環境変数が多少変わりました。以下のように指定すると良いでしょう。

export QT_IM_MODULE=fcitx
export GTK_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx

 
GTK_IM_MODULE は、多分今まで xim と指定していたかと思いますが、 fcitx5 からは fcitx と指定してください。これで Firefox でも日本語が打てるようになります。

 
fcitx5 を利用していて、もうひとつ困るのが設定についてです。KDE6 のパネルにウィジェットとして「入力メソッドパネル」を追加すると、日本語キーボードと mozc の切り替え、または動作モードが表示されますが、「インプットメソッドを設定」で fcitx5 のオン/オフやキーバインドの設定をするのですが、これには textproc/fcitx5-configtool が必要になります。がっ!! しかし、 textproc/fcitx5-configtool をコンパイルすると QT5 のファイルがドドドとインストールされてしまいます。で、QT6 のファイルと conflict が発生します。結構痛い・・。

一時的に textproc/fcitx5-configtool をインストールして、fcitx5 の設定が完了したらサクっと、 textproc/fcitx5-configtool を pkg delete して、かつ、 pkg autoremove して conflict した QT6 のアプリを再インストールするのが良いかと思われます。

 
fcitx5-configtool で設定した情報は ~/.config/fcitx5/config の設定ファイルとして保存されます。と、いうことは、このファイルを使い回せば大丈夫なわけですね。

せっかくなので、ここに僕の ~/.config/fcitx5/config を貼り付けておきましょう。
これをそのまま自分の環境に置くと textproc/fcitx5-configtool のインストールが不要になります。

[Hotkey]
# トリガーキーを押すたびに切り替える
EnumerateWithTriggerKeys=True
# 次の入力メソッドに切り替える
EnumerateForwardKeys=
# 前の入力メソッドに切り替える
EnumerateBackwardKeys=
# 切り替え時は第1入力メソッドをスキップする
EnumerateSkipFirst=False

[Hotkey/TriggerKeys]
0=Shift+space
1=Henkan
2=Muhenkan

[Hotkey/AltTriggerKeys]
0=Shift_L

[Hotkey/EnumerateGroupForwardKeys]
0=Super+space

[Hotkey/EnumerateGroupBackwardKeys]
0=Shift+Super+space

[Hotkey/ActivateKeys]
0=Hangul_Hanja

[Hotkey/DeactivateKeys]
0=Hangul_Romaja

[Hotkey/PrevPage]
0=Up

[Hotkey/NextPage]
0=Down

[Hotkey/PrevCandidate]
0=Shift+Tab

[Hotkey/NextCandidate]
0=Tab

[Hotkey/TogglePreedit]
0=Control+Alt+P

[Behavior]
# デフォルトで有効にする
ActiveByDefault=False
# フォーカス時に状態をリセット
resetStateWhenFocusIn=No
# 入力状態を共有する
ShareInputState=No
# アプリケーションにプリエディットを表示する
PreeditEnabledByDefault=True
# 入力メソッドを切り替える際に入力メソッドの情報を表示する
ShowInputMethodInformation=True
# フォーカスを変更する際に入力メソッドの情報を表示する
showInputMethodInformationWhenFocusIn=False
# 入力メソッドの情報をコンパクトに表示する
CompactInputMethodInformation=True
# 第1入力メソッドの情報を表示する
ShowFirstInputMethodInformation=True
# デフォルトのページサイズ
DefaultPageSize=5
# XKB オプションより優先する
OverrideXkbOption=False
# カスタム XKB オプション
CustomXkbOption=
# Force Enabled Addons
EnabledAddons=
# Force Disabled Addons
DisabledAddons=
# Preload input method to be used by default
PreloadInputMethod=True
# パスワード欄に入力メソッドを許可する
AllowInputMethodForPassword=False
# パスワード入力時にプリエディットテキストを表示する
ShowPreeditForPassword=False
# ユーザーデータを保存する間隔(分)
AutoSavePeriod=30

 

以上で fcitx5 のインストールは終わりです。

ただ、fcitx5 を利用するようになると、今度は japanese/fcitx-mozc が利用できなくなります。 japanese/fcitx-mozc を利用しなくなるので合わせて japanese/mozc-server も利用しなくなります。と、いうことで fcitx5 に対応した fcitx5-mozc を利用することになるのであります。

と、いうことで次へ。

 

3. fcitx5-mozc のインストール
FreeBSD-users-jp な ML でも何回か投稿がありました。ports-current の fcitx-mozc の mozc のバージョンは ja-fcitx-mozc-2.23.2815.102.01_25 ですが、 fcitx5 に対応した mozc は ja-fcitx5-mozc-2.31.5712.102_6 という、先進的なバージョンになります。

まずは、情報収集として以下の URL を確認します。

https://lists.freebsd.org/archives/freebsd-users-jp/2024-July/000379.html
https://github.com/kdeguchi/mozc-ports

 
では、インストール手順ですが、まず上の URL の github.com から mozc-ports-main.zip をダウンロードして展開し /usr/ports/ 配下に設置します。

# wget https://github.com/kdeguchi/mozc-ports/archive/refs/heads/main.zip -O mozc-ports-main.zip
# unzip mozc-ports-main.zip
# cp -pr mozc-ports-main /usr/ports/mozc-ports
# cd /usr/ports/mozc-ports/japanese/
# ls 
fcitx-mozc/   fcitx5-mozc/  ibus-mozc/    Makefile.inc  mozc-el/      mozc-server/  mozc-tool/    uim-mozc/

 
こんな感じです。で、/etc/make.conf に一行追加します。

# fcix5-mozc compile
OVERLAYS+=/usr/ports/mozc-ports

 

これで準備が整いました。コンパイルしていきます。
ちなみに mozc は最新版です。 mozc-ports/devel/bazel8 も合わせてインストールされて openjdk18 など java 関係のごついのが色々インストールされます。コンパイルにそれなりの時間がかかります。

# cd /usr/ports/mozc-ports/japanese/fcitx5-mozc/
# make install
# cd ../mozc-server
# make install
# cd ../mozc-tool
# make install
# cd ../mozc-el
# make install
# 

 
コンパイルは時間はかかりますが、順調に進むと思います。 python3 が BUILD_DEPENDS と RUN_DEPENDS で必要になります。既存でインストールされている python3.11 などを /usr/local/bin/python3 へと symlink する lang/python3 がインストールされます。

無事にコンパイルできて、インストールして、使えるようになったでしょうか?

僕の場合は特に問題なく動作しましたが、ただ、一点。 mozc-el がダメで emacs 中で日本語が利用できなくなりました。どうも /usr/local/libexec/mozc_emacs_helper が起動されない雰囲気です。色々試したけどやっぱりダメで emacs-lisp 部分の /usr/local/share/emacs/29.4/site-lisp/mozc/* のファイルを ja-mozc-el-2.23.2815.102.01_25 の、つまりは japanese/mozc-el がインストールしたものと入れ替えたら無事に動作しました。入れ替えるファイルは emacs-lisp の部分のみなので、mozc のバージョンに引きずられることもなく、無事に動作して一安心。

 
とまぁ、これで KDE6+Plasma6 と QT6 がインストールされ、日本語入力もできるようになり KDE5+Plasma5 から KDE6+Plasma6 と QT6 への移行が完了しました。

ただ、残りほんの少し QT5 を利用しているアプリが存在します。その一つが sddm になります。おかげで deskutils/plasma6-sddm-kcm をインストールして themes を別のに選択しても反映されない。とかが起きています。
あと、 KDE 系とは直接関係ないですが、 vlc も QT5 のライブラリを利用しています。今のところ最後の QT5 利用アプリはこの二つ。 pkg info | grep qt5- | wc -l すると 16 となっています。

 
あ。KDE6+Plasma6 の Wayland についてちょっと触れておきます。 sddm から Plasma (Wayland) を指定してログインしてもすぐに sddm の画面に戻ってしまい、 Wayland では利用できません。
sddm でのログイン時のログは ~/.local/share/sddm/wayland-session.log に保存されているので確認することができます。僕の環境では以下のログが出力されていました。

kwin_core: Could not determine the active graphical session
kwin_wayland_drm: failed to open drm device at "/dev/dri/card0"
kwin_wayland_drm: No suitable DRM devices have been found

 
なんか、AMD CPU と、そこに搭載されているグラフィックチップでは Wayland が動作しないようです。 nVidia とか Intel なGPU なら動作するかもしれんです・・(g_g)。

 
と、いうことで、ほぼ完全に移行が完了しました。これからドンドン使い込んでいきたいと思います。
KDE については KDE5 のときもそうでしたが、時々パラパラっとエントリ書いていますので、もしかしたらまた書くかもです。

 
あ。 japanese/mozc-server あたりは最新の 2.31.5712.102 にならないのかな? (独り言)

carp と hast で冗長構成な MySQL サーバ。

Linux 方面では pacemaker と corosync 、そして drbd で MySQL サーバの冗長構成を構築する。なんてのは日常茶飯事のようですが、同様な構成を FreeBSD で組んでみたい。
と、いうのも Linux 方面では pacemaker の管理用コマンドがややこしい。以前の CentOS7 辺りでは crm_mon を利用しているかと思っていたが、 AlmaLinux8 では どうやら crm_mon が利用できない。あと、 pacemaker のバージョンが 1 系から 2 系になり、設定ファイルに互換性がなくなり、もう一度、設定方法について勉強し直し。みたいな雰囲気で、そろそろ FreeBSD で MySQL サーバの冗長を組みたくなってきた。と、いう雰囲気です。

 
と、いうことで、今回は FreeBSD で carp と hast を利用して、二台のマシンで冗長構成な MySQL サーバを構築してみましょう。

そもそも、二台の FreeBSD を利用した冗長構成な MySQL サーバを構築するには何を利用したら良いの? Linux で言うところの pacemaker と drbd みたいなものって、何かあるの?などと、調査からはじめました。
carp が pacemaker 部分。 hast のほうが drbd を受け持っている。と、いう認識で良いかと思われます。

まずは順番に見ていきます。

 
1. 今回の構成
二台の FreeBSD を用意するわけですが、今回は VMware ESXi 上で動作する FreeBSD/amd64 14.2-RELEASE と bhyve 上で動作する FreeBSD/amd64 14.2-RELEASE を用意しました。二台のサーバ共、同一の ESXi 上に載せていても冗長構成になりませんからねf(^^;;。

ESXi 側の FreeBSD のホスト名は freebsd-esxi (192.168.202.53) 、bhyve上で動作している FreeBSD のホスト名は freebsd-bhyve (192.168.202.202) として運用します。あと、 VIP が必要ですが、これは 192.168.202.251 とします。

図に書くとこんな感じになります。

それぞれの仮想環境上に冗長構成として利用する 2 台のサーバを設置。各サーバは OS をインストールしたディスク (da0) と、hast 用 (Linux で言うところの drbd) にもう一個 da1 を用意します。それが、各ホストの下の「hast disk」です。

プライマリ側で hast で利用しているディスクに更新があると、チョロチョロチョロっと、対向のセカンダリ側の hast のディスクに書き込まれて同期が保たれます。で、セカンダリ側がマスタになると、そのまま hast disk をマウントしてサービスを開始します。

carp はプライマリとセカンダリを切り替える機能、 Linux で言うところの pacemaker と corosync に相当します。

それでは実際に hast と carp の設定について見ていくことにしましょう。

 
2. carp の設定
まずはネットワーク系に相当する carp の設定から見ていきます。
とは言いつつ、簡単です。

まずはカーネルモジュールのロード設定ですね。

o. /boot/loader.conf

carp_load="YES"

 
続いて VIP の IP アドレスの設定を /etc/rc.conf に記載します。
プライマリ側とセカンダリ側では多少設定が違います。

o. プライマリ側 /etc/rc.conf

ifconfig_em0_alias0="inet vhid 1 pass mysql00 alias 192.168.202.251/32"

 
o. セカンダリ側 /etc/rc.conf

ifconfig_em0_alias0="inet vhid 1 pass mysql00 advskew 50 alias 192.168.202.251/32"

 
まぁ、実際に、セカンダリの設定が入っているサーバがプライマリで動作しているときにプライマリの設定が入っているサーバが再起動すると、セカンダリとして動作するので、設定自体にあまり意味はないかもですね。

 
この設定を入れると em0 には VIPが付加されるのと、マルチキャストアドレスが付加されます。まずは上記設定を入れて再起動してみましょう。

$ ifconfig em0
em0: flags=1008943 metric 0 mtu 1500
        options=4e524bb
        ether 00:0c:29:75:28:84
        inet 192.168.202.211 netmask 0xffffff00 broadcast 192.168.202.255
        inet 192.168.202.251 netmask 0xffffffff broadcast 192.168.202.252 vhid 1
        inet6 fe80::20c:29ff:fe75:2884%em0 prefixlen 64 scopeid 0x1
        inet6 2001:470:fe36:feed:0:202:211:1 prefixlen 64
        carp: MASTER vhid 1 advbase 1 advskew 50
              peer 224.0.0.18 peer6 ff02::12
        media: Ethernet autoselect (1000baseT )
        status: active
        nd6 options=21

 
192.168.202.251 が alias で付加され、あと、carp: MASTER vhid 1 advbase 1 advskew 50 というのが付加されます。マルチキャストアドレスで、同期判断をしています。多分、Linux でいうところの drbd に相当する差分データも流れていると思います。

そして、一点注意点があります。VMwareESXi 上で動作している仮想マシンの em0 が接続する vSwitch はプロミスキャス・モードを有効にしてあげる必要があります。 ESXi 的に言うと『無差別モード』と、いうヤツですね。これを許可していないと二台サーバの同期ができません。
bhyve 側にはこの設定がありません。まぁ、bhyve の vSwitch に相当する部分はそもそも bridge インターフェイスなので、プロミスキャス・モードは既にオンになっていますね。

と、いうことでネットワークの設定は終了。
続いて hast 側、HDD の作成や、設定について見ていきましょう。

 
3. hast 用ディスクイメージの用意
上にも書いたとおり、ディスクイメージは二つ必要で、da0 側に OS イメージをインストールし、da1 側はフツーに ufs でフォーマットします。あ。多分 zfs でも行けると思いますが、僕は ufs でフォーマットしました。

両方のサーバで実施してください。

# newfs -U /dev/da1
# mount /dev/da1 /mnt/
/dev/da1  20308252      8   18683584     0%    /mnt
# umount /mnt

 
gpart で、パーティションを分けるようなことはせず、ダイレクトに /dev/da0 に対して newfs を実施します。その後、マウントして、サイズを確認します。2 台のサーバで同一容量になっている必要があります。

 
4. hast 用環境設定
続いて各種設定を見ていきます。

o. /etc/rc.conf

hastd_enable="YES"

 
o. /etc/hast.conf (新規に作成)

replication memsync
resource disk0 {
    on freebsd-esxi {
        local /dev/ada0
        remote 192.168.202.202
    }
    on freebsd-bhyve {
        local /dev/da1
        remote 192.168.202.53
    }
}

 
/etc/hast.conf ファイルは一個のディクスを用意する場合は上記の設定で、二個目の場合は resource disk1 { } みたいになります。
両方のサーバで同一の内容を記載します。
on freebsd-esxi { } の設定のところで remote の IP アドレスを記載します。対向のサーバの IP アドレスになります。
また、ホスト名は名前解決ができている必要があります。 DNS 登録がない場合は /etc/hosts に記載しましょう。

o. /etc/fstab

/dev/hast/disk0 /var/db/mysql   ufs     noauto,rw,noatime       0       0

 
とりあえず /var/db/mysql にマウントする設定内容で記載します。

設定内容はこんな感じですかね。 Linux 方面 の pacemaker と corosync、そして drbd の設定よりは格段に楽ちんです。

 
5. /dev/hast/disk0 の準備
まずは hastd を起動します。

# service hastd start
# ps -ax | grep hast
1053  -  Ss    0:00.01 /sbin/hastd

 
続いてディスクの初期化を実施します。

まずは、プライマリサーバ側から。今回は、プライマリ側サーバは IP アドレスの若版である、freebsd-esxi にします。

# hastctl create disk0
# hastctl role primary disk0

 
続いてセカンダリ側を。こちらは freebsd-bhyve になります。

# hastctl create disk0
# hastctl role secondary disk0

 
そしたら次に HDD 初期化とマウントを実施します。これは両方のサーバで実施してください。

# newfs -U /dev/hast/disk0
# fsck -fy -t ufs /dev/hast/disk0
# mount -o noatime -o rw /dev/hast/disk0 /var/db/mysql

 
ここまで来たら作業は完了。 hastctl でステータスを確認します。

# hastctl status disk0
Name    Status   Role           Components
disk0   degraded primary        /dev/ada0       192.168.202.51
# hastctl list
disk0:
  role: primary
  provname: disk0
  localpath: /dev/ada0
  extentsize: 2097152 (2.0MB)
  keepdirty: 64
  remoteaddr: 192.168.202.51
  replication: memsync
  status: degraded
  workerpid: 1747
  dirty: 75497472 (72MB)
  statistics:
    reads: 211
    writes: 150
    deletes: 0
    flushes: 0
    activemap updates: 36
    local errors: read: 0, write: 0, delete: 0, flush: 0
    queues: local: 0, send: 0, recv: 0, done: 0, idle: 255

 
こちらはプライマリ側の状態です。hastctl status disk0 で確認すると、primary と表示され、IP アドレスも合わせて表示されます。
セカンダリ側でも同様のコマンドで確認することができます。今回は割愛します。
hastctl list はディスク同期の詳細が表示されます。まぁ、簡単に言うと、この二つのコマンドは Linux でいうところの cat /proc/drbd みたいな感じでしょうか。

 
6. hast の状態の遷移
HDD イメージを二台のサーバ間で操るのですが、hastctl コマンドで制御します。

  • プライマリとして利用: hastctl role primary disk0
  • セカンダリとして利用: hastctl role secondary disk0
  • どちらでもない状態:   hastctl role init disk0

実際に運用し始めるとある程度解ってくると思います。

 
とまぁ、ここまでで carp と hast の設定が全て完了しました。これで、さぁてっ!! 冗長構成にするぜいっ!! と、は、実はまだなりません。

carp はサーバ障害発生時に IP アドレスを付け替えてくれます。hast は HDD 周りの同期を取ってくれます。がっ!! では、誰が /dev/hast/disk0 を /var/db/mysql にマウントしてくれるの?誰が切り替わった後に mysqld を起動してくれるの?

そーなのです。 carp+hast はこの部分に未対応です。なので、スクリプトを書く必要があるのであります。ありゃまっ!! orz

ここからはスクリプトについて見ていきましょう。

 
7. ホストダウンの検知
対向のホストがダウンした場合、検知は carp がしてくれます。カーネルモジュールを kldload しているので、実質的にはカーネルでの検知と、いうことになりますね。
ですので、イベントは devd で拾うことができます。まずは devd の carp.conf を作成します。設置場所はお好きなところに。僕は /usr/local/etc/devd/carp.conf を設置しました。

中身はこんな感じです。が、今回は以下のサイトを参考にさせて頂きました。ありがとうございました。

https://qiita.com/asakura_titems/7c117f2d7870afa76994

 
o. carp.conf

notify 0 {
    match "system"          "CARP";
    match "subsystem"       "[0-9]+@[0-9a-z]+";
    match "type"            "(INIT|MASTER|BACKUP)";
    action "/usr/local/bin/carphast.sh $type $subsystem";
};

 
system が CARP で、subsystem が ifconfig em0 したときの MASTER vhid で、type が ステータスですね。このイベントを拾ってから action で記載されたスクリプトが動作します。

スクリプトは以下になります。

o. carphast.sh

#!/bin/sh

services="mysql-server"
resources="all"

action=$1
vhid=${2%@*}
ifname=${2#*@}

syslog_facility="user.notice"
syslog_tag="carp-hast"
maxwait=60
delay=3

logger="/usr/bin/logger -p $syslog_facility -t $syslog_tag"

if [ "$resources" = "all" ]; then
    hastdevs=$(/sbin/hastctl dump | /usr/bin/awk '/^[[:space:]]*resource:[[:space:]]/ {print $2}')
else
    hastdevs="$resources"
fi

# 
case "$action" in
    MASTER|BACKUP|INIT)
        $logger "State Changed. I/F: $ifname VHID: $vhid state: $action"
        ;;

    AUTO)
        action=$(/sbin/ifconfig $ifname | /usr/bin/awk '/[[:space:]]*carp:[[:space:]]+([A-Z]+)[[:space:]]vhid[[:space:]]'"$vhid"'[[:space:]]?/ {print $2; exit}' )
        if [ "$action" ]; then
            $logger "State Changed. I/F: $ifname VHID: $vhid state: $action"
        else
            die "carp state not found"
        fi
        ;;
    
    *)
        die "$action is not yet implemented"
        ;;
esac

reverse_list()
{
    _revlist=
    for _revfile in $*; do
        _revlist="$_revfile $_revlist"
    done
    echo $_revlist
}

die()
{
    $logger "FATAL: "$*
    exit 1
}

# check hastd enabled
if ! /bin/pgrep -q hastd; then
    $logger "hastd not running"
    exit
fi

stop_services()
{
    for service in $( reverse_list $* ); do
        if /usr/sbin/service ${service} onestatus | /usr/bin/grep -q "running as" ; then
            /usr/sbin/service ${service} onestop \
                || $logger "Unable to stop service: ${service}."
        fi
    done
}

change_role()
{
    roletype=$1
    shift 1
    
    for hdev in $*; do
        /sbin/hastctl role $roletype $hdev \
            || $logger "Unable to change role to $roletype for resource: $hdev"
    done
}

# main
case "$action" in
    BACKUP|INIT)
        # stop services
        stop_services $services

        # unmount ufs
        for mdev in $(/sbin/mount -p | /usr/bin/awk '/^\/dev\/hast\// {print $1}'); do
            for hdev in $hastdevs; do
                if [ "$mdev" = "/dev/hast/$hdev" ]; then
                    /sbin/umount -f $mdev \
                        || $logger "Unable to unmount: ${mdev}."
                fi
            done
        done

        # change role
        if [ "$action" = "BACKUP" ]; then
            roletype="secondary"
        else
            roletype="init"
        fi
        change_role $roletype $resources

        $logger "Change role $roletype completed."
        ;;
    MASTER)
        # stop services
        stop_services $services

        # wait for not running secondary
        for hdev in $hastdevs; do
            for i in $(/usr/bin/jot $maxwait); do
                /bin/pgrep -fq "hastd: ${hdev} \(secondary\)" || break
                sleep 1
            done

            if /bin/pgrep -fq "hastd: ${hdev} \(secondary\)" ; then
                die "Secondary process for resource ${hdev} is still running after $maxwait seconds."
            fi
        done

        # change role primary
        change_role primary $resources
        sleep $delay

        # wait for the /dev/hast/* devices to appear
        for hdev in $hastdevs; do
            for i in $(/usr/bin/jot $maxwait); do
                [ -c /dev/hast/$hdev ] && break
                sleep 1
            done

            if [ ! -c /dev/hast/$hdev ]; then
                die "GEOM provider /dev/hast/$hdev did not appear."
            fi
        done

        # mount ufs
        for mdev in $(/usr/bin/awk '/^\/dev\/hast\// {print $1}' /etc/fstab); do
            for hdev in $hastdevs; do
                if [ "$mdev" = "/dev/hast/$hdev" ]; then
                    $logger "mount $mdev"
                    /sbin/mount -p | /usr/bin/grep -q -e "^${mdev}[[:space:]]" && break;
                    
                    /sbin/fsck -y -t ufs ${mdev} \
                        || die "Failed to fsck: ${mdev}."
                    
                    /sbin/mount ${mdev} \
                        || die "Unable to mount: ${mdev}."
                fi
            done
        done

        # start services
        for service in ${services}; do
            /usr/sbin/service ${service} onestart \
                || $logger "Failed to start service: ${service}."
        done

        $logger "Change role primary completed."
        ;;
esac

 
基本的に、MASTER の場合は hastctl role primary disk0 して /var/db/mysql をマウントして mysqld をスタートする感じ。
それ以外は hastctl role secondary disk0 する。それをもう少し複雑に色々している雰囲気でしょうか。
まぁ、切り替わったときにやる一連の作業を devd 経由で検知して、スクリプトを実行するようにした。と、いう感じです。

この辺り、の管理用スクリプトとか、ports になってないのかな?

 
僕の場合、もう一個、 /etc/rc.local から呼び出して実行するスクリプトを用意しています。サーバが再起動したとき hastctl status disk0 すると init になっているので、対向のホストに ssh してステータスを確認して hastctl role secondary disk0 を打つようにしました。

o. /usr/local/bin/hast_primary_check.sh

#!/bin/sh

REMOTE=`/usr/local/bin/sudo hastctl list | grep remoteaddr |awk '{print $2}'`
HBSTATUS=`/usr/bin/ssh -i /home/takachan/.ssh/id_rsa takachan@${REMOTE} /usr/local/bin/sudo hastctl status disk0 | grep ^disk0 | awk '{print $3}'`

if [ ${HBSTATUS} = 'primary' ];then
#    echo "sudo hastctl role secondary disk0"
    /usr/local/bin/sudo hastctl role secondary disk0
fi

 
再起動直後はセカンダリで良いので、起動時にステータスを更新してしまう。と、いう感じです。

 
さてと、これで carp+hast の冗長構成完了です。

Linux 方面の pacemaker と corosync、そして drbd の場合はスクリプト書かないんだけど、設定が面倒。 FreeBSD の場合は設定は簡単なんだけど、アプリ側に仕掛けとか何もなし。

どちらが良いかは自分で決めてくだされ。
ただ、これで冗長構成が完了したので、ヨシヨシ。と、いう感じかな。