Provisioning "Metropolis Microservices for Jetson" to Nvidia Jetson devices by using Mender

Pre-requisites

Hardware

This guide requires a Nvidia Jetson AGX Orin devkit or Nvidia Jetson Orin NX 16GB devkit (self built) with 128GB(min) NVMe drive.

This tutorial was tested on the Nvidia Jetson AGX Orin devkit

Flash your Jetson

It is required to install at least the BSP included in the JetPack 6.0 DP or newer.

Follow the official Nvidia documentation based on your board.

Install Mender

Install Mender in your Jetson board by following Mender’s docs instructions. When asked for naming the Device type during installation we recommend you follow Nvidia’s Jetson naming convention like jetson-agx-orin-devkit for the Jetson AGX Orin DevKit.

Also, install mender-artifact in your workstation by following this guide.

Additional resources

  1. Obtain a valid NGC API key: Generate & Retrieve NGC API key by following instructions in NGC User Guide
  • Login to ngc.nvidia.com.
  • Click your name in top right corner
    • Setup
    • Generate API key
  • Store the NGC API key that is displayed in a file named ngc-token. We will use it later. Treat it as a secret.
  1. Download from Nvidia the required tools, you need a NGC account:

Using Mender to deploy MMJ (by using a demo app)

Run all the following steps on your workstation.

Creating the Mender Update Module

Create a file named mmjprovision-mender-module with the following content:

#!/bin/bash

set -e

STATE="$1"
FILES="$2"

WORKDIR="/opt/workdir"

case "$STATE" in
    SupportsRollback)
        echo "No"
        ;;
    ArtifactInstall)
        # Creating the WORKDIR, you can modify it above
        mkdir -p $WORKDIR

        # Getting the IP Address
        echo "Getting the IP address for outputs" 1>&2
        ip_address=$(hostname -I | awk '{print $1}')
        echo "IP Address: ${ip_address}" 1>&2

        # Tweaking the kernel
        echo "Tweaking the kernel with jetson_clocks" 1>&2
        jetson_clocks

        # Increase the OS socket buffer sizes (for the Streamer)
        echo "Increase the OS socket buffer sizes (for the Streamer)" 1>&2
        sysctl -w net.core.wmem_max=2000000
        sysctl -w net.core.rmem_max=2000000

        # Maximize number of video streams processed by the system (for AI NVR)
        echo "Maximize number of video streams processed by the system (for AI NVR)" 1>&2
        sysctl -w net.core.rmem_default=2129920
        sysctl -w net.core.rmem_max=10000000

        echo "Reading token for NGC" 1>&2
        API_KEY=$(cat $FILES/files/ngc-token)

        # Let's login on the 
        echo "Login to NGC" 1>&2
        docker login nvcr.io -u "\$oauthtoken" -p $API_KEY

        # Setup and Launch NVStreamer
        echo "Setup NVStreamer" 1>&2
        tar -xvf $FILES/files/nvstreamer.tar.gz -C $WORKDIR
        cd $WORKDIR/nvstreamer
        echo "Launch NVStreamer" 1>&2
        docker compose -f compose_nvstreamer.yaml up -d  --force-recreate
        echo "Please open a browser in $ip_address:31000 for the Streamer" 1>&2
 
        # Setup and start Services

        echo "Launch jetson's redis and ingress" 1>&2
        systemctl start jetson-redis
        systemctl start jetson-ingress

        # Setup and Start Application (VST)
        echo "Setup VST" 1>&2
        tar -xvf $FILES/files/ai_nvr.tar.gz -C $WORKDIR
        cd $WORKDIR/ai_nvr
        cp $WORKDIR/ai_nvr/config/ai-nvr-nginx.conf /opt/nvidia/jetson/services/ingress/config/
        echo "Launch VST" 1>&2
        docker compose -f compose_agx.yaml up -d --force-recreate
        echo "Please open a browser in $ip_address:30080/vst for the VST application" 1>&2
        echo "Ready, continue with Nvidi's tutorial to connect both apps" 1>&2
        ;;
    
esac
exit 0

Install the Update Module

Copy the Update Module from above to your Jetson by following this guide.

Create a Mender Artifact

Replace the device-type per the one set in the mender setup process on the Jetson during the “Install Mender” part above.

Feel free to change the artifact-name as this is how this artifact will be named in the Mender ecosystem.

The type must match the name of the Update Module. In our example, we named it as mmjprovision-mender-module.

Notice it will include the three files (by using the file argument) we reference inside the $FILES directory inside the Update Module. Replace the /path/to/ from the command below with the actual path to these files.

mender-artifact write module-image \
    --artifact-name "mmj-installation" \
    --output-path "mmj-installation.mender" \
    --device-type "jetson-agx-orin-devkit" \
    --type "mmjprovision-mender-module" \
    --file /path/to/ai_nvr.tar.gz \
    --file /path/to/nvstreamer.tar.gz \
    --file /path/to/ngc-token

This will generate a Mender’s artifact named mmj-installation.mender that we can upload into our Mender Server and deploy into multiple Jetson devices from our fleet.

Verify your installation

After this artifact is deployed into a Jetson board, you should be able to open in your workstation’s browser the two webapps we installed: NV Streamer (in port 31000) and VST (in port 30080) and you should be able to follow this Nvidia’s tutorial for uploading a video into the NV Streamer and this one to import that video stream into VST.

The running containers should look like this:

CONTAINER ID   IMAGE                                                         COMMAND                  CREATED       STATUS       PORTS     NAMES
56dfb8485026   nvcr.io/e7ep4mig3lne/release/sdr:mmj_v1                       "sh -c '/wdm/dist/sd…"   2 hours ago   Up 2 hours             sdr-emdx
f446c50fcbb0   nvcr.io/e7ep4mig3lne/release/deepstream:mmj_v1                "/opt/nvidia/nvidia_…"   2 hours ago   Up 2 hours             deepstream
79fe67704b0a   nvcr.io/e7ep4mig3lne/release/vst:v1.2.37_aarch64              "sh -c '/root/vst_re…"   2 hours ago   Up 2 hours             vst
147d20ba4d1e   nvcr.io/e7ep4mig3lne/release/emdx-analytics:mmj_v1            "sh -c 'gunicorn --w…"   2 hours ago   Up 2 hours             emdx-analytics-01
78f19ba84b2c   nvcr.io/e7ep4mig3lne/release/sdr:mmj_v1                       "sh -c '/wdm/dist/sd…"   2 hours ago   Up 2 hours             sdr
90f0dad92f7c   nvcr.io/e7ep4mig3lne/release/emdx-analytics:mmj_v1            "sh -c 'gunicorn --w…"   2 hours ago   Up 2 hours             emdx-analytics-02
5cfdbde2ade9   nvcr.io/e7ep4mig3lne/release/emdx-analytics-web-api:mmj_v1    "sh -c 'gunicorn --w…"   2 hours ago   Up 2 hours             emdx-webapi
e666f408b448   nvcr.io/e7ep4mig3lne/release/ialpha-ingress-arm64v8:0.8       "sh -c '/nginx.sh 2>…"   2 hours ago   Up 2 hours             ingress
24cbeab8bcce   redisfab/redistimeseries:master-arm64v8-jammy                 "docker-entrypoint.s…"   2 hours ago   Up 2 hours             redis
646e974a3ba2   nvcr.io/e7ep4mig3lne/release/vst:nvstreamer_v0.2.24_aarch64   "sh -c '/root/vst_re…"   2 hours ago   Up 2 hours             nvstreamer

Just a couple of working screenshots: