Azure blob storageからLogstashを使ってデータを読む

概要

公式ドキュメントで、Logstashの標準でInputできるものを確認しますと、Azure関連ではazure_event_hubsevent_hubsはありますがAzure Blob Storageはありません。

www.elastic.co

AWS S3はあるのに何でAzure Blob Storageは無いんや!というAzure大好きっ子(もしくは、やんごとなき大人の事情でAzure使う人)は思うことでしょう。

安心してください。Elastic公式にはないけど、GithubのAzureのレポジトリにはあるよ!

github.com

これを使ってやってみますよっと。

実践

環境の準備

上のレポジトリには対応しているLogstashのバージョンについての言及がないので、最新版を用意します。 9月16日時点の最新は、7.3.2なのでこれを使います。

誰でも同じ環境となるように、Dockerを使って確認していきます。

docker pull docker.elastic.co/logstash/logstash:7.3.2

WebApps(Windows)のログファイルをAzure Blob Storageに出力するようにし、これをLogstashで読み込んでみる、というシナリオです。

インストール

dockerコンテナの中で以下のコマンドを実行します。

logstash-plugin install logstash-input-azureblob

インストール結果

f:id:tsgkdt:20190916215720p:plain

気になるログが数点出ています。

  1. unsupported Java version "11", defaulting to 1.7
  2. WARNING: Illegal reflective access by org.jruby.util.io.FilenoUtil (file:/usr/share/logstash/.m2/repository/org/jruby/jruby-core/9.1.2.0/jruby-core-9.1.2.0.jar) to method sun.nio.ch.SelChImpl.getFD()

  3. sh: line 0: cd: uri:classloader:/: No such file or directory org.glassfish:javax.json:1.1:compile

しかし、Installation successfulと出ているので、成功しているのでしょう。

設定ファイルの準備

ドキュメントに従いlogstashの設定ファイルをこしらえます。 見る限りポイントは、BlobStorageのアカウント名、アクセスキ―、コンテナ名、フィルタするならフィルタの指定ぐらいです。
このあたりは同じinputの中でもfileと似ていて想像しやすいですね。

input {
    azureblob
    {
        storage_account_name => 'mystorageaccount'
        storage_access_key => 'VGhpcyBpcyBhIGZha2Uga2V5Lg=='
        container => 'wad-iis-logfiles'
        path_filters => "hoge-APP/**/*.log"
        codec => line
    }
}    
filter {
  ## Ignore the comments that IIS will add to the start of the W3C logs
  #
  if [message] =~ "^#" {
    drop {}
  }

  grok {
      # https://grokdebug.herokuapp.com/
      match => ["message", "%{TIMESTAMP_ISO8601:log_timestamp} %{WORD:sitename} %{WORD:computername} %{IP:server_ip} %{WORD:method} %{URIPATH:uriStem} %{NOTSPACE:uriQuery} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:clientIP} %{NOTSPACE:protocolVersion} %{NOTSPACE:userAgent} %{NOTSPACE:cookie} %{NOTSPACE:referer} %{NOTSPACE:requestHost} %{NUMBER:response} %{NUMBER:subresponse} %{NUMBER:win32response} %{NUMBER:bytesSent} %{NUMBER:bytesReceived} %{NUMBER:timetaken}"]
  }

  ## Set the Event Timesteamp from the log
  #
  date {
    match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss" ]
      timezone => "Etc/UTC"
  }

  ## If the log record has a value for 'bytesSent', then add a new field
  #   to the event that converts it to kilobytes
  #
  if [bytesSent] {
    ruby {
      code => "event.set('kilobytesSent', event.get('bytesSent').to_i / 1024.0)"
    }
  }

  ## Do the same conversion for the bytes received value
  #
  if [bytesReceived] {
    ruby {
      code => "event.set('kilobytesReceived', event.get('bytesReceived').to_i / 1024.0 )"
    }
  }

  ## Perform some mutations on the records to prep them for Elastic
  #
  mutate {
    ## Convert some fields from strings to integers
    #
    convert => ["bytesSent", "integer"]
    convert => ["bytesReceived", "integer"]
    convert => ["timetaken", "integer"]

    ## Create a new field for the reverse DNS lookup below
    #
    add_field => { "clientHostname" => "%{clientIP}" }

    ## Finally remove the original log_timestamp field since the event will
    #   have the proper date on it
    #
    remove_field => [ "log_timestamp"]
  }

  ## Do a reverse lookup on the client IP to get their hostname.
  #
  dns {
    ## Now that we've copied the clientIP into a new field we can
    #   simply replace it here using a reverse lookup
    #
    action => "replace"
    reverse => ["clientHostname"]
  }

  ## Parse out the user agent
  #
  useragent {
    source=> "useragent"
    prefix=> "browser"
  }
}
output {
    stdout {  }
}

これを /tmp/azure.confとして保存しました。

logstash起動

Logstashを起動してみます。

logstash -f /tmp/azure.conf

起動してみると、以下のようなメッセージが表示されました。

Using version 0.9.x input plugin 'azureblob'. This plugin should work but would benefit from use by folks like you. Please let us know if you find bugs or have suggestions on how to improve this plugin.

f:id:tsgkdt:20190916221710p:plain

This pliugin should work. 動くはずである、と。

処理結果

grokパースエラーとはなりましたが、無事にBlobStorageに保存されたWebAppsのログが出力されていることが確認できました。

f:id:tsgkdt:20190916222353p:plain

改めて、サンプルを見てみますと、Example for Wad-IISとなっていました。

docs.microsoft.com

Microsoftのドキュメントを確認すると、以下のようになっています。

現在、Azure Websites からの IIS ログはサポートされていません。

Wad-IISを対象としたGrokのパターンだとエラーになるのは分かりましたが、自分でパターンを用意すれば良いということが分かれば十分です。

まとめ

ここまでやってみて、まとめます。

  1. Azure Blob Storageから読み出すプラグインは、いくつか警告が出ているものの動くといえば動く
  2. 細かなオプションは要調査
  3. 実運用するには、事前に十分なテストを

「転んでも泣かない」

こういう姿勢が大事だろうと思います。ではでは。