Azure

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

Azure Media Services(以下AMS)公式PHP SDK(正確にはazure-sdk-for-phpに含まれるMedia Services用ライブラリ)を使って条件指定でアセット一覧情報を取得するための方法について簡単に説明したい。2015年12月の時点でAMS PHP SDKが持っているBuilt-inのアセット一覧情報取得インターフェースはgetAssetList() のみとなっており様々な条件指定でアセット一覧情報を取得するための機能が存在しないためここでの説明は今回新しく用意したカスタム関数の追加を前提としている。

追加カスタム関数

上述のとおり2015年12月の時点でAMS PHP SDKが持っているBuild-inインターフェースでは条件指定によるアセット一覧の取得ができない。例えば次のような取得ができない:

– オフセット指定
– フィールド名の完全、前方、後方一致といったフィルター条件指定(AMS REST APIはOData v3をベースとしている)
– 一度に取得するアセット数やソート条件指定

よって、ここではMediaServicesRestProxy.phpに下記のgetAssetListByParam()関数を追加して条件指定によるアセット一覧取得を実現する。尚、この修正は既にGithub上の個人開発用ブランチにコミット済みでありマスターブランチとの差分はこちら。この修正についてはPull Req#766でプルリクエスト中なので無事通れば将来的にはマスターブランチに反映されるかもしれません。

    /**
    * Get asset list by params
    *
    * @param array of parameters to be added to request URL as query string
    * such as $skip, $filter, $top, and so on
    *
    * @return array of Models\Asset
    */

    public function getAssetListByParams($params)
    {
        $p = array();
        foreach($params as $k => $v){
            $p[] = $k.'='.$v;
        }
        $paramstr = implode('&', $p);
        $propertyList = $this->_getEntityList("Assets()?" . $paramstr );
        $result       = array();
        foreach ($propertyList as $properties) {
            $result[] = Asset::createFromOptions($properties);
        }
        return $result;
    }

使用例

例1: 1000件目以降の一覧情報取得
以前「TIPS: Azure Media Servicesでの利用アカウントの全アセット一覧の取得」で触れたとおりAzure Media Servicesではパフォーマンス上の理由から一度に返却できるアセット数の制限が1000に設定されている。よって、アセット数が1000以上ある場合、1000件以降のアセット一覧情報を取得するためにはオフセットの位置を調整する必要がある。ここでは$skipパラメータを使用してオフセット位置を調整している。

例2: アセット名が完全一致する一覧情報取得
$filterパラメータを使用してアセット名(Nameフィールド)が指定した名前と完全マッチするアセット情報一覧を取得する。

例3: アセット名が前方部分一致する最初のアセット情報を取得
$filterパラメータを使用してアセット名(Nameフィールド)が指定した名前と前方一致するアセット情報一覧を取得する。ここではさらに$topパラメータで最初の1件のみを取得している。

LINKS

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

Azureが提供するDNSによるトラフィックルーティングサービスであるTraffic Managerについて、既にAzure利用ユーザに使い尽くされて新鮮味に欠けるサービスではあるものの、そのエンドポイント監視はTraffic Managerを扱う上でとても重要なことなので今一度そのルールについて整理したい。

Traffic managerの実態はエンドポイントの監視+ルーティングを行うDNSサービスである。以下digの結果を見ていただいてわかる通りyoichika-demo1.trafficmanager.netという外向きの名前に対してこの時点ではwebappdemo3.cloudapp.netがCNAMEされている。Traffic Managerは利用ユーザが設定したエンドポイントを監視し、その結果に応じて適切なルーティングを行う。ルーティング方法にはフェールオーバー、ラウンドロビン、パフォーマンスの3通りがある。これについて詳しくは「Traffic Managerのルーティング方法」を参照いただきたい。

; <<>> DiG 9.9.5-4.3ubuntu0.1-Ubuntu <<>> yoichika-demo1.trafficmanager.net +noall +answer
;; global options: +cmd
yoichika-demo1.trafficmanager.net. 30 IN CNAME  webappdemo3.cloudapp.net.
webappdemo3.cloudapp.net. 60    IN      A       70.37.93.167

  

次に肝心のエンドポイントの監視について「Traffic Manager の監視について」の監視シーケンスを使って要点を整理する。


AzureTrafficManagerMonitoring

 

つまり、エンドポイントがダウンした場合、Probeにより使用不可とみなすのに最大120秒(30秒 x 4)、さらにDNSのTTLの期間(既定値は300秒)を加えると、完全に問題のあったエンドポイントへのトラフィックが停止するまでに標準的に420秒、約7分は見ておく必要があるということになる。当然ながらこの7分間トラフィックがロスする可能性があるため、俊敏なフェールオーバーを期待する場合は別の仕掛けを用意する必要がある。ご注意ください。

Azure仮想マシンV1の一括起動・停止する方法についてのナレッジをここに整理しておく。基本的にはPowerShellやAzure CLIのVM起動・停止コマンドを並列で実行する方法でいけます。ただし同一クラウドサービス内に複数のVMがある場合は単純なコマンドの並列処理実行ではうまくいかない。その場合はAzureで用意されている複数ロールの一括起動・停止用REST APIを使いましょうというお話し。尚、ここでの一括処理はyoichikavm[001-100]の100VMを対象とする。

VM起動・停止コマンドの並列実行

yoichikavm[001-100]がそれぞれ別のクラウドサービスを持っている場合は、VM起動・停止コマンドを単純に並列実行するという手法で問題なく一括起動・停止ができる。例えばWindowsマシンの場合はPowershellの(Start|Stop)-AzureVMコマンドをStart-Jobを使用してバックグラウンドジョブとして実行させてやる、MacやLinuxであればvm (start|stop)コマンドをforkさせて複数故プロセスを走らせてやるなど。ここではStart-Jobでの並列実行例を紹介する。

複数VMの一括起動: parallel-start.ps1

foreach($node in $( Get-AzureVM | Where-Object{$_.Name -match "yoichikavm*"}) ) {
    Write-Host $node.Name
    Start-Job -ScriptBlock{
        param($node)
        Start-AzureVM -ServiceName $node.ServiceName -Name $node.Name
    } -Arg $node
}

複数VMの一括停止: parallel-stop.ps1

foreach($node in $( Get-AzureVM | Where-Object{$_.Name -match "yoichikavm*"}) ) {
    Write-Host $node.Name
    Start-Job -ScriptBlock{
        param($node)
        Stop-AzureVM -ServiceName $node.ServiceName -Name $node.Name -Force
    } -Arg $node
}

Start/Stop Roles APIの利用(同一クラウドサービス内に複数VMがある場合)

これは実際に私が躓いた際に@ksasakimsさんに教えてもらった方法。冒頭で簡単に説明したとおり同一クラウドサービス内に複数のVMがある場合は上記のような単純なコマンドの並列処理実行ではうまくいかない。この場合、Start RolesShutdown RolesのREST APIを使うことで同一クラウドサービス内の複数VMの同時起動。停止を実現することができる。
以下、APIについて簡単にご説明する。両APIともPOST先は下記同一のエントリーポイントとなっており、またBodyにそれぞれ下記のように起動VM,停止VMを記述する。

POST用エントリーポイント

https://management.core.windows.net/サブスクリプションID/services/hostedservices/クラウドサービス/deployments/デプロイ名/roles/Operations

BODY例: 一括起動 yoichikavm[001-100]

<StartRolesOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <OperationType>StartRolesOperation</OperationType>
  <Roles>
    <Name>yoichikavm001</Name>
    <Name>yoichikavm002</Name>
    ... skip ...
    <Name>yoichikavm100</Name>
  </Roles>
</StartRolesOperation>

BODY例) 一括停止 yoichikavm[001-100]

<ShutdownRolesOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <OperationType>ShutdownRolesOperation</OperationType>
  <Roles>
    <Name>yoichikavm001</Name>
    <Name>yoichikavm002</Name>
    ... skip ...
    <Name>yoichikavm100</Name>
  </Roles>
  <PostShutdownAction>StoppedDeallocated</PostShutdownAction>
</ShutdownRolesOperation>

そして、共通ヘッダとして下記の2つが必要になる。

Content-Type: application/xml
x-ms-version: 2015-04-01    << サービス管理バージョン、これは最新の2015-04-01でOK

認証については他のサービス管理APIと同様にAzure ADの使用もしくは証明書を利用した認証を行う必要がある。詳細についてはを「サービス管理要求の認証」参照いただければと思う。

LINKS

Azure Media Servicesには一度に返却できるアセット情報(コレクション)の数に1000という制限があることは意外と知られていない。Azure Media Servicesでアセット一覧取得となるとほとんどの方がAzure公式ドキュメントにあるようにCloudMediaContextインスタンスのAssets(IAssetのリスト)を単純にループでまわすような記述をしているのではないかと推測するがそれだと後々問題になってくる。既に1000件以上のアセットがアップされている方は当然ながら、アセット数が少ない人についても下記のように1000件ずつもしくはそれ以下の数ずつAzure Media Servicesより取得してIAssetリストをループでまわすように実装しておいたほうが安全かと。

MediaServicesCredentials credentials = new MediaServicesCredentials(
                                    _accountName, _accountKey);
CloudMediaContext _context = new CloudMediaContext(credentials);

int selectlimit = 1000;
int offset = 0;
int selectposition = 0;
Console.WriteLine("Assets Total Count:" + _context.Assets.Count());
while (true)
{
    foreach (IAsset asset in _context.Assets.Skip(offset).Take(selectlimit))
    {
        selectposition++;
        Console.WriteLine("Asset ID: " + asset.Id);
        Console.WriteLine("Asset Name: " + asset.Name);
        Console.WriteLine("Asset LastModified: " + asset.LastModified);
    }
    if (selectposition == selectlimit)
    {
        offset += selectlimit;
        selectposition = 0;
    }
    else
    {
        break;
    }
}

サンプルコード
https://github.com/yokawasa/azure-samples/tree/master/ams-list-assets

UPDATED 2017-03-22: Added SOCKS Proxy Configuration for Internet Explorer

外部からの接続(SSH、HTTPなど)を受け付けていないAzure 仮想ネットワーク(以下VNET)内のリソースにSOCKSプロキシを経由して外部からアクセスしましょうというお話。本記事ではAzure VNET内の外部からのアクセス許可していないVMへのSSHログインとHTTPサーバコンテンツへのブラウジングの2つの方法を紹介する。
SOCKS(RFC1928) とはさまざまなアプリケーションが間にファイアーウォールを挟んでいても安全に快適にやり取りができるようにすることを目的として作られたプロトコルのことで、SOCKSプロキシはSOCKSプロトコルを受け取りファイアウォール内外との接続を可能にするものである。エンドポイントやNetwork Security Group (NSG)によりネットーワーク分離設定されたAzure VNET内のリソースに対して一時的に本来直接アクセス許可しないネットワークからアクセスが必要な状況はあるかと思う。そのような時に毎回設定変更で必要なプロトコル、アクセス先に対して穴をあけるのは非常に面倒であり、またサイト間VPN、ポイント対サイトVPNとなるとさらに手間がかかる。お手軽に、もしくは定常的ではないが一時的に内部リソースにアクセスしたい場合にSOCKSプロキシ経由でのアクセスを検討してみてはいかがだろうか。以下はSOCKSプロキシ経由によるAzure VNET内のプライベートリソースへのアクセスイメージである。


Accessing-AzureVNET-via-SOCKSProxy

SOCKSプロキシの作成

まずはOpenSSHのダイナミックポートフォワード機能を使ってSOCKSプロキシを作成する。ダイナミックポートフォワードはSSHをSOCKSプロキシとして振舞うことを可能にする。SSHでアクセス先ホストと DynamicFoward(-D)でポートを指定することでlocalhostにSOCKSプロキシが立ち上がり指定のTCPポート(SOCKSプロキシサーバは基本的は1080だが、割り当て可能なポートであればどのポートでもOK)をlocalhost側からログイン先ホストのSSHサーバに転送することができるようになる。もちろん経路は暗号化される。現状のサポートプロトコルはSOCKS4とSOCKS5。
例えば上図でいうとJump Server(踏み台)にDynamicFoward(-D)1080でログインすると、Jump Serverにポート1080を転送するSOCKSプロキシが localhostに立ち上がり、そのlocalhost:1080に対してSOCKS4またはSOCKS5プロトコルで接続することでJump Serverを経由して通信を行うことができるようになる。
localhost ポート1080のJump Serverへのダイナミックフォワードは次のように-Dオプションで行う。

$ ssh -2 -D 1080 -l [Account] [Jump Server]

毎回-Dオプション指定が面倒な場合は、次のようにconfg(ssh_config)にDynamicForwardの記述することも可能。

~/.ssh/config

Host JumpServer
   User         [Account名]
   HostName/IP  [Jump Serverホスト/IPアドレス]
   Protocol 2
   ForwardAgent  yes
   DynamicForward 1080

上記OpenSSHの設定は、Linux/Macの場合は標準Terminalを使えばよいが、Windowsの場合はCygwin、XmingなどX端末エミュレータソフトをインストールしていただく必要がある。またX端末エミュレーターをインストールしなくともWindowsでは有名なSSHクライアントソフトPuttyがダイナミックポートフォワードに対応しているためPuttyを使ってSOCKSプロキシ作成することも可能。詳しくは「Dynamic Port Forwarding with SOCKS over SSH」が参考になるかと。

SOCKSプロキシを使ったSSH接続

次に上記で作成したSOCKSプロキシを経由してVNET内のサーバにSSH接続をする。 netcatでSOCKSプロキシを経由してlocalhostから目的のVNET内サーバ(ServerX)間にnetcatトンネルを作成してServerXにはそのnetcatトンネルを通じて接続する。

local$ ssh -2 -l [Account] -o 'ProxyCommand nc -x localhost:1080 %h %p' [ServerX]

netcat のプロキシ指定は-xオプションで行う。 ここでは事前に作成したSOCKSプロキシ(localhost:1080)を指定。 netcatトンネルの作成コマンドはProxyCommandに記述する。こちらも毎回長いオプション入力を避けるために config(ssh_config)設定すると便利である。

~/.ssh/config

Host ServerX
   User        [Account]
   Protocol 2
   ForwardAgent  yes
   ProxyCommand nc -x localhost:1080 -w1 %h %p

注意点として、netcatにはGNU本家版とそれ以外にいくつか派生があるが-x オプションの利用可能なnetcatである必要がある。オリジナルのnetcatやGNU netcatには-xオプションはない。ここで使用しているnetcatはIPv6に対応しているOpenBSD netcat。

もちろんVNET内のVMへのSSH接続の別解としてProxyCommandでJump ServerからServerXへnetcatトンネルを作成してlocalからServerXにログインすることも可能。

local$ ssh -2 -o 'ProxyCommand ssh [Jump Server] nc -w1 %h %p' [ServerX]

実はこの方法のほうがProxyCommand でプロキシ設定を行うため事前に別コンソールで何かを用意する必要がなく間違いなくSOCKSプロキシ経由での接続よりも楽。ではSOCKSプロキシ経由で接続する理由は何か? 理由は単純で、通常Jump Serverはセキュリティ設定上の理由でログインしてもほとんど何もできないようにするために機能を無効化していることが多く、よってnetcatが使えない(ncはおろかsshコマンド以外ほとんど何も使えない)環境だったりする。この場合、上記で説明したようにSOCKSプロキシ経由でのSSHログインが有効な手段となる。

SOCKSプロキシ経由でのブラウジング

ブラウザーにSOCKSプロキシ対応のプラグインを 入れることでブラウザーによるプライベートリソース(内部ネットワーク内のアプリ・ミドルウェア等のウェブUIを持った管理ツールなど)の閲覧も可能となる。有名なものにSwitchySharp(Google Chrome)やFoxyproxy(Firefox)などがある。以下簡単な設定スクリーンショットを乗せておく。共に「http://yoichika-*.cloudapp.net*」なURIパターンの時にのみSOCKSプロキシlocalhost:12345経由でアクセスする設定となっている。

Google Chrome – SwitchySharp


GoogleChrome-SwitcySharp

Firefox – Foxyproxy


Firefox-FoxyProxyStandard

Internet Explorer – Out-of-box feature
As answered in Stack Overflow, Internet Explorer does support SOCKS proxies.
Tools > Internet Options > Connections > LAN Settings > Proxy Server > Advanced


IE-SOCKS-PROXY

Enjoy Accessing private resources with SOCKS Proxy!

ARMとAzure Insights API

Azure上のさまざまなサービスのメトリック情報をAPI経由で取得したい。そういうことであればAzure Service Management APIを使えばいいじゃないかという声が聞こえてきそうなところだが実は既にこのやり方は時代遅れとなっていることをご存じだろうか?
2014年5月ごろ?に登場したAzureの新しい考え方にResource、ResourceGroup、Azure Resource Managerというものがある。簡単な説明すると、Azure上のPaaSインスタンス、仮想マシンなどすべての管理可能な資源をリソース(Resource)とよばれる単位に細分化し、それらをグループ化したものがResourceGroup、そして全てのリソースはAzure Resource Manager(以下ARM)というもので管理可能になっている。そしてこのARMで管理可能な世界のリソース群に紐づくメトリックデータはAzure Insights APIで取得可能となっている。本記事ではさまざまなリソースの中でもWeb Appsに絞って、Azure Insights REST API (Metric)を使ってそのメトリックを取得する方法について紹介する。

ARM Explorerでどのメトリックが取得可能なのか確認する

ARM Explorer (https://resources.azure.com/) をご存じだろうか? これはその名の通りAzure上の全てのリソース(ご利用のサブスクリプションに紐づく全てのリソース)のエクスプローラーであり、これを使うことでこのARM管理下の世界のすべてのリソースをエクスプローラービューで閲覧することができる。このARM Explorerで閲覧可能な各リソースの情報の中にmetricdefinitionsというものがあって、これにはそのリソースに対して指定可能なメトリックの種類やその定義情報などが格納されている。リソースのメトリック取得をする際は、まずはARM Explorerで目的のリソースのmetricdefinitionsから指定可能なメトリックの種類を把握してからAPIリクエストを組み立てていただければと思う。ARM Explorerを使って本記事で取得対象としているWeb Apps(ここではサイト名yoichikademoを対象)のmetricdefinitionsを閲覧しているのが以下のスクリーンショットになる。


ARMExplorer

Azure Insights REST APIメトリック取得インターフェース

Azure Insights APIには次のような(1)メトリック定義一覧の取得と(2)対象リソースのメトリック情報取得の2つのインターフェースがある。当然ながらメトリックの取得には(2)のインターフェースを使用する。

APIの共通部分は下記の通り。Azure Insights APIへの全ての要求はAzure Active Directoryを使用して認証する必要があり、この認証により得られたトークンを各APIリクエストのAuthorizationヘッダに指定する必要がある。トークン取得の方法にはPowerShellを使用した方法とAzure管理ポータルを使用して認証する2つの方法がある。詳しくは「Azure インサイト要求を認証する」を参照ください。

実際のメトリクス取得APIでは$filterパラメータの付与が必要となる。$filterには主にメトリックの種類(name.value)、時間レンジ(startTime – endTime)、インターバール(timeGrain)の3種類の条件を指定する。

CpuTimeとMemoryWorkingSetメトリック指定例 (実際は1行にまとめる)

$filter=
  (name.value eq ‘CpuTime’ or name.value eq ‘MemoryWorkingSet’)
  and startTime eq ‘2015-08-01T15:00:00Z’ and endTime eq ‘2015-08-02T15:00:00Z’
  and timeGrain eq duration’PT1M’

$filterパラメータには実際はURL Encodeかけた文字列を渡す。メトリックのインターバル(timeGrain)は1分単位なら”PT1M”、5分単位なら”PT5M”、1時間単位ならば”PT1H”、1日単位ならば”PT1D”などを指定する。

サンプルコード

Azure Insightsのメトリック取得APIを使ってWeb Appのメトリックを取得するサンプルコードをGithubにアップした。同様のことを考えている人にとって少しでも参考になれば幸いである。

https://github.com/yokawasa/azure-samples/tree/master/GetAppServiceMetrics

このサンプルではCpuTime、MemoryWorkingSet、AverageResponseTimeの3つのメトリック情報を1時間ごとのインターバルで2015-08-01~2015-08-30の期間分取得するようになっている。この部分はハードコーディングしているので必要に応じてソースコード(Program.cs)を適宜変更いただければと思う。また利用者ごとの情報は設定ファイルApp.configで指定する。以下簡単にApp.configの設定内容を解説する。

App.config

<appSettings>
    <add key="subscriptionId" value="[your subscription Id]" />
    <add key="resourceGroup" value="[your resource group name]" />
    <add key="siteName" value="[site Name]" />
    <add key="tenantId" value="[you tenant ID]" />
    <add key="applicationId" value="[your application id]" />
    <add key="redirectUri" value='[redirect url]' />    
</appSettings>

LINKS

Azure Searchのインデックス更新方法には大きく分けてPUSHとPULLの2種類ある。PUSHは直接Indexing APIを使ってAzure SearchにコンテンツをPOSTして更新。PULLは特定データソースに対してポーリングして更新で、Azure Searchの場合、DocumentDBとSQL Databaseの2種類のデータソースを対象にワンタイムもしくは定期的なスケジュール実行が可能となっている。ここではDocumentDBをデータソースとしてインデックスを更新する方法を紹介する。

サンプル構成と処理フローの説明

データソースにDocumentDBを利用する。データ「DOCUMENTDB PYTHON SDKとFEEDPARSERで作る簡易クローラー」においてクローリングされDocumentDBに保存されたブログ記事データを使用する。そしてDocumentDBを定期的にポーリングを行い更新があったレコードのみをAzure Searchインデックスに反映するためにDocumentDBインデクサーを設定する。全体構成としては下記の通りとなる。


documentdb-indexer

DocumentDBと更新先検索インデックスのフィールドのマッピング

DocumentDBをデータソースとしてAzure Searchインデックスに更新を行うためDocumentDBの参照先コレクションのフィールドと更新先Azure Searchインデックスのフィールドをマッピングを行う。マッピングはデータソース定義中のDocumentDB参照用Queryで行う。Azure SearchインデックスにインジェストするフィールドをDocumentDBのSELECTクエリー指定するのだが、Azure SearchとDocumentDBのフィールドが異なる場合は下図のようにSELECT “Docdbフィールド名” AS “Searchフィールド名”でインジェスト先フィールド名を指定する。データソース定義については後述の設定内容を確認ください。


documentdb-azuresearch-mapping

Configuration

以下1~4のステップでデータソースの作成、検索インデックスの作成、インデクサーの作成、インデクサーの実行を行う。

  1. データソースの作成
  2. credential.connectionStringで接続先DocumentDB文字列と対象データベースの指定を行う。container.(name|query)で対象コレクション名と参照用SELECT文を指定する。SELECT文はDocumentDBとインジェスト先Azure Searchのフィールドセット(フィールド名と数)が同じであれば省略可。詳細はこちらを参照。

  3. インデックスの作成
  4. 下記のスキーマでAzure Searchインデックスを作成する。

    {
        "name": "articles-test",
        "fields": [
            { "name":"itemno", "type":"Edm.String", "key": true, "searchable": false },
            { "name":"subject", "type":"Edm.String", "filterable":false, "sortable":false, "facetable":false},
            { "name":"body", "type":"Edm.String","filterable":false,"sortable":false, "facetable":false, "analyzer":"ja.lucene"},
            { "name":"url", "type":"Edm.String", "sortable":false, "facetable":false },
            { "name":"date", "type":"Edm.DateTimeOffset", "facetable":false}
         ]
    }
  5. DocumentDBインデクサーの作成
  6. DocumentDBインデクサー作成のための設定。DatSourceNameとtargetIndexNameにそれぞれ1で作成したデータソース名とインジェスト先のインデックス名を指定する。スケジュール実行させたい場合は下記の通りscheduleを設定する。ここではintervalをPT5Mとしているがこれは5分毎実行を意味する。詳しくはこちらを参照。

  7. インデクサーの明示的に実行
  8. スケジュール実行ではなくインデクサーをすぐに実行したい場合は下記のフォーマットでPOSTリクエストを送信する。

    POST https://[Search service name].search.windows.net/indexers/[indexer name]/run?api-version=[api-version]
    api-key: [Search service admin key]

実行結果確認方法


AzureSearchIndexerStatus

上記イメージの通りAzureポータル(preview)よりAzure Search → indexersタイルをたどることでインデクサーの実行結果や過去の履歴を確認することができる。ただし、ここではAPI経由で取得する方法を紹介する。
下記フォーマットでGETリクエストすることでインデクサーの現在の稼働状態と実行履歴を取得することができる。実行履歴は最後の実行結果だけではなく最近完了した50件の実行内容が含まれる。

GET https://[Search service name].search.windows.net/indexers/[indexer name]/status?api-version=[api-version]
api-key: [Search service admin key]

以下実行結果。executionHistoryが履歴、lastResultが最後の実行結果、statusが現在のインデクサーのステータスとなっている。

{
    "@odata.context": "https://yoichidemo.search.windows.net/$metadata#Microsoft.Azure.Search.V2015_02_28_Preview.IndexerExecutionInfo",
    "executionHistory": [
        {
            "endTime": "2015-06-25T05:55:01.393Z",
            "errorMessage": "Data source 'docdbds-article' does not exist",
            "errors": [],
            "finalTrackingState": null,
            "initialTrackingState": null,
            "itemsFailed": 0,
            "itemsProcessed": 0,
            "startTime": "2015-06-25T05:55:01.393Z",
            "status": "transientFailure"
        },
        ...(omit)...
        {
            "endTime": "2015-06-25T02:15:02.155Z",
            "errorMessage": null,
            "errors": [],
            "finalTrackingState": "1434871500",
            "initialTrackingState": "1434871500",
            "itemsFailed": 0,
            "itemsProcessed": 0,
            "startTime": "2015-06-25T02:15:01.452Z",
            "status": "success"
        },
        {
            "endTime": "2015-06-25T02:10:01.144Z",
            "errorMessage": null,
            "errors": [],
            "finalTrackingState": "1434871500",
            "initialTrackingState": "1434871500",
            "itemsFailed": 0,
            "itemsProcessed": 0,
            "startTime": "2015-06-25T02:10:00.022Z",
            "status": "success"
        }
    ],
    "lastResult": {
        "endTime": "2015-06-25T05:59:02.016Z",
        "errorMessage": "Data source 'docdbds-article' does not exist",
        "errors": [],
        "finalTrackingState": null,
        "initialTrackingState": null,
        "itemsFailed": 0,
        "itemsProcessed": 0,
        "startTime": "2015-06-25T05:59:02.016Z",
        "status": "transientFailure"
    },
    "name": "docdbindexer",
    "status": "running"
}

Content DBの有効性について

ここではAzure SearchのfeedingソリューションとしてDocumentDBを使用したPULLインデックス更新方法を紹介した。このようにクローリングされたデータを直接Azure SearchのIndex APIを使ってインデックスを更新するのではなく、今回のDocumentDBのように所謂Content DBに格納してからそれを元にインデックスを更新するのにはいくつか意味がある。例えば、インデックス構造を変更したい場合、再フィードが必要になるがContent DBがあれば再度クローリングする必要がない。通常クローリング(特にフルクローリング)のコストは大きい。また、Content DBがあれば別アカウント、リージョンにインデックスのレプリカの構築、他に、同一のデータを使って別構造のインデックを構築するといったことも容易に可能になる。
さらに、現時点でAzure Searchがデータ加工のためのパイプラインの仕組み(Lucene/Solr, ElasticSearchでいうところのカスタムAnalyzer)がないことから、インデックスに放り込む前の一時データ加工用のデータベースとしても有効であると考えている。

LINKS