LoginSignup
2
1

More than 1 year has passed since last update.

【Docker】NginxのアクセスログをFluentd+Elasticsearch+Kibanaで可視化する

Last updated at Posted at 2023-03-29

やること

Nginx2台をコンテナで構築し、コンテナごとにIndexを分けてElasticsearchに送るようにします。

Nginx2台を構築すると、ポートを切り替えてアクセスする必要があります。
しかし、構成的に綺麗ではないので、
Trafikというリバプロを利用してパスベースでアクセス先のNginxを振り分けられるようにしました。これにより、Traefikの80番ポートだけ公開すれば良くなります。

構成図.png

Trafikの構成については以下を参考にしました。

ソース

ソースは以下にアップしています。

Quick Start

git clone https://github.com/v1tam1nb2/traefik-nginx-fluentd-elasticsearch.git
cd traefik-nginx-fluentd-elasticsearch
docker-compose build
docker-compose up -d
curl http://localhost/service-a.html
curl http://localhost/service-b.html

アクセス後、Kibanaにアクセスしてログを確認できるようにします。
初回は以下でデータビューの作成が必要になります。

データビューについては以下を参考にしてください。

最終的にこのようにログが確認できればOKです。

es.png

ソース

Traefik

以下がTraefikのセクションです。ポートの18000:8080はTraefikのDashboardにアクセスするためのものです。今回はあまり気にしなくてもOKです。

    # リバプロ
    traefik:
      image: traefik:latest
      container_name: "traefik"
      ports:
        - "80:80"
        - "18000:8080"
      volumes:
        - "/var/run/docker.sock:/var/run/docker.sock:ro"
        - ./src/traefik/traefik.yml:/etc/traefik/traefik.yml
traefik.yml
# Provider
providers:
  docker:
    exposedByDefault: false

# エントリーポイント
entryPoints:
  http:
    address: ":80"
  # clickhouse:
  #   address: ":9000"
  # udp-test:
  #   address: ":3179/udp"

api:
  # Dashboard有効化
  dashboard: true
  insecure: true

# ログレベル
log:
  level: DEBUG

Nginx

    nginx_a:
      image: nginx
      container_name: nginx_a
      hostname: nginx_a
      volumes:
        - ${PWD}/src/nginx/service-a.html:/usr/share/nginx/html/service-a.html
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.service-a.rule=PathPrefix(`/service-a`)"
        - "traefik.http.routers.service-a.entrypoints=http"
      depends_on:
        - fluentd
      logging:
        driver: "fluentd"
        options:
          fluentd-address: localhost:24224
          tag: nginx.a.access
          # 起動時に接続を確立的無くても contaienr は起動する設定
          fluentd-async-connect: "true"

    nginx_b:
      image: nginx
      container_name: nginx_b
      hostname: nginx_b
      volumes:
        - ${PWD}/src/nginx/service-b.html:/usr/share/nginx/html/service-b.html
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.service-b.rule=PathPrefix(`/service-b`)"
        - "traefik.http.routers.service-b.entrypoints=http"
      depends_on:
        - fluentd
      logging:
        driver: "fluentd"
        options:
          fluentd-address: localhost:24224
          tag: nginx.b.access
          # 起動時に接続を確立的無くても contaienr は起動する設定
          fluentd-async-connect: "true"

labelsでTraefikによるルーティング設定を定義しています。以下はhttp://localhost/service-a.htmlにアクセスすると、nginx_aコンテナのservice-a.htmlを見るようにする設定です。

traefik.http.routers.service-a.entrypointsにはtraefik.ymlに定義したentrypointを指定します。今回はhttpという名前で定義しています。

      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.service-a.rule=PathPrefix(`/service-a`)"
        - "traefik.http.routers.service-a.entrypoints=http"

以下はコンテナのログをFluentdに転送するための設定です。コンテナごとにIndexを分けるために、tagで識別できるようにしています。

      logging:
        driver: "fluentd"
        options:
          fluentd-address: localhost:24224
          tag: nginx.a.access
          # 起動時に接続を確立的無くても contaienr は起動する設定
          fluentd-async-connect: "true"

Fluentd

Elastisearch用のプラグインをインストールしています。

Dockerfile
# https://docs.fluentd.org/output/elasticsearch
FROM fluent/fluentd:v1.15.0-debian-1.0

USER root

# FluentdとElasticsearchを連携させるためのプラグインをインストール
RUN gem install fluent-plugin-elasticsearch --no-document --version 5.2.4

USER fluent
    fluentd:
      build: ./src/fluentd
      container_name: fluentd
      hostname: fluentd
      restart: always
      ports:
        - "24224:24224"
        - "24220:24220"
        - "24224:24224/udp"
      # depends_on:
      #   - es
      volumes:
        #- ${PWD}/log:/fluentd/log
        - ${PWD}/src/fluentd/fluent.conf:/fluentd/etc/fluent.conf:ro

confでは、tagごとにアウトプット先のIndexを分けるようにしています。nginx_aコンテナのログはIndex nginx-a-log*に、nginx_bコンテナのログはIndex nginx-b-log*に入れるようにします。

fluent.conf
# Fluentdの内部メトリックをHTTPで取得できる設定
# https://docs.fluentd.org/input/monitor_agent
<source>
  @type monitor_agent
  bind 0.0.0.0
  port 24220
</source>

# データのInput設定
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

# データのOutput設定 (FluentdからElasticsearch)
# tag "nginx.a"にマッチするログをESに転送
<match nginx.a.**>
  @type copy

  <store>
    @type elasticsearch
    host elasticsearch
    port 9200
    logstash_format true
    logstash_prefix nginx-a-log
    logstash_dateformat %Y%m%d
    include_tag_key true
    type_name access_log
    tag_key @log_name
    flush_interval 1s
  </store>

  <store>
    @type stdout
  </store>

  # バッファの定義
  <buffer>
    @type file
    flush_mode interval
    flush_interval 10s
    path /var/log/fluentd/elasticsearch
    chunk_limit_size 512m
    flush_at_shutdown true
  </buffer>
</match>

# データのOutput設定 (FluentdからElasticsearch)
# tag "nginx.b"にマッチするログをESに転送
<match nginx.b.**>
  @type copy

  <store>
    @type elasticsearch
    host elasticsearch
    port 9200
    logstash_format true
    logstash_prefix nginx-b-log
    logstash_dateformat %Y%m%d
    include_tag_key true
    type_name access_log
    tag_key @log_name
    flush_interval 1s
  </store>

  <store>
    @type stdout
  </store>

  # バッファの定義
  <buffer>
    @type file
    flush_mode interval
    flush_interval 10s
    path /var/log/fluentd/elasticsearch
    chunk_limit_size 512m
    flush_at_shutdown true
  </buffer>
</match>

Elasticsearch/Kibana

今回は8.4.3を利用しました。簡単にするためにシングルノードで構築している点に注意してください。

    # Elasticsearchコンテナ
    elasticsearch:
      image: docker.elastic.co/elasticsearch/elasticsearch:8.4.3
      container_name: elasticsearch
      hostname: elasticsearch
      restart: always
      environment:
        - discovery.type="single-node"
        - cluster.name="es-cluster"
        - node.name="elasticsearch"
        - bootstrap.memory_lock=true
        - xpack.security.enabled=false
        - TZ=Asia/Tokyo
      ulimits:
        memlock:
          soft: -1
          hard: -1
      # volumes:
      #   # データを永続化
      #   - ${PWD}/data:/usr/share/elasticsearch/data
      ports:
        - 9200:9200

    # Kibanaのコンテナ
    kibana:
      image: docker.elastic.co/kibana/kibana:8.4.3
      container_name: kibana
      hostname: kibana
      ports:
        - 5601:5601
      environment:
        - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
        - TZ=Asia/Tokyo
        - I18N_LOCALE=ja-JP
      depends_on:
        - elasticsearch
      restart: always

まとめ

コンテナのログをFluentd経由でElasticsearchに転送し、Kibanaで確認することができました。
Fluentdのtagを利用することでアウトプット先のIndexを分けることができました。

今回はログの加工などは行いませんでしたが、機会があればやってみたいと思います。

2
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
2
1