LoginSignup
1
5

More than 5 years have passed since last update.

エックスサーバーのログをDocker + EFKで可視化したい!

Last updated at Posted at 2017-08-24

やりたいこと

  • エックスサーバーのapacheログをもってきてEFK(Elasticsearch + Fluentd + Kibana)で可視化
  • 別途バックアップしていた30日以上前のgzipで圧縮されたログも一緒に見たい
  • dockerの勉強(これが一番の目的)

事前準備

エックスサーバーではSSHを使用するをONにしておいて、鍵の生成をしておく。

ファイル配置

.
├── docker-compose.yaml
├── fetch
│   ├── Dockerfile
│   ├── cron.sh
│   ├── fetch.sh
│   ├── init.sh
│   ├── private.key
│   └── oldlogs
│       ├── example.com.access_log_20170726.gz
│       ├── example.com.access_log_20170727.gz
│       ├── example.com.access_log_20170728.gz
│       ├── example.com.access_log_20170729.gz
│       ├── example.com.access_log_20170730.gz
│       └── example.com.access_log_20170731.gz
└── fluentd
    ├── Dockerfile
    ├── fluent.conf
    └── plugins

fetchコンテナ

  • エックスサーバーに鍵認証、ポート10022でSSH接続してログをrsync
  • cronで5分ごとに/home/username/example.com/logs/以下を/var/log/apache2/に持ってくる
  • 別途バックアップしていたログはホストのoldlogsディレクトリに配置しておき、コンテナの/var/log/apache2_old/に展開する
  • 当日のログはシンボリックリンクになっているので、rsyncは--copy-linksオプション必須

SSHの秘密鍵をどうやってコンテナに渡せばよいのか・・・
このやり方だとcommitしたときにイメージに含まれてしまう。

fetch/Dockerfile
FROM ubuntu

ENV XSRV_USER=username \
  XSRV_HOST=example.com \
  XSRV_PORT=10022

RUN apt-get update && \
  apt-get upgrade -y && \
  apt-get install -y openssh-client cron rsync && \
  mkdir -p /root/.ssh && \
  mkdir -p /var/log/apache2 && \
  touch /var/log/apache2/access.log && \
  touch /var/log/apache2/access.log.old

COPY "init.sh" "/root/init.sh"
COPY "cron.sh" "/root/cron.sh"
COPY "private.key" "/root/.ssh/private.key"

CMD /bin/bash /root/init.sh

最初の1回だけ実行するスクリプト

  • SSH秘密鍵のパーミッションを設定
  • 登録済みホストに登録
    • rsyncで使うとIPアドレスになって渡されるので、どうにかしたい
  • 昨日以前のgzになっているログを全部access.log.oldに展開
  • 環境変数をenv.shに書き出してcronに登録(c.f. http://qiita.com/rerofumi/items/fc0126c4e985b78f769b )
fetch/init.sh
#!/bin/bash

cd /var/log/apache2

if [ -d /var/log/apache2_old/ ]; then
  rsync -av /var/log/apache2_old/*.gz ./
fi

if [ -f /root/.ssh/private.key ]; then
  chmod 600 /root/.ssh/private.key
  ssh-keyscan -p ${XSRV_PORT} -H ${XSRV_HOST} > /root/.ssh/known_hosts
  rsync -av --copy-links -e "ssh -p ${XSRV_PORT} -i /root/.ssh/private.key" ${XSRV_USER}@${XSRV_HOST}:/home/${XSRV_USER}/${XSRV_HOST}/log/ ./
fi

zcat *.gz > access.log.old

printenv | awk '{print "export " $1}' > /root/env.sh
echo '*/5 * * * * root /bin/bash /root/cron.sh' >> /etc/crontab
cron -f

cronで起動するスクリプト

  • env.shから環境変数を読み込む
  • 当日分のログ(${XSRV_HOST}.access_log)をaccess.logにコピー
fetch/cron.sh
#!/bin/bash
. /root/env.sh

cd /var/log/apache2

if [ -f /root/.ssh/private.key ]; then
  rsync -av --copy-links -e "ssh -p ${XSRV_PORT} -i /root/.ssh/private.key" ${XSRV_USER}@${XSRV_HOST}:/home/${XSRV_USER}/${XSRV_HOST}/log/ ./
fi

cp -f ${XSRV_HOST}.access_log access.log

fluentdコンテナ

  • エックスサーバーの吐くapacheログのフォーマットを読み込む
  • ログをElasticsearchに渡す
fluentd/Dockerfile
FROM fluent/fluentd

RUN gem install fluent-plugin-elasticsearch
COPY fluent.conf /fluentd/etc/fluent.conf
fluentd/fluent.conf
<source>
  type tail
  path /var/log/apache2/access.log,/var/log/apache2/access.log.old
  read_from_head true
  tag apache.access_log
  pos_file /home/fluent/access.log.pos
  format /^(?<virtualhost>[^ ]*) (?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>(\\\"|[^\"])*)" "(?<agent>(\\\"|[^\"])*)")?$/
  time_format %d/%b/%Y:%H:%M:%S %z
  types code:integer,size:integer
</source>

<match apache.**>
  type copy
  <store>
    type elasticsearch
    include_tag_key true
    tag_key _tag
    host elasticsearch
    port 9200
    index_name access
    logstash_format true
    logstash_prefix logstash

    buffer_type file
    buffer_path /tmp/fluentd*.buffer
#    buffer_chunk_limit 1g
#    buffer_queue_limit 256
#    flush_interval 60s
#    retry_wait 5s
  </store>
</match>

docker-compose.yaml

  • ElasticsearchとKibanaはDockerHubのものではなく公式のものを使用
  • 永続化データはNamed Data Volumeに保存
  • ログをfluentdからElasticsearchに送るときにキューが溢れたりしないように、Elasticsearchのパラメータを調整
docker-compose.yaml
version: '2'

services:
  fetch:
    build: ./fetch
    volumes:
      - apachelog:/var/log/apache2
      - ./fetch/oldlogs:/var/log/apache2_old:ro
    restart: always

  fluentd:
    build: ./fluentd
    volumes:
      - apachelog:/var/log/apache2
      - fluentdata:/var/log/fluent
    environment:
      FLUENTD_CONF: fluent.conf
    restart: always
    depends_on:
      - elasticsearch

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:5.5.2
    volumes:
      - esdata:/usr/share/elasticsearch/data
      - esconfig:/usr/share/elasticsearch/config
    expose:
      - "9200"
    restart: always
    environment:
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - xpack.monitoring.enabled=false
      - xpack.watcher.enabled=false
      - xpack.graph.enabled=false
      - xpack.ml.enabled=false
      - http.max_content_length=1g
      - thread_pool.index.queue_size=-1
      - thread_pool.bulk.queue_size=-1
      - "ES_JAVA_OPTS=-Xms2048m -Xmx2048m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    mem_limit: 4g

  kibana:
    image: docker.elastic.co/kibana/kibana:5.5.2
    ports:
      - "5601:5601"
    restart: always
    environment:
      - "ELASTICSEARCH_URL=http://elasticsearch:9200"
      - xpack.graph.enabled=false
      - xpack.security.enabled=false
      - xpack.ml.enabled=false
    depends_on:
      - elasticsearch

volumes:
  apachelog:
    driver: local
  fluentdata:
    driver: local
  esdata:
    driver: local
  esconfig:
    driver: local

起動・終了

起動

docker-compose up -d --build

終了

docker-compose down

感想

  • SSH秘密鍵ってどうすればいいの?
    • 環境変数使うとcronからの実行時に見えないので、コンテナ内にファイルで書き出しておくのかな?
    • でもファイルに書き出すとcommitでイメージに含まれてしまう
    • docker swarmでないときにsecretって使えないの?
  • fluent.confpathにワイルドカードを指定しても認識してくれないんだけど・・・
    • しょうがないからgzipになっているログは全部1つのファイル(access.log.old)にまとめてしまえ。
    • ログが入れ替わった直後(毎日5時)は、ログが抜けるけど仕方ないかな。
    • 本当は前日までのログ(*.gz)と当日分のログを1つのファイルに結合させたいんだけど、inodeを変えないで差分だけ追記していく方法がうまくできなかった
  • 公式のElasticsearchとKibanaコンテナの設定難しい、難しくない?
1
5
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
1
5