Azure Container Appsのクイックスタート

Azure Container Appsは、2021年11月に開催された Ignite 2021 で発表され現在Public Preview中です。 azure.microsoft.com

Azureには、コンテナとしてアプリケーションを実行できるサービスがいくつかあります。

  • Azure App Service
  • Azure Functions
  • Azure Kubernetes Service
  • Azure Red Hat OpenShift
  • Azure Spring Cloud
  • Azure Container Instances

Azure Container Appsは、kubernetesの管理をまったく意識することなく、コンテナ化されたアプリケーションを実行することができる。 また、KEDA | Kubernetes Event-driven AutoscalingDapr - Distributed Application Runtime も使えるようになっています。

f:id:akubicharm:20211112104929p:plain

kubernetesのネームスペース単位に仮想ネットワークやLog Analyticsワークスペースが割り当てられるので、マルチテナントでkubernetesを利用するイメージです。

料金もAzure Kubernetes Serviceはノードごとの課金ですが、Azure Container Appsは、リソースの使用量によって算出されます。

ランタイムは、Linuxベースのコンテナイメージとなっているので、現時点ではワーカーノードはLinuxホストだけと推測されます。

クイックスタートを始める前に

AzureではAzure Resource Managerによって、Azureのデプロイおよび管理が行われています。Azureのリソースを利用する場合には、リソースプロバイダを登録する必要があります。

docs.microsoft.com

Azure Container Appsは、Microsoft.Web というリソースプロバイダが必要になります。大抵の方は、すでに登録済みだと思いますが、Azure Container Appsをデプロイする場合には、このリソースプロバイダを再登録する必要があります。(まだ、プレビューだからかも)

リソースプロバイダの登録は、AzureポータルからでもAzure CLIからでも可能です。登録方法は リソース プロバイダーとリソースの種類 - Azure Resource Manager | Microsoft Docs を参考にしてください。

クイックスタートをやってみる

リソースプロバイダの登録が終わったら、クイック スタート: 最初のコンテナー アプリをデプロイする | Microsoft Docs の手順に従って、やっていくだけです。 現在は、Public PreviewなのでAzure Container Appsが利用できるリージョンが限られていますので、ご注意ください。

Azure Spring Cloud Workshopをやってみた

Azure Spring CloudがGAになったので、Microsoft Learnで提供されているセルフラーニングハンズオンをやってみました。

 

docs.microsoft.com

 

Microsoft Learnって何?

Microsoft Learn は、Microsoft 製品についての対話式学習などを提供する無料のオンライン トレーニング プラットフォームです。Azureのサービスのワークショップには、Azureのサブスクリプションをお持ちでない方も、Sandboxでお試しいただくことができるものもあります。

 

Azure Spring Cloudって何?

Spring Boot アプリ向けのフル マネージド サービスです。ユーザーはインフラストラクチャの管理に煩わされることなく、アプリの構築と実行に集中できます。

特徴としては、こんな感じでしょうか。

  • Spring Bootのアプリケーションから、Azureのサービス(例えば、データベースサーバ)などを簡単にBindして利用
  • Azure Monitorを活用して、Logの可視化、JVMのメトリクスの取得、分散トレーシングが可能
  • Spring BootアプリケーションのScale Out/In、Scale Up/Downが用意

 

Azure Spring Cloud: Spring Boot アプリのフル マネージド サービスを一般提供開始 | Azure のブログと更新プログラム | Microsoft Azure

 

 

ワークショップをやるときのハマりポイント

ワークショップをやるときにちょっとだけハマりポイントがありましたので、みなさんがハマらないようにちょっとだけ説明します。

 

このワークショップを実施するには、AzureのSubscriptionが必要です。

ワークショップは手短に特徴がわかるような内容になっており、8つのユニットから構成されています。

 

Azure Spring Cloudを生成する

まずは、Azure Spring Cloudのインスタンスを生成していきます。

ここで注意しないといけないポイントは、次の通りです。

RESOURCE_GROUP_NAMEには、任意のリソースグループ名を設定し、SPRING_CLOUD_NAMEにはAzure Spring Cloudのインスタンス名を設定して、Azure Spring Cloudをデプロイします。

az spring-cloud create -g "$RESOURCE_GROUP_NAME" -n "$SPRING_CLOUD_NAME" --sku standard --enable-java-agent

 

 

 MySQLをデプロイする

az コマンドで mysqlをデプロイする場合には、--admin-password オプションは必須なので忘れずにつけましょう。

 

MySQLをアプリケーションにバインドする

Azure Spring CloudのアプリケーションのサービスバインディングでAzure Database for MySQLのユーザを指定する場合、ユーザ名@MySQLリソース名になるので注意が必要です。

接続アーキテクチャ - Azure Database for MySQL | Microsoft Docs

az mysql server create コマンドで、--nameオプションで "${SPRING_CLOUD_NAME}-mysql"、--admin-userオプションで "spring" と指定した場合は、サービスバインディグするときのユーザ名は"spring@${SPRING_CLOUD_NAME}-mysql"となりますので注意しましょう。

f:id:akubicharm:20210312185852p:plain

サービスバインディング設定画面

 

todo-serviceのテスト用エンドポイントへのアクセス

 todo-serviceの概要ページの右Pane上部でAssigne endpointボタンをクリックしてエンドポイントを作成し、出来上がったURLにアクセスすると期待するJSONが取得できます。

 

すごく簡単にAzure Spring Cloudを試せるコンテンツになっていますので、是非、試してみてください。 

【備忘録】Azure ADの削除

Azureポータルから自分が作成したAzure ADテナントが削除できなくなってしまった。

この画面のように、Azureリソースを削除するアクセス許可がないという状況で削除できない。

f:id:akubicharm:20200527143940p:plain

Azure ADテナント削除の画面

Azure Active Directory 管理センター(Azure Active Directory admin center)にログインして、削除すればできました。

https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-delete-howto

 

サブスクリプションの管理は、Microsoft 365管理センター(https://admin.microsoft.com/)で。

VSCodeのRemote Development-Containers

アプリケーションの開発をするときに、ローカルで環境で実行しているかのようにリモート環境に接続して、開発をすることができる便利な機能です。 この機能を利用すれば、ローカル環境にインストールされているプログラミング言語のバージョンがランタイムと異なっている場合でも、ローカル環境に影響を与えずにクラウドにデプロイするためにテストをすることができるようになります。

VSCode Remote Development の発表のブログRemote Development with Visual Studio Code

f:id:akubicharm:20191023033829p:plain

Remote Developmentでは、3種類のリモート接続して利用できる環境があります。

ここでは、Remote Development-Containerの利用方法を紹介します

VSCodeへのRemote Development拡張機能のインストール

  • VSCodeの左下の歯車マークをクリックし、プルダウンメニューから[Extensions]をクリックします。 f:id:akubicharm:20191023035348p:plain

  • [Remote Development] と検索キーワードを入力して拡張機能を検索し、[Remote Development]を選択してインストールします。 f:id:akubicharm:20191023035712p:plain

※インストールが完了すると、左下の歯車マークの下に緑色のRemote Developmentのアイコンが表示されます。 f:id:akubicharm:20191023040033p:plain

Remote Development-Containersでの開発

コンテナ環境を利用するために、Dockerデーモンを起動しておきます。

  • 画面左下のRemote Developmentアイコンをクリックしてコマンドパレットを開き、[Remote-Containers: Open Folder in Container...] をクリックします。 f:id:akubicharm:20191023041140p:plain

  • ダイアログで開きたいフォルダを選択します。 f:id:akubicharm:20191023041330p:plain

  • 開発する対象を選択します(ここではAzure Function & Node.js (LTS)を選択)。 f:id:akubicharm:20191023041602p:plain

  • Remote Development-Containers の環境を整備が開始されます。 f:id:akubicharm:20191023041841p:plain ここでやっていることは、開発に利用するDockerコンテナイメージを生成するためのDockerファイルの作成と、そのDockerファイルを使ったコンテナのビルドと実行です。 環境準備が終わると、指定したフォルダーには .devcontainer というディレクトリができています。

  • VSCodeのViewメニューからTerminalを選択します。 f:id:akubicharm:20191023042511p:plain

  • [Dev Containers]は、開発環境のDockerコンテナを実行しているターミナルです。もう一つターミナルを開いてプロンプトを確認するとDockerコンテナに入っていることがわかります。 f:id:akubicharm:20191023045312p:plain

Macのターミナルでも、docker ps コマンドを実行すると開発環境のDockerコンテナが実行されていることが確認できます。 f:id:akubicharm:20191023042900p:plain

Azure App ServiceでKeyVaultからSecretを取得する方法

基本的に https://docs.microsoft.com/ja-jp/azure/key-vault/tutorial-net-create-vault-azure-web-app の記載通りにやれば、権限を与えられたApp ServiceからKeyVaultに保存したSecretを取得することは可能です。

ここでは、各種設定で利用する値は以下の通りとします。

パラメータ名
リソースグループ名 MyGroup
ロケーション Japan East
KeyVault名 MyVault
Secret名 AppSecret
Secret値 MySecret

Azure CLI で実行するときに、コピペで行けるように環境変数にセットしておきます。

export RG_NAME="MyGroup"
export LOCATION="Japan East"
export KV_NAME="MyVault"
export SEC_NAME="AppSecret"
export SEC_VAL="MySecret"
export APP_NAME="MyApp"

リソースグループの作成

az group create --name $RG_NAME --location $LOCATION

KeyVaultの作成

az keyvault create --name $KV_NAME --resource-group $RG_NAME --location $LOCATION

キーコンテナにシークレットを追加

az keyvault secret set --vault-name $KV_NAME --name $SEC_NAME --value $SEC_VAL

値が正しく設定されていることを確認します。

az keyvault secret show --name $SEC_NAME --vault-name $KV_NAME

KeyVaultから値を取得するアプリケーションの実装

ここでは、C# を利用して Azure Function のアプリケーションを作成します。 完全なアプリケーションは https://docs.microsoft.com/ja-jp/azure/key-vault/tutorial-net-create-vault-azure-web-app#open-and-edit-the-solution を参照してください。

  • AzureServiceTokenProvider - トークンをメモリ内にキャッシュし、有効期限の直前に Azure AD から取得します。
  • KeyVaultClient - Key Vaultサービスに対して暗号化キー操作とボールト操作を実行するクライアントクラス

トークンを保持するインスタンスを生成します。

AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();

KeyVaultClientインスタンスを生成します。

KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));

KeyVaultのURLを指定して、シークレットを取得します。 KeyVault名とシークレット名は、自分の環境に合わせて編集します。

var secret = await keyVaultClient.GetSecretAsync("https://<KeyVault名>.vault.azure.net/secrets/<シークレット名>").ConfigureAwait(false);
Message = secret.Value;

アプリケーションをAzureにデプロイします。

KeyVaultのポリシーを設定

アプリケーションがKeyVaultからSecretを取得できるようにします。

デプロイしたアプリケーションのアプリケーションIDを生成します。

az webapp identity assign --name $APP_NAME --resource-group $RG_NAME

コマンドの実行結果として、アプリケーションID(principalId)が出力されます。

{
  "principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

アプリケーションにKeyVaultへのアクセス(get, list)を許可します。

export SP_ID=<コマンドで出力された principalId>

az keyvault set-policy --name $KV_NAME --object-id $SP_ID --secret-permissions get list

アプリケーションを実行すると、KeyVaultからSecretが取得できます。

Azure IoT Central でX509のデバイス認証

Azure IoT Central

Azure Iot Centralは、Azure で提供されている IoT を実現するためのSaaS (Software as a Service) プラットフォームです。デバイスさえあれば、テレメトリデータを蓄積、可視化、また、閾値を超えたらメールを送信するなどのアクションを簡単に設定することができます。 しかも、5デバイスまでならば無料で利用できるというプライスモデルで、何ができるかな?と迷っている方もお手軽に始められるところがすごい!

IoT Central は、Azure IoT Hub Device Provisioning Service を利用して、デバイスの認証と管理を行なっています。

f:id:akubicharm:20190508173711p:plain
https://docs.microsoft.com/ja-jp/azure/iot-dps/about-iot-dps

IoT Central にルート証明書、中間証明書を登録し、デバイスにはリーフ証明書とデバイスのプライベートキーとなる証明書を配置することによって、X.509 認証が利用可能になります。

Azure IoT Central のデプロイ

まずは、Azure IoT Central をデプロイします。ボタンを数回クリックするだけで5分くらいで自分専用のIoTの環境が出来上がります。

1. https://apps.azureiotcentral.com/ にアクセスします
2. "新しいアプリケーション" をクリックします

f:id:akubicharm:20190506162516p:plain:w300

3. アプリケーションの作成画面で、アプリケーション作成の情報を入力し"作成"ボタンをクリックします
名称
支払いプランの選択 評価版
アプリケーションテンプレートを選択する サンプルDevkits
Configure your application - アプリケーション名 適当な名称
Configure your appilcation - URL 一意になるFQDN

f:id:akubicharm:20190506163048p:plain:w600

デプロイが終わると、こんなダッシュボードが見えるようになります。既存のテンプレートではシミュレーションデバイスがすでに登録された状態になっています。

f:id:akubicharm:20190506163727p:plain:w600

Azure IoT Central の証明書の作成と登録

証明書の作成スクリプトが提供されているので、そのスクリプトを利用して証明書を作成していきます。

https://github.com/Azure/azure-iot-sdk-c/blob/master/tools/CACertificates/CACertificateOverview.md に記載の手順に沿って、証明書を作成します。

以下は、Bash での作成手順ですので、Power Shell を利用する場合は上記サイトを参照してください。

1. Azure IoT SDKをダウンロードします
方法1: ZIP 形式でダウンロードする場合

(1) https://github.com/Azure/azure-iot-sdk-c にブラウザでアクセスします

(2) 画面右上の"Clone or Download"のプルダウンメニューをクリックし、"Download ZIP" をクリックします

f:id:akubicharm:20190508120713p:plain:w600

(3) ダウンロードしたファイルを展開します

方法2: git clone する場合
git clone https://github.com/Azure/azure-iot-sdk-c
2. 証明証作成の環境を準備します

作業用ディレクトリを作成し、移動します。

mkdir work
cd work

azure-iot-sdk-c/tools/CACertificates/ から *.cnf, *.shファイルをコピーし、シェルスクリプトchmod コマンドで実行可能にします。

cp [ダウンロードしたディレクトリ]/azure-iot-sdk-c/tools/CACertificates/*.cnf .
cp [ダウンロードしたディレクトリ]/azure-iot-sdk-c/tools/CACertificates/*.sh .
chmod 700 certGen.sh
3. ルート証明書を作成します
./certGen.sh create_root_and_intermediate

たくさん新しいディレクトリやファイルが作成されていますが、ここから利用していくのは certs/ ディレクトリと private/ ディレクトリにあるファイルです。

4. IoT Centralへルート証明書を登録します

(1) IoT ポータル画面のメニューで"管理→デバイス接続"をクリックします

(2) 管理画面の資格情報エリアで"証明書(X.509)"タブを選択し、フォルダーアイコンのボタンをクリックします

f:id:akubicharm:20190508121215p:plain:w600

(3) ファイル選択ダイアログでルート証明書のファイル certs/azure-iot-test-only.root.ca.cert.pem を選択します

(4) 証明書の確認のために、歯車のボタンをクリックします

f:id:akubicharm:20190508131314p:plain:w600

(5) 証明書の確認ダイアログでリロード(丸い矢印)ボタンをクリックして、確認コードを生成します

f:id:akubicharm:20190508132612p:plain:w600

(6) コピーボタンをクリックして、確認コードをコピーします

f:id:akubicharm:20190508132730p:plain:w600

(7) 中間証明書を作成します

./certGen.sh create_verification_certificate [コピーした確認コード]

(8) 証明書の確認ダイアログに戻って"確認"ボタンをクリックし、ファイル選択ダイアログでcerts/verification-code.cert.pem を選択します

f:id:akubicharm:20190508132922p:plain:w600

(9) 証明書の確認ダイアログの上部に「確認済み」と表示されたことを確認して "Close" ボタンをクリックします

f:id:akubicharm:20190508132955p:plain:w600

バイス登録の準備

以降では、IoT Central用のサンプルプログラム(Python)を利用しますので、IoT Central 用の Python ライブラリが必要です。

1. デバイス用の証明書を作成します
./certGen.sh create_device_certificate mydevice
cd ./certs && cat new-device.cert.pem azure-iot-test-only.intermediate.cert.pem azure-iot-test-only.root.ca.cert.pem > new-device-full-chain.cert.pem

以下のファイルが新たに作成されています。

  • certs/new-device-full-chain.cert.pem
  • private/new-device.key.pem

スクリプト内に証明書ファイルのプレフィックスが固定で new-device と指定されていますので、ファイル名を可変にしたい場合はスクリプトを書き換えてください。

2. 証明書をデバイスにコピーします

次の2つのファイルをデバイス/usr/local/share/ca-certificates ディレクトリにコピーします。

  • certs/new-device-full-chain.cert.pem
  • private/new-device.key.pem
3. デバイスへのパッケージのインストール(Ubuntuの場合)
sudo apt -y update
sudo apt -y install python-pip
4. IoT Central の python ライブラリをインストールします
pip install iotc
5. クライアントプログラムをダウンロードします

github で公開されているサンプルプログラムをダウンロードします。

wget https://raw.githubusercontent.com/Azure/iot-central-firmware/master/RaspberryPi/app.py
6. X.509 認証ができるようにプログラムを編集します

編集前

    8 deviceId = "DEVICE_ID"
    9 scopeId = "SCOPE_ID"
   10 deviceKey = "PRIMARY/SECONDARY device KEY"
   11
   12 iotc = iotc.Device(scopeId, deviceKey, deviceId, IOTConnectType.IOTC_CONNECT_SYMM_KEY)
  • deviceId : IoT Central に登録される時に利用されるデバイスID

  • scopeId : Device Provisioning Service の識別ID。IoT Central のポータルのメニューで"管理→デバイス接続"をクリックして確認できます。 f:id:akubicharm:20190508135555p:plain

  • deviceKey : デバイスに接続するためのキー情報。ここでは、X.509認証に利用する keyfile と certfile のファイルのパスを指定するように変更します。

編集後

     8 deviceId = "dev01"
     9 scopeId = "0ne00057EA0"
    10 deviceKey = {
    11      "keyfile": "/usr/local/share/ca-certificates/private/new-device.key.pem",
    12     "certfile": "/usr/local/share/ca-certificates/certs/new-device-full-chain.cert.pem"
    13 }
    14 
    15 iotc = iotc.Device(scopeId, deviceKey, deviceId, IOTConnectType.IOTC_CONNECT_X509_CERT)

バイスからAzure IoT Centralへの接続

バイスをIoT Cenrtralに登録する方法は2つあります。

  • IoT Centralのポータルで事前登録
  • バイスがアクセスした時に自動登録

方法1: IoT Cenrtralのポータルで事前登録

1. デバイスエクスプローラーでデバイスを登録します

(1) IoT Centralのポータルの左Paneのメニューで "デバイスエクスプローラー" をクリックします

(2) エクスプローラーのテンプレート一覧で "Raspberr Pi (1.0.0)" をクリックします

(3) 右Pane上部の "+" プルダウンメニューの "実際" をクリックします

f:id:akubicharm:20190508140325p:plain

(4)新しいデバイスの作成画面でパラメータを入力し、"作成" をクリックします

f:id:akubicharm:20190508140453p:plain

2. サンプルプログラムを実行します
python app.py

以下のようなログが出力されれば接続成功です。

(1557297237.393921, '- iotc :: connect :: ')
(1557297239.495437, u'- iotc :: _loopAssign :: https://global.azure-devices-provisioning.net/0ne00058A7C/registrations/dev02/operations/4.99da589eb420cb29.8b56c569-372e-4507-ac92-3aba25128ddf?api-version=2018-11-01')
(1557297240.164666, u'- iotc :: _mqttConnect :: iotc-d1c9a56c-8bb6-4db4-9ff5-99c16448cb13.azure-devices.net')
(1557297240.166233, ' - iotc :: _mqttconnect :: created mqtt client. connecting..')
(1557297241.019479, 'mqtt-log : Sending CONNECT (u1, p0, wr0, wq0, wf0, c1, k120) client_id=dev02')
(1557297241.35323, 'mqtt-log : Received CONNACK (0, 0)')
(1557297241.353464, '- iotc :: _onConnect :: rc = 0')
(1557297241.353711, ' - iotc :: _mqttconnect :: on_connect must be fired. Connected ? True')

>>> 中 略  <<<
(1557297242.355496, "mqtt-log : Sending PUBLISH (d0, q0, r0, m6), '$iothub/twin/GET/?$rid=0', ... (1 bytes)")
(1557297242.355664, '- iotc :: MAKE_CALLBACK :: ConnectionStatus')
- [onconnect] => status:0
(1557297242.355846, '- iotc :: _onPublish :: None')
(1557297242.355868, '- iotc :: MAKE_CALLBACK :: MessageSent')
    - [onmessagesent] =>  
(1557297242.53629, u"mqtt-log : Received PUBLISH (d0, q0, r0, m0), '$iothub/twin/res/200/?$rid=0', ...  (276 bytes)")
(1557297242.536373, '- iotc :: _onMessage :: topic($iothub/twin/res/200/?$rid=0) payload({\r\n  "desired": {\r\n    "setCurrent": {\r\n      "value": 0\r\n    },\r\n    "setVoltage": {\r\n      "value": 0\r\n    },\r\n    "fanSpeed": {\r\n      "value": 0\r\n    },\r\n    "activateIR": {\r\n      "value": false\r\n    },\r\n    "$version": 1\r\n  },\r\n  "reported": {\r\n    "$version": 1\r\n  }\r\n})')

方法2: デバイスがアクセスした時に自動登録

1. サンプルプログラムを実行します
python app.py

以下のようなログが出力されて、サンプルプログラムが終了します。

(1557297143.836877, '- iotc :: connect :: ')
(1557297145.821161, u'- iotc :: _loopAssign :: https://global.azure-devices-provisioning.net/0ne00058A7C/registrations/dev02/operations/4.99da589eb420cb29.60660343-17b9-44c0-b940-baba1c034dbb?api-version=2018-11-01')
(1557297149.346818, u'- iotc :: _loopAssign :: https://global.azure-devices-provisioning.net/0ne00058A7C/registrations/dev02/operations/4.99da589eb420cb29.60660343-17b9-44c0-b940-baba1c034dbb?api-version=2018-11-01')
(1557297149.856327, "ERROR : (_mqttConnect) DPS L => {u'status': u'failed', u'registrationState': {u'status': u'failed', u'registrationId': u'dev02', u'lastUpdatedDateTimeUtc': u'2019-05-08T06:32:26.1041395Z', u'errorMessage': u'Custom allocation failed with status code: 401', u'createdDateTimeUtc': u'2019-05-08T06:32:25.9595725Z', u'errorCode': 400209, u'etag': u'IjAwMDA2OTFmLTAwMDAtMDEwMC0wMDAwLTVjZDI3N2ZhMDAwMCI='}, u'operationId': u'4.99da589eb420cb29.60660343-17b9-44c0-b940-baba1c034dbb'}")
2. IoT Centralのポータルでデバイスを確認します

(1) IoT Centralのポータルの左Paneで "デバイスエクスプローラー" をクリックします

(2) エクスプローラで "関連付けが解除されているデバイス" をクリックします

(3) デバイスチェックボックスをチェックして、右上の "関連付け" ボタンをクリックします

f:id:akubicharm:20190508144508p:plain

(4) デバイスを関連づけるダイアログでテンプレートを選択し、"関連付け" をクリックします f:id:akubicharm:20190508144618p:plain

3. 再度、サンプルプログラムを実行します
python app.py

参考

Azure Stream Analytics のクエリのTips 〜 JSON の配列を扱う方法〜

Azure Stream Analyticsとは

Azure Stream Analyticsは、SQL 風のシンプルな言語を使用して、IoT または非 IoT の複数のデータ ストリームに対する超並列のリアルタイム分析を簡単に開発および実行できます。(Stream Analytics - リアルタイム データ分析 | Microsoft Azure から引用)

f:id:akubicharm:20180927182425p:plain

データ分析のためのクエリ

IoTのデバイスなどから収集したデータを分析するクエリは SQL のように記述できるので、SQLを書いたことがある人ならはブスに理解できます。また、入力データのフォーマットにはJSON、 Avro、CSVを想定しているので、それらを簡単に処理するための組み込み関数などがいくつか用意されています。

今回は、入れ子要素の扱い方とJSON の配列データを扱う方法を紹介します。

入れ子要素の扱い

Stream Analytics のクエリでは、JSON入れ子データは「.」連結で簡単に取得することができます。 例えば、下記のようなデータが IoT Hub からStream Analyticsに送られてくる場合

{"id": "001",  "person":  {"name": "taro", "age": 20}}

person の入れ子要素のname、ageを取得するためのクエリは以下のようになります。

SELECT
  id
, person.name
, person.age
INTO
  [blob]
FROM
  [iothub]

配列要素の扱い

JSON の要素が配列の場合は、組み込み関数を利用して配列要素を取り出して、フラットなデータとして扱うためにGetArrayElements 関数とAPPLY句を利用します。

GetArrayElements関数

文法

GetArrayElements (配列要素のキー)

GetArrayElements関数で配列要素のキーを指定することで、配列要素を一行のデータとして扱うことができるようになります。 GetArrayElements関数で配列要素を取得すると、配列のインデックス(ArrayIndex)と配列の要素(ArrayValue)として値を取得することができます。

APPLY句

文法

FROM (入力ソースまたは入力ソースのエリアス)
{CROSS |OUTER} APPLY (配列要素)AS (配列要素のエリアス)

配列要素には GetArrayElements(配列要素のキー)を指定します。 配列要素の値を参照する場合には、SELECT句で(配列要素のエリアス).(要素名)と指定します。

APPLYには、CROSS APPLYとOUTER APPLYがあります。

  • CROSS APPLY : SQLの INNER JOINと同じでデータがある場合のみ取得可能です。
  • OUTER APPLY : SQLのOUTER JOINと同じでデータがない場合はNULL値が返ります。

以下のような入れ子の配列データを扱う方法を見ていきましょう。

[
{
 "id": "001",
 "data": [
    {"sub": 1001, "name": "alpha001"},
    {"sub": 2001, "name": "bravo001"},
    {"sub": 3001, "name": "charly001"}
  ]
},
{
 "id": "002",
 "data":[
    {"sub": 2, "name": "bravo"}
  ]
},
{
 "id": "003",
 "dummy": [
    {"sub": 3, "name": "charly"}
  ]
}
]

INNER JOIN風な使い方

配列の要素をINNER JOINして利用する場合には、CROSS APPLY句を利用します。下記のサンプルでは、

8行目で、GetArrayElements関数で入力となるJSONからdata要素を配列として取得し、arrayElementというエリアスで参照できるようにしています。そして、id と取得したdata要素をJOINしています。

3行目では、配列要素として取得したdata要素の配列インデックスを取得しています。id=001のデータはdata要素配列は3なので、0, 1, 2 というインデックスが取得されます。

4-5行目では、配列要素として取得したdata要素の値を取得しています。

f:id:akubicharm:20180927202906p:plain

1:    SELECT  
2:        event.id,
3:        arrayElement.ArrayIndex, 
4:        arrayElement.ArrayValue.sub,
5:        arrayElement.ArrayValue.name
6:    into [blob] 
7:    FROM [iothubsim] as event 
8:    CROSS APPLY GetArrayElements(event.data) AS arrayElement

クエリの結果は、以下のようになります。

ID ARRAYINDEX SUB NAME
"001" 0 1001 "alpha001"
"001" 1 2001 "bravo001"
"001" 2 3001 "charly001"
"002" 0 2 "bravo"

OUTER JOIN 風な使い方

配列の要素をINNER JOINして利用する場合には、OUTER APPLY句を利用します。下記のサンプルでは、

8行目で、GetArrayElements関数で入力となるJSONからdata要素を配列として取得し、arrayElementというエリアスで参照できるようにしています。そして、id と取得したdata要素をOUTER JOINしています。

f:id:akubicharm:20180927203302p:plain

1:    SELECT  
2:        event.id,
3:        arrayElement.ArrayIndex, 
4:        arrayElement.ArrayValue.sub,
5:        arrayElement.ArrayValue.name
6:    into [blob] 
7:    FROM [iothubsim] as event 
8:    OUTER APPLY GetArrayElements(event.data) AS arrayElement

クエリの結果は、以下のようになります。

ID ARRAYINDEX SUB NAME
"001" 0 1001 "alpha001"
"001" 1 2001 "bravo001"
"001" 2 3001 "charly001"
"002" 0 2 "bravo"
"003" null null null

おわりに

SQLのように記述できる Stream Analytics のクエリの組み込み関数を上手く使えば、欲しいデータを簡単に取得することができます。 今回紹介した関数以外にも、配列を扱うための関数には GetArrayElementGetArrayLengthもありますので用途にあわせて使ってみてください。