はじめに
[Azure x IoT]Azure IoTHub とAzure Functionsを連携しようでは、UI操作を紹介しながらアプリケーションを作成しましたが、「そんなちまちまやらずにインフラ構築はterraformに任せてとりあえず試してみたい!」という方向けの記事です
本記事のゴール
以下をterraformで構築します
コード
下記レポジトリを参照してください
https://github.com/ironkicka/tff_az_templates/tree/main/iotHub_to_function
構築
以下はレポジトリのREADMEの転載です。
1.デプロイ
terraform plan
terraform apply
2.関数の中身のデプロイ
cd IoTHubTriggeredFunction && npm i && npm run deploy
3.IoTHub上にデバイスを作成
export IOTHUB_NAME=xxxx
export DEVICE_NAME=xxxx
az iot hub device-identity create -n $IOTHUB_NAME -d $DEVICE_NAME
4.SASトークンを発行
export IOTHUB_NAME=xxxx
export EXPIRATION_SECONDS=xxxx
az iot hub generate-sas-token -n $IOTHUB_NAME --du $EXPIRATION_SECONDS
5.IoTHubにメッセージを送信
export SAS=xxxx
export IOTHUB_NAME=xxxx
export DEVICE_NAME=xxxx
sh publish.sh
参考 publish.sh
curl -i -X POST \
-H "Content-Type:application/json" \
-H "Authorization:$SAS" \
-d '{"value":"hello,world from iothub"}' \
"https://$IOTHUB_NAME.azure-devices.net/devices/$DEVICE_NAME/messages/events?api-version=2018-06-30"
6.確認
メッセージを送信後、FunctionAppのモニターログに以下が表示されたら成功です。
解説
今回のアプリケーションを構築する上で中心的役割を果たすリソースのみ解説していきます
IotHub
resource "azurerm_iothub" "my-iot-hub" {
name = "terra-iot-hub"
resource_group_name = azurerm_resource_group.rg.name
location = var.resource_group_location
sku {
capacity = 1
name = "F1"
}
}
単にメッセージを受け取るだけであれば上記の定義だけで大丈夫です!skuはF1(無料)を選べるのは、自分のサブスクリプションに他にF1のiothubがいない時だけなので注意してください。
またIoTHubを使ったことのある方はお気づきかもしれませんが、terraformではIoTHub内のデバイスを定義する項目がありませんでした。
そのため、”構築”セクションでazコマンドにより作成しています。
Function App周り
以下の4つを定義します
-
AzureStorageAccount
Functionのトリガーの管理やログを保存するのに必要
参考: -
AzureServicePlan
課金プラン -
AzureFunctionApp
Function本体 -
ApplicationInsights
アプリケーションログを見るためのリソース
上3つのterraform
# randomなidを生成するためのリソース
resource "random_id" "randomId" {
keepers = {
# Generate a new ID only when a new resource group is defined
resource_group = azurerm_resource_group.rg.name
}
byte_length = 8
}
# AzureStorageAccount
resource "azurerm_storage_account" "mystorageaccount" {
name = "st${random_id.randomId.hex}"
resource_group_name = azurerm_resource_group.rg.name
location = var.resource_group_location
account_tier = "Standard"
account_replication_type = "LRS"
tags = {
environment = "Terraform Demo"
}
}
resource "azurerm_service_plan" "myAppservicePlan" {
name = "my-app-service-plan-${random_id.randomId.hex}"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Linux"
sku_name = "S1"
}
resource "azurerm_application_insights" "myAppInsight" {
name = "tf-test-appinsights"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
application_type = "Node.JS"
}
Azure Function
resource "azurerm_function_app" "myFunction" {
name = "my-iothub-triggered-function"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
app_service_plan_id = azurerm_service_plan.myAppservicePlan.id
storage_account_name = azurerm_storage_account.mystorageaccount.name
storage_account_access_key = azurerm_storage_account.mystorageaccount.primary_access_key
os_type = "linux"
version = "~4"
app_settings = {
APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.myAppInsight.connection_string
APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.myAppInsight.instrumentation_key
eventHubCompatibleEndpoint = "Endpoint=${azurerm_iothub.my-iot-hub.event_hub_events_endpoint};SharedAccessKeyName=${azurerm_iothub.my-iot-hub.shared_access_policy[0].key_name};SharedAccessKey=${azurerm_iothub.my-iot-hub.shared_access_policy[0].primary_key};EntityPath=${azurerm_iothub.my-iot-hub.event_hub_events_path}"
FUNCTIONS_WORKER_RUNTIME ="node"
WEBSITE_RUN_FROM_PACKAGE =1
}
site_config {
linux_fx_version = "node|14"
}
}
実はazurerm_function_app
は型落ちしたリソースで、最新のリソースはazurerm_linux_function_app
です.
なぜわざわざこのようなことをしているかというと、azurerm_linux_function_app
でリソースを作成した際に,azure functionのコードのデプロイがうまくいかないという問題が発生したためです。自分の何らかの設定ミスなのかバグなのか定かではないですが、現状うまくいくことが確認できたazurerm_function_app
で構成しています.もし原因ご存知の方がいたら共有いただきたいです!
azurerm_function_app
azurerm_linux_function_app
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_function_app
忘れてはいけないポイントは、app_settingsブロックでeventHubCompatibleEndpoint
をきちんと定義することです。この値はIoTHubとの連携を担う値で、Functionコードから参照されます。Functionコードのfunction.jsonと同じ名前になるようにしてください。
おわりに
いかがでしたでしょうか。UI操作より圧倒的なスピードで動作確認できたのではないでしょうか。
次はAzure専用のbicepも試してみたいと思います。