Mackerelのホストメタデータ機能を使って、ホスト上にインストールされているパッケージ一覧をログインなしに確認する
こんにちは、Mackerel CREの
id:do-su-0805 です。
この記事は Mackerel Advent Calendar 2025 11日目の記事です。
さて、みなさまMackerelのメタデータ機能をご存じでしょうか。
メタデータ機能は、ホストやサービス、ロールに対して任意のJSONデータを登録・取得できる機能です。
※mackerel-agentで自動取得される、 interface やクラウドプラットフォーム上の情報(メタ情報)とは異なります。また、Mackerelに関するメタデータAPI - Mackerel ヘルプとも異なります。
たとえば直近10分間でログインしたユーザの名前の一覧や、ホスト構築時のメモといったお好きな情報をJSON形式で用意することで、ホストのメタデータに投稿できます。
投稿にあたってはAPIを利用することもできますし、mackerel-agentの設定に[plugin.meta.XXXXX]という設定を入れることで、mackerel-agentに定期的なメタデータの取得、投稿を任せることもできます。
今回は例として、対象ホスト上にインストールされているパッケージとそのバージョン一覧を投稿し、ログインなしにパッケージ一覧を確認できるようにしてみます。また、その情報を利用して、カスタムダッシュボードにパッケージ一覧を表示させてみようと思います。
※ 文中に例としてシェルスクリプトを紹介しておりますが、簡易的なものとなるため動作保証はできません。また、MITライセンス(Copyright (c) 2025 do-su-0805)の下で公開されています。
メタデータを試してみる
※ 以下、MACKEREL_APIKEYにはご利用中のオーガニゼーションの書き込み権限APIキーが、HOSTIDにはメタデータを投稿したいホストのホストIDが格納されています。
Mackerelのメタデータ機能では、メタデータの種類を特定する識別子であるネームスペースを決めて利用します。
ホストメタデータの一覧APIを利用してみると、デフォルトでは何も登録されていないことが分かります。
$ curl -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/hosts/${HOSTID}/metadata {"metadata":[]}
ためしに、testというネームスペースを利用して投稿してみましょう。
なお、ネームスペース名についての制約については、メタデータAPIの説明をご参照ください。
$ curl -X PUT -H "Content-Type: application/json" -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/hosts/${HOSTID}/metadata/test -d '{"hoge":"fuga"}' {"success":true}
成功したようです。では一覧を再度確認してみましょう。
$ curl -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/hosts/${HOSTID}/metadata {"metadata":[{"namespace":"test"}]}
test namespace が登録されていることが分かります。では内容を取得してみましょう。
$ curl -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/hosts/${HOSTID}/metadata/test {"hoge":"fuga"}
さきほど登録した {"hoge":"fuga"} が取得できました。メタデータはこのように利用できます。
パッケージ一覧を出力するメタデータプラグインを作成し、mackerel-agentから定期取得するようにする
メタデータの使い方が分かったところで、例としてパッケージ一覧を取得し投稿してみようと思います。 上記の例ではAPIを利用しましたが、メタデータの投稿については mackerel-agent に以下のような設定を入れることで、command に指定したコマンドを定期実行し、その結果をメタデータに投稿してくれます。
# package ネームスペースに対して投稿する例 [plugin.meta.package] command = ["/path/to/metadata_plugin"]
そのため、今回は「パッケージ一覧をJSON形式で出力するプラグインを作成」し、「mackerel-agent.confに設定を記載し定期実行する」ことをやってみます。
というわけで試しに作ってみたのがこちら
#!/bin/sh # ----------------------------------------------------------------------------- # MIT License # Copyright (c) 2025 do-su-0805 # # このコードはMITライセンスに基づき提供されます。 # 詳細はブログ記事(https://do-su-dairyquestions.hatenablog.com/entry/2025/12/11/000347)を参照してください。 # ----------------------------------------------------------------------------- # インストール済みパッケージの一覧を作成 DNFLIST=$(mktemp) ## `dnf list --installed` コマンドでインストール済みパッケージの名前とバージョンの一覧を取得 dnf list --installed | tail -n +2 >> ${DNFLIST} # gojo を使って、`[{"name":"<package_name>","version":"<package_version"}]` 形式のJSONを作成し出力する ## [ ## { ## "name": "acl.x86_64", ## "version": "2.3.1-2.amzn2023.0.2" ## }, ## ... ## ] gojo -a $(while read LINE; do gojo name=$(echo ${LINE} | awk '{print $1}') version=$(echo ${LINE} | awk '{print $2}'); done < ${DNFLIST}) rm ${DNFLIST}
上記は dnf でパッケージ管理している環境にて、dnf list --installed コマンドからパッケージ一覧を取得し、それを gojo を利用して json 化して出力する例です。
実行すると以下のように、{"name":"パッケージ名","version":"バージョン"}の配列が出力されます。
$ ./list-dnf.sh [{"name":"acl.x86_64","version":"2.3.1-2.amzn2023.0.2"},{"name":"acpid.x86_64","version":"2.0.32-4.amzn2023.0.2"},{"name":"alternatives.x86_64","version":"1.15-2.amzn2023.0.2"},...
作ったプラグインを任意の場所に配置し、以下のように設定して mackerel-agent reload してみましょう。
# namespace に packages を指定する例。packages を置き換えることで任意の namespace を利用できます。 [plugin.meta.packages] command = ["/path/to/plugin"]
一覧をみると、packages namespaceが増えてます。
$ curl -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/hosts/${HOSTID}/metadata {"metadata":[{"namespace":"packages"},{"namespace":"test"}]}
取得してみると、先ほど実行した結果がそのまま格納されています。
$ curl -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/hosts/${HOSTID}/metadata/packages [{"name":"acl.x86_64","version":"2.3.1-2.amzn2023.0.2"},{"name":"acpid.x86_64","version":"2.0.32-4.amzn2023.0.2"},{"name":"alternatives.x86_64","version":"1.15-2.amzn2023.0.2"},...
これで、たとえば特定のロールを持つサーバ上で利用している特定パッケージの利用バージョン一覧が知りたいときなどに、mkr hosts -s <service> -r <role> の結果からホストID一覧を取得の上、メタデータAPIを利用して各サーバのパッケージ情報を確認できるようになりました。
ホストに投稿されたパッケージ一覧をもとに、カスタムダッシュボードにパッケージ一覧を表示する
メタデータはホスト詳細画面から確認できないので、目に見える形にしてみたいですよね。
ということで、ホストのメタデータからパッケージ一覧を取得し、ダッシュボードAPIを利用してダッシュボードのMarkdownウィジェットに投稿してみます。
下準備として、表示したいダッシュボードを用意し、その中にパッケージ一覧を取得するための Markdown ウィジェットを用意します。名前は何でもいいですし、内容もいったん適当でよいです。今回は以下のように「対象」というタイトルで、中身は「TEST」にしました。

準備ができたら、以下のようなスクリプトを用意して実行してみましょう。
注意点としては、ダッシュボードのIDについてはコンソール上から確認できないため、ダッシュボードの一覧APIや、CLIツール mkrを利用したmkr dashboards pullなどで確認する必要があります。
#!/bin/sh # ----------------------------------------------------------------------------- # MIT License # Copyright (c) 2025 do-su-0805 # # このコードはMITライセンスに基づき提供されます。 # 詳細はブログ記事(https://do-su-dairyquestions.hatenablog.com/entry/2025/12/11/000347)を参照してください。 # ----------------------------------------------------------------------------- HOSTID="<対象ホストID>" METADATA_NAMESPACE="<対象ホストでパッケージ一覧を投稿したnamespace名>" DASHBOARDID="<作成したダッシュボードのID>" DASHBOARDWIDGETNAME="<ダッシュボード内に作成したMarkdownウィジェットの名前>" # メタデータに投稿したパッケージ一覧(json)を取得する PACKAGELIST=$(curl -s -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/hosts/${HOSTID}/metadata/${METADATA_NAMESPACE}) # Markdownの表形式に変換する。ヘッダー行を差し込む。 MARKDOWN=$(echo ${PACKAGELIST} | jq '[null,"name","package",null],[null,"--","--",null],(.[] | [null,.name,.version,null]) | join("|")' -r) # 対象となるダッシュボードのjsonを取得 DASHBOARD=$(curl -s -H "X-Api-Key: ${MACKEREL_APIKEY}" https://api.mackerelio.com/api/v0/dashboards/${DASHBOARDID}) # 対象となるダッシュボード内のパッケージ一覧を表示したいウィジェットを、ウィジェットタイトルで絞り込んで内容を置き換える。 POSTDATA=$(echo $DASHBOARD | jq --arg markdown "${MARKDOWN}" --arg title "${DASHBOARDWIDGETNAME}" '.widgets |= map( if .title == $title then .markdown = ($markdown | @html) else . end )') # 置き換えたjsonを使ってダッシュボードを更新する curl -X PUT -H "X-Api-Key: ${MACKEREL_APIKEY}" -H "Content-Type: application/json" https://api.mackerelio.com/api/v0/dashboards/${DASHBOARDID} -d "$(echo ${POSTDATA})"
すると、先ほど作成したウィジェットにパッケージ一覧が投稿されました。

このスクリプトを定期的に実行することで、いつでもカスタムダッシュボード上でホストのパッケージ一覧が確認できます。
以下を参考に、ホスト上でダッシュボード更新スクリプトを実行させ、mkr wrapで実行監視するのもいいかもしれません。
終わりに
今回はMackerelのホストメタデータ機能を使ってパッケージ一覧の保存と、保存されたデータを利用してMarkdownウィジェットに表示するまでの例をご紹介しました。
さまざまな使い方ができる機能だと思いますので、ちょうどよい用途があればぜひ使ってみてください。
Mackerelの公式メトリックプラグインとOpenTelemetry Receiverの取得内容の比較 : NGINX 編
Mackerel - Qiita Advent Calendar 2024 - Qiita 3日目の記事です。
2日目は
id:missasan の Mackerel CREチーム ディレクターが育休復帰3ヶ月でやったこと - missasan's notebook でした。
id:missasan が復帰してから、そのブランクを感じさせない大立ち回りっぷりを見せており、さすがだなぁと同じチームメンバーとして感じていたのですが、そのまとめと背景についての記事となっておりました。ここ最近のMackerelの活動まとめにもなっております。ぜひご一読いただければと思います。
こんにちは、
id:do-su-0805 です。仕事では
id:do-su-0805 を利用していますが、普段は
id:do_su_0805 として生活しています。
はてなでは約5年ほど Platform SRE を担当した後、2023/05 よりMackerel CREチームでテクニカルサポートを担当しております。
2024年3月にOpenTelemetry 対応(パブリックベータ)提供開始 - Mackerel ブログ #mackerelioでのお知らせ以後、2024年11月、Mackerelのメトリックがオブザーバビリティ標準であるOpenTelemetryに正式対応し、あわせて価格体系を全面的に改定します - Mackerel ブログ #mackerelioや、Mackerelはオブザーバビリティプラットフォームとして進化していきます - Mackerel ブログ #mackerelio などでもお知らせしているように、MackerelはOpenTelemetryに対応する機能を公開・拡充し続けています。
詳しくは過去の公開記事等を参照いただけたらと思いますが、今回はOpenTelemetry Metricsに関するお話です。
OpenTelemetry Metricsに対応しました!といっても「いままでmackerel-agentで監視していたものから移行できるのかな?」という不安・懸念へのご案内の一つとして、NGINXの監視を題材とし、Mackerel公式プラグインである mackerel-plugin-nginx と、OpenTelemetry Collector の Receiver である NGINX Receiver での取得方法や取得内容を比較してみました。
mackerel-plugin-nginxを利用したメトリック取得設定の方法や、NGINX Receiver を利用したメトリック取得設定の方法については、以下をご参照ください。
- mackerel-plugin-nginx : ミドルウェアのメトリック可視化に公式プラグイン集を使う - Mackerel ヘルプ
- NGINX Receiver : Mackerel で OpenTelemetry のラベル付きメトリックを使ってみよう - Mackerel ブログ #mackerelio
NGINX のメトリック取得に必要な NGINX の設定について
取得に関しては、いずれも取得用の機構(プラグイン,Receiver)実行時に、ngx_http_stub_status_moduleの結果を提供するパスにアクセスする仕組みになっており、差分はありません。
mackerel-plugin-nginx
メトリックプラグイン - mackerel-plugin-nginx - Mackerel ヘルプ
mackerel-plugin-nginxは、実行された際にngx_http_stub_status_moduleの結果をパースしメトリックとして投稿しています。
NGINX Receiver
NGINX Receiverは、Receiverとして設定を有効にしたCollectorが起動した場合に、ngx_http_stub_status_moduleの結果をパースしメトリックとして投稿しています。
投稿されるメトリックについて
投稿されるメトリックに関しては、mackerel-plugin-nginxとNGINX Receiverではグルーピングの違いや差分値計算の有無といった違いがあります。*1
mackerel-plugin-nginx
プラグインヘルプ内監視できるメトリックに記載の通り、"Nginx Connections","Nginx requests","Nginx connection status"の3種類にグルーピングされた状態で投稿されます。

NGINX Receiver
opentelemetry-collector-contrib/receiver/nginxreceiver/documentation.md at main · open-telemetry/opentelemetry-collector-contrib に記載の通り、"nginx.connections_accepted","nginx.connections_current","nginx.connections_handled"の3種類にグルーピングされた状態で投稿されます。

投稿されるメトリックの比較
グルーピングの違い
現在の接続数を示すメトリックは、mackerel-plugin-nginxでは"Nginx Connection"に含まれる"Active connections"(custom.nginx.connections.connections)として投稿されていますが、NGINX Receiverでは"nginx.connections_current"として投稿される4本のうちstate="active"である1本になっています。


現在の接続数の内訳を示すメトリックは、mackerel-plugin-nginxでは"Nginx connection status"に含まれる"Reading"(custom.nginx.queue.reading),"Writing"(custom.nginx.queue.writing),"Waiting"(custom.nginx.queue.waiting)としてグルーピングされ投稿されており、NGINX Reveiverでも"nginx.connections_current"として投稿される4本のうちstate="reading",state="writing","state="waiting" の3本になっています。

受け付けたクライアント数や処理した接続数などを示すメトリックは、mackerel-plugin-nginxでは"Nginx requests"に含まれる"Accepted connections"(custom.nginx.requests.accepts),"Handled connections"(custom.nginx.requests.handled),"Handled requests"(custom.nginx.requests.requests)としてグルーピングされ投稿されていますが、NGINX Receiverでは"nginx.connections_accepted","nginx.connections_handled","nginx.requests"として投稿される1本のメトリックとして分かれて投稿されています。

確認できるメトリックの差分
上記「グルーピングの違い」に示した図を見ていただくと分かるように、受け付けたクライアント数や処理した接続数などを示すRequest,Accepts,Handledを表現するメトリックのみ、mackerel-plugin-nginxとNGINX Receiverでは値が異なっています。 mackerel-plugin-nginxでは差分値(前回の取得値との差分)となっており、NGINX Receiverでは累積値(ngx_http_stub_status_moduleが返す値をそのまま利用)となっています。
ただし、当方の検証環境では NGINX Receiver を利用した ngx_http_stub_status_module の結果取得をするためのリクエストにて"accepts"ならびに"handled"が増加せず、"requests"のみが増加する様子を確認しており*2、 実際に利用する際にはご自身の環境での出力の様子を併せてご確認いただき、必要な差分計算等をCollectorや利用時のPromQLにて実施いただくとよいと思います。
監視設定例
NGINX への現在の接続数が100を超えた場合にアラートを上げる例を紹介します。
mackerel-plugin-nginxを利用している場合は、以下のように custom.nginx.connections.connections メトリックに対してホストメトリック監視を作成いただくことで監視が可能です。

NGINX Receiverを利用している場合は、以下のように nginx.connections_current{state="active"} を対象にクエリによる監視を作成いただくことで監視が可能です。必要に応じてさらにラベルによる絞り込みなどを設定してください。

まとめ
Mackerelの公式メトリックプラグインであるmackerel-plugin-nginxと、OpenTelemetry Receiverである NGINX Receiver での取得内容について見ていきました。 一部、NGINX Receiverを利用する際は差分計算が必要な点は調整が必要となるかもしれませんが、取得内容としては同様の内容であるため、既存の監視から ためしにシフトしやすいものなのではないかと思います。
CREは仲間を探しています
CREは仲間になってくれる人を探しています。気になった人はぜひお声がけください。
明日の Mackerel Advent Calendar 2024 は
id:RyuGoo の記事です。12/02時点で書き終えているとのことでしたので、お楽しみに。
個人AWSアカウントでNATGWの料金がしんどかったので、NATインスタンスに置き換えた
あまり活用できていないんだけど、ちょっとした物置としてAWSアカウントを1つ運用している。 初期導入などのためにNATGWを配置していたんだけど、ご存じの通り結構な料金が発生する。

NATGW自体は素晴らしいサービスだと思っているが、やはり個人ユーズにはきつい費用である。
詳しい損益分岐点をちゃんと計算したわけではないが、全然通信しないようなNATGWならインスタンスに置き換えたほうが安いに決まっているだろうと、実際に置き換えた。
NATインスタンスの作り方はいろいろとあるが、今回は fck-nat を採用した。 上記公式サイトを参照してスムーズに構築できた。

見てわかるように、大幅に費用削減できた。

見てわかるように全然通信していない。しばらくはこれでよいだろう。
Zendesk explore の「ベータ版ビルダー」を利用したダッシュボードにおける高さを素早く伸ばす Tips
小ネタです。
Zendesk explore でダッシュボードを作成する時、従来版とベータ版の2種類を 2023/07/21 現在は選択できます。

このうち、ベータ版を利用する際にダッシュボードの高さを伸ばすためのテクニックの紹介です。
なお、従来版であれば、「タグオプション」に高さのオプションが、「ダッシュボード」に幅のオプションがあるため、数値で変更することができます。 ( thx to
id:tukaelu )
やり方
まずはベータ版ビルダーを使って、表示されている高さと一致するようなウィジェットを2つ配置します。

次に、配置したウィジェットのうち片方を掴み、もう片方の上に持っていきます。

最後に、上に配置したウィジェットの右下を掴み、サイズ変更ができるようになったら、スクロールをかけ、止まったらちょっと掴んだままマウスを下にづらし、またスクロールをかけ...を繰り返します。

M1 Mac と Type-C モニター(USB-A ハブ付き) の相性
MBP2021 (M1/13inch) と HP U28 4K における話。
U28 4K の USB ハブに HHKB Pro2 Type-S と Scarlett Solo Gen.3 (オーディオインターフェース) を挿して、 USB Type-C ケーブルで MBP と繋いでる。
なんとなくわかってきた相性として、「起動時にType-C 挿しっぱなし」だとほぼほぼ USBインターフェースが認識しない(ディスプレイとしては認識する)。そのタイミング〜ログイン画面では USB ハブ側のケーブルも、Type-C ケーブルも抜き差ししたところでなかなか認識されない。たまに認識されるがなぜかはわからない。
が、一度ログインしてデスクトップまで行ってから Type-C ケーブルを抜き差しすると(記憶が確かなら)100%認識する。
不思議。一瞬オーディオインターフェースの起電力的なあれか?とか思ったけど、別に HHKB だけ挿してもさほど症状は変わらなかった。
「頭が冴える! 毎日が充実する! スゴい早起き」を読んだ
注意
感想記事を書くにあたって、「ブログや scrapbox といった公共発信においてどこまで内容などに触れて良いか」を軽く調査しました。
結果として、「引用や翻案権に注意する」「表紙の写真は貼らない」などのポイントが見えてきたのでそれを実践しつつ記載して見ます。
何か問題などありましたら do_su_0805 (@do_su_0805) | Twitter までよろしくお願いいたします。
慣れてきたりもう少しまとまってきたらそちらもブログに書けたらと思います。
読んだ本
https://www.amazon.co.jp/dp/B07KWLFXX1/
ISBN-10 : 4799107771 ISBN-13 : 978-4799107775
感想
はじめに、僕は結構この手の本を読むのを諦めることが多い。
理由としては、ライフスタイルなどに関する本において、大体筆者の行動のきっかけに共感ができなかったり、差し込みにイラッとすることが多いからである。 *1
今回もそうかなぁ... とビクビクしながら読んでみたところ、そこまでのものはなく「そういうことがしたかったんだね」くらいに思える程度での紹介などで読みやすかったというのが助かった。*2.
タイトルの通り、「早起きをして活動を行うとどういうメリットがあるか」という話ではあるんだが、筆者の体験や経験、理論に基づいて「別の誰か」に実践したもらった時のストーリーや結果があるのがパターン評価できてよかった。
結構「とにかく早起きはすごいんだ!」みたいな論調になる本を見かけるけど、この本だと「この人はこういう目標がある中こういうことに困っていた。そこで早起きをして活動時間を確保したところ、こういうメリットを享受できて、結果目標を達成できた(ないしはできそうである)」という流れでの紹介が何パターンもあり、自分の場合どういう実践が取れるかという参考になるのがとてもよかった。
また、心理学的なメソッドやパターンを紹介しつつ、それに当てはめた説明がなされることも納得感がありよかった。根性論みたいな話題でもないので心穏やかな気持ちで読み進めることができた。
少し引いた視点で読んでみると、「早起きをするという『活動』を継続するためのメソッド」をさまざまに説明してくれている本でもあるので、任意の活動に置き換えた時のアプローチパターンという読み方もできるな、と終盤気づいてこれは新鮮な気持ちになった。
( ただし、具体的なメソッドを省いて要約するとつまりは PDCA なんだな、ということもなんとなくわかり、PDCA!PDCA! と叫ぶだけではなくて、それが自然と遂行されるような具体的なメソッドまで落とし込んで説明・理解することが大事なんだな、ということにも気づいて面白かった )
終わりに
今日遭遇した ShellCheck
久々に shellscript 書いていたら二つほど koalaman/shellcheck: ShellCheck, a static analysis tool for shell scripts に注意されたのでメモ
SC2003 expr is antiquated. Consider rewriting this using $((..)), ${} or [[ ]].
SC2003 · koalaman/shellcheck Wiki
shellscript の中で expr を使ったところ食らった。シェルコマンドに組み込まれている奴らを使いなさいな、とのこと。
自然と expr ${i} + 1 書きがちだし気をつけようと思った
SC2012 Use find instead of ls to better handle non-alphanumeric filenames.
SC2012 · koalaman/shellcheck Wiki
とあるフォルダ配下に、実行後のログファイルを連番でおいていこうとした時に、ついこう書いてしまった。
count=$(ls ${dir} | wc -l) if [ "${count}" == "" ]; then ${count}=0 fi filenum=$(expr ${count} + 1)
これも (*.gz) とか知らなかったし、さっきの SC2003 にもあった #var とかも全然使ってないのでふむふむといいながらやっていた。
今回の場合は、count=$(find ${dir} -maxdepth 1 -type f -name "*.csv.gz" | wc -l) にした。一応いいところ取りのつもりではある。
余談
- alphanumeric : 英数字 はえ〜ってなった。
おまけ : VSCode で ShellCheck
timonwong/vscode-shellcheck: An extension to use shellcheck linter in vscode があるので是非使いましょう。便利