はじめに
Advent Calendar25日目ということでクリスマスですね!
でも、いつもと変わらないですね!
ということで、
今回は、異常検知してくれる?ElasticStackのX-Packの中のMachine Learningについて試してみましたので書きたいと思います( ゚Д゚)ゞビシッ1
こんな流れで話すよ
- ログ取込フロー
- 環境について
- ALBのログを出力して、LogstashからElasticsearchにストア
- Machine Learning使うよ!
ログ取込フロー
AWSでWebサービスを提供している環境で、WebAPサーバの前段にはALBを配置してます。
以下の流れでログを取り込みます。
- ALBログを指定バケットに出力
- LogstashがS3からALBのログを収集
- LogstashがElasticsearchにストア
環境について
- ALB
- Amazon Linux AMI 2017.09.1 (HVM)
- Logstash 6.0
- logstash-input-s3
- Elasticsearch 6.0
- Kibana 6.0
- X-Pack 6.0
ElasticStackは、事前にインストールしていることを前提にしてます。
インストールされていない環境は、以下を参考にして頂ければと思います。
ALBのログを出力して、LogstashからElasticsearchにストア
ALBのロギングを有効化については以下を参考にしてください。
ここからは、S3に格納されているALBログをLogstashで取得するための方法について書きます。
S3 input pluginをインストール
S3からログを取得するには、Logstashのプラグインである"S3 input plugin"をインストールする必要があります。
インストール方法を以下に書きます。
$ cd /usr/share/logstash
$ bin/logstash-plugin install logstash-input-s3
ALBのログを取り込むための準備
ALBのログは、以下の形式で出力されます。
### Log Format
type timestamp elb client:port target:port request_processing_time target_processing_time response_processing_time elb_status_code target_status_code received_bytes sent_bytes "request" "user_agent" ssl_cipher ssl_protocol target_group_arn trace_id
### Sample Log
http 2016-08-10T22:08:42.945958Z app/my-loadbalancer/50dc6c495c0c9188
192.168.131.39:2817 10.0.0.1:80 0.000 0.001 0.000 200 200 34 366
"GET http://www.example.com:80/ HTTP/1.1" "curl/7.46.0" - -
arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067
"Root=1-58337262-36d228ad5d99923122bbe354"
この出力されたログを取り込むために、Grok Patternを作成したり、型変換をLogstashで施す必要があります。
フィールド定義
それでは、ログフォーマットからフィールド名と型の定義を行います。
ALBが受け付けてからクライアントに返すまでの処理時間を表すフィールドをfloatにします。
対象は、"request_processing_time"、"target_processing_time"、"response_processing_time"です。
Log | Field | Type |
---|---|---|
type | type | string |
timestamp | date | date |
elb | elb | string |
client:port | client_port | string |
target:port | target_port | string |
request_processing_time | request_processing_time | float |
target_processing_time | target_processing_time | float |
response_processing_time | response_processing_time | float |
elb_status_code | elb_status_code | string |
target_status_code | target_status_code | string |
received_bytes | received_bytes | long |
sent_bytes | sent_bytes | long |
request | ELB_REQUEST_LINE | string |
user_agent | user_agent | string |
ssl_cipher | ssl_cipher | string |
ssl_protocol | ssl_protocol | string |
target_group_arn | target_group_arn | string |
trace_id | trace_id | string |
Grok Pattern
ALBのログに正規表現をかけて、構造化するため、Grokする必要があります。
Grokを直接Logstashのconfファイルに書くことも可能ですが、可読性を重視するため、パターンファイルとして外出しします。
以下が、ALBのログをよしなに取り込むためのGrok Patternファイルです。
### Application Load Balancing
ALB_ACCESS_LOG %{NOTSPACE:type} %{TIMESTAMP_ISO8601:date} %{NOTSPACE:elb} (?:%{IP:client_ip}:%{INT:client_port}|-) (?:%{IP:backend_ip}:%{INT:backend_port}|-) (:?%{NUMBER:request_processing_time}|-1) (?:%{NUMBER:target_processing_time}|-1) (?:%{NUMBER:response_processing_time}|-1) (?:%{INT:elb_status_code}|-) (?:%{INT:backend_status_code}|-) %{INT:received_bytes} %{INT:sent_bytes} \"%{ELB_REQUEST_LINE}\" \"(?:%{DATA:user_agent}|-)\" (?:%{NOTSPACE:ssl_cipher}|-) (?:%{NOTSPACE:ssl_protocol}|-) %{NOTSPACE:target_group_arn} \"%{NOTSPACE:trace_id}\"
Multiple Pipelines
Logstashのconfファイルを呼び出すためにMultiple Pipelinesを使用します。
Pipeline.ymlの定義は、以下です。
- pipeline.id: alb
pipeline.batch.size: 125
path.config: "/etc/logstash/conf.d/alb.cfg"
pipeline.workers: 1
Pipelineの設定については、以下を参考にして頂ければと思います。
Logstashのディレクトリ構成
ここまで準備しましたが、以下の様に各ファイルを配置します。
/etc/logstash
├ logstash.yml
├ conf.d
│ └ alb.cfg
├ jvm.options
├ log4j2.properties
├ alb_patterns
└ pipelines.yml
- ALBのalb.cfgをconf.d配下に配置
- ALBのGrok PatternファイルをLogstash配下に配置
- alb.cfgを呼び出すpipeline.ymlをLogstash配下に配置
ALBのconfファイルを作成するよ
- Input: S3からALBのログを取得する2
- Filter: 取得したログに対してフィルタをかける
- Output: Elasticsearchにストア
input {
s3 {
region => "ap-northeast-1"
bucket => "hoge"
prefix => "hoge"
### S3へのポーリング間隔を指定
interval => "60"
sincedb_path => "/var/lib/logstash/sincedb_alb"
}
}
filter {
### 読み込むGrok Patternファイルを"patterns_dir"で指定
grok {
patterns_dir => ["/etc/logstash/alb_patterns"]
match => { "message" => "%{ALB_ACCESS_LOG}" }
}
date {
match => [ "date", "ISO8601" ]
timezone => "Asia/Tokyo"
target => "@timestamp"
}
### グローバルIPから国などをマッピングするために指定
geoip {
source => "client_ip"
}
### デフォルトの型がstringのため、フィールド定義で定義した型に変換
mutate {
convert => [ "request_processing_time", "float" ]
convert => [ "response_processing_time", "float" ]
convert => [ "target_processing_time", "float" ]
convert => [ "received_bytes", "int" ]
convert => [ "sent_bytes", "int" ]
### 不要なフィールドを削除
remove_field => [ "date", 'message' ]
}
}
output {
elasticsearch {
hosts => [ "localhost:9200" ]
}
}
ここまで整ったらLogstashを起動
$ initctl start logstash
logstash start/running, process 3121
Machine Learning使うよ!
KibanaでアクセスしてMachine Learingをクリックします。
新しくジョブを作成するので、"Create new job"をクリックします。
以下の画面で"Single metric"をクリックします。
"Aggregation"と"Filed"を指定します。
Filedは、"target_processing_time"にすることで、バックエンドのサーバへリクエストしてから返ってくるまでの時間をみます。
そうすることで、サーバ内の処理遅延が発生しているかを確認できます。
画面の右上から期間を指定します。
"Name"と"Description"を入力し、"Create job"をクリックします。
ジョブが実行され、結果を表示するため"View Results"をクリックします。
指定期間の中で普段より乖離している部分を赤やオレンジでマークされます。
今回は、Single metricでやりましたが、Multi metricを使うことで、
グローバルIPアドレスやUserAgentと合わせて検出することも可能です。
さいごに
いかがでしたか?ログを取り込んでジョブを作成するだけで簡単に実行できました。
今までは、人の目で判断していたところをMachine Learningを用いることで、普段の傾向から乖離している部分を自動で検出してくれるのは便利ですね。
Advent Calendar最終日ですが、これにておしまいです。
ありがとうございました!