㊙️
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
jqを駆使したクラウド・リソース統計の自動集計:group_byとreduceによる高効率なログ分析
【導入と前提】 APIから取得した肥大なJSON配列を、ステータスや属性ごとに集計・要約する処理を自動化します。本ガイドでは、大規模なリソース一覧を「人間が読める統計データ」へ堅牢に変換するSRE手法を解説します。
実行環境:GNU/Linux (Ubuntu/RHEL/CentOS)
必須ツール:
jq(1.6以上推奨),curl,bash
【処理フローと設計】
graph TD A["API/Log Input"] -->|curl/cat| B["jq: group_by"] B -->|Array of Arrays| C["jq: map/reduce"] C -->|Structured JSON| D["Output: Summary/Alert"] D -->|Optional| E["Systemd Timer: Periodic Check"]
group_byで特定のキーごとにデータを分類し、reduceまたはmapを用いて要素数(length)や特定値の合計を算出します。このパイプラインにより、スクリプト側での複雑なループ処理を排除し、処理の高速化と記述の簡素化を実現します。
【実装:堅牢な自動化スクリプト】 以下は、インスタンス一覧を取得し、ステータスごとのカウントとIDリストを生成するスクリプト例です。
#!/usr/bin/env bash
# --- 安全なシェル設定 ---
set -euo pipefail
# -e: エラー発生時に即座に終了
# -u: 未定義変数参照時にエラー
# -o pipefail: パイプライン途中のエラーを伝播
# 作業用の一時ファイルをクリーンアップするトラップ
TMP_FILE=$(mktemp /tmp/resource_stats.XXXXXX.json)
trap 'rm -f "$TMP_FILE"' EXIT
# --- データ取得シミュレーション (実際はAPI call) ---
# 本来は curl -sfL "https://api.example.com/v1/instances" 等を利用
cat << 'EOF' > "$TMP_FILE"
[
{"id": "i-1", "type": "t3.micro", "status": "running"},
{"id": "i-2", "type": "t3.small", "status": "stopped"},
{"id": "i-3", "type": "t3.micro", "status": "running"},
{"id": "i-4", "type": "m5.large", "status": "running"},
{"id": "i-5", "type": "t3.small", "status": "stopped"}
]
EOF
echo "--- Generating Resource Summary ---"
# --- jqによる高度な集計処理 ---
# 1. group_by(.status) でステータスごとに配列をネスト
# 2. map() で各グループを {status, count, ids} のオブジェクトに変換
jq -r '
group_by(.status)
| map({
status: .[0].status,
count: length,
ids: map(.id)
})
' "$TMP_FILE"
# --- reduceを用いた特定の属性(type)の出現頻度集計 ---
echo "--- Aggregating Instance Types (using reduce) ---"
jq -r '
reduce .[] as $item ({}; .[$item.type] += 1)
' "$TMP_FILE"
定期実行が必要な場合は、以下のsystemdユニット(例)を活用します。
# /etc/systemd/system/resource-summary.timer [Unit] Description=Run Resource Summary every hour [Timer] OnCalendar=hourly Persistent=true [Install] WantedBy=timers.target
【検証と運用】
正常系の確認: 上記スクリプトを実行し、
runningとstoppedが正しくグルーピングされ、countが一致することを確認します。ログの確認: systemdタイマーで実行する場合、以下のコマンドで実行ログを確認できます。
journalctl -u resource-summary.service空データの挙動: 入力JSONが空配列
[]の場合、group_byは空配列を返し、エラーにならないことを確認済みです。
【トラブルシューティングと落とし穴】
group_byのソート特性:group_byは指定されたキーで入力をソートしてからグループ化します。巨大なJSON(数万行以上)を処理する場合、メモリ消費量が増加するため、ストリーム処理(jq --stream)の検討が必要になる場合があります。権限問題: APIキーなどの認証情報を環境変数から読み込む際、
set -uにより未定義エラーを防げますが、exportする際は、~/.bashrc等に平文で置かず、Secret Management ツール(AWS Secrets Manager 等)を介することを推奨します。一時ファイルの漏洩防止:
mktempとtrapの組み合わせを欠かさないようにしてください。
【まとめ】 運用の冪等性と堅牢性を維持するための3つのポイント:
処理の局所化:複雑な集計ロジックをBashのループで書かず、
jqの中で完結させる。エラーの早期検知:
set -euo pipefailを必須とし、パイプラインの失敗を無視しない。リソースのクリーンアップ:
trapシグナルハンドリングを使い、異常終了時もゴミを残さない。


コメント