はじめに
第1章 Elastic Stackとは
第2章 GoではじめるElasticsearch
第3章 AWSでLogstashを使ってみる
第4章 LogstashのGrokフィルターを極める
第5章 複数のデータソースを取り扱う
第6章 Beatsを体験する
第7章 Curatorを用いてIndexを操作する
第8章 Kibanaを使ってデータを可視化する
第9章 もっと便利にKibanaを利用するために
著者紹介
この本で取り扱っている各ツールのバージョンはElasticsearch、Logstash、Kibana共に「6.2」を使用しています。Elastic Stackはバージョンアップがかなり早いツールです。バージョンによって挙動がかなり違うため、別バージョンを使用した場合とコンフィグの書き方や操作方法が異なる場合があります。あらかじめご了承ください。
この本は次の章に別れています。
・Elastic Stackとは?
・GoではじめるElasticsearch
・AWSでLogstashを使ってみる
・LogstashのGrokフィルターを極める
・複数のデータソースを取り扱う
・Beatsを体験する
・Curatorを用いてIndexを操作する
・Kibanaを使ってデータを可視化する
・もっと便利にKibana6を利用するために
Elastic Stackとは?という方はまずはじめにElastic Stackとは?を読むと良いでしょう。基本機能の解説・インストール方法一式を紹介しています。
ローカルで試してみる場合、zipファイルをダウンロードして環境構築するのが簡単です。
この本の情報はElastic社の公式ドキュメントを元に作成していますが、本の情報を用いた開発・制作・運用に対して発生した全ての結果に対して責任を負うことはできません。必ずご自身の環境でよく検証してから導入をお願いします。
Elastic社の公式URLhttps://www.elastic.co/guide/index.html
本書に掲載されたコードと正誤表などの情報は以下のURLで公開しています。
https://github.com/Introduction-of-Elastic-Stack6/manuscript
本書に記載されている会社名、製品名などは、一般に各社の登録商標または商標、商品名です。会社名、製品名については、本文中では©、®、™マークなどは表示していません。
本書に記載された内容は、情報の提供のみを目的としています。したがって、本書を用いた開発、製作、運用は、必ずご自身の責任と判断によって行ってください。これらの情報による開発、製作、運用の結果について、著者はいかなる責任も負いません。
本書籍は、技術系同人誌即売会「技術書典3」および「技術書典4」で頒布されたものを底本としています
Elastic Stackは、Elasticsearch社が提供するプロダクトです。2016年までは、Elasticsearch、Logstash、Kibanaの頭文字をとったELKという呼び名で親しまれていました。しかし、Beatsという新たなプロダクトが増えたことにより、ELKでは違和感があるのと、ELKにうまい具合にB(Beatsの頭文字)を追加することも難しくなりました。そこでELKではなく「Elastic Stack」という呼び方に統合し、主に次の4つがプロダクトとして構成されています。
・Elasticsearch
・Logstash
・Beats
・Kibana
この4つは有名かつOSSとして利用できるプロダクトです。特に検索エンジンとしてのElasticsearchは競合がいないのでは?というくらいよく使われているミドルウェアです。
Elasticsearchのプロセス監視に特化したWatcher、Elasticsearchに保存されているデータの傾向を観察し異常なデータがあればアラートをあげるMachine LearningなどもElastic Stackの中に含まれています。しかし、これらのプロダクトは有償利用となるためこの本では扱いません。
Elastic Stackはやりたいことを実現できるだけのカスタマイズ性の高さ、より利便性を求めてアップデートをかけていく姿勢が魅力です。
Elasticsearh・Logstash・Kibanaの記事を読む際は、バージョンが5より前か後かをきちんと確認してください。コンセプトも少しずつ変化していますし、何より機能の統廃合が進みすぎているので昔「ELK」と呼ばれていたものと現在のElastic Stackはもはや別物です。
Elastic Stackで作るBI環境 誰でもできるデータ分析入門(石井 葵著、インプレスR&D刊)(https://nextpublishing.jp/book/8889.html)によると、Elasticsearchは、Javaで作られている分散処理型の検索エンジンです。クラスタ構成を組むことができるのが特徴なので、大規模な環境で検索エンジンとして利用されることがあります。
と説明されています。用途としては、リアルタイムデータ分析、ログ解析、全文検索などさまざまなところで利用されています。
昔は自分たちでElasticsearchを構築・運用するか、AWSの機能としてAmazon Elasticsearch Service(https://aws.amazon.com/jp/elasticsearch-service/)を利用するしかありませんでした。しかし、Elastic Stack5からはElasticsearch社が提供するクラウドサービスElastic Cloud(https://www.elastic.co/jp/cloud)を利用することで、Elasticsearchの管理・バージョンアップ・データのバックアップなども柔軟に行うことができるようになりました。基盤の持ち方の選択肢が増えるのはありがたいですよね。
Elasticsearchは独自のクエリを使用してデータの問い合わせをおこなうことが特徴です。が、今後のアップデートでSQLを利用してデータの問い合わせをできるようになることが発表されています(https://www.elastic.co/jp/elasticon/conf/2017/sf/elasticsearch-sql)。SQLの方が普及率も高いので、さらにElasticsearchを便利に利用することができそうです。
世の中にはたくさんのログやデータがあります。サーバー運用など、いろんなかたちで携わっている方が多いのではないでしょうか。例を挙げると、Webサービスをログから分析したり、障害対応でログの調査を行うときが考えられますね。ログに何らかの形で携わったことがある人は、一度はログやデータの解析は面倒な作業だと思ったのではないでしょうか1。
ログ収集し、分析するところまでいければまだましな方です。現実は、まずログ自体の取得が非常に大変で、心が折れてしまうこともあります。さらに解析対象のサーバーが1台ならいいのですが、数十台では辛さしかありません。そこでLogstashの出番です。Logstashは各環境に散らばっているログを集め、指定した対象に連携できるツールです。ログの連携だけではなく、ログの加工機能も持ち合わせています2。
ログの取得というとファイルからの取得を思い浮かべますが、プラグインを利用することでAmazon s3やTwitterから直接データを取得することも可能です。
類似プロダクトとしてはTresure Data社製のOSSである、fluentd(https://www.fluentd.org)が存在します。エラーのわかりやすさ、環境構築の簡単さを取るのであればfluentdを、Elastic Stackとしてプロダクトをセットで運用するのであればLogstashを利用するとよいでしょう。
Logstashはバージョン6からLogstashのプロセスをMultiple pipelineとして分割できるようになりました。これを利用すると、AのデータとBのデータをLogstashで取得したいときにLogstashプロセスを2つ作ることができます。片方のプロセスが止まっても、もう片方のデータ連係は継続して行うことができるので、対障害性が上がります。詳しくは「AWSでLogstashを使ってみる」を参照してください。
Beatsは用途に合わせてデータを簡単に送ることができる軽量データシッパーです3。Go言語で作成されており、動作に必要なリソースが他プロダクトと比較して少ないことが特徴です。用途に合わせてXXBeatsというように、名前が異なります。ドキュメントも種別ごとに異なりますので、注意が必要です。
Elastic Stack 6からはModulesという機能が追加されました。Modulesを利用すると、Elasticsearchへのデータ連係とKibanaのグラフ作成を自動で行ってくれます。ただし、Apacheのaccess.logなど利用できるデータが限られています。公式ドキュメント、またはKibanaのGUIで確認してください。
サーバーにある大量のログファイルなどのファイルを一箇所に集約する用途で用います。また、集約だけでなく、転送時にあらかじめ用意されたモジュールを利用することで、自動でパース処理を行い、ElasticsearchやLogstashに転送することが可能です。さらに取り込んだデータをビジュアライズするためのダッシュボードも用意されており、簡単に導入することができます。
メトリックという名前だけあって、システムやサービスのメトリックを収集することができます。たとえば、サーバーのCPUや、メモリーの使用率、ディスクIOなどのデータだけでなく、プロセスなども収集できます。また、ビジュアライズするためのダッシュボードもあらかじめ用意されており、こちらも導入が簡単です。
サービスについても簡単に収集するためのモジュールが用意されており、PostgreSQLやDockerなどのメトリクスを取得可能です。
ネットワークを流れるパケットを収集することができます。パケットを収集するためにWiresharkなどで取得する場面があると思いますが、Packetbeatはより簡単に専門的な知識がなくてもビジュアライズまで可能とするものです。さまざまなプロトコルに対応しているため、MySQLのクエリなどについてKibanaを用いてビジュアライズすることも可能です。
Windowsのイベントログを収集することができます。たとえば、Windowsサーバーを運用しており、監査目的でログオンしたユーザーを把握したい場合は、イベントIDの"ログオン: 4624"や"ログオン失敗: 4625"を指定するだけでイベントログを収集することが可能です。取得したいイベントIDを指定するだけなので、簡単に導入できます。
Windowsの動作ログを取得したい場合、1番導入が簡単で手軽なプロダクトなのではないでしょうか。
サーバーの監査ログを収集することができます。通常、auditdのログを監査ログとして利用する場面が多いと思いますが、Auditbeatを使用することで、必要な情報をグルーピングし、Elasticsearchに転送することができます(要は意識せずストアまでやってくれます)。また、Modulesに対応しているため、導入からKibanaを用いたデータの可視化までを一括で行うことができます。
サーバーの稼働状況を監視できます。ICMPでサーバーの稼働状況を把握することも可能ですし、HTTPでサービス稼働も把握することが可能です。また、TLS、認証やプロキシにも対応しているため、あらゆる状況でも稼働状況を監視することができます。
KibanaはElasticsearch内に保存されているデータを参照し、グラフを利用して可視化できるツールです。Elastic Stack 6からは拡張機能を利用することでLogstashのプロセスの流れをGUIで可視化(Logstash pipeline)することや、Elasticsearchのデータを元に閾値を超えたら通知などのアクションをすることができるようになるMachine Learningを利用できます。なお、Logstash pipelineとMachine Learningは有償になっています。
2017年12月に開催されたElastic {ON} Tour Tokyoで発表された情報と、2018年2月に開催されたカンファレンスElastic {ON}で発表された情報から、注目度が高いものを記述します。
Elastic Stackへのクエリを投げるために、今までElasticsearch独自のクエリを書く必要がありました。しかし、独自のクエリを覚えたり調べたりするのは大変ですよね。
今後のアップデートで、SQLクエリを利用してElasticsearhにクエリを発行できるようになります。Insertなど特定のクエリのみ、かつ標準SQLのサポートになりますが、それでも大分楽になりますね。
Elasticsearch社からライセンスを購入しないと利用できない機能の名前をX-Packといいます。今まではソースコードが非公開となっていました。しかし、Elastic {ON}でX-Packのソースコードが公開されることが発表されました。
有償版の機能は引き続きライセンスを買わないと使うことはできません。OSSになったわけではありません。
Elasticsearchの入門情報の多くはREST APIを使ったものが多いのですが、実際にアプリケーションを作成する際は何らかの言語のSDKを利用するかと思います。そうした際に意外と「あれ、これってどうやるんだ?」となる場合が多いものです。
そこで、本章ではElasticsearchの基本操作についてGo言語を利用して体験していきます。Elasticsearchの基本的な操作を中心に、ちょっとしたTipsについても触れていきます。
Elasticsearchはとても多くの機能を有しています。そのため、本書で全ての機能をカバーすることは難しいです。よって、本章では代表的な機能について紹介します。
また本章ではElasticsearchのAPIを主に扱います。
今回はElastic社が提供している公式Dockerイメージを利用します。次のコマンドを実行してDockerイメージを取得してください。
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.2.2
Dockerイメージが起動できるかを確認します。この章の後半でElasticsearchの外部プラグインをインストールします。Dockerイメージは停止するとイメージ内のデータは消えてしまいます。そのため本書ではインストールしたプラグインを保存する先としてpluginsディレクトリを作成し、Dockerイメージの起動時にマウントさせて利用します。ローカルPC上に作成したpluginsディレクトリが存在する場所でDockerイメージの起動をおこなってください。
docker run -p 9200:9200 -e "discovery.type=single-node"(紙面の都合で改行)
-e "network.publish_host=localhost"(紙面の都合で改行)
-v plugins:/usr/share/elasticsearch/plugins(紙面の都合で改行)
docker.elastic.co/elasticsearch/elasticsearch:6.2.2
起動に成功すると、プロンプト上に起動ログが出力されます。ポートマッピングで指定している9200ポートは、ElasticsearchへのAPIを実行するためのエンドポイントです。Elastic社のDockerイメージを利用すると、Docker起動時に環境変数経由でElasticsearchの設定を変更できます。
起動時にいくつかオプションを指定しているため解説します。
まず、オプションdiscovery.typeをsingle-nodeに設定しています。これはElasticsearchはクラスタを構成せず、シングルノード構成であることを明示しています。すると、起動時に自分自身をマスタノードとして設定し起動します。
次に、network.publish_hostをloccalhostに設定しました。ここではElasticsearchのAPIエンドポイントとして公開するIPアドレスを指定します。指定しなかった場合、Dockerコンテナ内部のプライベートIPアドレスとなり、ローカルホストから直接Elasticsearchのエンドポイントへ接続することができないため、この設定を入れています。
Dockerが正常に起動しているか確認してみましょう。さきほどマッピングした9200ポートでElasticsearchはREST APIのエンドポイントを公開しています。リスト2.3を用いてElasticsearchの基本情報について取得できるか確認してください。
curl http://localhost:9200
# curl http://localhost:9200
{
"name" : "7JNxM8W",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "uaHKm_QGR6yzRCbH87JIcA",
"version" : {
"number" : "6.2.2",
"build_hash" : "10b1edd",
"build_date" : "2018-02-16T19:01:30.685723Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
ElasticsearchのDockerイメージの起動オプションなどは、DockerHubのドキュメント(https://hub.docker.com/_/elasticsearch/)に記載があります。
まずはElasticsearchを操作するためのクライアントライブラリを決める必要があります。Elastic社の公式クライアントhttps://github.com/elastic/go-elasticsearchもあるのですが、現時点では依然開発中なうえにあまり活発にメンテナンスもされていません。
今回はElastic:An Elasticsearch client for the Go(https://github.com/olivere/elastic)を利用します。こちらのクライアントは開発も活発で、Elasticの早いバージョンアップにもいち早く対応しています。
本書で扱う内容もolivere/elasticのGetting Started(https://olivere.github.io/elastic/)をもとにしているため、より多くの機能の使い方などを知るためにもぜひこちらもご参照ください。
それではクライアントをインストールしましょう。今回はgo getでインストールしますが、実際のプロダクト利用時はdepなどのパッケージ管理ツールの利用をお勧めします。
また、事前にGoのインストール及びGOPATHの設定をしてください。
go get "github.com/olivere/elastic"
さて、いよいよGoでElasticsearchを操作していきましょう。その前に、検索するデータを投入するためのIndexとTypeを作成します。
Elasticsearchで検索をおこなうために、まずIndexとTypeを作成する必要があります。これらはRDBMSで例えると次のものに相当します。
・Index:スキーマ/データベース
・Type:テーブル
このようにRDBMSで例えられることが多いのですが、TypeはElasticsearch7系以降に廃止が予定されています。また5系までは1つのIndexに複数のTypeを作成できたのですが、6系では1つのIndexに1つのTypeのみ作成できる仕様へ変わっています(参考:https://www.elastic.co/guide/en/elasticsearch/reference/master/removal-of-types.html)。
本章ではElasticsearch6系を利用するため、1 Indexに1 Typeを作成します。
また、ElasticsearchはMapping定義を作成しなくてもデータを投入することもできます。その際は投入したJSONデータにあわせたMappingが自動で作成されます。
実際の検索アプリケーションでElasticsearchを利用する場合、Mapping定義によりデータスキーマを固定して利用することの方が多いかと思います。また、Mapping定義を作成することにより各フィールド単位でより細かな検索設定をおこなうことが可能なため、本章ではMapping定義を最初から作成して利用します。
本章ではChatアプリケーションを想定したIndex/Typeをもとに操作をおこなっていきます。
Elasticsearchの操作に必要なMapping定義をリスト2.5に記述しました。
{
"mappings": {
"chat": {
"properties": {
"user": {
"type": "keyword"
},
"message": {
"type": "text"
},
"created": {
"type": "date"
},
"tag": {
"type": "keyword"
}
}
}
}
}
今回はchatというTypeへドキュメントを登録していきます。また、propertiesにフィールドの項目を設定します。フィールド名とそのデータ型をtypeで指定していきます。今回指定しているデータ型について説明します。
・keywordはいわゆるString型です。後述するtext型もString型に相当します。しかしkeyword型の場合、そのフィールドへアナライザは適用されません。
・textはString型に相当します。text型を指定したフィールドはアナライザと呼ばれるElasticsearchの高度な検索機能を利用した検索が可能となります。
・dateは日付型です。Elasticsearchへのデータ投入はJSONを介して行うため、実際にデータを投入する際はdateフォーマットに即した文字列を投入することになります。
keyword型とtext型は両者ともString型に相当します。その違いはアナライザを設定できるか否かです。詳細は後ほど説明しますが、アナライザを適用することでそのフィールドに対し高度な検索を行うことができます。一方でkeyword型はアナライザが適用されないため、完全一致での検索が求められます。また、フィールドに対してソートをおこなう場合、keyword型を指定する必要があります。
Elasticsearch6系のデータ型の詳細は公式ドキュメント(https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html)を参照してください。多くのデータ型が標準でサポートされています。
それでは、このMapping定義をElasticsearchへ投入します。先ほどのMapping定義をmapping.jsonとして保存してください。本書ではcurlコマンドを利用しElasticsearchのAPIを実行します。
curl -XPUT 'http://localhost:9200/<Index名>' -H "Content-Type: application/json" -d @mapping.json
Index名に作成するIndexの名前を指定し、先ほど作成したMapping定義をPUTします。本書ではIndexとTypeの両方をchatとします。
# curl -XPUT http://localhost:9200/chat -H "Content-Type: application/json" -d @mapping.json
{"acknowledged":true,"shards_acknowledged":true,"index":"chat"}⏎
作成されたIndexを確認します。リスト2.7のエンドポイントから指定したIndex/TypeのMapping定義を確認できます。
curl -XGET 'http://localhost:9200/<Index名>/_mapping/<Type名>?pretty'
# curl -XGET 'http://localhost:9200/chat/_mapping/chat?pretty'
{
"chat" : {
"mappings" : {
"chat" : {
"properties" : {
"created" : {
"type" : "date"
},
"message" : {
"type" : "text"
},
"tag" : {
"type" : "keyword"
},
"user" : {
"type" : "keyword"
}
}
}
}
}
}