Skip to content

Commit 021311f

Browse files
committed
chore: libcluster config
Adds libcluster configs to scale edgehog horizontally. This allows edgehog to manage the workload among different replicas for - campaign execution - notifications - reconciliation tasks New environment vairables have been introduced, to allow different edgehog nodes to see eachother based on the deployment strategy. - `EDGEHOG_CLUSTERING_STRATEGY`: one of `none`, `docker-compose` or `kubernetes`. This chooses the strategy edgehog will use to lookup other nodes in the cluster. - `EDGEHOG_CLUSTERING_KUBERNETES_SELECTOR`: The endpoint label to get other edgehog instances. This defaults to `app=edgehog`. - `EDGEHOG_CLUSTERING_KUBERNETES_NAMESPACE` the kubernetes namespace to find other edgehog instances. This defaults to `edgehog`. Signed-off-by: Luca Zaninotto <luca.zaninotto@secomind.com>
1 parent 2f21d87 commit 021311f

File tree

5 files changed

+124
-0
lines changed

5 files changed

+124
-0
lines changed

REUSE.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,9 @@ path = ".github/CODEOWNERS"
8686
precedence = "aggregate"
8787
SPDX-FileCopyrightText = "2026 Seco Mind Srl"
8888
SPDX-License-Identifier = "Apache-2.0"
89+
90+
[[annotations]]
91+
path = "backend/rel/env.sh.eex"
92+
precedence = "aggregate"
93+
SPDX-FileCopyrightText = "2026 Seco Mind Srl"
94+
SPDX-License-Identifier = "Apache-2.0"

backend/lib/edgehog/application.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,15 @@ defmodule Edgehog.Application do
4545
Router.Helpers.astarte_trigger_url(Endpoint, :process_event, slug)
4646
end
4747

48+
clustering_opts = [Config.clustering_topologies!(), [name: Edgehog.Cluster.Supervisor]]
49+
4850
children = [
4951
# Prometheus metrics
5052
Edgehog.PromEx,
5153
# Start the Ecto repository
5254
Edgehog.Repo,
55+
# Clustering supervisor
56+
{Cluster.Supervisor, clustering_opts},
5357
# Start the Telemetry supervisor
5458
EdgehogWeb.Telemetry,
5559
# Start the PubSub system

backend/lib/edgehog/config.ex

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ defmodule Edgehog.Config do
2424
"""
2525
use Skogsra
2626

27+
alias Edgehog.Config.ClusteringStrategy
2728
alias Edgehog.Config.GeocodingProviders
2829
alias Edgehog.Config.GeolocationProviders
2930
alias Edgehog.Config.JWTPublicKeyPEMType
@@ -96,6 +97,26 @@ defmodule Edgehog.Config do
9697
type: GeocodingProviders,
9798
default: [GoogleGeocoding]
9899

100+
@envdoc "The Erlang cluster strategy to use. One of `none`, `kubernetes`, `docker-compose`. Defaults to `none`."
101+
app_env :clustering_strategy, :edgehog, :clustering_strategy,
102+
os_env: "EDGEHOG_CLUSTERING_STRATEGY",
103+
type: ClusteringStrategy,
104+
default: :none
105+
106+
@envdoc "The endpoint label to query to get other edgehog instances. Defaults to `app=edgehog`."
107+
app_env :edgehog_clustering_kubernetes_selector,
108+
:edgehog,
109+
:edgehog_clustering_kubernetes_selector,
110+
os_env: "EDGEHOG_CLUSTERING_KUBERNETES_SELECTOR",
111+
type: :binary,
112+
default: "app=edgehog"
113+
114+
@envdoc "The Kubernetes namespace to use when `kubernetes` Erlang clustering strategy is used. Defaults to `edgehog`."
115+
app_env :clustering_kubernetes_namespace, :edgehog, :clustering_kubernetes_namespace,
116+
os_env: "EDGEHOG_CLUSTERING_KUBERNETES_NAMESPACE",
117+
type: :binary,
118+
default: "edgehog"
119+
99120
@doc """
100121
Returns true if edgehog should use an ssl connection with the database.
101122
"""
@@ -190,4 +211,40 @@ defmodule Edgehog.Config do
190211
admin_jwk!()
191212
:ok
192213
end
214+
215+
@doc """
216+
The clustering topology to use. The topology sets up node discovery.
217+
"""
218+
def clustering_topologies! do
219+
case clustering_strategy!() do
220+
:none ->
221+
[]
222+
223+
:kubernetes ->
224+
[
225+
edgehog_k8s: [
226+
strategy: Cluster.Strategy.Kubernetes,
227+
config: [
228+
mode: :ip,
229+
kubernetes_node_basename: "edgehog",
230+
kubernetes_selector: edgehog_clustering_kubernetes_selector!(),
231+
kubernetes_namespace: clustering_kubernetes_namespace!(),
232+
polling_interval: 10_000
233+
]
234+
]
235+
]
236+
237+
:docker_compose ->
238+
[
239+
edgehog: [
240+
strategy: Cluster.Strategy.DNSPoll,
241+
config: [
242+
polling_interval: 5_000,
243+
query: "edgehog-backend",
244+
node_basename: "edgehog"
245+
]
246+
]
247+
]
248+
end
249+
end
193250
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#
2+
# This file is part of Edgehog.
3+
#
4+
# Copyright 2026 SECO Mind Srl
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
# SPDX-License-Identifier: Apache-2.0
19+
#
20+
21+
defmodule Edgehog.Config.ClusteringStrategy do
22+
@moduledoc """
23+
The clustering strategy that the node should use to discover other nodes.
24+
"""
25+
26+
use Skogsra.Type
27+
28+
@strategies [:none, :kubernetes, :docker_compose]
29+
@allowed_strategies ~w(none kubernetes docker-compose)
30+
@strategy_map @allowed_strategies |> Enum.zip(@strategies) |> Map.new()
31+
32+
@impl Skogsra.Type
33+
def cast(value) when is_binary(value) do
34+
Map.fetch(@strategy_map, value)
35+
end
36+
37+
@impl Skogsra.Type
38+
def cast(value) when value in @strategies do
39+
{:ok, value}
40+
end
41+
42+
@impl Skogsra.Type
43+
def cast(_) do
44+
:error
45+
end
46+
end

backend/rel/env.sh.eex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
3+
export RELEASE_DISTRIBUTION=name
4+
5+
if [ -z "$MY_POD_IP" ]
6+
then
7+
HOSTNAME=`hostname -i`
8+
export RELEASE_NODE="<%= @release.name %>@$HOSTNAME"
9+
else
10+
export RELEASE_NODE="<%= @release.name %>@$MY_POD_IP"
11+
fi

0 commit comments

Comments
 (0)