Dapr on Azure IoT Edge

Vitaliy Slepakov
3 min readDec 24, 2019

--

This post assumes that you are familiar with Dapr and its concepts as well as Azure IoT Edge.

A couple of customer scenarios motivated me to look at possibilities for using Dapr on IoT Edge. Some of the obvious benefits of using Dapr are:

  • Standardized development across Cloud and Edge, allowing to move functionality between those easier.
  • Rich application development on Edge made easier.
  • Abstraction of underlying technology, e.g. the same code for using RabbitMQ or Kafka. Dapr Components is the key here. Among other things, this abstraction allows to switch to a different product for reasons like: change of support terms, change of licencing etc. without touching the application. Surely this kind of switching will have more aspects/moving parts to it but this is a different story.

Right now Dapr supports two operation modes: running locally and running on Kubernetes. Well, IoT Edge is none of those but is closer to the ‘local’ option. Both options use the Sidecar pattern.

When using Dapr locally your application does not actually run in a container but rather as a normal process talking to the companion daprd service/daemon. When running on Kubernetes, Dapr deploys an additional container (sidecar) with your Pod.

To achieve this kind of setup on IoT Edge (which is container based), I basically make daprd part of the container image like this:

...
RUN wget https://github.com/dapr/dapr/releases/download/v0.3.0/daprd_linux_amd64.tar.gzRUN tar -zxvf daprd_linux_amd64.tar.gz
...
CMD ["/bin/bash", "runWithDapr.sh", "nodeapp", "3000", "3501", "50002"]

At runtime, first the actual application is started then followed by daprd. This is the runWithDapr.sh script:

#!/bin/bash

node app.js &
sleep 3
daprd --dapr-id $1 --app-port $2 --dapr-http-port $3 --dapr-grpc-port $4

There is one gotcha though. Since I still run Dapr in sort of standalone mode, it uses multicast DNS for service discovery. In this architecture:

Dapr runtime of the Python app needs to discover the Dapr runtime of the Node app. Using the aforementioned discovery mechanism it always results in localhost:port. When the application containers are NOT running on the Docker Host network, the communication fails since the notion of localhost has different meanings in each of the containers. The solution for now is to run all application containers on the Host network as a common denominator. As you can see I need to specify dapr-http-port and dapr-grpc-port which need to be different per application since I cannot bind to the same ports more than once (btw. default is 3500 and 50001).

This limitation was the only reason for running on the Host network, everything else worked pretty much on every network so far.

To run an IoT Edge module on the Host network, createOptions in the deployment manifest need to look something like this:

“createOptions”: {
“NetworkingConfig”: {
“EndpointsConfig”: {
“host”: {}
}
},
“HostConfig”: { “NetworkMode”: “host” }
}

UPDATE:

In this architecture:

there is no need to run on the Host network and/or use different Dapr runtime ports since the runtime instances are not talking directly to each other. The communication happens through a message broker (RabbitMQ in my example).

Please find complete samples in my Github repo:

Next, I will bring Dapr Actors to IoT Edge and maybe implement a custom component.

UPDATE: here are the Actors on IoT Edge

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response