DroneDB on Kubernetes

I finally got some time to look into spinning up my own DroneDB instance.

I dusted off my Linux box and did a lot of updating, including completely reinstalling Docker and the latest Docker Desktop to get bind mounts working, but I was able to get the docker run example from the README.md up and running. I also got the docker/production example up as well.

So I thought “hey, let’s put this in Kubernetes.”

My deployment has the JSON and SQL configs from the production Docker example added as config maps, and they look reasonable. The database container comes up fine, but the registry container terminates with exit code 0 very shortly after starting up. The logs aren’t very informative – here they are:


		*** Registry.Web - v1.0.16 ***

 ?> Running in RELEASE
 ?> Using storage folder '/data'
 ?> Using address '0.0.0.0:5000'
 ?> Initialized DDB
 ?> DDB version 1.0.11 (git commit f9f7d50)
 -> Setting up storage folder
 ?> Hub folder is ok
 -> Verifying settings
 -> Updating settings
 -> Starting web host
[03:42:59 DBG] Hosting starting
[03:42:59 WRN] Using an in-memory repository. Keys will not be persisted to storage.
[03:42:59 WRN] Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when application exits.

I am woefully unfamiliar with dot net and friends, so I am not sure how best to diagnose the problem. Has anyone else seen this?

Here’s the somewhat-sanitized output of kubectl describe configmap registry showing the two configuration files:

Name:         registry
Namespace:    dronedb
Labels:       <none>
Annotations:  <none>

Data
====
appsettings.json:
----
{
    "AppSettings": {
        "Secret": "biglongsecret",
        "TokenExpirationInDays": 7,
        "RevokedTokens": [],
        "AuthProvider": "Mysql",
        "RegistryProvider": "Mysql",
        "HangfireProvider": "Mysql",
        "DefaultAdmin": {
            "Email": "[email protected]",
            "UserName": "admin",
            "Password": "hahano"
        },
        "StoragePath": "./data",
        "DatasetsPath": "./datasets",
        "CachePath": "./cache",
        "MaxRequestBodySize": null,
        "BatchTokenLength": 32,
        "RandomDatasetNameLength": 16,
        "ChunkedUploadSessionTimeout": "01:00:00",
        "AuthCookieName": "jwtToken",
        "ExternalUrlOverride": "",
        "ExternalAuthUrl": null,
        "CacheProvider": null,
        "WorkerThreads": -1,
        "ThumbnailsCacheExpiration": "00:30:00",
        "TilesCacheExpiration": "00:30:00",
        "ClearCacheInterval": "01:00:00",
        "UploadBatchTimeout": "01:00:00"
    },
    "AllowedHosts": "*",
    "ConnectionStrings": {
        "IdentityConnection": "Server=db;Database=RegistryAuth;Uid=registry;Pwd=hahano",
        "RegistryConnection": "Server=db;Database=RegistryData;Uid=registry;Pwd=hahano",
        "HangfireConnection": "Server=db;Database=RegistryHangfire;Uid=registry;Pwd=hahano;Allow User Variables=true"
    },
    "Serilog": {
        "LevelSwitches": {
            "$controlSwitch": "Debug"
        },
        "MinimumLevel": {
            "ControlledBy": "$controlSwitch"
        },
        "Using": [
            "Serilog.Sinks.Console",
            "Serilog.Sinks.File"
        ],
        "WriteTo": [
            {
                "Name": "Console"
            },
            {
                "Name": "File",
                "Args": {
                    "path": "./logs/registry.txt"
                }
            }
        ],
        "Enrich": [
            "FromLogContext",
            "WithMachineName",
            "WithThreadId"
        ],
        "Destructure": [
            {
                "Name": "ToMaximumDepth",
                "Args": {
                    "maximumDestructuringDepth": 4
                }
            },
            {
                "Name": "ToMaximumStringLength",
                "Args": {
                    "maximumStringLength": 100
                }
            },
            {
                "Name": "ToMaximumCollectionCount",
                "Args": {
                    "maximumCollectionCount": 10
                }
            }
        ],
        "Properties": {
            "Application": "Registry"
        }
    }
}

initialize.sql:
----
CREATE USER 'registry'@'%' IDENTIFIED BY 'hahano';
GRANT USAGE ON *.* TO 'registry'@'%';
FLUSH PRIVILEGES;

CREATE DATABASE `RegistryData` /*!40100 COLLATE 'latin1_general_ci' */;
CREATE DATABASE `RegistryAuth` /*!40100 COLLATE 'latin1_general_ci' */;
CREATE DATABASE `RegistryHangfire` /*!40100 COLLATE 'latin1_general_ci' */;

GRANT 
    EXECUTE, SELECT, SHOW VIEW, ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, INDEX, INSERT, REFERENCES, TRIGGER, UPDATE, LOCK TABLES 
    ON `RegistryAuth`.* TO 'registry'@'%' WITH GRANT OPTION;
GRANT 
    EXECUTE, SELECT, SHOW VIEW, ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, INDEX, INSERT, REFERENCES, TRIGGER, UPDATE, LOCK TABLES 
    ON `RegistryData`.* TO 'registry'@'%' WITH GRANT OPTION;
GRANT 
    EXECUTE, SELECT, SHOW VIEW, ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, INDEX, INSERT, REFERENCES, TRIGGER, UPDATE, LOCK TABLES 
    ON `RegistryHangfire`.* TO 'registry'@'%' WITH GRANT OPTION;

FLUSH PRIVILEGES;

Events:  <none>

Hope that helps!

ETA: I think I’ve tracked down the right part of the ASP .Net core code. Somewhere in this block, things exit.

Mm, I’m not too familiar with Kubernetes unfortunately, so I’m not sure. I think you might have more chances of getting a reply here though (Hedo88TH who developed most of Registry’s codebase checks for messages there): Discussions · DroneDB/DroneDB · GitHub

1 Like

For those who are curious, here’s what I was doing wrong with my setup:

  • I had one deployment with the db and registry. For the default configuration to work, the db needed to be in its own deployment with its own service.
  • The external URL override was required to get past the next issue, which was the website not properly showing the datasets.

I now have my own instance of DroneDB talking to my own instance of WebODM. Woo!

3 Likes

Woohoo!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.