はじめに
新しく立てたlinux2のインスタンスにansibleでtd-agentの最新版を入れたのでその手順を記します。
目次
1. 対応バージョンの確認
まず古いlinuxAMIのEC2で使っていた既存のtd-agentのバージョンを確認しました。
td-agent v2でした。中身はfluentd v0.12です。
$ td-agent --version
td-agent 0.12.40 # ここで表示されるのはtd-agent内部で使用されてるfluentdのバージョン
td-agentはfluendと呼ばれるクロスプラットフォームのオープンソースデータ収集ソフトを簡易に利用できるようにした安定版パッケージなので、中身はfluentdみたいです。
td-agent と fluentd の違い
tg-agentの公式サイトで現在の推奨バージョンを確認します。
td-agent v2 vs v3 vs v4
v2はとても古いためAmazonLinux2は未対応。
td-agent v2
This is for v0.12 and old distribution users. We don't recommend this version for new deployments.
v3は古い安定版で、内部でRuby2.4が使用。
td-agent v3
Old stable.
Ruby 2.4
Fluentd v1
Windows Support
Remove fluentd-ui from the package
v4は最新の安定版で、内部でRuby2.7が使用。
td-agent v4
New stable. Major feature updates to td-agent v4 are as follows:
Ruby 2.7
Fluentd v1
Arm64 Support
See also Changes from Treasure Agent 3.
ログ収集はユーザーの行動分析やサイトのモニタリングなどに使う非常に重要な処理なので、とりあえず最新の安定版を入れておこうとtd-agent v4を使うことに決めました。
2. 使用してるプラグインの確認
td-agentは、ログのフィルタリングができたり、ログのインプット、アウトプット先などを連携するプラグインに応じて変更するなど、柔軟にカスタマイズができるみたいです。
既存のtd-agent.confを読んで、fluent-plugin-forestとfluent-plugin-bigqueryのプラグインが使われていることを確認しました。
これらも一旦今回のインスコ対象に含めることにしました。
3. playbookの作成
今回は5台のサーバに入れる必要があったので、ansbileのplaybookを作成しました。
手順書って理解するのに時間かかったり抜け漏れが怖かったりするし、再現性も担保されないから、こういう時にplaybookがすぐ作れると便利だなと思いました。
ただ、ansibleの書き方ってweb上にある記事を色々見た印象だと人によってもかなり違うし、versionの違いで記法も変わるし、環境ごとに独自のやり方を取ってたりするので、他人のplaybookをそのまま流用するのはほぼ不可能で、部分的に拝借してくっつけて利用するのが良いなという印象です。
(AnsibleRole化されてる場合は環境ごとの再現性も担保されてるはずなので使用しても問題ないはず)
参考までに自分が書いたplaybookを掲載
- hosts: all
  vars_files:
    - vars/{{ inventory_hostname }}.yml
  any_errors_fatal: true
  gather_facts: no
  user: my_user
  become: true
  tasks:
    - name: test
      debug:
        msg: "接続先ホスト名: {{ inventory_hostname }}"
    - name: Create my_user_keys directory for td-agent
      file: path="/home/my_user/my_user_keys" state=directory owner=my_user group=my_user mode=0775
    - name: Put my_user_key.json
      template: src=my_user_key.j2 dest=/home/my_user/my_user_keys/my_user_key.json backup=true owner=my_user group=my_user mode=0644
    - name: Install td-agent v4
      shell:
        cmd: /bin/bash -lc "curl -L https://toolbelt.treasuredata.com/sh/install-amazon2-td-agent4.sh | sh"
      become: yes
    - name: Put action_schema.json
      template: src=td-agent/action_schema.json.j2 dest=/etc/td-agent/action_schema.json backup=true owner=my_user group=my_user mode=0644
    - name: Put td-agent.conf
      template: src=td-agent/td-agent.conf.j2 dest=/etc/td-agent/td-agent.conf backup=true owner=my_user group=my_user mode=0644
    - name: Install td-agent-gem plugin fluent-plugin-bigquery
      shell:
        cmd: /bin/bash -lc "td-agent-gem install fluent-plugin-bigquery"
      become: yes
    - name: Install td-agent-gem plugin fluent-plugin-forest
      shell:
        cmd: /bin/bash -lc "td-agent-gem install fluent-plugin-forest"
      become: yes
    - name: Setting root user
      lineinfile:
        dest: /usr/lib/systemd/system/td-agent.service
        backrefs: yes
        regexp: ^User=
        line: User=root
        state: present
    - name: Setting root group
      lineinfile:
        dest: /usr/lib/systemd/system/td-agent.service
        backrefs: yes
        regexp: ^Group=
        line: Group=root
        state: present
    - name: Enabled and Running td-agent
      systemd:
        name: td-agent
        daemon_reload: yes
        state: restarted
        enabled: yes
playbookの解説
- 
td-agentのインスコ前に、Bigqueryとの接続のために使うApiKeyを配置してます。 - 
AmazonLinux2用のtd-agent v4インストールコマンドは公式にあります。 - 
td-agentのインスコ後は、ログのスキーマ定義用のjsonファイルと設定ファイルを配置してます。 - その後、
td-agent-gemコマンドを使ってプラグインをインスコしてます。 - 
td-agentの実行ユーザーをtd-agentでなくrootに変更したくて、起動時に読み込んでるsystemdのファイルをlineinfileモジュールを使って書き換えてます。 - 書き換え処理が終わったら
daemon_reloadで設定を読み込んだあと、リスタートさせてます。 
ハマりポイント
- conf内で使ってるプラグイン(
td-agent-gem)が入っていないと、こういうエラーがでます。プラグイン依存をやめてconfを書き換えれる場合はそのほうがいいですが、ダメならプラグインを入れましょう。 
fluent/log.rb:369:error: config error file="/etc/td-agent/td-agent.conf" error_class=Fluent::ConfigError error="Unknown output plugin 'forest'. Run 'gem search -rd fluent-plugin' to find plugins"
今回入れたプラグイン
$ td-agent-gem list
fluent-plugin-bigquery (2.2.0)
fluent-plugin-forest (0.3.3)
- バージョン確認の省略コマンドはない
 
$ td-agent -vでバージョン確認しようとするとなぜかバージョンが表示されずstdoutにログが垂れ流されてきて謎だったんですが、単にコマンドが--versionしかないだけでした。
この時、fluent/log.rb:369:error: unexpected error error_class=Errno::EADDRINUSE error="Address already in use - bind(2) for 0.0.0.0:24224"
というエラーが出て24224ポートが既に使用中なのだと勘違いし、よくあるエラーか?とこの記事を見ながらプロセスを消して立ち上げ直したりなどしてましたが徒労でした。
- 実行ユーザーを
rootに変更 
最初にお試し導入したときに実行ログを眺めてると、このようなエラーに出会いました。
fluent/log.rb:369:error: unexpected error on reading data host="127.0.0.1" port=54444 error_class=Fluent::Plugin::Buffer::BufferOverflowError error="can't create buffer file for /var/log/td-agent/buffer/action_rack/buffer.*.log. Stop creating buffer files: error = Permission denied @ rb_sysopen - /var/log/td-agent/buffer/action_rack/buffer.b5b62c41c60856775a9a0b08a26f55fac.log"
/var/logの所有者はrootユーザーなので、Permission deniedでBufferファイルの生成に失敗してるようです。
td-agent で /var/log/messages の情報を読み込めないの記事を参考にしつつ、td-agentの実行ユーザーがデフォルトだとtd-agentになっているのをrootに修正することにしました。
# 起動時に読み込んでるファイルを確認するためにstatusを開く
$ sudo systemctl status td-agent.service
● td-agent.service - td-agent: Fluentd based data collector for Treasure Data
   Loaded: loaded (/usr/lib/systemd/system/td-agent.service; enabled; vendor preset: disabled) # ここが起動時設定ファイル
   Active: active (running) since 金 2020-12-11 19:19:55 JST; 11h ago
     Docs: https://docs.treasuredata.com/articles/td-agent
  Process: 5133 ExecStop=/bin/kill -TERM ${MAINPID} (code=exited, status=0/SUCCESS)
  Process: 5142 ExecStart=/opt/td-agent/bin/fluentd --log $TD_AGENT_LOG_FILE --daemon /var/run/td-agent/td-agent.pid $TD_AGENT_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 5151 (fluentd)
   CGroup: /system.slice/td-agent.service
           ├─5151 /opt/td-agent/bin/ruby /opt/td-agent/bin/fluentd --log /var/log/td-agent/td-agent....
           └─5154 /opt/td-agent/bin/ruby -Eascii-8bit:ascii-8bit /opt/td-agent/bin/fluentd --log /va...
上記のsystemdの設定ファイル内にUser=td-agent、Group=td-agentと記載されてるので、そこをansibleのlineinfileを使って正規表現検索をかけて、rootに書き換えます。
そして、設定ファイルを再度読み込ませるためにdeamon_reloadしてrestartすればrootで実行されるので解決です。
(ちなみにansibleのserviceモジュールではdeamon_reloadはできず、systemdモジュールが完全に上位互換に見えたので、サービスの自動起動設定などの際はsystemdモジュールを使うのがオススメです。)
4. playbookの実行
td-agent v4(fluentd v1.11.2)が無事インストールされました。
$ td-agent --version
td-agent 1.11.2
5. 動作確認
ログの確認
$ tail -f /var/log/td-agent/td-agent.log
Bigqueryでの計測データ確認
SELECT FORMAT_TIMESTAMP('%Y-%m-%d %H:%M:%S', TIMESTAMP_SECONDS(time), 'Asia/Tokyo') AS date, message FROM `my_project.my_dataset.action_rack_20201211` ORDER By date DESC limit 100
両方に問題なければおkです。
おしまい
(余談:td-agentがエラーを吐いたときにアラートを出す仕組みがあるとよさそうです。ログ欠損怖い。)