LoginSignup
1
0

More than 1 year has passed since last update.

[Azure x IoT] AzureIoTHubとAzureFunctionを連携しよう(Terraform編)

Last updated at Posted at 2022-04-01

はじめに

[Azure x IoT]Azure IoTHub とAzure Functionsを連携しようでは、UI操作を紹介しながらアプリケーションを作成しましたが、「そんなちまちまやらずにインフラ構築はterraformに任せてとりあえず試してみたい!」という方向けの記事です

本記事のゴール

以下をterraformで構築します

image.png

コード

下記レポジトリを参照してください

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のモニターログに以下が表示されたら成功です。

image.png

解説

今回のアプリケーションを構築する上で中心的役割を果たすリソースのみ解説していきます

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コマンドにより作成しています。

Terraform Registry

Function App周り

以下の4つを定義します

  • AzureStorageAccount
    Functionのトリガーの管理やログを保存するのに必要
    参考:

    Storage considerations for Azure Functions

  • 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

https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/function_app#attributes-reference

  • 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も試してみたいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0