同じGoエージェントをLinuxとOpenWrtで動かす:Fleetdの導入設計
Fleetd v0.3.0の対応アーキテクチャ、systemdとprocd、状態の永続化、ファームウェア更新後の復旧、監視機能の違いを解説します。
クラウドサーバーにも自宅のルーターにも、実行ファイルを置き、設定を書き、起動する。最初は同じ作業に見えます。しかし常用すると、再起動後に誰がプロセスを立ち上げるのか、ネットワークが未準備ならどうするのか、ログはどこにあるのか、機器の識別情報やコマンドの記録は残るのか、といった違いが重要になります。
Fleetd は Linux サーバーと OpenWrt、iStoreOS のルーターを管理します。機器の接続とブラウザによる署名に続き、今回は常駐・運用できるシステムサービスへの組み込みを扱います。対象は v0.3.0。現行インストーラーは amd64、arm64 と systemd または OpenWrt の procd に対応しており、Linux カーネルを使う全機器を対象にしているわけではありません。
ソースは共通、実行ファイルはアーキテクチャ別
OpenWrt も Linux なので、接続、認証、コマンドの認可、カーネルからの基本指標取得は共通化できます。Fleetd はサーバー用とルーター用のコードを分けず、同じソースから Linux 向けの amd64 と arm64 をビルドします。
「同じクライアント」とはソースとプロトコルが同じという意味です。amd64 の実行ファイルをそのまま arm64 で動かすことはできません。
| 機器が報告するアーキテクチャ | 選択する成果物 |
|---|---|
x86_64、amd64 |
amd64 |
aarch64、arm64 |
arm64 |
| その他 | 現行インストーラーは中止 |
OpenWrt が対応する MIPS や 32 ビット ARM は、この導入経路には含まれません。Go のクロスコンパイル機能と、プロジェクトとしての対応範囲は別です。追加時には依存ライブラリ、成果物、機種判定、更新処理、実機動作まで確認が必要です。
uname -m は最初の確認に使えますが、カーネル、ユーザー空間、利用できるシステム機能も実行条件になります。
単一ファイルは実行環境の準備を軽くする
ビルドでは CGO_ENABLED=0 を指定し、対象側の C 動的リンク環境への依存を減らしています。各機器に Go コンパイラーや Node.js、Python の実行環境を入れてから起動する必要はありません。ストレージやパッケージ構成が小さいルーターには有用です。
ただし、実行条件がなくなるわけではありません。ネットワークへの到達性、HTTPS の証明書を検証できる環境、書き込める設定領域、必要なカーネル機能が要ります。コンテナ情報には docker、WireGuard 情報には wg も必要です。
基本導入を軽くしつつ、追加機能の依存条件を明示する設計です。
環境を確認してからサービスへ登録する
現行インストーラーの流れは次のとおりです。
- root 権限を確認し、CPU アーキテクチャを判定する。
- systemd または OpenWrt の procd 環境を確認する。
- 自分の Fleetd サーバーから対応する実行ファイルを取得する。
versionを実行し、少なくとも起動可能であることを確認する。- 設定を新規作成または保持し、プログラムとサービスを配置して起動する。
- 機器の指紋を表示し、管理画面で照合・承認する。
ダウンロード成功はファイルが届いた証拠で、version の成功は基本的に起動できる証拠です。長時間接続、指標取得、権限、自動起動、ファームウェア更新後の復旧までは確認していません。
取得には curl を優先し、なければ wget を使います。軽量環境では、その実装が必要な HTTPS 通信を行えるかも確認します。OpenWrt の版やファームウェアごとに構成が違うため、パッケージ導入コマンドを一律には示しません。
初回導入の信頼関係にも注意が必要です。サーバーはアップロード済みのリリースパッケージを検証して実行ファイルを取り出します。インストーラーはそのサーバーと HTTPS を信頼し、対象機器で取得ファイルを独立して署名検証するわけではありません。以降のエージェントによる更新パッケージ検証は別の流れで、更新の回で扱います。
systemd と procd が同じプロセスを管理する
導入後は、OS のサービス管理機構にライフサイクルを任せます。
| 項目 | systemd | OpenWrt / procd |
|---|---|---|
| プログラム | /usr/local/bin/fleetd-agent |
/usr/bin/fleetd-agent |
| 設定 | /etc/fleetd/agent.yaml |
/etc/fleetd/agent.yaml |
| サービス定義 | /etc/systemd/system/fleetd-agent.service |
/etc/init.d/fleetd-agent |
| 新規導入時の状態領域 | /var/lib/fleetd |
/etc/fleetd |
| ログ | systemd journal | OpenWrt のシステムログ |
systemd では ExecStart に実行ファイルを指定し、Restart=always と五秒の再起動待ち時間、network-online.target に対する起動順序を設定します。
OpenWrt では USE_PROCD=1 を使う起動ファイルを生成し、起動順、コマンド、respawn を指定します。標準出力と標準エラーはシステムログへ送ります。両方とも同じエントリーポイントを実行し、同じ形式の YAML を読みます。差異は導入とサービス連携の層に置き、通信処理へ散らしません。
復旧も二種類あります。プロセス終了にはサービス管理機構、接続切断にはエージェント自身の再接続処理が対応します。 サーバーに届かなくてもプロセスは生きたままバックオフして再試行できます。一方、終了したプロセスの中では再接続コードは動けません。
起動順序だけで遠隔サーバーの準備は保証できません。ネットワークターゲットや遅い起動順でも、DNS、上流回線、サーバーが揃って利用可能とは限らないため、接続失敗への対応が必要です。
OpenWrt では保存先そのものが重要
これは前回のリプレイ防止にも関係します。一般的なサーバーでは /var/lib/fleetd が状態の保存先になりますが、よくある OpenWrt の構成では /var が RAM 上の一時領域を使います。プロセス再起動と機器全体の再起動では、ファイルへの影響が違います。
そのため OpenWrt 向けの新規設定では state_dir を /etc/fleetd にします。三つのファイルを区別しておきます。
| ファイル | 役割 |
|---|---|
agent.yaml |
接続先、信頼する鍵、権限、状態領域の設定 |
agent.key |
機器の識別に使うエージェント自身の鍵 |
seen.json |
リプレイ防止用の受け付け済み要求 ID |
最初の二つは既定で /etc/fleetd にあります。seen.json は state_dir に従い、新規 systemd 環境なら /var/lib/fleetd、OpenWrt なら /etc/fleetd です。
識別鍵を失って再生成すると、別の機器識別情報になります。要求 ID の記録を失えば、まだ有効な過去の要求を必ず重複と判断できるとはいえません。
書き込みが成功しただけでなく、そのパスが永続領域を指しているか確認します。独自ファームウェア、読み取り専用構成、特殊なマウントでは実際の構成に合わせた確認が必要です。
フラッシュへの保存には書き込み負担もあります。現行実装が記録を更新するのは新しい認可要求を受け付けたときで、十秒ごとの指標をこのファイルへ保存するわけではありません。高頻度タスク実行へ用途が広がるなら、保存頻度とフラッシュ条件を再評価する必要があります。寿命や処理量の実測保証は示していません。
設定の保持とサービス復旧は別
OpenWrt のインストーラーは /etc/fleetd/ を /etc/sysupgrade.conf に追加します。設定保持に対応し、それを有効にした更新手順では、設定と識別情報を残す助けになります。
しかし /usr/bin/fleetd-agent と /etc/init.d/fleetd-agent まで必ず残る保証ではありません。更新後に設定はあっても、実行ファイルや起動定義を再導入する場合があります。工場出荷状態へのリセットや設定を破棄する更新も、この仕組みの保証外です。
復旧時には次を確認します。
- 設定と識別鍵が残っているか。
- プログラムとサービス定義があり、実行できるか。
- 復旧後の指紋が以前と一致するか。
- 報告が来ない理由がサービス停止、ネットワーク不通、承認待ちのどれか。
これは確認手順の提案で、この記事で実機の書き換え試験を実施したという意味ではありません。
既存の agent.yaml がある場合、インストーラーを再実行しても保持されます。プログラムとサービス定義は更新されますが、新しく渡した --permission、--server、--signer は既存設定を上書きしません。以前の状態パスが誤っていても自動修正されないため、設定を確認し、変更後にクライアントを再起動します。
共通クライアントでも監視範囲は同一ではない
基本指標は主に /proc から取得します。CPU、メモリー、負荷、稼働時間、ネットワークの累積量などです。CPU 使用率や通信速度には二回のサンプルが必要で、起動直後の一回分を完全な計測区間として扱うことはできません。インターフェース再生成でカウンターが減った場合、その回の速度計算は省略します。
追加の収集には環境依存があります。
| 収集対象 | 現在の依存先 |
|---|---|
| 失敗したサービス | systemctl list-units --state=failed |
| コンテナ | docker ps -a |
| WireGuard ピア | wg show all dump |
procd で起動できることと、procd のサービス健全性を収集できることは別です。現在の失敗サービス取得は systemd のコマンドを使います。外部ツールが存在しない、または実行に失敗した場合、その収集はデータなしとなり、基本監視は続行できます。Docker を全ルーターに要求せずに済む一方、異常データがないことは、全サービスが正常という証明にはなりません。
機能非対応、ツール不在、呼び出し失敗、実際に対象がゼロという状態は区別する必要があります。現行実装は欠落理由をすべて詳細に説明するわけではありません。
基本指標は十秒ごと、ディスク、サービス、コンテナ、WireGuard は六回の報告周期ごとに収集する設定です。外部コマンドの時間、ネットワーク、負荷が実際の間隔に影響するため、厳密なリアルタイム保証ではありません。
導入後は動作のつながりを確認する
起動、プロセス管理、再接続、再起動後の設定と識別情報の保持まで確認します。systemd では状態と最近のログから始められます。
systemctl status fleetd-agent
journalctl -u fleetd-agent -n 50 --no-pager
OpenWrt ではシステムログを確認します。
logread -e fleetd
これらは診断用で、機器を再起動するコマンドではありません。設定変更を反映するクライアント再起動は、systemd なら systemctl restart fleetd-agent、OpenWrt なら /etc/init.d/fleetd-agent restart です。
管理画面で承認済みか、報告時刻が進むかを確認し、CPU とネットワークの後続サンプルも待ちます。監視だけなら monitor のままでよく、確認のために root コマンドを許可する必要はありません。
機器全体の再起動やファームウェア更新は保守時間に行います。インターネットや遠隔接続を担うルーターでは特に重要です。制御した再起動後に同じ指紋で自動復帰する確認は、version を何度も動かすより実運用に近い証拠になります。
CI にはテストと amd64/arm64 ビルドが含まれますが、全 OpenWrt イメージでの実機検証とは異なります。この記事にはメモリー消費、CPU 負荷、最小フラッシュ容量の実測値もありません。空き容量と自分の負荷を確認してください。
Fleetd はプロトコルと処理を共用し、サービス管理やディレクトリの違いを明示的な適応箇所へ置いています。ルーターを同一構成の小さなサーバーと見なさずにコードを再利用するためです。次回は、集めた指標から役に立つアラートを作る話へ進みます。
コメント・議論
質問や実践の経験をお寄せください。コメントは承認後に表示されます。メールアドレスは公開されません。 コメントのプライバシー
コメントを読み込み中…