fluentd+elasticsearch+kibanaによるログの一元管理とログの可視化
どうも,筆者です.
最近,自宅の raspberry pi とミニマシンに docker を入れて LAN 内にサーバを立てている.時々,問題が発生することがあるため,なんとか一元管理したいと考えていた.
少し調べると,fluentd でログを転送し,elasticsearch でログを蓄積する.そして,kibana により蓄積したログの可視化ができるとのこと.今回は,これらを用いてログの一元管理とログの可視化を行う.
準備
バージョンの調査
elasticsearch と kibana はバージョンが違うと動かないことがあるらしい.ここでは,下記のサイトで最新版を調べた上で導入する.また,通常のものの場合,ライセンス料がかかるみたいなので,oss 版を利用する.
今回,利用する elasticsearch と kibana のバージョンは,どちらも 7.10.2 である.
fluentd の config 調査
ログを転送する際に fluentd を用いる.この時,利用する fluentd のバージョンにより書き方が異なるらしい.ここでは,docker images の都合上,alpine 版のバージョン 1.12 を利用する.(ブログにまとめているときに気づくが,別途追加したフィルタリングプラグインは不要だった)
環境構築
環境構築時には,以下のサイトを参考にした.
fluentd
まずは,fluentd の環境構築を行う.
サンプルの取得
github の「How to build your own image」を参考に環境構築を行う.ここでは,VERSION を「v1.12」,OS を「alpine」とするので,それに合わせてリンクを修正する.
具体的に実行するコマンドは以下のようになる.ここで,今回の環境構築に不要な処理は削除している.
# ディレクトリを作成し,その中に移動 mkdir fluentd cd fluentd # config と shell script を取得 curl https://raw.githubusercontent.com/fluent/fluentd-docker-image/master/v1.12/alpine/fluent.conf > fluent.conf curl https://raw.githubusercontent.com/fluent/fluentd-docker-image/master/v1.12/alpine/entrypoint.sh > entrypoint.sh # Dockerfile を取得 curl https://raw.githubusercontent.com/fluent/fluentd-docker-image/master/Dockerfile.sample > Dockerfile
Dockerfile の修正
elasticsearch への転送とタグ情報の取得のために,プラグインを追加する.追加するプラグインは以下の 2 つである.
- fluent-plugin-elasticsearch
- fluent-plugin-forest
これらを追加した Dockerfile を以下に示す.また,entrypoint.sh に実行権限を与えている.
FROM fluent/fluentd:v1.12-1 USER root RUN apk add --no-cache --update --virtual .build-deps sudo build-base ruby-dev \ # cutomize following instruction as you wish && sudo gem install fluent-plugin-elasticsearch fluent-plugin-forest \ && sudo gem sources --clear-all \ && apk del .build-deps \ && rm -rf /home/fluent/.gem/ruby/2.5.0/cache/*.gem COPY fluent.conf /fluentd/etc/ COPY entrypoint.sh /bin/ RUN chmod +x /bin/entrypoint.sh USER fluent
fluent.conf の設定
fluentd の config を設定する.ここでは,ログの転送元でコンテナ名をタグとして割り当て,そのタグに合わせて集計できるようにする.例えば,nginx 向けの場合,転送時に「docker.nginx」というタグをつけ,fluentd 側でタグごとに index を割り当てる.index については,詳細を知らないため,各自調べてほしい.
今回は,外部から送られてきたログを elasticsearch に転送する.その際に,コンテナ名を index に割り当てる.これを config として設定した結果を以下に示す.この config の書き方は細かく理解できていない.
<source> @type forward port 24224 bind 0.0.0.0 </source> <match docker.**> @type forest subtype elasticsearch remove_prefix docker. <template> host elasticsearch port 9200 type_name docker.${tag_parts[1]} logstash_format true logstash_prefix logstash-${tag_parts[1]} </template> </match>
先ほど導入した「fluent-plugin-forest」プラグインを用いて,docker.xxx の xxx を取り出し,index に logstash-xxx という形式で prefix を付ける.logstash_format と index の関係は,公式サイトを参考のこと.
ここまでの作業により,以下のようなディレクトリ構成となる.
./ --- fluentd | + --- Dockerfile | + --- entrypoint.sh | + --- fluent.conf
elasticsearch と kibana
次に,elasticsearch と kibana の設定を行う. elasticsearch と kibana は,image を取得しそのまま起動させるだけである.このため,Dockerfile や config ファイルの設定は不要である.
docker-compose.yml の作成
今回作成した docker-compose.yml を以下に示す.
version: '3.7' x-logging: &default-json-logging driver: json-file options: max-size: "10m" max-file: "1" services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2 container_name: elasticsearch restart: always expose: - "9200" - "9300" environment: discovery.type: "single-node" ES_JAVA_OPTS: "-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 volumes: - elasticsearch-data:/usr/share/elasticsearch/data logging: *default-json-logging kibana: image: docker.elastic.co/kibana/kibana-oss:7.10.2 container_name: kibana restart: always ports: - "5601:5601" depends_on: - elasticsearch links: - elasticsearch:elasticsearch logging: *default-json-logging fluentd: build: context: ./fluentd dockerfile: Dockerfile container_name: fluentd image: custom-fluentd:latest ports: - "24224:24224" volumes: - ./fluentd/fluent.conf:/fluentd/etc/fluent.conf:ro depends_on: - elasticsearch logging: *default-json-logging volumes: elasticsearch-data: driver: local
ディレクトリ構成は,以下のようになる.
ここまでの作業により,以下のようなディレクトリ構成となる.
./ --- + --- docker-compose.yml | + --- fluentd | + --- Dockerfile | + --- entrypoint.sh | + --- fluent.conf
ログの転送設定
最後に,ログの転送設定を行う.筆者の環境では,dns や nginx,web サーバを立ち上げている.これらを fluentd を立ち上げたマシンに転送する.docker-compose.yml の例を以下に示す.
version: '3.4' x-logging: &default-logging driver: fluentd options: fluentd-address: 192.168.33.5:24224 # fluentd+elasticsearch+kibana が起動しているサーバを指定 tag: docker.{{.Name}} # docker.container_name となるようにタグを指定 services: nginx: build: context: ./nginx dockerfile: Dockerfile image: custom_nginx restart: always container_name: nginx ports: - 80:80 volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params:ro logging: *default-logging links: - django depends_on: - django django: build: context: ./django dockerfile: Dockerfile image: custom_django container_name: django restart: always volumes: - ./django/uwsgi.ini:/uwsgi.ini:ro - ./django/src:/code:ro logging: *default-logging expose: - 8001 links: - database depends_on: - database database: build: context: ./mariadb dockerfile: Dockerfile image: custom_mariadb container_name: mariadb restart: always environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: db MYSQL_USER: django MYSQL_PASSWORD: password TZ: "Asia/Tokyo" volumes: - database:/var/lib/mysql logging: *default-logging expose: - 3306 volumes: database:
上記の設定で,stdout/stderr に出力されたログが fluentd に転送される.