カテゴリー
Linux

【ELK スタック】Docker Compose アプリ (コンテナ) のログを別の Docker Comose のネットワークの Elasticsearch へ送る構成

はじめに

Docker ロギング・ドライバを使ってコンテナログを ELK スタックで利用する – oki2a24 の続きです。

前回は、 1 つの Docker Compose に、 アプリ (Nginx) も Logstash も Elasticsearch も Kibana も全部入っていました。

開発環境ではこれで足ります。けれども、他のアプリのログも集めたいとなりますと、 Elasticsearch と Kibana は独立させたいと思うようになりました。

今回、以下の 2 つの Docker Compose を用意し、これらを Docker のネットワークで繋ぐことで ELK スタックを実現できましたので、ノートいたします。

  • Docker Compose その 1: Nginx と Logstash
  • Docker Compose その 2: Elasticsearch と Kibana

ポイント

  • "Docker Compose その 2: Elasticsearch と Kibana" を最初に起動し、次に、 "Docker Compose その 1: Nginx と Logstash" を起動しなければならない。逆にすると、 "その 1" でログ出力しても "その 2" が立ち上がっていないので受け取れない。それにそもそも、 "その 1" 起動時に、エラーになるようにした。
  • "その 2" 起動時に、他の Docker Compose から接続できるように名前付きのネットワークを作成するようにした。これを行わない場合、別途 Dokcer ネットワークを作成しておく必要があるので、面倒。
    • "その 2" の docker-compose.yml でトップレベルの networks で name オプションを指定したネットワークを作成する。そのためには、 Docker Compose のバージョンを、 3.5 とする必要がある。なお、他の Docker Compose のバージョンは 3 でも問題なかった。
  • "その 1" から "その 2" に接続するには、
    • "その 1" の docker-compose.yml でトップレベル の networks 設定で外部ネットワークを指定し、接続したい services での networks でも外部ネットワークを指定する必要がある。

コード

ディレクトリ構成

$ tree
.
├── app1
│   ├── docker-compose.yml
│   └── logstash
│       └── pipeline
│           └── logstash.conf
└── es
    └── docker-compose.yml

4 directories, 3 files
$

Docker Compose その 1: Nginx と Logstash

ディレクトリ構成での app1 に当たります。

  • トップレベルの networks で外部の Docker ネットワークの es_net を指定。ちなみに、 es_net が存在していなければ、エラーとなる。
  • services の logstash の networks で、 es_net を指定。これによって、 logstash の output は es_net へと流れるようになる。

app1/docker-compose.yml

version: "3"

services:
  logstash:
    image: docker.elastic.co/logstash/logstash-oss:7.0.1
    ports:
      - "12201:12201/udp"
    volumes:
      - "./logstash/pipeline:/usr/share/logstash/pipeline"
    networks:
      - es_net

  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    logging:
      driver: gelf
      options:
        gelf-address: udp://localhost:12201
        tag: "docker.{{.Name}}"
    depends_on:
      - logstash

networks:
  es_net:
    external: true

次のファイルは前回と同じです。

app1/logstash/pipeline/logstash.conf

input {
  gelf {
    type => docker
      port => 12201
  }
}

filter {
  grok {
    match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
    remove_field => "message"
  }
  mutate {
    add_field => { "read_timestamp" => "%{@timestamp}" }
  }
  date {
    match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
    remove_field => "[nginx][access][time]"
  }
  useragent {
    source => "[nginx][access][agent]"
    target => "[nginx][access][user_agent]"
    remove_field => "[nginx][access][agent]"
  }
  geoip {
    source => "[nginx][access][remote_ip]"
    target => "[nginx][access][geoip]"
  }
}

output {
  elasticsearch {
    hosts => [ 'elasticsearch' ]
    index => "access_log1"
  }
}

Docker Compose その 2: Elasticsearch と Kibana

ディレクトリ構成での es に当たります。

  • フォーマットの version は 3.5 を指定する。そうしないと、 networks の name オプションが使えない。
  • トップレベルの networks で、 name オプションで名前をつけておく。これによって、 docker compose up すると同時に、 name オプションで指定した名前で Docker ネットワークが作成される。この名前で、他の Dokcer Compose からアクセスできるようになる。

es/docker-compose.yml

version: "3.5"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.0.1
    ports:
      - "9200:9200"
      - "9300:9300"
    environment:
      discovery.type: "single-node"
    volumes:
      - "es_data:/usr/share/elasticsearch/data"

  kibana:
    image: docker.elastic.co/kibana/kibana-oss:7.0.1
    ports:
      - "5601:5601"
    environment:
      ELASTICSEARCH_URL: "http://elasticsearch:9200"
    depends_on:
      - elasticsearch

volumes:
  es_data:
    driver: local

networks:
  default:
    name: es_net

確認

cd es/
docker-compose up -d

cd ../app1/
docker-compose up -d

その後、

  1. http://localhost/ にアクセスして Nginx ウェルカムページを確認する。
  2. http://localhost:9200/_cat/indices?v にアクセスして、 Elasticsearch に indexaccess_log1 のデータができているかを確認する。
  3. http://localhost:5601/app/kibana#/dev_tools/console?_g=() にアクセスし、 Console で GET /access_log1/_search?pretty=true を実行して、 Nginx のログが出力されることを確認する。

となりましたので、 OK です。やったぜ!!!

おわりに

実は、この後で詰まっています。

複数の Docker コンテナからそれぞれ異なる index で "その 2" の Elasticsearch へとログを送ったのですけれども、 2 つ目の index を送った時点で Elasticsearch コンテナが Exit してしまいます。

これでは、実用になりません。色々いじくる、そしてそもそも Elasticsearch そのものについてお勉強する、ということが必要になってきたと感じます。

詰まっていますけれども、その前に、一つ前回の投稿からはステップアップできましたので、今回投稿いたしました。

次のページが参考になりました。ありがとうございます?。

以上です。

コメントを残す