fluentdの設定ファイルをテンプレートから生成する

繰り返し同じ設定を記述するfluentdの設定ファイルをスクリプトを使ってテンプレートから生成してみました。
2022.09.30

はじめに

最近古めのtd-agent (v2.x)を最新のfluentd(v1.15)にアップデートする作業をしていました。この環境ではfluent-plugin-forestを使っていましたが、このプラグインは既にメンテナンスされていないのでこのまま使い続けるのは避けたいです。fluetnd v0.14以降一部のプラグインではtag placeholderを使った置換が行えるのですが、今回のケースで使用しているプラグインが対応していないため使用することができません。苦肉の策ですが設定ファイルをテンプレート化してタグ名の置換を自前で行うことにしました。

やること

fluentdはコンテナ上で動作させるのでイメージのビルド時に設定ファイルの生成を行うことにします。今回展開するタグのパターンは既知であるとします。

テンプレートファイル

テンプレートファイルは下記の通りになります。このファイルの${tag[N]} をタグ名に置換します。

<match mop.${tag[0]}.${tag[1]}>
  @type cloudwatch_logs
  @id ${tag[0]}-${tag[1]}-cwl
  region ap-northeast-1
  log_group_name my-app
  auto_create_stream true
  use_tag_as_stream true
  <buffer tag>
    @type file
    path /var/log/td-agent/buffer/${tag[0]}_${tag[1]}.log/cwl
    chunk_limit_size 128m
    flush_mode interval
    flush_interval 30s
    flush_at_shutdown true
  </buffer>
</match>

スクリプト

スクリプトは以下のようになります。タグのリストをテンプレートに置換しながらたたみ込みます。

# 設定テンプレートから設定ファイルを生成する
# 生成する設定ファイルには使用するタグの数だけ複製されたテンプレートファイルの内容が含まれる。

# template_fileで示す設定テンプレートファイルの中身をtagsの要素数だけ繰り返す。
# テンプレート中のタグを表す表記`${tag[N]}`はタグに置換される。
def expand_tags(tags, template_file)
  template  = File.read(template_file)
  tags.map {|tag| replace_tag(tag, template)}.join("\n\n")
end

# template文字列内の`${tag[N]}`をタグの各パーツに置換する
def replace_tag(tag, template)
  parts = tag.split('.')
  # 以下の置換を繰り返し実行する: ${tag[0]} => tag[0], ${tag[1]} => tag[1], ....
  template = parts.each_with_index.inject(template) do |acc , (part, index)|
    acc.gsub(/\$\{tag\[#{index}\]\}/, part)
  end
end

TAGS = %w[
  app.access
  app.audit
  worker.error
]

File.write(File.join(__dir__, 'out.conf'), expand_tags(TAGS, File.join(__dir__, 'template.conf')))

実行結果

Rubyスクリプトに定義したタグがテンプレート内のプレースホルダに置換されて展開されました。

<match app.access>
  @type cloudwatch_logs
  @id app-access-cwl
  region ap-northeast-1
  log_group_name my-app
  auto_create_stream true
  use_tag_as_stream true
  <buffer tag>
    @type file
    path /var/log/td-agent/buffer/app_access.log/cwl
    chunk_limit_size 128m
    flush_mode interval
    flush_interval 30s
    flush_at_shutdown true
  </buffer>
</match>

<match app.audit>
  @type cloudwatch_logs
  @id app-audit-cwl
  region ap-northeast-1
  log_group_name my-app
  auto_create_stream true
  use_tag_as_stream true
  <buffer tag>
    @type file
    path /var/log/td-agent/buffer/app_audit.log/cwl
    chunk_limit_size 128m
    flush_mode interval
    flush_interval 30s
    flush_at_shutdown true
  </buffer>
</match>

<match worker.error>
  @type cloudwatch_logs
  @id worker-error-cwl
  region ap-northeast-1
  log_group_name my-app
  auto_create_stream true
  use_tag_as_stream true
  <buffer tag>
    @type file
    path /var/log/td-agent/buffer/worker_error.log/cwl
    chunk_limit_size 128m
    flush_mode interval
    flush_interval 30s
    flush_at_shutdown true
  </buffer>
</match>

まとめ

fluentdの設定ファイルをテンプレートから生成してみました。実際に生成される設定ファイルは冗長ですが同じ設定を繰り返し適用し、コンテナにデプロイする(設定ファイルを手動で偏抗すことがない)前提があれば管理にもそれほど苦労しないのではと思います。