neiam
/diogramos
diogramos
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
moar
6c31c2e · gmorell · 2026-04-28 01:00
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