Single URL over application of several devices

Hey again :smiley: Sorry for the many questions!

I have searched in the documentation, but did not find anything relevant. If someone has a lot of devices attached to a Balena application and need to expose a single public URL for the whole application so that the incoming traffic would be spread to the devices, what would be the best approach?

I am trying to find something to direct me on what I should do, but I am not sure I am even searching it correctly, due to being new on this kind of stuff :slight_smile:

Thank you in advance :smiley:

Hey @pavlospt no need to be sorry. Please keep the questions coming : )

First of all, what is your end goal here?

Based on your previous post, I assume that you want to setup a load balancer. I’m not aware of any balena projects that showcase how one could build a load balancer. Though it definitely sounds interesting and useful.

I guess one could setup 2 applications to achieve this. The first application will have 1 device that redirects traffic to the devices in the second application. So you expose the public URL of this device in the first app. This first app will be also responsible for monitoring the load of the fleet in the second app. Though I’m talking naively here as I’m not an expert on this topic. This also doesn’t feel like something trivial to setup.

Perhaps you could look into HAProxy, It’s an open source load balancer that we internally use at balena.

I’ll ping couple of my teammates in case they’d like to chime in with more sensible approaches.

Thanks for the reply @gelbal! I was thinking about a setup K8s like where I can utilize my devices as “pods” and have a single URL exposed to talk to my service/application, without me needing to know which “pod” will finally handle this request.

Interesting use case @pavlospt. We don’t offer such functionality right now. I raised this topic for internal discussion to hear if we ever plan to support this use case. My teammates might followup.

Thank you for the insights @gelbal. Would definitely be interested to hear more opinions on the matter :smiley:

Hi @pavlospt,

I’ve been asked to step in here to see if I can help a bit more. I understand the concept, you’d essentially like some service discovery for balena devices for a single app like K8’s use of nginx (but not actually using K8).

There’s a few different scenarios that might occur here, a really fundamental question is “Are all the devices on the same network?”. This is important, because if they aren’t then this has extra ramifications for public accessibility of devices and also security issues. I’m going to assume all devices are on the same network, if this isn’t the case we can get into some potential solutions for other cases. Before we start, it’s important to note that currently, public URLs by default are insecure and support only HTTP (this is due to change in the future, however).

In this case, we’d have two applications:

  • LoadBalancer - An application with a public URL, where all traffic for the service arrives; a local ingress
  • Workers - The worker application, which contains all the devices which carry out the work depending on the request being processed

In this scenario, for the LoadBalancer application, I’d create a small app based on HAproxy (although obviously other load balancers exist :wink: ), which also runs a local endpoint called ‘/register’. This endpoint would be used by all devices in the Workers application to register with the LoadBalancer application to provide their services as a working backend.

For the LoadBalancer app:

  1. Create a Dockerfile that includes HAproxy
  2. Write a small listener service that exposes a ‘/register’ endpoint to the local network, which devices running the Worker application register with
  3. Broadcast the IP address of the LoadBalancer device across the local network so that Worker devices know the address and endpoint to register with
  4. Have the listener update the HAproxy configuration when a Worker device registers itself, using the IP address source and restart HAproxy

This would allow every Worker device to then register itself as a backend with the LoadBalancer application, and update the HAproxy config. You’d end up with a config looking something like:

# The frontend takes all the traffic from the public URL
frontend:
  ...
  default_backend workers

backend workers:
  ...
  server worker1 192.168.1.10 check port 80
  server worker2 192.168.1.11 check port 80
  ...

We add check port here as a very basic healthcheck to make sure that the device for the Worker application is working before we send traffic onto it. You can obviously change the config depending on how you want to schedule Worker devices and what healthchecks you might need.

This should be a pretty simple setup to get you going, although there may well be some code out there that does this kind of thing (I’ve not looked!), so it’s probably worth a search.

Obviously if your setup is different, get back to us and we can think about another way of approaching this!

Best regards,

Heds

Thank you very much for your answer @hedss. I think the proposed solution requires 2 applications at least, which in turn means at least 1 device per application. I will see if I can experiment with this approach and let you know :smiley: