Can an Azure IoT Edge container be deployed in the cloud?

In the last couple of years, I wrote several blog posts about deploying standard, generic (third-party) Docker container or custom docker containers on the Azure IoT Edge.

Why? Because we can!

Azure IoT Edge is a great container delivery solution for docker containers and can be used in non-IoT-related solutions too.

I agree this is a little bit awkward. Azure IoT Edge has this relationship with IoT. Can we ignore the Internet of Things part?

Yes, we are able to control containers remotely. And as a bonus, IoT related telemetry can be gathered and IoT related logic can be excuted.

So, more generally, we see most of the times this deployment of a mix of both IoT-related modules and generic, but still IoT-related (third-party), modules.

Still, the magic of deploying whatever you want is a big surprise.

The same goes for the opposite idea. Can we roll out IoT Edge modules in the cloud, without the confinements of Azure IoT Edge?

This is an interesting question.

What makes a docker container an Azure IoT Edge module?

Let’s discuss first what is so special about an Azure IoT Edge module?

As with all Docker containers, Azure IoT Edge modules are basically just applications running forever inside a container.

This could be a C# console app, a NodeJS app, Python app, etc.

The difference with ‘generic’ containers is the urge to connect the module to the Azure IoT Edge hub routing system. We want to ingest and egress messages over the supported inputs and outputs. Maybe we even want to participate in reading or writing messages to child devices or nested edge devices.

To do this, we make use of the Azure IoT Edge module templates which include the Microsoft Azure IoT Edge SDKs.

These SDKs connect the internal module logic (the application) to the routing mechanism.

I have used this same principle with a custom Blazor app that connects to the routing system to ingest messages to be sent to the browser app using Websockets.

Switching between logic

You are interested of excuting the special logic which normally runs on the edge, in the cloud. But you want to disable the Azure IoT Edge specific ingest and egress. You just want to able to switch over to another way of communication with that same logic.

So technically, an Azure IoT Edge should be modified to run as a regular application that makes its own decisions.

Imagine a console app in an azure container that conditionally switches between connecting to an Azure IoT Edge input route to receive messages or exposing an HTTP Rest endpoint.

Could this be done?

Somehow the application needs to know the context it lives in. And this context must be configurable.

The answer is Environment variables.

Docker containers can be attributed using environment variables.

And because the usage of the Azure IoT Edge SDK is available for use to change, we can do magic.

Here, the first lines of code of the sample Echo module are shown. See how a ‘regular’ C# console app is attributed with the Azure IoT Edge routing logic:

Imagine we can start other custom code instead of this connection to the Azure IoT Edge routing mechanism. Then, we are good to go!

Let’s explore this further.

Alternatives

Alternatives to environment variables are:

  • A file on a volume. Yes, the container could access a folder on the host file system to read certain configuration files. Azure Container instances do not support volumes though.
  • Making a REST call or exposing a RESt endpoint for configuration. This is not stateful so the call must be made every time the module restarts. And it makes the module vulnerable to hacking.

So, environment variables are much more interesting.

Sample app

To test this, I used the same test app as seen before, a Blazor web app which is generated as a container.

Just follow that tutorial until the module is tagged and pushed to your own container registry.

Note: I use the Docker hub in this example.

I only made two changes:

  1. Reading all environment variables and showing them on the main page
  2. Environment variable in the docker file

The second step does not have that much added value. In the end, the variable is hardcoded too. Still, this can come in handy if you want to make decisions eg. in your development pipeline.

So, the default Blazor app got an updated Index.razor page:

Note: We make use of code-behind instead of inline C#.

The part under the break shows a list of variables when the button is clicked:

@page "/"

@inherits IndexBase

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<br />

<button @onclick="GetEnvironmentValues">Click</button>

<ul>

    @if (vars != null)
    {
    @foreach(var item in vars)
        {
    <li>@item</li>
        }
    }
</ul>

So, we call a file named IndexBase.cs, places next to the Index.razor:

Here, we just call the GetEnvironmentVariables function and fill a list with all key-value pairs:

using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;

namespace BlazorConfigurableWebApplication.Pages
{
    public class IndexBase : ComponentBase
    {
        public List<string> vars;

        public void GetEnvironmentValues()
        {
            var vs = Environment.GetEnvironmentVariables();

            vars = new List<string>();

            foreach (var v in vs)
            {
                var vk = ((System.Collections.DictionaryEntry)v).Key;

                var vv = ((System.Collections.DictionaryEntry)v).Value;

                vars.Add(vk.ToString() + "=" + vv.ToString());
            }
        }
    }
}

I also added that ‘hardcoded’ variable in the Dockerfile:

Compile and run it as a container in your development environment.

With ‘docker ps’ we can see the container is created:

And the website is shown. I pushed the button:

As you can see, a list of environment variables is created.

So we could add extra code to make that decision between acting as an Azure IoT Edge module or as some custom container without Azure IoT Edge context.

I tagged and pushed the container to Docker Hub:

docker pull svelde/blazorconfigurablewebapplication

Azure Container Instances

To test this, I deploy the same module as a container in Azure Container Instances.

Run Docker containers on-demand in a managed, serverless Azure environment. Azure Container Instances is a solution for any scenario that can operate in isolated containers, without orchestration. Run event-driven applications, quickly deploy from your container development pipelines, and run data processing and build jobs.

So, I create this new instance in the portal. (this could be done in eg. CLI or PowerShell):

I give it a new name and reference the (public) docker container image in Docker Hub.

I generated my container for Linux so that is ok already. I leave the Size as-is.

In the Network tab, I provide a DNS name label:

Because this is a demonstration, I leave port 80 access publically accessible. In a production environment, this probably has to change…

Go to the advanced tab, here we can enter environment variables:

As you can see, I added a ‘unsecure key’ and a ‘secure key’. As you can see already, the ‘secure value’ is obfuscated. See also the documentation.

With that, you can review and create the container instance.

Checking out the container instance

Once the container is created, check out the portal settings.

Soon after, the instance is already up and running:

Notice we get an IP address and a DNS name.

We can see the environment variables here:

Notice, again the ‘secure key’ is obfuscated.

It is NOT possible to CHANGE the variables. You have to redeploy the module again if you want to change them.

So, open a browser and browse the web page within our container:

It just works as advertised!

We see both the unsecure and secure key. And we also see that FOO key.

Conclusion

We have seen we only need Docker environment variables to change an Azure IoT Edge module into a ‘normal’ Docker container. If this works for a Blazor app, this will work for an Azure IoT Edge template app too.

We have also seen we can indeed deploy a C# container both on the edge and in the cloud (as Azure Container Instance) while being able to read a separate set of environment variables.

So we can conclude it is indeed possible to roll out cloud containers on the edge and edge containers in the cloud.

Azure Container instances is just one of many ways to handle Docker containers in Azure.

Check out the other solutions like Containerized WebApps and Kubernetes too.

Geef een reactie

Vul je gegevens in of klik op een icoon om in te loggen.

WordPress.com logo

Je reageert onder je WordPress.com account. Log uit /  Bijwerken )

Google photo

Je reageert onder je Google account. Log uit /  Bijwerken )

Twitter-afbeelding

Je reageert onder je Twitter account. Log uit /  Bijwerken )

Facebook foto

Je reageert onder je Facebook account. Log uit /  Bijwerken )

Verbinden met %s