ElasticStack

UPDATED on Feb 3, 2018 – Elastic社イベントサイトを追加

イベント開催日から少々時間が経過したが、Elastic {ON} Tour 2017 東京(2017年12月14日開催)というElastic社オフィシャルのユーザーカンファレンスにて登壇させていただく機会があり、そこで「15分でお届けする Elastic Stack on Azure 設計・構築ノウハウ」というお題でお話をさせていただいた。個人的にとても大好きなプロダクトなので、そのユーザーカンファレンスでお話をさせていただいたということと、そのプロダクトのAzureでの利用促進に微力ながらも貢献できたということは光栄至極である。ここではそのElastic {ON} Tourでの発表で使用したスライドに補足解説を加えて共有させていただく。

セッションスライド(+デモ動画)

15分でお届けする Elastic Stack on Azure 設計・構築ノウハウ from Yoichi Kawasaki

補足解説

デプロイメント

AzureでのElastic Stackの利用は当然ながら仮想マシン(VM)を並べてそこにクラスタを構築することになる。残念ながら現時点でマネージドのElasticサービスはAzureには存在しない。VMベースということで特にオンプレと変わらずマニュアルであったり、ChefやAnsibleなどの構成管理ツールを使ってクラスタを組んだり柔軟な構築が可能であるものの、ここではAzureでの構築ということでARMテンプレートを使ったデプロイメントの方法を紹介している。

推奨仮想ハードウェアとDISK

Elasticクラスタ全体のパフォーマンスを引き出すためには機能別に適正なVMインスタンスとサイズを選択ください。またVMにアタッチするディスクについてはビルトインで可用性設定がされているManaged Disk、もしくはPremium Managed Diskを選択することをお忘れなく。

elastic-stack-on-azure-vm-size

可用性の設定について

AzureでIaaSで可用性の設定といえばおなじみの可用性セット(Availability Set)と可用性ゾーン(Availability Zone)。当然Elastic Stackのクラスタを組む時もこれらの設定を入れましょうというお話。可用性ゾーンは、その可用性レベルの高さから将来的には可用性ゾーンが主流な設定になっていくはずであるものの、2017年12月時点でPreviewリリースであり、利用可能リージョンが米国東部第2、西ヨーロッパのみというとても限定的なものとなっている。現時点でプロダクション用途となると可用性セット一択なので何も考えずに可用性セットを組んでください。

可用性セット(Availability Set)

可用性ゾーン(Availability Zone)

ネットワークセキュリティグループの設定

AzureのIaaSにおけるネットワークフィルタリングの設定に、ネットワークセキュリティグループ(NSG)とよばれるL4フィルタリングがある。当然ながら、既にX-Packを導入していればそのセキュリティ機能の1つとしてネットワークレベルのアクセス制御についても行うことができるが、X-Packを導入していない場合は確実にNSGの設定は必要になってくる。また、Elastic Stack以外のアプリケーションとの連携の際にも必ず必要になってくる。Azure上でのシステム構築では欠かすことのできない設定の1つ。

Azureサービスからのデータコレクション

elastic-stack-on-azure-data-injestion

Azure VMについては、オンプレ同様に、ビルトインのBeatsやlogstashとの連携により、そのログやMetricsなどのデータコレクションを実現することができる。一方、Azureが特に力を入れているPaaS(Platform as a Services)からのデータコレクションについてはどうかというと、下記のサービスについては既にビルトインで用意されている機能や、コミュニティ製Logstash Input プラグインを利用することでデータコレクションを実現することができる。

  • Azure Blob Storage: logstash-input-azureblob
  • Azure Service Bus (Topic): logstash-input-azuretopic
  • Azure Event Hub: logstash-input-azureeventhub
  • Azure SQL Database: logstash-input-jdbc
  • Azure Database for MySQL: logstash-input-jdbc
  • Azure Database for PostgreSQL: logstash-input-jdbc
  • Azure HDInsight: ES-Hadoopによる連携
  • ちなみに、Azureサービス向けLogstashプラグイン一覧についてはこちら – Logstash plugins for Microsoft Azure Services

    Azure Diagnostics、Activities、Metricsログのコレクション

    elastic-stack-on-azure-metrics-diagnostics-logs

    基本的にIaaS、PaaS問わずAzureのほとんどのサービスから下記の情報が出力され、これらの情報はBlobストレージまたはEvent Hubに出力設定が可能となっている。

  • 診断ログ(Diagnostics log)
  • アクティビティログ(Activity log)
  • メトリック
  • また上記に加えて、PaaSサービスに展開するアプリケーション固有のログについても少なくともBlobストレージに書き込むことはできる。つまるところ、上記データコレクションの項目でご紹介したようにBlobストレージやEvent hubに出力されたデータはLogstashを通じてElastic Stackに取り込むことが可能であり、Azureリソース関連情報を含めた全てのログはElastic Stackで一元管理することができるのである。

    参考Links

    Elastic{ON} Tour Tokyo 2017イベントLinks

    Logstash is an open source, server-side data processing pipeline that ingests data from a multitude of sources simultaneously, transforms it, and then sends it to your favorite destinations. Here is a list of logstash plugins for Microsoft Azure Services.

    Plugin NameTarget Azure ServicesNote
    logstash-input-azureeventhubEventHubLogstash input plugin reads data from specified Azure Event Hubs
    logstash-input-azureblobBlob StorageLogstash input plugin that reads and parses data from Azure Storage Blobs
    logstash-input-azuretopicService Bus TopicLogstash input plugin reads messages from Azure Service Bus Topics
    logstash-input-azuretopicthreadableService Bus TopicLogstash input plugin reads messages from Azure Service Bus Topics using multiple threads
    logstash-output-applicationinsightsApplication InsightsLogstash output plugin that store events to Application Insights
    logstash-input-azurewadtable Table StorageLogstash input plugin for Azure Diagnostics. Specifically pulling diagnostics data from Windows Azure Diagnostics tables
    logstash-input-azurewadeventhubEventHubLogstash input plugin reads Azure diagnostics data from specified Azure Event Hubs and parses the data for output
    logstash-input-azurewadtable Table StorageLogstash input plugin reads Azure diagnostics data from specified Azure Storage Table and parses the data for output
    logstash-output-documentdbDocumentDBlogstash output plugin that stores events to Azure DocumentDB
    logstash-output-azuresearchAzure Searchlogstash output plugin that stores events to Azure Search
    logstash-output-azure_loganalyticsLog Analyticslogstash output plugin that stores events to Azure Log Analytics
    logstash-input-jdbc
    SQL Database, Azure Database for MySQL/PostgreSQLInput plugin to ingest data in any database with a JDBC interface into Logstash that support most of major RDBMS such as MySQL、PostgreSQL、OracleDB、Microsoft SQL, etc

    (as of Dec 29, 2016)



    logstash

    これはElasticsearch Advent Calendar 2015の17日目のエントリー

    ARMテンプレートと呼ばれるデプロイ手法を使ってAzure上にElasticsearchクラスタをさくっと構築する方法についてのお話で、主にAzure界隈のElasticsearchユーザ向けの内容となっている。タイトルにある3分でというのは実際に計ったわけではないがそれくらい簡単且つ短時間でできることを強調したく使わせていただいている・・・ということを前もって補足しておく(汗)。

    ARMテンプレートとは?

    ARMテンプレートの前にARMについて少し解説する。ARMはAzure Resource Managerの略で、アプリケーション構築に必要な
    リソース(ストレージ、ネットワーク、コンピュート/仮想マシンなど)をデプロイし管理するための仕組みである。どんなソリューションのデプロイにおいても少なからず仮想ネットワーク、仮想マシン、ストレージ、LBなどのインフラの構築が必要で旧来のやり方ではこれらを1つ1つデプロイしていたかと思う。一方ARMの世界では必要な構築要素をリソースという単位にして、これらリソースを個別にデプロイするのではなく全てのリソースをグループ化してまとめてデプロイし、それらを管理・監視することができる。そして、それら複数のリソースはJSON形式のテンプレートで表現・展開できるようになっていて、このテンプレートのことをARMテンプレートと呼ぶ。Infrastructure as Codeなんて言葉がはやっていたりするが、まさにそれをAzureで実現するための公式な仕組みがARMであり、ARMテンプレートなのである。

    ちなみにこのARMテンプレート、手でいちから作る必要はなく、Azureクイックスタートテンプレートにさまざまなテンプレートが公開されているのでまずは自分の目的に似たようなことを実現しているテンプレートを選んでデプロイしてみることをお勧めする。完成されたものを見ることでお作法が学べるし、それをベースにカスタマイズしていくのが効率的である。

    Elasticsearchクラスタのデプロイ

    上記で説明したARMテンプレートを利用してElasticsearchクラスタのデプロイを行う。ここで使うARMテンプレートはAzureクイック・スタートテンプレートギャラリーにあるElasticsearchテンプレートを利用する。ARMテンプレートを使ったデプロイには複数の方法があるがここではLinux上でAzure CLIを使った方法で行う。ここでの実行OSはUbuntu 14.10。

    最新版のAzure CLIをインストールしてからAzureサブスクリプションに接続する

    $ sudo npm install -g azure-cli
    $ azure --version
    $ azure login

    Azure コマンド ライン インターフェイス (Azure CLI) からの Azure サブスクリプションへの接続」に書かれているように、Azure CLI バージョン 0.9.10 以降では、対話型の azure login コマンドを使用して、任意の ID でアカウントにログインできる。尚、バージョン 0.9.9 以降は、多要素認証をサポートしている。

    デプロイ用のリソースグループを作成する
    ここでは西日本(Japan West)リージョンにResource-ES-JapanWestという名前のリソースグループを作成する。

    # azure group create -n "<リソースグループ名>" -l "<リージョン名>"
    $ azure group create -n "Resource-ES-JapanWest" -l "Japan West"

    ARMテンプレートのダウンロードとパラメータの編集
    Githubよりazure-quickstart-templatesをコピーして、Elasticsearch用テンプレートディレクトリに移動する

    $ git clone https://github.com/Azure/azure-quickstart-templates.git
    $ cd azure-quickstart-template/elasticsearch

    azuredeploy.parameters.jsonを編集してデプロイ用パラメータを入力する。ここでの入力内容は下記のとおり

    {
      "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "adminUsername": {
          "value": "yoichika"       # 管理用ユーザ名
        },
        "adminPassword": {
          "value": "*********"      # 上記管理ユーザパスワード
        },
        "vmDataNodeCount": {
          "value": 3                # データノード数
        },
        "virtualNetworkName": {
          "value": "esvnet"         # 仮想ネットワーク名
        },
        "esClusterName": {
          "value": "elasticsearch"  # ESクラスタ名
        },
        "loadBalancerType": {
          "value": "internal"       # LBタイプ external or internal
        },
        "vmSizeDataNodes": {      
          "value": "Standard_D1"    # データノード用のVMインスタンスサイズ
        },
        "vmClientNodeCount": {
          "value": 0               #クライアントノード数
        },
        "marvel": {
          "value": "no"             # Marvel有効化: yes or no
        },
        "kibana": {
          "value": "yes"            # Kibana有効化: yes or no
        },
        "OS": {
          "value": "ubuntu"        
        }
      }
    }

    ARMテンプレートを元にクラスタのデプロイ

    一通り準備が整ったのでARMテンプレートを元に上記で作成したリソースグループにESクラスタをデプロイする。

    # azure group create "<resource group名>" "<リージョン>" \
    #    -f <azuredeploy.jsonファイル>
    #    -d "<deploy名>"
    #    -e <azuredeploy.parameters.jsonファイル>

    $ azure group create "Resource-ES-JapanWest" "JapanWest" \
       -f azuredeploy.json \
       -d "Deploy-ES-JapanWest" \
       -e azuredeploy.parameters.json

    途中のデプロイメント状況は次のコマンドで確認することができる。

    # azure group deployment show "<Resource group名>" "<deployment名>"
    $ azure group deployment show  "Resource-ES-JapanWest" "Deploy-ES-JapanWest"

    上記コマンドの処理が完了すればデプロイ完了。たったこれだけ。出来上がった構成だが、手っ取り早くはAzureポータルで確認することができる。デプロイ用に作成したリソースグループ(ここではResource-ES-JapanWest)の中身を見ていただくとデプロイされた様々なリソース一覧(ストレージ、仮想ネットワーク、ロードバランサー、仮想マシン、ネットワークセキュリティグループ、パブリック用IP・・・など)が出来上がっていることが分かる。尚、出来上がったESクラスタは合計8VMで構成されており、ESマスターノード用に3つ、ESデータノード用に3つ、Kibana用に1つ、踏み台サーバ用に1つとなっている。仮想ネットワーク内のVMの配置状況を図にすると次のようになる。


    ES-cluster-deployment

    テスト実行

    テスト用のデータセットを投入して、問題なくクラスタが動作するのかを確認してみる。データはこちらでテストに提供されている shakespeare.jsonを利用する。shakespeare.jsonをダウンロード済みであること前提に下記のようにESクラスタにデータを投入する。

    まずはshakespeareデータセットのためにフィールドのMappingを実行

    curl -XPUT http://<ESノードのアドレス>:9200/shakespeare -d '
    {
     "mappings" : {
      "_default_" : {
       "properties" : {
        "speaker" : {"type": "string", "index" : "not_analyzed" },
        "play_name" : {"type": "string", "index" : "not_analyzed" },
        "line_id" : { "type" : "integer" },
        "speech_number" : { "type" : "integer" }
       }
      }
     }
    }
    '
    ;

    次にshakespeareデータセットをESクラスタにロード。

    curl -XPOST "<ESノードのアドレス>:9200/shakespeare/_bulk?pretty" --data-binary @shakespeare.json

    上記処理完了後無事ロードが完了したかどうかインデックスのステータスを確認する。

    $ curl '<ESノードのアドレス>:9200/_cat/indices?v'

    (結果)
    health status index               pri rep docs.count docs.deleted store.size pri.store.size
    green  open   shakespeare           5   1     111396            0     36.2mb           18mb
    green  open   .kibana               1   1          2            0     35.6kb         17.8kb

    念のために検索クエリーを投げてみる。

    $ curl -s '<ESノードのアドレス>:9200/shakespeare/_search?q=*&size=1' | \
      python -mjson.tool| perl -Xpne 's/\\u([0-9a-fA-F]{4})/chr(hex($1))/eg'

    (結果)
    {
        "_shards": {
            "failed": 0,
            "successful": 5,
            "total": 5
        },
        "hits": {
            "hits": [
                {
                    "_id": "4904",
                    "_index": "shakespeare",
                    "_score": 1.0,
                    "_source": {
                        "line_id": 4905,
                        "line_number": "3.3.74",
                        "play_name": "Henry VI Part 1",
                        "speaker": "JOAN LA PUCELLE",
                        "speech_number": 18,
                        "text_entry": "See, then, thou fightst against thy countrymen"
                    },
                    "_type": "line"
                }
            ],
            "max_score": 1.0,
            "total": 111396
        },
        "timed_out": false,
        "took": 9
    }

    さらにKibanaにアクセスしてESクラスタとの連携に問題がないか確認する。念のためにKibanaのエントリポイントはhttp://Kibanaアドレス:5601。特に問題なければKibana上で検索すると次のようにテストロードしたデータセットが閲覧できるはず。


    Kibana-Page

    elasticsearch-headでクラスタノードの状態を確認

    elasticsearch-headはクラスタの構成やインデックスの中身表示、検索クエリの作成、結果取得など手軽に確認することができる便利なGUIツール。このelasticsearch-headを使ってクラスタノードの状態を確認する。インストールは次のようにプラグインコマンドで行う。

    $ sudo /usr/share/elasticsearch/bin/plugin install mobz/elasticsearch-head

    elasticsearch-headのエントリーポイントはhttp://<host>:9200/_plugin/headで結果は次のとおり。


    elasticsearch-head-snapshot-shakespeare

    これを分かりやすくトポロジーにしてみたのが下図。緑の太枠のところがプライマリーシャードで細枠がレプリカシャードを表す。


    ES-Cluster-Topology

    ノードdiscoveryについて

    Elasticsearchはノードdiscovery方式としてデフォルトでmulticastモードを使うようになっており、ノード間でクラスタ名(ここではelasticsearch)を合わせることで内部的に勝手にクラスタ構成を組んでくれるようになっている。このクラスタ内ノード探索はzen discoveryという探索モジュールが使われている。ただし、Azureの場合は仕組み上マルチキャストが利用できない(これはAWSでも同じ)ためunicastモードを使って見つける必要がある。

    ノードdiscovery方式はelasticsearchの設定ファイルelasticsearch.ymlに指定し、unicastモードの場合はdiscovery.zen.ping.unicast.hostsパラメターにノード群のIPをカンマ区切りで指定する。参考までに今回のデータノードのelasticsearch.ymlでは下記のように3つのデータノードのIPをdiscovery.zen.ping.unicast.hostsに指定している。

    /etc/elasticsearch/elasticsearch.yml

    cluster.name: elasticsearch
    node.name: esdatavm0
    path.data: /datadisks/disk2/elasticsearch/data,/datadisks/disk1/elasticsearch/data
    discovery.zen.ping.multicast.enabled: false
    discovery.zen.ping.unicast.hosts: ["10.0.0.10","10.0.0.11","10.0.0.12"]
    node.master: false
    node.data: true
    discovery.zen.minimum_master_nodes: 2
    network.host: _non_loopback_

    Azure Cloud pluginの紹介
    最後にAzure Cloud pluginの紹介をしたい。これはAzure APIを使って自動でAzureに展開されたノードの探索を行うことができるノードdiscoveryプラグインで、unicastモードのようにノードIPをいちいち指定する必要がない点でmulticastモードに似ている。ただし注意点としてこのプラグインはクラシックデプロイモデル管理下のリソース(V1)のみとなっている。よって、今回のようにARMテンプレートでデプロイしたESクラスタは対象外であるが、もしクラシックモデルでデプロイしたESクラスタであればノードdiscovery方式の1つとして是非お試しいただければと思う。

    Enjoy Elasticsearch on Azure!!

    おわり

    LINKS