外部API連携による設定ファイルの動的YAML生成とSystemd管理の自動化

Tech

META: [TITLE] JSON/YAML相互変換による設定ファイル動的生成の自動化パイプライン [SRE_LEVEL] Senior [TAGS]

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

外部API連携による設定ファイルの動的YAML生成とSystemd管理の自動化

【導入と前提】

APIから取得したJSONメタデータを、システムが要求するYAML形式へ安全に変換し、systemdによるライフサイクル管理までを自動化します。

  • 前提条件:

    • OS: Linux (Ubuntu 22.04+ / RHEL 8+ 推奨)

    • ツール: curl, jq (JSON処理), yq (YAML処理/v4以降), systemd

【処理フローと設計】

graph TD
A["外部API / JSONソース"] -->|curl| B("テンポラリJSON保存")
B -->|jq filter| C{"データ整形"}
C -->|yq conversion| D["プロダクションYAML設定"]
D -->|Validation| E["Systemd Service Reload"]
E -->|Success| F["一時ファイル削除"]
E -->|Failure| G["ロールバック/通知"]

このフローでは、データの取得から反映までをアトミックに実行します。中間ファイルに mktemp を使用することで、競合状態を防止し、yq による厳密なスキーマ検証を経てから本番環境へ配置します。

【実装:堅牢な自動化スクリプト】

#!/usr/bin/env bash

# ---------------------------------------------------------


# 設定ファイル動的生成スクリプト


# ---------------------------------------------------------

set -euo pipefail  # エラーで停止、未定義変数禁止、パイプエラーの伝播
trap 'cleanup' EXIT # 終了時に一時ファイルを確実に削除

# 定数定義

API_ENDPOINT="https://api.example.com/v1/config"
DEST_CONFIG="/etc/myapp/config.yaml"
TMP_JSON=$(mktemp /tmp/config.XXXXXX.json)
TMP_YAML=$(mktemp /tmp/config.XXXXXX.yaml)

# クリーンアップ関数

cleanup() {
    rm -f "$TMP_JSON" "$TMP_YAML"
}

echo "INFO: 設定の取得を開始します..."

# 1. リトライ付きでJSONを取得


# -s: 進捗非表示, -S: エラー表示, -f: HTTPエラー時に失敗, -L: リダイレクト追従


# --retry: 通信失敗時のリトライ回数

curl -sSfL --retry 3 "$API_ENDPOINT" -o "$TMP_JSON"

# 2. jqによるフィルタリングとyqによるYAML変換


# jq -r: 生の文字列を出力


# yq eval: プロパティの置換やフォーマット変換

cat "$TMP_JSON" | \
    jq -r '.data | .env="production"' | \
    yq eval -P > "$TMP_YAML"

# 3. 妥当性チェック(スキーマ検証の代用)

if ! yq eval 'has("database")' "$TMP_YAML" > /dev/null; then
    echo "ERROR: 必須パラメータ 'database' が欠落しています。" >&2
    exit 1
fi

# 4. アトミックな配置と権限設定


# sudo権限が必要な場合は、実行ユーザーに適切なsudoers設定が必要

sudo install -m 644 -o root -g root "$TMP_YAML" "$DEST_CONFIG"

# 5. Systemdユニットのリロード

if systemctl is-active --quiet myapp.service; then
    echo "INFO: サービスの再読み込みを実行します..."
    sudo systemctl reload myapp.service
fi

echo "SUCCESS: 設定ファイルの更新が完了しました。"

Systemd Timerによる定期実行(例)

/etc/systemd/system/config-sync.timer

[Unit]
Description=Run config sync every 30 minutes

[Timer]
OnBootSec=5min
OnUnitActiveSec=30min
Unit=config-sync.service

[Install]
WantedBy=timers.target

【検証と運用】

  1. 正常系の確認:

    • スクリプトを手動実行し、$DEST_CONFIG の中身が期待通りのYAML構造になっているか確認。

    • journalctl -u config-sync.service で実行ログを確認。

  2. エラー時のログ確認:

    • systemctl status config-sync.service で終了ステータスを確認。

    • JSONが不正な場合、jq が標準エラー出力に吐き出すパースエラーを確認。

【トラブルシューティングと落とし穴】

  • 権限問題: sudo install を使用していますが、自動化スクリプトを実行するユーザー(例: deploy-agent)には、特定のコマンド実行(systemctl reload等)をパスワードなしで許可する visudo 設定が必要です。

  • 環境変数の漏洩防止: APIキーなどをスクリプトに直書きせず、export された環境変数や AWS Secrets Manager 等から注入してください。

  • yqのバージョン互換性: Python版 yq と Go版 yq (mikefarah/yq) は構文が異なります。本稿では主流の Go版 (v4) を前提としています。

  • 一時ファイルの放置: set -e で停止しても trap が実行されるよう設計していますが、ディスクフル等の極端な状況下では手動確認が必要です。

【まとめ】

運用の冪等性を維持するための3つのポイント:

  1. アトミックな書き換え: 一時ファイルで生成・検証を終えてから mv または install で一気に置換する。

  2. 検証の強制: 変換直後に yqjq で必須キーの存在チェックをかけ、不完全な設定をデプロイしない。

  3. 状態の可視化: 成功・失敗を標準出力/標準エラー出力に明確に分離して吐き出し、systemd-journal で追跡可能にする。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました