Run IoT Telemetry Simulator in ACI
Tags: azure, iothub, aci
Published: 2022-12-21 03:02:09

[IoT Telemetry Simulator](https://github.com/Azure-Samples/Iot-Telemetry-Simulator/) is great tool to generate telemetries against IoT Hub/Event Hub when doing e2e and/or load test.

We can run this tool on any docker environment, and I explain how to run this in Azure Container Instance (ACI).

## Prerequisits

- Azure
- IoT Hub
- IoT Hub devices registered in advance

The device name should be sim000001, sim000002 naming convention.

## Number of Devices per ACI

We can specify number of devices we want to run. By default, the tool use naming convention to start device as sim000001, sim000002...

As ACI has some limitation about resources, I run 10 devices per ACI.

You can check ACI resource limitation [here](https://learn.microsoft.com/en-us/azure/container-instances/container-instances-region-availability#linux-container-groups).

To make sure each ACI use unique name, we need to use ``DeviceList`` which includes names to pick up when running devices.
 
## Bicep

This is the bicep file I use to run the tool in ACI. I generate device name lists by using ``numberOfACIs`` and ``numberOfDevicesPerACI`` paramter. Set ``restartPolicy`` to ``Never`` so that it won't keep sending. You can tweak other parameters as you need.

```ini
@description('Location')
param location string = resourceGroup().location

@description('number of ACI')
param numberOfACIs int = 10

@description('number of devices per ACI')
param numberOfDevicesPerACI int = 10

@description('number of messages per device')
param messageCount int = 10

@description('IotHubConnectionString')
param iotHubConnectionString string

var deviceLists = [for x in range(1, numberOfACIs):{
  deviceNames: take(skip(devices, (x-1)*numberOfDevicesPerACI), numberOfDevicesPerACI)
}]

var devices = [for i in range(1, numberOfACIs*numberOfDevicesPerACI):'sim${padLeft(string(i), 6, '0')}']

resource container 'Microsoft.ContainerInstance/containerGroups@2021-10-01' = [for i in range(1, numberOfACIs): {
  name: 'aci-simulator-${i}'
  location: location
  tags: {
  }
  properties: {
    containers: [
      {
        name: 'azureiot-telemetrysimulator'
        properties: {
          image: 'mcr.microsoft.com/oss/azure-samples/azureiot-telemetrysimulator'
          command: [
          ]
          ports: [
            {
              protocol: 'TCP'
              port: 8080
            }
          ]
          resources: {
            requests: {
              cpu: 4
              memoryInGB: 2
            }
          }
          environmentVariables: [
            {
              name: 'IotHubConnectionString'
              value: iotHubConnectionString
            }
            {
              name : 'DeviceList'
              value : join(deviceLists[i-1].deviceNames, ',')
            }
            {
              name: 'Template'
              value: '{ "deviceId": "$.DeviceId", "rand_int": $.Temp, "rand_double": $.DoubleValue, "Ticks": $.Ticks, "Counter": $.Counter, "time": "$.Time" }'
            }
            {
              name: 'Variables'
              value: '[{"name": "Temp", "random": true, "max": 25, "min": 23}, {"name":"Counter", "min":100, "max":102}, {"name": "DoubleValue", "randomDouble":true, "min":0.22, "max":1.25}]'
            }
            {
              name: 'DeviceCount'
              value: '${numberOfDevicesPerACI}'
            }
            {
              name: 'MessageCount'
              value: '${messageCount}'
            }
            {
              name: 'Interval'
              value: '10'
            }
          ]
        }
      }
    ]
    restartPolicy: 'Never'
    osType: 'Linux'
    ipAddress: {
      type: 'Public'
      ports: [
        {
          protocol: 'TCP'
          port: 8080
        }
      ]
    }
  }
}]
```

## Performance

As long as I tested, each ACI could send about 500 messages/sec. I use 10 ACIs (100 devices in total) in the test which generates 5,000 messages/sec which is good enough for load testing.

## Summary

The most time-consuming part was to register IoT Hub devices, as it takes longer time than I expected. Another caveat is that bicep won't wait until devices finish sending telemetries, but it ends as soon as ACI provision completed.

You can take a look into ``Logs`` of container in ACI to see for detail log, or confirm the status becomes ``Terminated``.