LoginSignup
0
1

More than 3 years have passed since last update.

ECSのログをSplunkに送る

Posted at

はじめに

この記事ではEC2 HostingのECSにデプロイしたアプリケーションのログをSplunkにインデックスする方法についての記事を書きます
Fargateについては別の記事に書きます

概要

ECSのログはコンテナごとにLog Driverを選択することでログの出力先を指定できます
Splunkにはre:Invent 2019で発表された FireLens を使ってログを送ります
log_routerはFluentdです(Fluent Bitじゃないよ)

Log DriverにSplunkを指定することもできますが、あえてFireLensのfluentdを使います
理由は↓

  • fluentdを使うことでSplunkが障害やメンテナンスで落ちてるときに再送してくれる
  • JavaのStack Traceのような複数行のログイベントも1イベントとしてまとめてくれる

Splunk log driverはこのようなメリットの裏返しのデメリットがあります

HTTP Event Collectorに直接HTTP POSTするだけなので、再送処理はしてくれません

また、デフォルトでログがJSON形式になってしまいます
Dockerコンテナ内のログをSplunkに入れてみた を参考にログを強引にいい感じの形式にしても、複数行のログをまとめることはできないのです
Splunkで props.conftransforms.conf でなんとかしようとしても、HTTP POSTで1行ずつ送ってくるっぽいので、どうしようもありません
うーん、過去の自分の記事を否定してるみたいでやだな

ということで、この ドキュメント(いちおう公式) を参照しながら設定しました

設定方法

以下の手順で設定します

1. SplunkでHTTP Event Collectorを有効化

設定方法は ここらへんの記事 を参考にしてください

2. log_routerコンテナ追加

ログを取りたいサービスが入っているタスク定義に log_router コンテナを追加して登録します

kikeyama-services-task.yaml
- cpu: 0
  environment: []
  essential: true
  firelensConfiguration:
    type: fluentd
    options:
      config-file-type: s3
      config-file-value: arn:aws:s3:::mybucket/fluent.conf
  image: splunk/fluentd-hec:1.2.0
  logConfiguration:
    logDriver: awslogs
    options:
      awslogs-group: /ecs/kikeyama-services
      awslogs-region: us-west-2
      awslogs-stream-prefix: ecs
  memoryReservation: 100
  mountPoints: []
  name: log_router
  portMappings: []
  user: '0'
  volumesFrom: []
# タスク定義を登録
aws ecs register-task-definition --cli-input-yaml file://./kikeyama-services-task.yaml

ポイントは↓

  • コンテナイメージは splunk/fluentd-hec:1.2.0 を指定
  • firelensConfiguration でS3からfluentdの設定ファイルをとってきているところ(以下抜粋)
抜粋
  firelensConfiguration:
    type: fluentd
    options:
      config-file-type: s3
      config-file-value: arn:aws:s3:::mybucket/fluent.conf

オプションとして、log_routerそのもののログをCloudWatch Logsに送ってます
うまくいかなかったとき用のトラブルシューティングとしてね

3. Fluentd設定ファイルを作成してS3に保存

以下のファイルを作成してタスク定義に指定しているS3バケット、パスにアップロードします

fluent.conf
<system>
  log_level info
</system>

<filter **spring-sfx-demo**>
  @type concat
  key log
  stream_identity_key stream
  multiline_start_regexp /^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\.\d{3}/
  flush_interval 5s
  timeout_label @SPLUNK
  use_first_timestamp true
</filter>

<match **>
  @type relabel
  @label @SPLUNK
</match>

<label @SPLUNK>
  <match **>
    @type splunk_hec
    protocol <SPLUNK_HEC_SCHEME (http|https)>
    hec_host <SPLUNK_HEC_HOST>
    hec_port <SPLUNK_HEC_PORT>
    hec_token <SPLUNK_HEC_TOKEN>
    index <SPLUNK_INDEX>
    host_key ec2_instance_id
    source_key ecs_cluster
    sourcetype_key ecs_task_definition
    insecure_ssl true
    <fields>
      container_id
      container_name
      ecs_task_arn
      source
    </fields>
    <format>
      @type single_value
      message_key log
      add_newline false
    </format>
  </match>
</label>

<label @ERROR>
  <match **>
    @type relabel
    @label @SPLUNK
  </match>
</label>

ポイントは↓

  • ラベル @SPLUNKsplunk_hec プラグインを利用
  • <fiter xxxxx> でコンテナごとに concat を使って multiline_start_regexp でログイベントの最初の文字を正規表現で指定して複数行ログも取り込み可能に

といったところです
今回はJava Spring Bootで作った spring-sfx-demo という名前のコンテナのアプリケーションのログを取得します(filter で指定してる名前ね)

@SPLUNK ラベル内の <SPLUNK_XXXX> については適宜自分の環境の値を入れてください(< > は要らないよ)

では、このファイルをS3にアップロードしましょう

4. サービスを更新

ECSのサービスを更新して上記ステップ2.で登録したタスク定義を指定しましょう
これでログはSplunkに送信されます

Splunkでログを確認

ちゃんと複数行のStack Traceも1ログイベントにまとまってますね

ecs_log_firelens_fluentd.png

今気づいたけどデフォルトでは日付時刻の抽出がちゃんとできてないですね
fluent.conf でちゃんとparseする必要がありますが忘れてました

さいごに

fluentdを使ったのはほぼ初めてなのでけっこう苦戦しました
もう少し設定をちゃんとする余地はあるものの、とりあえずログは取れてるのでヨシとしましょう

タイムスタンプのparseについては、気が向いたら対応します

Fargateは若干クセがあったので、ECSと全く同じというわけにはいかなかったです
それについては後日別の記事に書きます乞うご期待

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1