moar

6c31c2e · gmorell · 2026-04-28 01:00

10 files +85 -15

Files changed

modified app.yml
+38 −5
@@ -3,6 +3,39 @@ kind: Namespace
3 3 metadata:
4 4 name: diogramos
5 5 ---
6 +# RBAC for libcluster's Kubernetes strategy. The ServiceAccount on the
7 +# pod gets read-only access to its own namespace's pods so it can
8 +# discover peer node IPs.
9 +apiVersion: v1
10 +kind: ServiceAccount
11 +metadata:
12 + name: diogramos
13 + namespace: diogramos
14 +---
15 +apiVersion: rbac.authorization.k8s.io/v1
16 +kind: Role
17 +metadata:
18 + name: diogramos-pod-reader
19 + namespace: diogramos
20 +rules:
21 + - apiGroups: [""]
22 + resources: ["pods"]
23 + verbs: ["get", "list", "watch"]
24 +---
25 +apiVersion: rbac.authorization.k8s.io/v1
26 +kind: RoleBinding
27 +metadata:
28 + name: diogramos-pod-reader
29 + namespace: diogramos
30 +roleRef:
31 + apiGroup: rbac.authorization.k8s.io
32 + kind: Role
33 + name: diogramos-pod-reader
34 +subjects:
35 + - kind: ServiceAccount
36 + name: diogramos
37 + namespace: diogramos
38 +---
6 39 apiVersion: apps/v1
7 40 kind: Deployment
8 41 metadata:
@@ -27,6 +60,7 @@ spec:
27 60 labels:
28 61 name: diogramos
29 62 spec:
63 + serviceAccountName: diogramos
30 64 containers:
31 65 - image: r.g.gmp.io/neiam/diogramos:latest
32 66 imagePullPolicy: Always
@@ -43,15 +77,14 @@ spec:
43 77 - name: POOL_SIZE
44 78 value: "10"
45 79
46 − # Cluster glue: every pod becomes diogramos@<pod-ip>, joins
47 − # via DNS query against the headless service below, and
48 − # shares Authority registry state through Horde.
80 + # Cluster glue: every pod becomes diogramos@<pod-ip>.
81 + # libcluster (Cluster.Strategy.Kubernetes) discovers peers
82 + # via the K8s API (RBAC defined above) and Horde rides on
83 + # top to keep the Authority registry coherent.
49 84 - name: POD_IP
50 85 valueFrom:
51 86 fieldRef:
52 87 fieldPath: status.podIP
53 − - name: DNS_CLUSTER_QUERY
54 − value: diogramos-headless.diogramos.svc.cluster.local
55 88 - name: RELEASE_COOKIE
56 89 valueFrom:
57 90 secretKeyRef:
modified config/config.exs
+18 −0
@@ -92,6 +92,24 @@ config :sentry,
92 92 root_source_code_paths: [File.cwd!()],
93 93 environment_name: Mix.env()
94 94
95 +# libcluster — uses the Kubernetes plugin to find peer pods via the API
96 +# and form an Erlang cluster. RBAC for the diogramos ServiceAccount is
97 +# defined in app.yml. In dev/test the topology is empty, so no clustering
98 +# happens locally.
99 +config :libcluster,
100 + topologies: [
101 + diogramos: [
102 + strategy: Cluster.Strategy.Kubernetes,
103 + config: [
104 + mode: :ip,
105 + kubernetes_node_basename: "diogramos",
106 + kubernetes_selector: "name=diogramos",
107 + kubernetes_namespace: "diogramos",
108 + polling_interval: 10_000
109 + ]
110 + ]
111 + ]
112 +
95 113 # Import environment specific config. This must remain at the bottom
96 114 # of this file so it overrides the configuration defined above.
97 115 import_config "#{config_env()}.exs"
modified config/dev.exs
+3 −0
@@ -11,6 +11,9 @@ config :diogramos, Diogramos.Repo,
11 11 pool_size: 10,
12 12 port: 54329
13 13
14 +# No clustering in local dev.
15 +config :libcluster, topologies: []
16 +
14 17 # For development, we disable any cache and enable
15 18 # debugging and code reloading.
16 19 #
modified config/test.exs
+3 −0
@@ -29,6 +29,9 @@ config :diogramos, DiogramosWeb.Endpoint,
29 29 # flow flip this back via Application.put_env/3 and then restore it.
30 30 config :diogramos, :registration_open, true
31 31
32 +# Disable libcluster in test — we don't try to talk to the k8s API.
33 +config :libcluster, topologies: []
34 +
32 35 # In test we don't send emails
33 36 config :diogramos, Diogramos.Mailer, adapter: Swoosh.Adapters.Test
34 37
modified lib/diogramos/application.ex
+20 −9
@@ -12,15 +12,20 @@ defmodule Diogramos.Application do
12 12 config: %{metadata: [:file, :line]}
13 13 })
14 14
15 − children = [
16 − DiogramosWeb.Telemetry,
17 − Diogramos.Repo,
18 − {DNSCluster, query: Application.get_env(:diogramos, :dns_cluster_query) || :ignore},
19 − {Phoenix.PubSub, name: Diogramos.PubSub},
20 − Diogramos.Diagrams.Authority,
21 − DiogramosWeb.Presence,
22 − DiogramosWeb.Endpoint
23 − ]
15 + topologies = Application.get_env(:libcluster, :topologies, [])
16 +
17 + children =
18 + [
19 + DiogramosWeb.Telemetry,
20 + Diogramos.Repo
21 + ] ++
22 + cluster_children(topologies) ++
23 + [
24 + {Phoenix.PubSub, name: Diogramos.PubSub},
25 + Diogramos.Diagrams.Authority,
26 + DiogramosWeb.Presence,
27 + DiogramosWeb.Endpoint
28 + ]
24 29
25 30 # See https://hexdocs.pm/elixir/Supervisor.html
26 31 # for other strategies and supported options
@@ -35,4 +40,10 @@ defmodule Diogramos.Application do
35 40 DiogramosWeb.Endpoint.config_change(changed, removed)
36 41 :ok
37 42 end
43 +
44 + defp cluster_children([]), do: []
45 +
46 + defp cluster_children(topologies) do
47 + [{Cluster.Supervisor, [topologies, [name: Diogramos.ClusterSupervisor]]}]
48 + end
38 49 end
modified mix.exs
+2 −1
@@ -69,7 +69,8 @@ defmodule Diogramos.MixProject do
69 69 {:bandit, "~> 1.5"},
70 70 {:sentry, "~> 10.0"},
71 71 {:hackney, "~> 1.20"},
72 − {:horde, "~> 0.9.0"}
72 + {:horde, "~> 0.9.0"},
73 + {:libcluster, "~> 3.4"}
73 74 ]
74 75 end
75 76
modified mix.lock
+1 −0
@@ -24,6 +24,7 @@
24 24 "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
25 25 "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
26 26 "lazy_html": {:hex, :lazy_html, "0.1.11", "136c8e9cd616b4f4e9c1562daa683880891120b759606dc4c3b6b18058ba5d79", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "3b1be592929c31eca1a21673d25696e5c14cddfe922d9d1a3e3b48be4163883b"},
27 + "libcluster": {:hex, :libcluster, "3.5.0", "5ee4cfde4bdf32b2fef271e33ce3241e89509f4344f6c6a8d4069937484866ba", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.3", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebf6561fcedd765a4cd43b4b8c04b1c87f4177b5fb3cbdfe40a780499d72f743"},
27 28 "libring": {:hex, :libring, "1.7.0", "4f245d2f1476cd7ed8f03740f6431acba815401e40299208c7f5c640e1883bda", [:mix], [], "hexpm", "070e3593cb572e04f2c8470dd0c119bc1817a7a0a7f88229f43cf0345268ec42"},
28 29 "merkle_map": {:hex, :merkle_map, "0.2.2", "f36ff730cca1f2658e317a3c73406f50bbf5ac8aff54cf837d7ca2069a6e251c", [:mix], [], "hexpm", "383107f0503f230ac9175e0631647c424efd027e89ea65ab5ea12eeb54257aaf"},
29 30 "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},

Parents: 8c257f3