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

2024年1月30日火曜日

docker のログを logspout で集約する

docker のログを logspout で集約する

概要

logspout は docker のソケットファイルを使ってログを監視し監視しているログを別のログ集約システムに流すことができるツールです
監視するログはルールによって変更することができるため特定のログだけを特定の場所に飛ばしたりすることができます
今回はとりあえず動かすのが目的なので docker のすべてのログを logstash に流してみます

環境

  • macOS 14.2.1
  • docker 24.0.7
  • docker-compose 2.23.3
  • logspout 3.2.14

docker-compose.yml

logger は logstash コンテナで syslog を受取れるようにします
logspout は docker.sock を使い docker ログを監視します
今回の設定はすべてのログ (docker デーモン自体のログ) も監視対象です
web はデバッグ用のアプリになります

version: '3.8'
services:
  logger:
    image: logstash:8.12.0
    volumes:
      - ./logstash:/etc/logstash
    ports:
      - 5000:5000/udp
    environment:
      - XPACK_MONITORING_ENABLED=false
    command: logstash -f /etc/logstash/logstash.conf
  logspout:
    image: gliderlabs/logspout:v3.2.14
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock
    depends_on:
      - logger
    command: syslog://192.168.1.23:5000
  web:
    image: nginx
    ports:
      - "80:80"
    depends_on:
      - logspout

logstash.conf

syslog を受取りそれを標準出力します
ポイントは type = docker にする点です

input {
  syslog {
    port => 5000
    type => "docker"
  }
}

output {
  stdout {}
}

動作確認

  • docker-compose up -d

コンテナを起動しアプリにアクセスします
そして logger のログを見るとちゃんとアプリのログが logspout 経由で飛ばされているのが確認できると思います

  • docker-compose logs -f
  • curl localhost
web-1       | 192.168.65.1 - - [24/Jan/2024:05:53:36 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.4.0" "-"
web-1       | 192.168.65.1 - - [24/Jan/2024:05:53:54 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.4.0" "-"
logger-1    |        "message" => "<14>1 2024-01-24T05:53:36Z f9940f8079d8 docker-web-1 67205 - - 192.168.65.1 - - [24/Jan/2024:05:53:36 +0000] \"GET / HTTP/1.1\" 200 615 \"-\" \"curl/8.4.0\" \"-\"\n",
logger-1    |         "original" => "<14>1 2024-01-24T05:53:36Z f9940f8079d8 docker-web-1 67205 - - 192.168.65.1 - - [24/Jan/2024:05:53:36 +0000] \"GET / HTTP/1.1\" 200 615 \"-\" \"curl/8.4.0\" \"-\"\n"

特定のログだけフィルタするには

このままだとカーネルログも監視するので logger コンテナのログの量が大変なことになってしまいます
logspout は特定のログだけ監視することができる機能があり例えばコンテナ名で絞り込むには filter.name という機能を使います

logspout の command で filter.name を指定します
ワイルドカードで複数のコンテナ名で絞り込むことも可能です

これでカーネルのログは表示されなくなります

version: '3.8'
services:
  logger:
    image: logstash:8.12.0
    volumes:
      - ./logstash:/etc/logstash
    ports:
      - 5000:5000/udp
    environment:
      - XPACK_MONITORING_ENABLED=false
    command: logstash -f /etc/logstash/logstash.conf
  logspout:
    image: gliderlabs/logspout:v3.2.14
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock
    depends_on:
      - logger
    command: "syslog://192.168.1.23:5000?filter.name=*web*"
  web:
    image: nginx
    ports:
      - "80:80"
    depends_on:
      - logspout

最後に

logspout を試してみました
現状だと docker のロギングドライバで直接 fluentd や logstash に流すことができるのであまり使用する場面は少ないのかもしれません
またここ最近あまりメンテナンスもされていないため使用は控えたほうがいいのかもしれません

参考サイト

2024年1月29日月曜日

docker で gelf ドライバを使って logstash にログを送信してみる

docker で gelf ドライバを使って logstash にログを送信してみる

概要

過去に fluent-driver を使って fluentd にログを送信する方法を紹介しました
今回は gelf driver を使って logstash にログを送信してみました
なおコンテナは docker-compose で動作させます

環境

  • macOS 14.2.1
  • docker 24.0.7
  • docker-compose 2.23.3
  • logstash 8.12.0

docker-compose.yml

logstash と適当なアプリを起動します
ポイントはアプリ側の driver 指定で gelf を指定します
ここが logstash が起動するエンドポイントを指定する部分です

logstash は logger として docker-compose 内で指定します
12201:udp として起動します
logstash.conf はあとで紹介しますが今回は Elasticsearch などには連携せず受け取ったアプリからのログをそのまま標準出力するだけです

  • vim docker-compose.yml
version: '3.8'
services:
  logger:
    image: logstash:8.12.0
    volumes:
      - ./logstash:/etc/logstash
    command: logstash -f /etc/logstash/logstash.conf
    ports:
      - 12201:12201/udp
  web:
    image: nginx
    ports:
      - "80:80"
    logging:
      driver: gelf
      options:
        gelf-address: udp://192.168.1.23:12201
        tag: docker.web
    depends_on:
      - logger

logstash/logstash.conf

12201 で受け取ったログを標準出力します

  • vim logstash/logstash.conf
input {
  gelf {
    port => 12201
  }
}

output {
  stdout {}
}

動作確認

コンテナを起動します

  • docker-compose up -d

あとはログを確認しつつアプリにアクセスします
すると logstash 側に以下のようなログが出力されることが確認できます

  • docker-compose logs -f
  • curl localhost
logger-1  | {
logger-1  |               "host" => "docker-desktop",
logger-1  |           "image_id" => "sha256:6c7be49d2a11cfab9a87362ad27d447b45931e43dfa6919a8e1398ec09c1e353",
logger-1  |              "level" => 6,
logger-1  |            "version" => "1.1",
logger-1  |            "created" => "2024-01-24T00:28:59.739392089Z",
logger-1  |        "source_host" => "192.168.65.1",
logger-1  |           "@version" => "1",
logger-1  |     "container_name" => "docker-web-1",
logger-1  |         "@timestamp" => 2024-01-24T00:29:47.975Z,
logger-1  |         "image_name" => "nginx",
logger-1  |            "message" => "192.168.65.1 - - [24/Jan/2024:00:29:47 +0000] \"GET / HTTP/1.1\" 200 615 \"-\" \"curl/8.4.0\" \"-\"",
logger-1  |                "tag" => "docker.web",
logger-1  |            "command" => "/docker-entrypoint.sh nginx -g daemon off;",
logger-1  |       "container_id" => "2c997b2676e305f5fb7d29e49415c45a5cb9d7edcd6f73ad03d45124d158c246"
logger-1  | }

ElasticSearch に接続できないというエラーがずっと出る

以下のようなエラーがずっとログに出力されていました

logger-1  | [2024-01-24T00:35:42,235][ERROR][logstash.licensechecker.licensereader] Unable to retrieve Elasticsearch cluster info. {:message=>"No Available connections", :exception=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::NoConnectionAvailableError}
logger-1  | [2024-01-24T00:35:42,236][ERROR][logstash.licensechecker.licensereader] Unable to retrieve license information from license server {:message=>"No Available connections"}
logger-1  | [2024-01-24T00:35:42,752][INFO ][logstash.licensechecker.licensereader] Failed to perform request {:message=>"elasticsearch: Name or service not known", :exception=>Manticore::ResolutionFailure, :cause=>#<Java::JavaNet::UnknownHostException: elasticsearch: Name or service not known>}
logger-1  | [2024-01-24T00:35:42,753][WARN ][logstash.licensechecker.licensereader] Attempted to resurrect connection to dead ES instance, but got an error {:url=>"http://elasticsearch:9200/", :exception=>LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError, :message=>"Elasticsearch Unreachable: [http://elasticsearch:9200/
][Manticore::ResolutionFailure] elasticsearch: Name or service not known"}

おそらく logstash の output に ElasticSearch の設定がないからだと思います
今回のようにテスト用途で ES に接続しないのであれば XPACK_MONITORING_ENABLED=false という環境変数を logstash に設定してあげると自動で接続しにいかなくなります

version: '3.8'
services:
  logger:
    image: logstash:8.12.0
    volumes:
      - ./logstash:/etc/logstash
    command: logstash -f /etc/logstash/logstash.conf
    environment:
      - XPACK_MONITORING_ENABLED=false
    ports:
      - 12201:12201/udp
  web:
    image: nginx
    ports:
      - "80:80"
    logging:
      driver: gelf
      options:
        gelf-address: udp://192.168.1.23:12201
        tag: docker.web
    depends_on:
      - logger

最後に

docker + logstash を連携してみました
基本的にはこのあとログを ElasticSearch に格納することになります
fluentd ではなく logstash を使いたい場合には gelf ドライバを使いましょう

参考サイト

2021年1月9日土曜日

fluentd -> kafka -> logstash -> elasticsearch の順番でログを格納する方法

概要

fluentd -> kafka -> logstash -> elasticsearch という順番でログを確認する方法を紹介します
fluentd, kafka, elasticsearch の構築方法は過去に紹介しているので別記事を参照しています

環境

  • kafka 2.6.0
  • logstash 7.10.1
  • elasticsearch 6.4.0

fluent-kafka-plugin が動作する環境の構築

こちらを参考に構築してください
kafka と fluent-kafka-plugin がインストールされた fluent コンテナが起動している状態になれば OK です

elasticsearch の構築

こちらを参考に構築してください
9200 ポートで elasticsearch にアクセスできれば OK です

logstash のインストール

  • brew install logstash

logstash kafka input plugin のインストールと設定

ここが今回の肝になる部分です
logstash-integration-kafka を使います

  • logstash-plugin install logstash-integration-kafka

インストールが完了したら設定ファイルを作成していきます
kafka からデータを受け取って elasticsearch に流す設定を定義します

  • cp /usr/local/etc/logstash/logstash-sample.conf /usr/local/etc/logstash/logstash.conf
  • vim /usr/local/etc/logstash/logstash.conf
input {
  kafka {
    bootstrap_servers => "192.168.1.2:9092"
    topics => ["test"]
    decorate_events => true
  }
}

filter {
  json {
    source => "message"
  }
}

output {
  elasticsearch {
    hosts => ["http://192.168.1.2:9200"]
    index => "%{[@metadata][kafka][topic]}-%{+YYYY.MM.dd}"
  }
}


decorate_events を true にしないと [@metadata][kafka][topic] が output セクションで使えないので true にしています

また filter で json を使っています
どうやらデフォルトでは kafka から受け取ったログはすべて「message」というフィールドに格納されています
なのでそれぞれのフィールドに分割するために filter を挟んでいます

  • logstash -f /usr/local/etc/logstash/logstash.conf

起動に少し時間がかかりますが ERROR がでなければ OK です

動作確認

まずは適当なログを 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)\\\",\\\"msg\\\":\\\"hello\\\"}\"; sleep 3; done;"


ある程度待った後に elasticsearch にインデックスが作成されているか確認しましょう

  • curl 'http://192.168.1.2:9200/_cat/indices?v'
  • curl 'http://192.168.1.2:9200/test-2021.01.06?pretty'

最後に

必ずしも kafka は必要ではないですがスケールによっては必要になります

参考サイト