Azure

In this article, I’d like to introduces a solution to collect events from various sources and send them into HTTP Trigger function in Azure Functions using fluent-plugin-azurefunctions. Triggers in Azure Functions are event responses used to trigger your custom code. HTTP Trigger functions allow you to respond to HTTP events sent from fluentd and cook them into whatever you want!


fluent-plugin-azurefunctions

[note] Azure Functions is a (“serverless”) solution for easily running small pieces of code, or “functions,” in Azure. Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. fluent-plugin-azurefunctions is a fluentd output plugin that enables to collect events into Azure Functions.

Pre-requisites

Setup: Azure Functions (HTTP Trigger Function)

Create a function (HTTP Trigger). First, you need to have an function app that hosts the execution of your functions in Azure if you don’t already have. Once you have an function app, you can create a function. Here are instructions:

A quick-start HTTP trigger function sample is included under examples/function-csharp in Github repository. You simply need to save the code (run.csx) and configuration files (function.json, project.json) in the same Azure function folder. Explaining a little bit about each of files, the function.json file defines the function bindings and other configuration settings. The runtime uses this file to determine the events to monitor and how to pass data into and return data from function execution. The project.json defines packages that the application depends. The run.csx is a core application file where you write your code to process Your jobs. Here is a sample run.csx:

Setup: Fluentd

First of all, install Fluentd. The following shows how to install Fluentd using Ruby gem packger but if you are not using Ruby Gem for the installation, please refer to this installation guide where you can find many other ways to install Fluentd on many platforms.

# install fluentd
sudo gem install fluentd --no-ri --no-rdoc

# create fluent.conf
fluentd --setup <directory-path-to-fluent-conf>

Also, install fluent-plugin-azurefunctions for fluentd aggregator to send collected event data into Azure Functions.

sudo gem install fluent-plugin-azurefunctions

Next, configure fluent.conf, a fluentd configuration file as follows. Please refer to this for fluent-plugin-azurefunctions configuration. The following is a sample configuration where the plugin writes only records that are specified by key_names in incoming event stream out to Azure Functions:

# This is used by event forwarding and the fluent-cat command
<source>
    @type forward
    @id forward_input
</source>

# Send Data to Azure Functions
<match azurefunctions.**>
    @type azurefunctions
    endpoint  AZURE_FUNCTION_ENDPOINT   # ex. https://<accountname>.azurewebsites.net/api/<functionname>
    function_key AZURE_FUNCTION_KEY     # ex. aRVQ7Lj0vzDhY0JBYF8gpxYyEBxLwhO51JSC7X5dZFbTvROs7uNg==
    key_names key1,key2,key3
    add_time_field true
    time_field_name mytime
    time_format %s
    localtime true
    add_tag_field true
    tag_field_name mytag
</match>

[note] If key_names not specified above, all incoming records are posted to Azure Functions (See also this).

Finally, run fluentd with the fluent.conf that you configure above.

fluentd -c ./fluent.conf -vv &

TEST

Let’s check if test events will be sent to Azure Functions that triggers the HTTP function (let’s use the sample function included in Github repo this time). First, generate test events using fluent-cat like this:

echo ' { "key1":"value1", "key2":"value2", "key3":"value3"}' | fluent-cat azurefunctions.msg

As both add_time_field and add_tag_field are enabled, time and tag fields are added to the record that are selected by key_names before posting to Azure Functions, thus actual HTTP Post request body would be like this:

{
    "payload": '{"key1":"value1", "key2":"value2", "key3":"value3", "mytime":"1480195100", "mytag":"azurefunctions.msg"}'
}

If events are sent to the function successfully, a HTTP trigger function handles the events and the following logs can be seen in Azure Functions log stream:

2016-11-26T21:18:55.200 Function started (Id=5392e7ae-3b8e-4f65-9fc1-6ae529cdfe3a)
2016-11-26T21:18:55.200 C# HTTP trigger function to process fluentd output request.
2016-11-26T21:18:55.200 key1=value1
2016-11-26T21:18:55.200 key2=value2
2016-11-26T21:18:55.200 key3=value3
2016-11-26T21:18:55.200 mytime=1480195100
2016-11-26T21:18:55.200 mytag=azurefunctions.msg
2016-11-26T21:18:55.200 Function completed (Success, Id=5392e7ae-3b8e-4f65-9fc1-6ae529cdfe3a)

Advanced Senarios

1. Near Real-time processing

Function Apps can output messages to different means or data stores. For example, fluentd collects events generated from IoT devices and send them to Azure Function, and the the HTTP trigger function transforms the events and processes the data to store in a persistent storage or to pass them to different means. Here are some of options available at the time of writing:

2. Background jobs processing

If the jobs are expected to be large long running ones, it’s recommended that you refactor them into smaller function sets that work together and return fast responses. For example, you can pass the HTTP trigger payload into a queue to be processed by a queue trigger function. Or if the payload is too big to pass into the queue, you can store them onto Azure Blob storage at first, then pass only limited amount of the data into a queue just to trigger background workers to process the actual work. These approaches allow you to do the actual work asynchronously and return an immediate response.

LINKS

END

OCRとはOptical Character Recognitionの略で日本語にすると光学文字認識と訳されており、ざっくりと画像の中の文字をテキストに変換する技術のことを指す。テキストに変換されるということは勘が鋭い皆さんはお気づきだと思うが、テキストの全文検索であったり、テキストから音声への変換、さらには機械翻訳を使って多言語への変換といった展開が考えられる。そんな可能性を秘めたOCRであるが、ここではそのOCRの技術を使ってビデオファイルから抽出したテキストデータを元にビデオに字幕表示したり、動画中に表示される文字を全文検索をするデモを紹介したい。内容的には「Azure Media & Cognitiveデモ:Speech-To-Text」で紹介したデモのOCR版といったところ。



Video OCR Demo Screenshot

( デモサイト | Source Code )

主要テクノロジーと機能

Azure Media OCRメディアプロセッサによるテキスト抽出

このデモではAzure Media OCRメディアプロセッサー(MP)を使用してビデオファイル内のテキストコンテンツを検出してテキストファイルを生成している。OCRメディアプロセッサーは入力パラメータによりビデオ解析の挙動を調整することができる。主なパラメータとしては検索対象テキストの言語(日本語もサポート)、テキストの向き、サンプリングレート、ビデオフレーム内のテキスト検出対象のリージョンがあるが、本デモでの入力パラメータ(Video-OCR-Search-Python/src/ocr-detectregion.json)は以下の通り検索対象言語は日本語、1秒おきのサンプリングレート、テキスト検出対象のリージョンからビデオフレーム内の上部1/4を省く設定(検出対象をフレームトップから85 pixel以下を対象)にしている。

{
    "Version":"1.0",
    "Options":
    {
        "Language":"Japanese",
        "TimeInterval":"00:00:01.000",
        "DetectRegions":
        [
            {"Left":"0","Top":"85","Width":"1280","Height":"635"}
        ]
    }
}

そして、Azure Media OCRメディアプロセッサはビデオで検出された文字を下記のような表示時間に基づいてセグメント化された形で結果出力する。結果ファイルの完全版はこちら(azuresubs.json)を参照ください。

{
    "fragments": [
        {
            "start": 0
            "interval": 319319,
            "duration": 319319,
            "events": [
                [
                    {
                        "language": "Japanese",
                        "text": "Azure の 契 約 内 容 を 変 更 す る Microsoft Azure"
                    }
                ]
            ]
        },
        {  /* fragment1 */ },
        {  /* fragment2 */ },
        ...
        {  /* fragmentN */ }
    ],
    "version": 1,
    "framerate": 29.97,
    "height": 720,
    "width": 1280,
    "offset": 0,
    "timescale": 30000
}

入力パラメータと出力形式共に詳細はこちらのドキュメントを参照いただくとしてAzure Media OCRメディアプロセッサ利用の注意点として次の2つがある:

字幕(Closed Caption)データフォーマットへの変換

まず上記Azure Media OCRメディアプロセッサー(MP)から出力されたJSONファイルの内容を元に字幕用のデータフォーマットであるWebVTTフォーマットファイルを生成している。そして「Azure Media & Cognitiveデモ:Speech-To-Text」でも紹介したようにHTML5のtrackタグエレメントによるビデオファイルの字幕表示機能使ってOCRの内容の字幕表示を実現している。本デモではHTML5に下記のように動画(TransferanAzuresubscriptionJP.mp4)をVideoソースとしてtrackエレメントにWebVTTファイル(azuresubs.vtt)を指定している。

<video id="Video1" controls autoplay width="600">
    <source src="TransferanAzuresubscriptionJP.mp4" srclang="en" type="video/mp4">
    <track id="trackJA"  src="azuresubs.vtt"  kind="captions" srclang="ja" label="OCR Subtitle" default>
</video>

Azure Searchによる全文検索

デモページ上部にある検索窓にキーワードを入力してGoボタンを押すとビデオコンテンツからOCR抽出されたテキストを元に生成された字幕データを全文検索してキーワードにマッチしたテキストとその表示時間に絞り込むことができる。仕組みは「Azure Media & Cognitiveデモ:Speech-To-Text」と全く同じで、Azure Searchを使用して字幕データを解析して字幕表示時間とその対応テキストを1ドキュメントレコードとしてAzure Searchにインジェストしてその生成されたインデックスに対してキーワードを元に全文検索することで実現している。検索用のインデックススキーマもまったくおなじで次のように字幕表示時間とその対応テキストをレコード単位となるように定義している。

{
    "name": "ocr",
    "fields": [
        { "name":"id", "type":"Edm.String", "key": true, "searchable": false, "filterable":false, "facetable":false },
        { "name":"contentid", "type":"Edm.String","searchable": false, "filterable":true, "facetable":false },
        { "name":"beginsec", "type":"Edm.Int32", "searchable": false, "filterable":false, "sortable":true, "facetable":false },
        { "name":"begin", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"end", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"caption", "type":"Edm.String", "searchable": true, "filterable":false, "sortable":false, "facetable":false, "analyzer":"ja.microsoft" }
     ]
}

デモデータ作成手順

GithubプロジェクトページVideo-OCR-Search-Pythonの1. Preparationと2. Batch executionを実施いただければOCR抽出されたテキストを元に字幕データ*.vttファイルが生成され、そのテキストがAzure Searchに格納されてデモページ表示のための準備は完了する。最後に表示用のページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlとsearch.jsの変更のみでいけるはず。

本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。

Enjoy Video OCR demo!

ビデオコンテンツを音声認識エンジンでテキスト化してそれを元にスピーチ検索するデモコンテンツを紹介したい。これは過去にde:code2016というマイクロソフトの開発者向けイベントで行ったブレイクアウトセッション「DEV-18: Azure Search Deep Dive」にて紹介したビデオコンテンツのスピーチ検索デモを簡略化して再利用しやすいものにしたものである。



Video STT Demo Screenshot

( デモサイト | Source Code )

主要テクノロジーと機能

Azure Media Indexer 2 Previewによる音声からテキスト抽出

このデモではAzure Media Indexer 2 Preview メディア プロセッサー (MP)を使用してビデオコンテンツからテキストを抽出している。このAzure Media Indexer 2 Previewは自然言語処理(NLP)や音声認識エンジンを駆使してビデオコンテンツより字幕用データ(時間やテキスト)や検索可能にするためのメタデータを抽出することができる。Indexer 2という名前の通り前のバージョンであるAzure Media Indexerが存在するが、これと比較すると、Azure Media Indexer 2 Previewは、インデックス作成が高速化され、より多くの言語をサポートしていることが特徴である。2016年11月6日時点で英語、スペイン語、フランス語、ドイツ語、イタリア語、中国語、ポルトガル語、アラビア語などがサポートされている(残念ながら日本語はまだ未サポート)。

下イメージはAzure Media Indexer 2 (Preview)で生成されるTTMLWebVTTという代表的な字幕データフォーマット。


AzureMediaIndexer-ClosedCaption

HTML5と字幕(Closed Caption)

HTML5にはtrackタグエレメントを使ってビデオファイルに字幕を表示する機能が標準的に実装されている。本デモではHTML5に下記のように動画(Python_and_node.js_on_Visual_Studio.mp4)をVideoソースとしてtrackエレメントに字幕WebVttファイル(build2016breakout.vtt)を指定している。

<video id="Video1" controls autoplay width="600">
    <source src="Python_and_node.js_on_Visual_Studio.mp4" srclang="en" type="video/mp4">
    <track id="trackJA"  src="build2016breakout.vtt"  kind="captions" srclang="ja" label="Closed Captions" default>
</video>

Azure Searchによる全文検索

デモページ上部にある検索窓にキーワードを入力してGoボタンを押すとビデオコンテンツの字幕データを全文検索してキーワードにマッチしたテキストとその表示時間に絞り込むことができる。ここでは全文検索エンジンにAzure Searchを使用し、Azure Media Indexer 2 (Preview)より抽出された字幕データを解析して字幕表示時間とその対応テキストを1ドキュメントレコードとしてAzure Searchにインジェストしてその生成されたインデックスに対してキーワードを元に全文検索することで実現している。字幕データ検索用のインデックススキーマは次のように字幕表示時間とその対応テキストをレコード単位となるように定義している。

{
    "name": "stt",
    "fields": [
        { "name":"id", "type":"Edm.String", "key": true, "searchable": false, "filterable":false, "facetable":false },
        { "name":"contentid", "type":"Edm.String","searchable": false, "filterable":true, "facetable":false },
        { "name":"beginsec", "type":"Edm.Int32", "searchable": false, "filterable":false, "sortable":true, "facetable":false },
        { "name":"begin", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"end", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false },
        { "name":"caption", "type":"Edm.String", "searchable": true, "filterable":false, "sortable":false, "facetable":false, "analyzer":"en.microsoft" }
     ]
}

デモデータ作成手順

GithubプロジェクトページVideo-STT-Search-Pythonの1. Preparationと2. Batch executionを実施いただければ字幕データ*.vttファイルが生成され、そのテキストがAzure Searchに格納されてデモページ表示のための準備は完了する。最後に表示用のページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlとsearch.jsの変更のみでいけるはず。

本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。

Enjoy Video Speech-to-text demo!

UPDATED 2016-10-31: paramsオプション + Bash Completion追加

みんな大好きSSHとAzureのお話し。物理サーバ、EC2/仮想マシン、コンテナなどなんでもよいがその上にLinuxサーバをたてたらまずやることの1つにSSHログインのためにそのIPアドレス調べて~/.ssh/configにそのエントリーを追加してやることがあるんじゃないかと思います。この作業、エントリー数が少なければ大したことはないものの、追加対象のホストが大量にある場合はかなり面倒な作業になってきます。さらにDHCPなどでアドレスを動的に取得するような設定であればサーバの上げ下げのたびにIPアドレスが変わってくるので~/.ssh/configの更新が必要になってきて、どうしようもなく面倒になってきます。こういった単純でどうしようもなくつまらない作業は自動化したいですよね? ここではそんな皆さんのためにazuresshconfigというツールを紹介させていただきます。

これは皆さんのAzureサブスクリプション下に作られた仮想マシン一覧(ARMに限る)の情報を取得して各仮想マシンごとのエントリー情報(マシン名とIPアドレス)を~/.ssh/configに追加・更新してくれるツール。新規に仮想マシンを追加した際や、仮想マシンのIPアドレスが追加した際にはazuresshconfigを実行してあげることで~/.ssh/configが最新のエントリー情報でアップデートされ、各マシンにマシン名でSSHログインできるようになります。

ちなみに、~/.ssh/configとは何ですか?という人はQiitaの記事「~/.ssh/configについて」がとても分かりやすく書かれているので参考になるかと。

インストール

Pythonパッケージ管理ツールpipを使ってazuresshconfigをインストールしてください。インストール時に何かエラーが発生した場合は、こちらのページを参照いただき特に該当する事象がないか確認ください。

pip install azuresshconfig

設定ファイルの編集(サービスプリンシパル)

vi $HOME/.azure/azuresshconfig.json

{
    "subscription_id": "<YOUR SUBSCRIPTION ID>",
    "client_id": "<YOUR APPLICATION CLIENT IP>",
    "client_scret": "<YOUR APPLICATION CLIENT SCRET>",
    "tenant_id": "<YOUR TENANT ID>"
}

サービスプリンシパルを作る必要があります。サービスプリンシパルの作り方が分からない人、とってもよいドキュメントがあります。こちらを参照ください:「Use Azure CLI to create a service principal to access resources

使い方

azuresshconfig --help

usage: azuresshconfig.py [-h] [--version] [--init] [--profile PROFILE]
                         [--user USER] [--identityfile IDENTITYFILE]
                         [--private] [--resourcegroups RESOURCEGROUPS]
                         [--params PARAMS]

This program generates SSH config from Azure ARM VM inventry in subscription

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --init                Create template client profile at
                        $HOME/.azure/azuresshconfig.json only if there is no
                        existing one
  --profile PROFILE     Specify azure client profile file to use
                        ($HOME/.azure/azuresshconfig.json by default)
  --user USER           SSH username to use for all hosts
  --identityfile IDENTITYFILE
                        SSH identity file to use for all hosts
  --private             Use private IP addresses (Public IP is used by
                        default)
  --resourcegroups RESOURCEGROUPS
                        A comma-separated list of resource group to be
                        considered for ssh-config generation (all resource
                        groups by default)
  --params PARAMS       Any ssh-config params you want to add with query-
                        string format: key1=value1&key2=value2&...

実行する

1. パラメータ指定なしで実行

azuresshconfig

~/.ssh/configには下記のように### AZURE-SSH-CONFIG BEGIN ### ~ ### AZURE-SSH-CONFIG END ###のブロック内にマシン名とそのIPアドレス(デフォルト:パブリック)のエントリー一覧が追加・更新されます。

cat ~/.ssh/config

### AZURE-SSH-CONFIG BEGIN ###

Host myvm1
    HostName 40.74.124.30

Host myvm2
    HostName 40.74.116.134
....

### AZURE-SSH-CONFIG END ###

2. SSHユーザと鍵指定

azuresshconfig --user yoichika --identityfile ~/.ssh/id_rsa

~/.ssh/configには各エントリーにIPアドレスに加えてユーザ名と鍵のパス情報が追加されます。

cat ~/.ssh/config

### AZURE-SSH-CONFIG BEGIN ###

Host myvm1
    HostName 40.74.124.30
    IdentityFile /home/yoichika/.ssh/id_rsa
    User yoichika

Host myvm2
    HostName 40.74.116.134
    IdentityFile /home/yoichika/.ssh/id_rsa
    User yoichika
....

### AZURE-SSH-CONFIG END ###

3. プライベートIPを指定

azuresshconfig --user yoichika --identityfile ~/.ssh/id_rsa --private

privateオプションを付けて実行することで~/.ssh/configの各エントリーにはデフォルトのパブリックIPアドレスではなくてプライベートIPアドレスが追加されます。

4. リソースグループで絞る

azuresshconfig --user yoichika --identityfile ~/.ssh/id_rsa --resourcegroups mygroup1,mygroup2

resourcegroupsオプションを指定することで指定されたリソースグループに所属する仮想マシンのエントリーのみが~/.ssh/configに追加されます。

5. 追加ssh-configパラメータの指定

azuresshconfig.py --user yoichika \
                --identityfile ~/.ssh/id_rsa \
                --params "Port=2222&Protocol=2&UserKnownHostsFile=~/.ssh/known_hosts&ForwardAgent=yes"

paramsオプションを指定することでその他指定可能なssh-configパラメータを追加することができます。上記のようにparamsにssh-configのPort、Protocol、UserKnownHostsFile、ForwardAgentキーと値をセットすることで次のように出力されるssh-configに指定したキーと値がセットされます。

cat ~/.ssh/config

### AZURE-SSH-CONFIG BEGIN ###

Host myvm1
    HostName 40.74.124.30
    IdentityFile ~/.ssh/id_rsa
    User yoichika
    Port 2222
    Protocol 2
    UserKnownHostsFile ~/.ssh/known_hosts
    ForwardAgent yes

Host myvm2
    HostName 40.74.116.134
    IdentityFile /home/yoichika/.ssh/id_rsa
    User yoichika
    Port 2222
    Protocol 2
    UserKnownHostsFile ~/.ssh/known_hosts
    ForwardAgent yes
....

### AZURE-SSH-CONFIG END ###

Shell Completion

Bashでの補完

次のようにbash/azuresshconfig_completion.bashをbash起動時に読み込ませてあげることでazuresshconfigのパラメータ補完ができるようになります.

# copy this under either of following directories
cp azuresshconfig_completion.bash (/etc/bash_completion.d | /usr/local/etc/bash_completion.d | ~/bash_completion.d)

# or append 'source /path/to/azuresshconfig_completion.bash' to .bashrc like this
echo 'source /path/to/azuresshconfig_completion.bash' >> .bashrc

次のようにtabでazuresshconfigのパラメータ補完を行います。

$ azuresshconfig -[tab]
-h                --identityfile    --params          --profile         --user
--help            --init            --private         --resourcegroups

$ azuresshconfig --i[tab]
--identityfile  --init

$ azuresshconfig --p[tab]
--params   --private  --profile

$ azuresshconfig --user [tab]
$ azuresshconfig --user <ssh_user>
$ azuresshconfig --user <ssh_user> --identityfile [tab]
$ azuresshconfig --user <ssh_user> --identityfile <ssh_identity_file>

その他

インストール時のエラーや実行時のエラーについてはこちらに見つけ次第事象とその対応方法を追加しています。
https://github.com/yokawasa/azure-ssh-config/blob/master/Issues.md

もしバグを見つけたり、追加機能のリクエストがある場合にこちらにIssue追加ください。頑張って時間をみつけて対応します。
https://github.com/yokawasa/azure-ssh-config/issues

LINKS

azuresshconfig makes your SSH life on Azure easy!

Here is a list of embulk plugins that you can leverage to transfer your data between Microsoft Azure Services and various other databases/storages/cloud services.

Plugin NameTarget Azure ServicesNote
embulk-output-azure_blob_storageBlob StorageEmbulk output plugin that stores files onto Microsoft Azure Blob Storage
embulk-input-azure_blob_storageBlob StorageEmbulk input plugin that reads files stored on Microsoft Azure Blob Storage.
embulk-output-sqlserverSQL Databases, SQL DWHEmbulk output plugin that Inserts or updates records to SQL server type of services like SQL DB/SQL DWH
embulk-input-sqlserverSQL Databases, SQL DWHEmbulk input plugin that selects records from SQL type of services like SQL DB/SQL DWH
embulk-output-documentdbDocumentDBEmbulk output plugin that dumps records to Azure DocumentDB
embulk-output-azuresearchAzure SearchEmbulk output plugin that dumps records to Azure Search

(as of Aug 30, 2016)

For embulk, check this site: https://github.com/embulk/embulk



embulk-screenshot

I’d like to announce fluent-plugin-documentdb finally supports Azure DocumentDB Partitioned collections for higher storage and throughput. If you’re not familiar with fluent-plugin-documentdb, read my previous article before move on.

Partitioned collections is kick-ass feature that I had wanted to support in fluent-plugin-documentdb since the feature came out public (see the announcement). For big fan of fluent-plugin-documentdb, sorry for keeping you waiting for such a long time 🙂 If I may make excuses, I would say I haven’t had as much time on the project, and I had to do ruby client implementation of Partitioned collections by myself as there is no official DocumentDB Ruby SDK that supports it (As a result I’ve created tiny Ruby DocumentDB client libraries that support the feature. Check this out if you’re interested).


fluentd-azure-documentdb-collection

What are Partitioned collections?

According to official documentation, Partitioned collections can span multiple partitions and support very large amounts of storage and throughput. You must specify a partition key for the collection. Partitioned collections can support larger data volumes and process more requests compared to Single-partitioned collection. Partitioned collections support up to 250 GB of storage and 250,000 request units per second of provisioned throughput [Updated Aug 21, 2016] (@arkramac pointed that out for me) Partitioned collections support unlimited storage and throughput. 250GB storage and 250k req/sec are soft cap. You can increase these limits by contacting and asking Azure support.

On the other hand, Single-partition collections have lower price options and the ability to query and perform transactions across all collection data. They have the scalability and storage limits of a single partition. You do not have to specify a partition key for these collections.

Creation of Partitioned collections

You can create Partitioned collections via the Azure portal, REST API ( >= version 2015-12-16), and client SDKs in .NET, Node.js, Java, and Python. In addition, you let fluent-plugin-documentdb create Partitioned collections automatically by adding the following configuration options upon the ones for single-partitioned collection in fluentd.conf:

It creates a partitioned collection as you configure in starting the plugin if not exist at that time.

Configuration Example

Suppose that you want to read Apache access log as source for fluentd, and that you pick “host” as a partition Key for the collection, you can configure the plugin like this following:

<source>
    @type tail                          # input plugin
    path /var/log/apache2/access.log   # monitoring file
    pos_file /tmp/fluentd_pos_file     # position file
    format apache                      # format
    tag documentdb.access              # tag
</source>

<match documentdb.*>
    @type documentdb
    docdb_endpoint https://yoichikademo.documents.azure.com:443/
    docdb_account_key Tl1xykQxnExUisJ+BXwbbaC8NtUqYVE9kUDXCNust5aYBduhui29Xtxz3DLP88PayjtgtnARc1PW+2wlA6jCJw==
    docdb_database mydb
    docdb_collection my-partitioned-collection
    auto_create_database true
    auto_create_collection true
    partitioned_collection true
    partition_key host
    offer_throughput 10100
    localtime true
    time_format %Y%m%d-%H:%M:%S
    add_time_field true
    time_field_name time
    add_tag_field true
    tag_field_name tag
</match>

Basically that’s all additional configuration for Partitioned collections. Please refer to my previous article for the rest of setup and running work for the plugin.

Happy log collections with fluent-plugin-documentdb!!

LINKS

In this article, I’d like to introduces a solution to collect logs and store them into Azure DocumentDB using fluentd and its plugin, fluent-plugin-documentdb.

Azure DocumentDB is a managed NoSQL database service provided by Microsoft Azure. It’s schemaless, natively support JSON, very easy-to-use, very fast, highly reliable, and enables rapid deployment, you name it. Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. fluent-plugin-documentdb is fluentd output plugin that enables to store event collections into Azure DocumentDB.

This article shows how to

UPDATED:

Here is a list of fluentd plugins for Microsoft Azure Services.

Plugin NameTarget Azure ServicesNote
fluent-plugin-azurestorageBlob StorageAzure Storate output plugin buffers logs in local file and upload them to Azure Storage periodicall
fluent-plugin-azureeventhubsEvent HubsAzure Event Hubs buffered output plugin for Fluentd. Currently it supports only HTTPS (not AMQP)
fluent-plugin-azuretablesAzure TablesFluent plugin to add event record into Azure Tables Storage
fluent-plugin-azuresearchAzure SearchFluent plugin to add event record into Azure Search
fluent-plugin-documentdbDocumentDBFluent plugin to add event record into Azure DocumentDB
fluent-plugin-azurefunctionsAzure FunctionsAzure Functions (HTTP Trigger) output plugin for Fluentd. The plugin aggregates semi-structured data in real-time and writes the buffered data via HTTPS request to HTTP Trigger Function.
fluent-plugin-azure-loganalyticsLog AnalyticsAzure Log Analytics output plugin for Fluentd. The plugin aggregates semi-structured data in real-time and writes the buffered data via HTTPS request to Azure Log Analytics.

(as of Nov 23, 2016)



fluentd

デイジーチェーンとは複数の周辺機器を直列につないでいく配線方法のこと。複数VNETをデイジーチェーン接続した構成で、真ん中のVNETを中継してマルチホップアクセスするための設定方法について色々と手こずったのでここに備忘録として残しておく。また似たようなシナリオ(*注)にApp Servicesと複数VNETのデイジーチェーン接続構成でのマルチホップアクセスがあると思うがこちらの設定についても残しておく。同様の設定で困っている人にとって少しでも参考になれば幸いである。

*注 – マルチホップアクセスが必要なシナリオ例
2015年12月時点でVNet の共存する ExpressRoute 接続とサイト間 VPN 接続の構成における制限としてポイント対サイトVPNとExpressRouteを同じVNETに共存できない仕様となっている。よって、ポイント対サイトVPN接続クライアントからExpressRoute接続したVNETにアクセスしたい場合は、ExpressRoute に接続されているのと同じVNETへのシングルホップアクセスはできないので、間にトランジット用の中間VNETを挟んだいわゆるデイジーチェーン接続構成にしてマルチホップなアクセスにしてやれば実現可能である。

1. 複数VNET間のデイジーチェーン接続

サンプルとして下図のように3つのVNETを用意してデイジーチェーン接続設定を行う。ここでは分かりやすく1-1と1-2でそれぞれシングルホップアクセスしかできない例とマルチホップアクセスできる設定例を紹介する。


VPN-Daisy-Chain-Site2Site

VNET Name
Address Space
VPN gateway
vnet1172.17.0.0/1640.74.135.162
vnet2172.18.0.0/16
40.74.143.191
vnet3172.19.0.0/16
40.74.136.22

用意するローカルネットワークは次の5つ。local-vnet1~local-vnet3はそれぞれ、vnet1~vnet3のVPN Gateway経由でそれぞれvnet1~vnet3のアドレス空間にアクセスするためのローカルネットワーク設定。またlocal-vnet2-1はvnet2のVPN Gatewayを経由してvnet2とvnet1のアドレス空間にアクセスするためのローカルネットワーク設定で、local-vnet2-3はvnet2のVPN Gatewayを経由してvnet2とvnet3のアドレス空間にアクセスするためのローカルネットワーク設定である。

ローカルネットワーク一覧

Local VNET Name
Address Space
VPN gateway
local-vnet1172.17.0.0/16
40.74.135.162
local-vnet2172.18.0.0/16
40.74.143.191
local-vnet3172.19.0.0/16
40.74.136.22
lcoal-vnet2-1
172.18.0.0/16, 172.17.0.0/1640.74.143.191
lcoal-vnet2-3172.18.0.0/16, 172.19.0.0/1640.74.143.191

ネットワーク設定用XMLのLocalNetworkSites設定内容

<LocalNetworkSites>
  <LocalNetworkSite name="local-vnet1">
    <AddressSpace>
      <AddressPrefix>172.17.0.0/16</AddressPrefix>
    </AddressSpace>
    <VPNGatewayAddress>40.74.135.162</VPNGatewayAddress>
  </LocalNetworkSite>
  <LocalNetworkSite name="local-vnet2">
    <AddressSpace>
      <AddressPrefix>172.18.0.0/16</AddressPrefix>
    </AddressSpace>
    <VPNGatewayAddress>40.74.143.191</VPNGatewayAddress>
  </LocalNetworkSite>
  <LocalNetworkSite name="local-vnet3">
    <AddressSpace>
      <AddressPrefix>172.19.0.0/16</AddressPrefix>
    </AddressSpace>
    <VPNGatewayAddress>40.74.136.22</VPNGatewayAddress>
  </LocalNetworkSite>
  <LocalNetworkSite name="local-vnet2-1">
    <AddressSpace>
      <AddressPrefix>172.18.0.0/16</AddressPrefix>
      <AddressPrefix>172.17.0.0/16</AddressPrefix>
    </AddressSpace>
    <VPNGatewayAddress>40.74.143.191</VPNGatewayAddress>
  </LocalNetworkSite>
  <LocalNetworkSite name="local-vnet2-3">
    <AddressSpace>
      <AddressPrefix>172.18.0.0/16</AddressPrefix>
      <AddressPrefix>172.19.0.0/16</AddressPrefix>
    </AddressSpace>
    <VPNGatewayAddress>40.74.143.191</VPNGatewayAddress>
  </LocalNetworkSite>
</LocalNetworkSites>


1-1. 隣同士のVNETへのシングルホップアクセスのための設定例

3つのVNETをvnet1とvnet2、vnet2とvnet3をサイト対サイトVPN接続してデイジーチェーン接続構成にする。2つのサイト対サイトVPN接続設定では共に隣のVNETに接続できるように設定を行う。この場合、当然ながら隣のVNETには接続できるようになるが、VNET1 → VNET3やVNET3 → VNET1のように中間VNETを跨いでマルチホップなアクセスはできない。以下その設定イメージ図とネットワーク設定XMLファイルのVirtualNetworkSitesの内容になる。


VPN-Daisy-Chain-Site2Site-Config-SingleHopAccess

下記VirtualNetworkSitesでは、vnet1からはvnet2のアドレス空間にアクセスできるようにlocal-vnet2を接続先ローカルネットワークとして設定しており、vnet2からはvnet1とvnet3のアドレス空間にアクセスできるようにlocal-vent1とlocal-vnet3を接続先ローカルネットワークとして設定、そしてvnet3からはvnet2のアドレス空間にアクセスできるようにlocal-vnet2を接続先ローカルネットワークとして設定している。

ネットワーク設定用XMLのVirtualNetworkSites設定内容

<VirtualNetworkSites>
  <VirtualNetworkSite name="vnet1" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.17.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.17.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.17.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet2">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
  <VirtualNetworkSite name="vnet2" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.18.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.18.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.18.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet1">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
        <LocalNetworkSiteRef name="local-vnet3">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
  <VirtualNetworkSite name="vnet3" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.19.0.0/19</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.19.0.0/22</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.19.4.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet2">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
</VirtualNetworkSites>
</VirtualNetworkConfiguration>


1-2. VNET1-VNET3間マルチホップアクセスのための設定

1-1と同様に3つのVNETをvnet1とvnet2、vnet2とvnet3をサイト対サイトVPN接続してデイジーチェーン接続構成にする。ただしここでは2つのサイト対サイトVPN接続設定で隣のVNET以外にvnet1 → vnet3やvnet3 → vnet1のようにvnet2をトランジット用中間VNETとしてマルチホップにアクセスできるよう設定する。以下その設定イメージ図とネットワーク設定XMLファイルのVirtualNetworkSitesの内容になる。


VPN-Daisy-Chain-Site2Site-Config-MultipleHopAccess

下記VirtualNetworkSitesでは、vnet1からはvnet2のVPN Gatewayを経由してvnet2とvnet3のアドレス空間にアクセスできるようにlocal-vnet2-3を接続先ローカルネットワークとして設定しており、vnet2からはvnet1とvnet3のアドレス空間にアクセスできるようにローカルネットワークlocal-vent1とlocal-vnet3を接続先ローカルネットワークとして設定、そしてvnet3からはvnet2のVPN Gatewayを経由してvnet2とvnet1のアドレス空間にアクセスできるようにlocal-vnet2-1を接続先ローカルネットワークとして設定している。

ネットワーク設定用XMLのVirtualNetworkSites設定内容

<VirtualNetworkSites>
  <VirtualNetworkSite name="vnet1" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.17.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.17.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.17.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet2-3">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
  <VirtualNetworkSite name="vnet2" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.18.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.18.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.18.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet1">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
        <LocalNetworkSiteRef name="local-vnet3">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
  <VirtualNetworkSite name="vnet3" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.19.0.0/19</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.19.0.0/22</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.19.4.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet2-1">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
</VirtualNetworkConfiguration>


2. App Servicesと複数VNET間のデイジーチェーン接続

サンプルとして下図のように1つのWeb Appと2つのVNETを用意してAppとvnet1はポイント対サイトVPNで、vnet1とvnet2はサイト対サイトVPN接続でデイジーチェーン接続設定を行う。1と同様に2-1と2-2でそれぞれマルチホップできない例とできる設定例を紹介する。


VPN-Daisy-Chain-Apps2Site2Site

VNET基本情報

VNET NameAddress SpaceVPN Client Address PoolVPN gateway
vnet1172.17.0.0/16
192.168.1.0/28
40.74.135.162
vnet2172.18.0.0/16
40.74.143.191

用意するローカルネットワークは次の3つ。local-vnet1、local-vnet2はそれぞれvnet1、vnet2のVPN Gateway経由でそれぞれvnet1、vnet2のアドレス空間にアクセスするためのローカルネットワーク設定。またlocal-vnet1-pはvnet1のVPN Gatewayを経由してvnet1のアドレス空間とポイント対サイト用VPNクライアント用アドレス空間にアクセスするためのローカルネットワーク設定となっている。

ネットワーク設定用XMLのLocalNetworkSites設定内容

Local VNET name
Address Space
VPN gateway
local-vnet1
172.17.0.0/16
40.74.135.162
local-vnet2172.18.0.0/16
40.74.143.191
local-vnet1-p172.17.0.0/16, 192.168.1.0/28
40.74.135.162


2-1. App Services-VNET2間でマルチホップアクセスできない設定例

Web Appとvnet1はポイント対サイトVPN接続設定を行う。一方vnet1とvnet2間のサイト対サイトVPN接続設定では互いのVNETに接続できるように設定を行う。この場合、当然ながらApp → vnet1、vnet1 → vnet2へのシングルホップのアクセスはできるがApp → vnet2のマルチホップアクセスはできない。


VPN-Daisy-Chain-P2S-S2S-Config-SingleHopAccess

ネットワーク設定用XMLのVirtualNetworkSites設定内容

<VirtualNetworkSites>
  <VirtualNetworkSite name="vnet1" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.17.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.17.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.17.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <VPNClientAddressPool>
        <AddressPrefix>192.168.1.0/28</AddressPrefix>
      </VPNClientAddressPool>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet2">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
  <VirtualNetworkSite name="vnet2" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.18.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.18.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.18.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet1">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
</VirtualNetworkSites>
</VirtualNetworkConfiguration>


2-2. App Services-VNET2間マルチホップアクセスのための設定

2-1と同様にWeb Appとvnet1はポイント対サイトVPN接続設定、vnet1とvnet2間はサイト対サイトVPN接続設定を行いデイジーチェーン接続構成にする。ただしここではvnet2 → vnet1のサイト対サイトVPN接続設定においてvnet1のVPN Gatewayを経由してvnet1のアドレス空間とVPNクライアント用アドレス空間にアクセスできるようにlocal-vnet1-pを接続先ローカルネットワークとして設定している。これでApp → vnet2のマルチホップアクセスが可能となる。


VPN-Daisy-Chain-P2S-S2S-Config-MultipleHopAccess

ネットワーク設定用XMLのVirtualNetworkSites設定内容

<VirtualNetworkSites>
  <VirtualNetworkSite name="vnet1" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.17.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.17.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.17.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <VPNClientAddressPool>
        <AddressPrefix>192.168.1.0/28</AddressPrefix>
      </VPNClientAddressPool>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet2">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
  <VirtualNetworkSite name="vnet2" Location="Japan West">
    <AddressSpace>
      <AddressPrefix>172.18.0.0/16</AddressPrefix>
    </AddressSpace>
    <Subnets>
      <Subnet name="Subnet-1">
        <AddressPrefix>172.18.0.0/19</AddressPrefix>
      </Subnet>
      <Subnet name="GatewaySubnet">
        <AddressPrefix>172.18.32.0/29</AddressPrefix>
      </Subnet>
    </Subnets>
    <Gateway>
      <ConnectionsToLocalNetwork>
        <LocalNetworkSiteRef name="local-vnet1-p">
          <Connection type="IPsec" />
        </LocalNetworkSiteRef>
      </ConnectionsToLocalNetwork>
    </Gateway>
  </VirtualNetworkSite>
</VirtualNetworkSites>
</VirtualNetworkConfiguration>

おわり

LINKS

複数のオンプレミスのサイトを仮想ネットワークに接続
PowerShell を使用してサイト間 VPN 接続で仮想ネットワークを作成する
Using VNET integration and Hybrid connections with Azure Websites

これは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