ラベル fluentd の投稿を表示しています。 すべての投稿を表示
ラベル fluentd の投稿を表示しています。 すべての投稿を表示

2025年9月21日日曜日

ElastAlert2 を使ってみる

ElastAlert2 を使ってみる

概要

前回ES9をdockerで構築しました
今回は ElastAlert2 を組み合わせて特定のログがES9に格納されたらアラートされる仕組みを作成してみます

環境

  • macOS 15.6.1
  • docker 28.4.0
    • ElasticSearch 9.0.7
    • Kibana 9.0.7
    • fluentd 1.19-1
    • ElastAlert 2.26.0

elastalert.yaml

EalstAlert2 共通の設定を作成します
接続する ElasticSearch9 の設定やルールを管理するディレクトリを指定します

  • vim elastalert.yaml
rules_folder: /opt/elastalert/rules

run_every:
  seconds: 10

buffer_time:
  minutes: 15

es_host: 192.168.1.152
es_port: 9200
use_ssl: true
verify_certs: false
es_username: elastic
es_password: xxx

writeback_index: elastalert_status

alert_time_limit:
  days: 2

rules/test_alert.yaml

とりあえずテスト用のアラートファイルを作成します
今回は必ずアラートが上がるように @timestmp フィールドを監視し5分間の間に2回レコードが格納された場合にアラートが上がるようにします

  • mkdir rules
  • rules/test_alert.yaml
name: "test_alert"
type: "frequency"
index: "fluentd*"
is_enabled: true
num_events: 2
realert:
  minutes: 5
terms_size: 50
timeframe:
  minutes: 5
timestamp_field: "@timestamp"
timestamp_type: "iso"
use_strftime_index: false
alert_subject: "Test {} 123 aa☃"
alert_subject_args:
  - "log"
alert_text: "Test {}  123 bb☃"
alert_text_args:
  - "source"
filter:
  - query:
      query_string:
        query: "@timestamp:*"
alert:
  - "slack"
slack_webhook_url: 'https://hooks.slack.com/services/xxx'
slack_channel_override: "#private"
slack_emoji_override: ":kissing_cat:"
slack_msg_color: "warning"
slack_parse_override: "none"
slack_username_override: "elastalert"

各種項目の説明

ルールの基本

name: "test_alert"
ルールの名前。Slack 通知などに出てくる。

type: "frequency"
「一定時間内に指定した件数以上のイベントがあるとアラートを出す」というタイプ。

index: "fluentd"
監視対象の Elasticsearch インデックス名。

is_enabled: true
このルールが有効になっている。

発火条件

num_events: 2
  イベント件数のしきい値。

timeframe: minutes: 5
  評価対象の時間範囲。
  → 「5分間に2件以上あればアラート」

realert: minutes: 5
  一度アラートが出た後、同じ条件で再度アラートを出すまでのクールダウン時間。
  → 5分間は抑止する。

terms_size: 50
  集計クエリのサイズ。frequency ルールでは多くの場合デフォルトでOK。

タイムスタンプ関連

timestamp_field: "@timestamp"
  イベントの時刻として使う Elasticsearch のフィールド。

timestamp_type: "iso"
  日時フォーマットの種類。ISO 8601 形式。

use_strftime_index: false
  インデックス名に日付を埋め込まない(例: fluentd-%Y.%m.%d ではなく fluentd 固定)。

通知メッセージ

alert_subject: "Test {} 123 aa☃"
  Slack の件名やタイトル部分に使うテンプレート。
  {} に alert_subject_args のフィールドが入る。

alert_subject_args: "log"
  → log フィールドの値が {} に挿入。

alert_text: "Test {} 123 bb☃"
  本文テンプレート。
  {} に alert_text_args のフィールドが入る。

alert_text_args: "log"
  → log フィールドの値が {} に挿入。

検索条件

filter:
  単純に @timestamp フィールドが存在する全ログを対象にする。
  実質「全件」になる。

ElastAlert2 コンテナの起動

ではコンテナを起動します
ホスト側に作成した各種設定ファイルがちゃんとコンテナにマウントされるようにしましょう

  • docker run -d --name elastalert --restart=always -v $(pwd)/elastalert.yaml:/opt/elastalert/config.yaml -v $(pwd)/rules:/opt/elastalert/rules jertel/elastalert2 --verbose

ログを見ると

Background alerts thread 0 pending alerts sent at 2025-09-17 23:35 UTCINFO:elastalert:1 rules loaded

でルールが有効になっていることが確認できます
また以下のログがあれば Slack に通知できているログになります

INFO:elastalert:Ran test_alert from 2025-09-17 23:54 UTC to 2025-09-17 23:55 UTC: 2 query hits (0 already seen), 1 matches, 1 alerts sent

動作確認

5分間待って Slack に通知が来ることを確認しましょう

以下のように変数部分が <MISSING VALUE> になる場合は ES9 上に指定のフィールドが存在するか確認してください

おまけ: 事前にルールファイルの確認をする

  • docker run --entrypoint "" --rm -v $(pwd)/elastalert.yaml:/opt/elastalert/config.yaml -v $(pwd)/rules:/opt/elastalert/rules jertel/elastalert2 elastalert-test-rule /opt/elastalert/rules/test_alert.yaml

最後に

ES9 と ElastAlert2 を連携させて特定のログが出た場合に Slack に通知する仕組みを試してみました
基本的には filter や timeframe などの監視条件をいろいろ変更してログ監視ルールを作成していく感じになります

また今回の構成だと rules ディレクトリにルールファイルをどんどん追加していく感じになりますが追加したルールファイルが1つでも壊れている(YAML構文エラーや必須のディレクティブが定義されていないなどがある)と ElastAlert2 自体が起動しないので注意してください

今回紹介した機能以外にもたくさんの機能があるので興味があれば参考サイトから公式のドキュメントを参照してみてください

参考サイト

2025年9月20日土曜日

docker で ElasticSearch9 を試す

docker で ElasticSearch9 を試す

概要

過去にES8を試しました
ES9が出たので久しぶりに試してみました

環境

  • macOS 15.6.1
  • docker 28.4.0
    • ElasticSearch 9.0.7
    • Kibana 9.0.7
    • fluentd 1.19-1

ElasticSearch の起動

  • docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name es docker.elastic.co/elasticsearch/elasticsearch:9.0.7

パスワードなどの確認や CA 証明書の取得などは同じ流れでした

  • docker exec -it es /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic -a
  • docker cp es:/usr/share/elasticsearch/config/certs/http_ca.crt .
  • curl --cacert http_ca.crt -u elastic https://localhost:9200
Enter host password for user 'elastic':
{
  "name" : "528f80bd51ca",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "pBMuWf9vTBuFEj1PHoZiFA",
  "version" : {
    "number" : "9.0.7",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "c6d8fb31b39450a223671e79141dd1c4b2759b5f",
    "build_date" : "2025-09-10T22:06:39.784049935Z",
    "build_snapshot" : false,
    "lucene_version" : "10.1.0",
    "minimum_wire_compatibility_version" : "8.18.0",
    "minimum_index_compatibility_version" : "8.0.0"
  },
  "tagline" : "You Know, for Search"
}

エンロールメントトークンも取得しておきます

  • docker exec -it es /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana --url "https://localhost:9200"

Kibana 起動

  • docker run -d -p 5601:5601 --name kibana docker.elastic.co/kibana/kibana:9.0.7

Kibana ログイン時に認証コードが必要なので取得しておきます

  • docker exec kibana bin/kibana-verification-code

ログ送信

fluentd コンテナを使って送信します

  • vim Dockerfile
FROM fluent/fluentd:v1.19-1

USER root
RUN gem install fluent-plugin-elasticsearch
  • docker build -t my_fluentd .

fluent.conf を作成します
ES9 に接続するには認証情報などが必要になります
ssl_verify=false を設定しないと fluentd -> es で SSL のエラーが発生しました

  • vim fluent.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match docker.**>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type elasticsearch
    user elastic
    password xxx
    ca_file /fluentd/etc/http_ca.crt
    ssl_verify false
    scheme https
    host 192.168.1.152
    port 9200

    logstash_format true
    logstash_prefix fluentd
  </store>
</match>

@timestamp フィールドを使うので logstash_format: true を設定しています

  • docker run --name fluentd -d -p 24224:24224 -p 24224:24224/udp -v $(pwd):/fluentd/etc -e FLUENTD_CONF=fluent.conf my_fluentd

あとは fluentd にログを投げるコンテナを起動すれば OK です

  • docker run --rm --log-driver=fluentd --log-opt fluentd-address=host.docker.internal:24224 --log-opt tag="docker.{{.Name}}" alpine /bin/sh -c "while :;do date; sleep 3; done;"

動作確認

Kibana を確認して fluentd インデックスにログがあることを確認します
Discover で棒グラフが表示されない場合は

最後に

ElasticSearch9 を docker で動かしてみました
認証方法などはほぼ ES8 と変わってませんでした

fluentd からログを送信する際にも認証情報は必要になるので注意しましょう

参考サイト

2025年7月29日火曜日

Python の fluent-logger でタイムアウトを設定する方法

Python の fluent-logger でタイムアウトを設定する方法

概要

過去に fluent-logger の使い方を紹介しました
今回は fluent-logger でタイムアウトを設定する方法を紹介します

環境

  • macOS 15.5
  • Python 3.12.11
  • fluent-logger 0.11.1

サンプルコード

from fluent import sender

# デフォルトのタイムアウトは3.0秒
logger = sender.FluentSender(
    "app",
    host="127.0.0.3",
    port=24224,
    timeout=10.0,
)
result = logger.emit("follow", {"from": "userA", "to": "userB"})
print(result)

最後に

FluentSender の場合もし host にアクセスできない宛先を指定しても Exception は発生しません
emit してその結果を True/Flase を確認することで初めて送れたかどうかを確認できます
なので host にアクセス出来なかった理由が詳細にわからないので注意しましょう

事前に host に接続できるかどうかチェックしたい場合は以下のようなメソッドを自前で準備する必要がありそうです

import socket

def check_fluentd_reachable(host, port, timeout=2):
    try:
        with socket.create_connection((host, port), timeout):
            return True
    except Exception as e:
        print(f"[FluentD Unreachable] {e}")
        return False

if check_fluentd_reachable('localhost', 24224):
    logger.emit('app.test', {'message': 'hi'})
else:
    print("Fluentd に接続できません")

参考サイト

2023年7月5日水曜日

Python fluent-logger 超入門

Python fluent-logger 超入門

概要

python から fluentd にメッセージを送信してみました
簡単なサンプルコードを紹介します

環境

  • macOS 13.4.1
  • Python 3.11.3
  • fluentd 1.16.1

準備

  • pipenv install fluent-logger

fluentd 起動

とりあえずメッセージを受け取り標準出力に表示するだけの fluentd を起動します

  • vim fluent.conf
<source>
  type forward
  port 24224
</source>

<match app.**>
  type stdout
</match>
  • docker run -it --rm -v $(pwd):/fluentd/etc -p 24224:24224 -p 24224:24224/udp fluent/fluentd:edge-debian-arm64 -c /fluentd/etc/fluent.conf

AppleSillicon なので arm64 版のイメージを起動しています

サンプルコード

起動した fluentd にメッセージを送信するサンプルコードです
タグは app.* で指定します

  • vim ./app.py
from fluent import sender

logger = sender.FluentSender('app', host='localhost', port=24224)
logger.emit('follow', {'from': 'userA', 'to': 'userB'})

動作確認

  • pipenv run python app.py

で fluentd 側のログに以下のようなログが表示されることを確認します

2023-06-30 05:55:55.000000000 +0000 app.follow: {"from":"userA","to":"userB"}

最後に

Python から fluentd に直接メッセージを送信してみました
ちょっとユースケースが思い浮かばないのですがログ以外でメッセージブローカとして fluentd を使うケースなどには使えそうです

2022年5月6日金曜日

fluent コンテナは root ユーザでは動作しないが FLUENT_UID を使えば fluent ユーザの UID を変更できる

fluent コンテナは root ユーザでは動作しないが FLUENT_UID を使えば fluent ユーザの UID を変更できる

概要

fleunt コンテナでホスト領域をマウントする場合にはマウントする領域の権限に合わせて FLUENT_UID を使って uid を変更する必要があります

環境

  • Ubuntu 18.04
  • docker 20.10.4
  • fluent 1.3.2

動作確認

# docker run --rm -e FLUENT_UID=998 fluent/fluentd id fluent
uid=998(fluent) gid=998(fluent) groups=998(fluent)

# docker run --rm fluent/fluentd id fluent
uid=1000(fluent) gid=1000(fluent) groups=1000(fluent)

2022年4月28日木曜日

docker で起動した Gitlab の production_json.log を fluentd で elasticsearch に飛ばす方法

docker で起動した Gitlab の production_json.log を fluentd で elasticsearch に飛ばす方法

概要

Gitlab のコンテナの標準出力のログは JSON 形式ではないので docker の fluentd ドライバが使えません
なのでコンテナ内に出力されるアプリケーションのログファイルを見る必要があります

ポイントはコンテナ内のログファイルをホストにマウントする点です

環境

  • Gitlab-ee 14.7.7
  • fluentd 1.3.2
  • fluent-plugin-elasticsearch 4.3.3
  • elasticsearch 7.17.1
  • elasticsearch 7.17.3
  • kibana 7.17.3

ElasticSearch 起動

  • docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.17.3

Kibana 起動

  • docker run -d -e ELASTICSEARCH_HOSTS=http://192.168.100.10:9200 -p 5601:5601 docker.elastic.co/kibana/kibana:7.17.3

fluentd ビルド&起動

  • vim Dockerfile
FROM fluent/fluentd

RUN apk add --update --virtual .build-deps \
        sudo build-base ruby-dev \
 && sudo gem install \
        elasticsearch -v 7.17.1 \
 && sudo gem install \
        fluent-plugin-elasticsearch -v 4.3.3 \
 && sudo gem sources --clear-all \
 && apk del .build-deps \
 && rm -rf /var/cache/apk/* \
           /home/fluent/.gem/ruby/2.5.0/cache/*.gem
  • vim fluent.conf
<source>
  @type tail
  format json
  path /fluentd/gitlab_log/production_json.log
  pos_file /fluentd/gitlab_log/production_json.log.pos
  tag gitlab.production
  keep_time_key true
</source>

<match gitlab.production>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type elasticsearch
    host 192.168.100.10
    port 9200
    index_name gitlab.production
    type_name fluentd
	    logstash_format true
    time_key time
  </store>
</match>
  • docker build -t my_fluentd .
  • docker run -d -v $(pwd):/fluentd/etc -v /path/to/log/gitlab-rails:/fluentd/gitlab_log -e FLUENTD_CONF=fluent.conf -e FLUENT_UID=998 my_fluentd

ポイント

  • Gitlab のログをホスト側でマウントしてそれを tail で飛ばす
  • 上記の場合は fluentd コンテナの /fluentd/gitlab_log にログをマウントしている
  • マウント先は /fluentd 配下でないと権限がないと言われて怒られる
  • また fluent ユーザの UID は 998 にしている、998は Gitlab 上で動作している git ユーザの UID でログファイルの権限が git ユーザの権限になっている、fluent ユーザのデフォルトの UID は 1000 になっており 1000 のまま fluentd コンテンを起動するとログの権限が 1000 になり Gitlab からログが書き込めずエラーになるのでそれの対応になる
  • production_json.log にはタイムスタンプ用に time フィールドがあるが keep_time_key: true を設定しないと消えるので注意
  • Elasticsearch のバージョンに合わせて elasticsearch-ruby のバージョンも合わせる必要がある
  • ログファイルの権限と fluentd 側の権限 (uid, gid) は合わせる必要がありそう

最後に

他のログも同じように転送することができます

2022年4月11日月曜日

rewrite_tag_filter を使って特定のログを Slack に通知する方法

rewrite_tag_filter を使って特定のログを Slack に通知する方法

概要

前回 fluentd-plugin-slack を使って fleuntd に来たログを slack に通知する方法を紹介しました
今回は特定の文字列を含むログだけを slack に通知する方法を紹介します

grep ではなく rewrite_tag_filter プラグインを使います

環境

  • Ubuntu 18.04
  • docker 20.10.7
  • fluentd 1.3.2

Dockerfile

  • vim Dockerfile
FROM fluent/fluentd

RUN apk add --update --virtual .build-deps sudo build-base ruby-dev \
 && sudo gem install fluent-plugin-slack fluent-plugin-rewrite-tag-filter \
 && sudo gem sources --clear-all \
 && apk del .build-deps \
 && rm -rf /var/cache/apk/* /home/fluent/.gem/ruby/2.5.0/cache/*.gem

イメージ作成

  • docker build -t my_fluentd .

fleunt.conf 作成

  • vim fluent.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match docker.**>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type rewrite_tag_filter
    <rule>
      key log
      pattern /notify slack/
      tag slack.${tag}
    </rule>
  </store>
</match>

<match slack.**>
  @type slack
  webhook_url https://hooks.slack.com/services/xxx/xxx/xxxxxx
  channel private
  username test
  message_keys log
  icon_emoji :ghost:
  flush_interval 60s
</match>

今回は log キー内に「notify slack」という文字列を含むログだけを slack に通知します

fluentd コンテナ起動

  • docker run -d -p 24224:24224 -p 24224:24224/udp -v $(pwd):/fluentd/etc -e FLUENTD_CONF=fluent.conf --name my_fluentd my_fluentd

動作確認

  • docker run --rm --log-driver=fluentd --log-opt fluentd-address=192.168.100.1:24224 --log-opt tag="docker.{{.Name}}" alpine /bin/sh -c "echo notify slack"

最後に

filter プラグインの grep を使ってもできると思います

参考サイト

2022年4月8日金曜日

docker で簡単に fluentd-plugin-slack を試す

docker で簡単に fluentd-plugin-slack を試す

概要

fluentd-plugin-slack は fluentd に来たログを slack に投げることができます
今回は docker で試してみました

環境

  • Ubuntu 18.04
  • docker 20.10.7

Dockerfile

  • vim Dockerfile
FROM fluent/fluentd

RUN apk add --update --virtual .build-deps sudo build-base ruby-dev \
 && sudo gem install fluent-plugin-slack \
 && sudo gem sources --clear-all \
 && apk del .build-deps \
 && rm -rf /var/cache/apk/* /home/fluent/.gem/ruby/2.5.0/cache/*.gem

イメージ作成

  • docker build -t my_fluentd .

fleunt.conf 作成

  • vim fluent.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match docker.**>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type slack
    webhook_url https://hooks.slack.com/services/xxx/xxx/xxxxxx
    channel private
    username test
    message_keys log
    icon_emoji :ghost:
    flush_interval 60s
  </store>
</match>

message_keys で fluentd に流れてきた JSON ログのキーを指定することでその値を Slack のメッセージとして流すことができます

fluentd コンテナ起動

  • docker run -d -p 24224:24224 -p 24224:24224/udp -v $(pwd):/fluentd/etc -e FLUENTD_CONF=fluent.conf --name my_fluentd my_fluentd

動作確認

  • docker run --rm --log-driver=fluentd --log-opt fluentd-address=192.168.100.1:24224 --log-opt tag="docker.{{.Name}}" alpine /bin/sh -c "date"

今回は flush_interval 60s なので 1 分ごとにまとめて通知されます

特定のログだけ通知するには

grep プラグインと組み合わせます
こちらは次回紹介します

参考サイト

2020年12月14日月曜日

fluent-plugin-kafka を使ってみた

概要

fluentd から kafka にメッセージを送信することができるプラグインがあるので使ってみました
kafka の構築に関してはこちらを参考にしてください
また今回 fluentd はコンテナで動作させます

環境

  • macOS 10.15.7
  • fluentd
  • kafka 2.6.0

事前準備

kafka と zookeeper を起動させておきましょう

  • brew services start zookeeper
  • brew services start kafka

fluent-plugin-kafka がインストールされたイメージの作成

fluent/fluentd には fluent-plugin-kafka がインストールされていないのでインストールされているイメージを作成します

  • vim Dockerfile
FROM fluent/fluentd

RUN apk add --update --virtual .build-deps \
        sudo build-base ruby-dev \
 && sudo gem install \
        fluent-plugin-kafka zookeeper \
 && sudo gem sources --clear-all \
 && apk del .build-deps \
 && rm -rf /var/cache/apk/* \
           /home/fluent/.gem/ruby/*/cache/*.gem


  • docker build -t my_fluentd .

fluent.conf の作成

次に作成した fluentd イメージ上で動作させる設定ファイルを作成します
コンテナを作成する場合にホストマシン上のファイルをマウントして動作させます

今回はわかりやすいように copy を使って kafka にログを流すのと同時に fluentd コンテナの標準出力にもログを出しています

  • vim fluent.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match docker.**>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type kafka2
    brokers 192.168.1.2:9092
    zookeeper 192.168.1.2:2181
    default_topic test
    <format>
      @type json
    </format>
  </store>
</match>

fluentd コンテナの起動

作成したイメージと設定ファイルを使ってコンテナ起動します
問題なくコンテナが起動していることを確認しましょう

  • docker run -d -p 24224:24224 -p 24224:24224/udp -v $(pwd):/fluentd/etc -e FLUENTD_CONF=fluent.conf my_fluentd

動作確認用コンテナの作成

何でも OK です
今回は JSON の情報を echo で 3 秒おきに出力するコンテナにしています
ロギングドライバだけ fluentd を指定しましょう

  • docker run --rm --log-driver=fluentd --log-opt fluentd-address=192.168.1.2:24224 --log-opt tag="docker.{{.Name}}" alpine /bin/sh -c "while :;do echo \"{\"timestamp\":\"$(date)\"}\"; sleep 3; done;"

動作確認

kafka-console-consumer を使って fluentd からログが飛んできているか確認しましょう
fluentd がデフォルトで 10s バッファするのでログが飛んでくるのは 10s おきになっているのが確認できると思います

  • kafka-console-consumer --bootstrap-server 192.168.1.2:9092 --topic test --from-beginning


また fluentd コンテナで logs を確認しても良いと思います
そもそも fluentd コンテナに出力されていない場合は kafka にも当然ログは飛んできません

トラブルシューティング

zookeeper が localhost でしか LISTEN していない場合には設定ファイルを編集しましょう

  • vim /usr/local/etc/kafka/zookeeper.properties
clientPort=2181
clientPortAddress=192.168.1.2

最後に

fluent-plugin-kafka を使ってみました
今回は Output プラグインを使いましたが Input プラグインもあり kafka からの入力を受け取ることもできます

kafka がすでにあればかなり簡単に使える印象です

参考サイト

2020年12月4日金曜日

docker stack deploy で logging driver の fluentd を使う方法

概要

Swarm クラスタ上にデプロイしたコンテナで fluentd のロギングドライバを使う方法を紹介します
デプロイには docker-compose を使います

環境

  • macOS 10.15.7
  • docker-machine 0.16.2

Swarm クラスタ構築

こちらを参考に事前に構築してください
今回は上記で構築した想定で docker-machine + vagrant 上で確認します

fluentd コンテナの起動

まずは fluentd コンテナを起動します
この fluentd に Swarm クラスタ上で動作しているコンテナからログを投げて動作確認します

  • vim fluent.conf
<source>
  @type forward
</source>

<match docker.**>
  @type stdout
</match>


  • docker run -d -p 24224:24224 -p 24224:24224/udp -v $(pwd):/fluentd/etc -e FLUENTD_CONF=fluent.conf fluent/fluentd

docker-machine で構築したのであればリモートの docker を操作してもちゃんとローカルにあるファイルを転送してくれるようです

docker-compose の準備

次に Swarm 上にデプロイするコンテナを定義します
今回は簡単に確認できるように nginx のコンテナでも立ててみます
192.168.100.109 は fluentd コンテナを立ち上げたホストになります

version: '3.7'
services:
  web:
    image: nginx
    ports:
      - "80:80"
    deploy:
      replicas: 2
    logging:
      driver: fluentd
      options:
        fluentd-address: 192.168.99.109:24224
        tag: docker.{{.ID}}


  • docker stack deploy -c docker-compose.yml test

動作確認

各ホストにデプロイされた nginx にアクセスしてログがちゃんと fluentd コンテナに飛んでいるか確認します

  • docker logs -f angry_pare

angry_pare は fluentd コンテナの名前になります

  • curl $(docker-machine ip master)
  • curl $(docker-machine ip node1)

これで fluentd 側にログが流れていることが確認できれば OK です

2020-12-03 03:17:25.000000000 +0000 docker.bc58810c5e27: {"log":"10.0.0.2 - - [03/Dec/2020:03:17:25 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.69.1\" \"-\"","container_id":"bc58810c5e2769927422c23098fbe800c8e94b3d7e00a95434057b6642bdc4b8","container_name":"/test_web.1.wm9thorpotwi3v71l064v6b7f","source":"stdout"} 2020-12-03 03:17:32.000000000 +0000 docker.5a3def862387: {"container_id":"5a3def8623872a47750b3a66bf01a7776ddd130c65530f3d26d309a781cc58f5","container_name":"/test_web.2.zd5jilpjax5qk1qkwdr8c021a","source":"stdout","log":"10.0.0.3 - - [03/Dec/2020:03:17:32 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.69.1\" \"-\""}

最後に

fluentd コンテナは fluent.conf ファイルがうまく転送できれば docker-compose に混ぜても良いと思います
あとは転送したログを好きな場所に飛ばせば OK です

参考サイト

2018年9月6日木曜日

Docker コンテナのログを fluentd を経由して外部の ElasticSearch に送信する方法

概要

fluentd を docker 上で動かしてログを外部の ElasticSearch に送ってみたいと思います
外部というのは fluentd コンテナが動作しているホストとは別のホストのことで例えば ElasticSearch はコンテナではなく VM の上で動作している場合などを想定しています
もちろん ElasticSearch の API のエンドポイントには fluentd コンテナからアクセスできる必要があります

環境

  • macOS 10.13.6
  • docker 18.06.0-ce
  • fluentd (v1.2)
  • ElasticSearch (docker.elastic.co/elasticsearch/elasticsearch:6.4.0)
  • Kibana (docker.elastic.co/kibana/kibana:6.2.4)

Elasticsearch Output Plugin

Dockerhub で公開されている fluentd には基本的にプラグインがインストールされていません
なので ElasticSearch のプラグインがインストールされたイメージを作成します

  • vim Dockerfile
FROM fluent/fluentd

RUN apk add --update --virtual .build-deps \
        sudo build-base ruby-dev \
 && sudo gem install \
        fluent-plugin-elasticsearch \
 && sudo gem sources --clear-all \
 && apk del .build-deps \
 && rm -rf /var/cache/apk/* \
           /home/fluent/.gem/ruby/2.4.0/cache/*.gem
  • docker build -t my_fluentd .

fluent.conf の作成

インストールしたプラグインを使って ElasticSearch にログを送信する設定ファイルを作成します

  • vim fluent.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match docker.**>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type elasticsearch
    host 192.168.99.1
    port 9200
    index_name fluentd
    type_name fluentd
  </store>
</match>

ElasticSearch にログを送るには @type elasticsearch を使います
そして host で外部の ElasticSearch の IP を指定します
今回は copy を使って stdout にも出力していますが不要であれば削除してください

この設定ファイルを使って fluentd コンテナを起動します

fluentd コンテナの起動

  • docker run -d -p 24224:24224 -p 24224:24224/udp -v $(pwd):/fluentd/etc -e FLUENTD_CONF=fluent.conf my_fluentd

先程作成した fluent.conf があるディレクトリを /fluentd/etc にマウントします
そして設定ファイル名を指定するための環境変数 FLUENTD_CONF に設定ファイル名を指定します

あとは TCP/UCP で 24224 をオープンすれば OK です
この 24224 ポートに対して各コンテナはログを投げつけます

動作確認

適当にログを投げつけるコンテナを作成しましょう

  • docker run --rm --log-driver=fluentd --log-opt fluentd-address=192.168.99.1:24224 --log-opt tag="docker.{{.Name}}" alpine /bin/sh -c "while :;do date; sleep 3; done;"

ポイントとなる必須のオプションは 3 つです

  • --log-driver=fluentd
  • --log-opt fluentd-address=192.168.99.1:24224
  • --log-opt tag="docker.{{.Name}}"

1 つ目はロギングドライバを指定するオプションです
2 つ目は外部にある ElasticSearch のエンドポイントです
当然ですがコンテナからアクセスできる必要があります
3 つ目は tag では fluent.conf に定義した match に合わせる必要があります

これでコンテナの stdout が fluentd に拾われて ElasticSearch に投げられます

Kibana を見てみる

ElasticSearch が Kibana と連携しているのであればあとはインデックス (fluentd) を作成するだけでログが見れるようになります

Kibana にアクセスしてインデックスを作成しましょう
ちなみに ElasticSearch に送信されるインデックス名は fluent.conf の index_name fluentd で指定することができます

「index pattern」に「fluentd」と入力して「Next step」を選択します
fluentd_to_es_on_docker1.png

「Create index pattern」を選択します
fluentd_to_es_on_docker2.png

あとは Discover などを見れば ElasticSearch にあるログが確認できると思います
fluentd_to_es_on_docker3.png

最後に

Docker 上で fluentd を動かして各コンテナから受け取ったログを外部の ElasticSearch に送信する方法を紹介しました
各コンポーネントがバラバラに動作しているケースには今回紹介した方法が使えると思います

多くのコンテナからログを受けつける場合には fluentd コンテナのサイズなどを調整しましょう
fluentd クラスタなどを組んでも良いですが今回は紹介しないので興味があれば調べてみてください