普段リソースのプロビジョンは断然 Terraform 派で、なければ貢献するという私ですが、今回は他の会社さんにお願いするという関係上、PowerShell か Bash かという縛りがありチームで Azure CLI を主に使ってプロビジョンすることになりましたので、使い方をメモしておきます。
Azure CLI をデプロイに使うときのメリットデメリット
Azure CLI を使ったデプロイはなかなか思ったより快適です。
メリット
- 簡単に書ける (ARM template よりずっと楽)
- Azure CLI というオフィシャルのツールのみあれば、他にインストール要らない
- Cloud Shell からも使える (これは Terraformも)
- だいたいどのOSでも動く (Linux, Mac, Windows 最近 PowerShell もそうなりつつあるが、挙動はまだ怪しい)
デメリット
Terraform みたいに間違えたら定義変えてデプロイとかのルーチーンができない
- べき等性はない
- Terraform 程簡潔ではない
インストール
めんどくさかったら、Cloud Shell を使うといいですし、面倒でなければ下記のドキュメントを見てインストールしてもいいし、Docker イメージを使ってもいいです。
ログイン
Azure CLI を使うためには、Login が必要です。(Cloud Shell なら既にログイン済み)
az login
インタラクティブにしたくない場合は
az login -u username(e-mail) -p password
もしくは、Service Principal も使用可能です。
Log in with a service principal using client secret.
az login --service-principal -u http://azure-cli-2016-08-05-14-31-15 -p VerySecret --tenant
contoso.onmicrosoft.com
Log in with a service principal using client certificate.
az login --service-principal -u http://azure-cli-2016-08-05-14-31-15 -p ~/mycertfile.pem
--tenant contoso.onmicrosoft.com
EventHubs で使いがちなコマンド
EventHubs のデプロイで使うだろうコマンドを整理します。おそらく、EventHubs の Namespace のデプロイと、EventHub のデプロイ、そして、アクセスキーや、コネクションストリングの取得でしょう。
EventHubs Namespace
az eventhubs namespace create -g {resource_group_name} -n {namespace name} -l eastus --sku Basic
{
"createdAt": "2018-06-28T05:55:16.393000+00:00",
"id": "/subscriptions/xxxxxxxxxxxx/resourceGroups/xxxxxxxxxx0109-rg/providers/Microsoft.EventHub/namespaces/dooh2tsushisome",
"isAutoInflateEnabled": false,
"location": "East US",
"maximumThroughputUnits": 0,
"metricId": xxxxxxx:xxxxxxxxxx",
"name": "xxxxxx",
"provisioningState": "Succeeded",
"resourceGroup": "dooh2tsushipro0109-rg",
"serviceBusEndpoint": "https://xxxxxxxx.servicebus.windows.net:443/",
"sku": {
"capacity": 1,
"name": "Basic",
"tier": "Basic"
},
"tags": {},
"type": "Microsoft.EventHub/Namespaces",
"updatedAt": "2018-06-28T0
EventHub
ちなみにマニュアルだと、必須は、最初の3つとのことですが、実際は、違いました。ここに書いているのをしているする必要がありました。
$ az eventhubs eventhub create --name {eventhub name} --namespace-name {namespace name} -g {resource group name} --message-retention 1 --partition-count 15
{
"additionalProperties": {
"location": "East US"
},
"captureDescription": null,
"createdAt": "2018-06-28T06:00:59.453000+00:00",
"id": "/subscriptions/022b3013-c323-4ec6-a859-5ea2eff17ba2/resourceGroups/dooh2tsushipro0109-rg/providers/Microsoft.EventHub/namespaces/xxxxxxxxxx/eventhubs/downtime",
"messageRetentionInDays": 1,
"name": "downtime",
"partitionCount": 15,
"partitionIds": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14"
],
"resourceGroup": "dooh2tsushipro0109-rg",
"status": "Active",
"type": "Microsoft.EventHub/Namespaces/EventHubs",
"updatedAt": "2018-06-28T06:01:06.417000+00:00"
}
PrimaryKey と Connection String
az eventhubs namespace authorization-rule keys
というサブコマンドがありました。
az eventhubs namespace authorization-rule keys list --resource-group {resource group name} --namespace-name {namespace name} --name RootManageSharedAccessKey
{
"aliasPrimaryConnectionString": null,
"aliasSecondaryConnectionString": null,
"keyName": "RootManageSharedAccessKey",
"primaryConnectionString": "YOUR_CONNECTION_STRING",
"primaryKey": "YOUR_PRIMARY_KEY",
"secondaryConnectionString": "YOUR_SECONDARY_CONNECTION_STRING",
"secondaryKey": "YOUR_SECONDARY_KEY"
}
最後にクエリーを書けば直接取得できます。
az eventhubs namespace authorization-rule keys list --resource-group dooh2tsushipro0109-rg --namespace-name dooh2tsushisome --name RootManageSharedAccessKey --query primaryKey --output tsv
YOUR_PRIMARY_KEY_HERE
Stream Analytics
Stream Analytics の方は残念ながら、Azure CLI は対応していません。また、Output / Input の設定とかクエリの設定とかいかにも面倒くさそうです。クエリってどうやってデプロイすればいいだろう、、、と悩みますが基本的にデプロイに関しては ARM テンプレートで可能です。Stream Analytics の Visual Studio 連携を試してみるのエントリで書いたのですが、Visual Studio で Stream Analytics 連携を使って SQL や、Input/Output を開発すると ARM テンプレートを自動で吐いてくれます。今回はその中身を見てみましょう。
テンプレート
コードをよく見ると、クエリーや、Input/Output の設定がすでに組み込まれています。これは素晴らしい。後はパラメータとして、コネクションストリングなどを渡せばよさそうです。
template.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"StreamAnalyticsJobName": {
"type": "string",
"minLength": 3,
"maxLength": 63,
"metadata": {
"description": "Stream Analytics Job Name, can contain alphanumeric characters and hypen and must be 3-63 characters long"
}
},
"Location": {
"type": "string"
},
"OutputStartMode": {
"type": "string",
"allowedValues": [
"JobStartTime",
"CustomTime",
"JobStartTime"
]
},
"DataLocale": {
"type": "string"
},
"OutputErrorPolicy": {
"type": "string",
"allowedValues": [
"Drop",
"Stop"
]
},
"EventsLateArrivalMaxDelayInSeconds": {
"type": "int"
},
"EventsOutOfOrderMaxDelayInSeconds": {
"type": "int"
},
"EventsOutOfOrderPolicy": {
"type": "string",
"allowedValues": [
"Adjust",
"Drop"
]
},
"StreamingUnits": {
"type": "int",
"minValue": 1,
"maxValue": 48,
"metadata": {
"description": "Number of Streaming Units"
},
"allowedValues": [
1,
3,
6,
12,
18,
24,
30,
36,
42,
48
]
},
"CompatibilityLevel": {
"type": "string",
"allowedValues": [
"1.0",
"1.1"
]
},
"Input_downtime_serviceBusNamespace": {
"type": "string"
},
"Input_downtime_eventHubName": {
"type": "string"
},
"Input_downtime_sharedAccessPolicyName": {
"type": "string"
},
"Input_downtime_sharedAccessPolicyKey": {
"type": "string"
},
"Output_cosmosdb_accountId": {
"type": "string"
},
"Output_cosmosdb_accountKey": {
"type": "string"
},
"Output_cosmosdb_database": {
"type": "string"
},
"Output_cosmosdb_collectionNamePattern": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.StreamAnalytics/StreamingJobs",
"apiVersion": "2015-10-01",
"name": "[parameters('StreamAnalyticsJobName')]",
"location": "[parameters('Location')]",
"properties": {
"outputStartMode": "[parameters('OutputStartMode')]",
"outputStartTime": null,
"sku": {
"name": "standard"
},
"eventsOutOfOrderPolicy": "[parameters('EventsOutOfOrderPolicy')]",
"outputErrorPolicy": "[parameters('OutputErrorPolicy')]",
"eventsOutOfOrderMaxDelayInSeconds": "[parameters('EventsOutOfOrderMaxDelayInSeconds')]",
"eventsLateArrivalMaxDelayInSeconds": "[parameters('EventsLateArrivalMaxDelayInSeconds')]",
"dataLocale": "[parameters('DataLocale')]",
"compatibilityLevel": "[parameters('CompatibilityLevel')]",
"inputs": [
{
"name": "downtime",
"properties": {
"type": "Stream",
"datasource": {
"type": "Microsoft.ServiceBus/EventHub",
"properties": {
"serviceBusNamespace": "[parameters('Input_downtime_serviceBusNamespace')]",
"eventHubName": "[parameters('Input_downtime_eventHubName')]",
"consumerGroupName": null,
"sharedAccessPolicyName": "[parameters('Input_downtime_sharedAccessPolicyName')]",
"sharedAccessPolicyKey": "[parameters('Input_downtime_sharedAccessPolicyKey')]"
}
},
"compression": {
"type": "None"
},
"serialization": {
"type": "Json",
"properties": {
"encoding": "UTF8"
}
}
}
}
],
"outputs": [
{
"name": "cosmosdb",
"properties": {
"serialization": {
"type": "Json",
"properties": {
"encoding": "UTF8",
"format": "LineSeparated"
}
},
"datasource": {
"type": "Microsoft.Storage/DocumentDB",
"properties": {
"accountId": "[parameters('Output_cosmosdb_accountId')]",
"accountKey": "[parameters('Output_cosmosdb_accountKey')]",
"database": "[parameters('Output_cosmosdb_database')]",
"collectionNamePattern": "[parameters('Output_cosmosdb_collectionNamePattern')]",
"partitionKey": null,
"documentId": null
}
}
}
}
],
"transformation": {
"name": "Transformation",
"properties": {
"streamingUnits": "[parameters('StreamingUnits')]",
"query": "WITH SelectPreviousEvent AS\r\n(\r\nSELECT\r\n TeamId,\r\n System.TimeStamp As Time,\r\n Count(*) as Count\r\nFROM\r\n downtime TIMESTAMP BY Date\r\nGROUP BY\r\n TeamId,\r\n TumblingWindow(second, 1)\r\n)\r\n\r\nSELECT \r\n TeamId,\r\n System.Timestamp As Time,\r\n Count(*) As Count\r\nINTO\r\n [cosmosdb]\r\nFROM SelectPreviousEvent\r\nGroup BY\r\n TeamId,\r\n TumblingWindow(minute, 1)"
}
},
"functions": []
}
}
]
}
パラメータ
パラメータも吐いてくれます。私の固有のデータをはいているところは null 等に変更しましたが、基本的にキー以外は埋めてくれます。
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"StreamAnalyticsJobName": {
"value": null
},
"Location": {
"value": "Central US"
},
"OutputStartMode": {
"value": "JobStartTime"
},
"DataLocale": {
"value": "en-US"
},
"OutputErrorPolicy": {
"value": "Drop"
},
"EventsLateArrivalMaxDelayInSeconds": {
"value": 5
},
"EventsOutOfOrderMaxDelayInSeconds": {
"value": 0
},
"EventsOutOfOrderPolicy": {
"value": "Adjust"
},
"StreamingUnits": {
"value": 1
},
"CompatibilityLevel": {
"value": "1.1"
},
"Input_downtime_serviceBusNamespace": {
"value": null
},
"Input_downtime_eventHubName": {
"value": "downtime"
},
"Input_downtime_sharedAccessPolicyName": {
"value": "RootManageSharedAccessKey"
},
"Input_downtime_sharedAccessPolicyKey": {
"value": null
},
"Output_cosmosdb_accountId": {
"value": null
},
"Output_cosmosdb_accountKey": {
"value": null
},
"Output_cosmosdb_database": {
"value": "leaderboard"
},
"Output_cosmosdb_collectionNamePattern": {
"value": "DowntimeRecord"
}
}
}
ARM テンプレートを Azure CLI からコールする
さて、このパラメータの数をみるとうんざりするのではないでしょうか?これをパラメータとしてAzure CLI に渡すのは面倒すぎです。そのケースだと、デフォルト値とか、固定値はこのパラメータファイルを使って、足りないところだけをパラメータで渡せる様子です。次のような感じです。
az group deployment create --name StreamAnalyticsDeployment --resource-group $resourceGroupName --template-file stream_analytics_arm_template.json --parameters @stream_analytics_arm_parameter.json --parameters StreamAnalyticsJobName=$streamAnalyticsJobName Location=$location Input_downtime_serviceBusNamespace=$eventHubsNamespace Input_downtime_sharedAccessPolicyKey=$eventhubsKey Output_cosmosdb_accountId=$cosmosDBName Output_cosmosdb_accountKey=$cosmosdbKey
ちなみに、EventHubsとCosmos のシークレット取得は次のコードです。$xxxx
は変数になっています。
echo -e "Retrieving cosmosdb connection string\n"
cosmosdbKey=$(az cosmosdb list-keys --name $cosmosDBName --resource-group $resourceGroupName --query primaryMasterKey --output tsv)
echo -e "Retriving eventhubs primary key string\n"
eventhubsKey=$(az eventhubs namespace authorization-rule keys list --resource-group $resourceGroupName --namespace-name $eventHubsNamespace --name RootManageSharedAccessKey --query primaryKey --output tsv)
これで、デプロイも完成です。
Stream Analytics Job起動
さて、最後の関門として、Stream Analytics の Job 起動の問題があります。PowerShell だとできますが、Azure CLI はサポートしていません。ただ、.Net SDK はサポートしていますので、.NET Core で起動、停止のコマンドを作って、それを呼ぶようにしようと思います。下記のパーサーとか有用そうです。
あと、シングルバイナリになってくれればなぁ。