krisleech

krisleech

We are deploying an Elixir application to production for the first time (first ever Elixir app for me :tada:) and realised that we need to cluster the nodes because things like Quantum will run on every instance, with a cluster we can configure it to run on a single node.

We are using libcluster with the gossip strategy and it works locally.

We can start two iex sessions with different names and they form a cluster.

We can see the other nodes with Node.list().

However once deployed to AWS, whilst we can manually connect the nodes, they do not automatically connect.

In the logs we can see the gossip protocol heartbeat.

Given we can connect manually and we see the heartbeat are there other reasons this might be failing?

This is how we have things setup:

defmodule Shared.Application do
  use Application

  def start(_type, _args) do
    children =
      [
        {
          Cluster.Supervisor, 
          [
            cluster_topologies(), 
            [name: Shared.ClusterSupervisor]
          ]
        }
      ]

    opts = [strategy: :one_for_one, name: Shared.Supervisor]
    Supervisor.start_link(children, opts)
  end

  defp cluster_topologies do
    [
      gossip: [
        strategy: Cluster.Strategy.Gossip
      ]
    ]
  end
end

Any ideas much appreciated!

Showing Posts 1 to 10

Hermanverschooten

Hermanverschooten

I am doing something similar in dev, in production however I use a different strategy.
I have this in my runtime.exs:

  topology_hosts =
    System.get_env("PARTNERS") ||
      raise """
      environment variable PARTNERS is missing, no cluster will be active
      """
  config :gratwifi,
    topology: [
      ipc: [
        strategy: Cluster.Strategy.Epmd,
        config: [
          hosts: topology_hosts |> String.split(",") |> Enum.map(&String.to_atom/1)
        ]
      ]
    ]

And then in application.exs:

def start(_type, _args) do
    topologies = Application.get_env(:gratwifi, :topology)
...
children = 
  [
    ...
        {Cluster.Supervisor, [topologies, [name: GratWiFi.ClusterSupervisor]]},
    ...
  ]

The PARTNERS environment variable is set to a comma-separated list of all my nodes.

AND very important the access to the epmd port is restricted to these hosts on all my nodes.

LostKobrakai

LostKobrakai

The default for the gossip strategy is to use multicast, which is not necessarily supported by all networks as mentioned on later docs to what you linked: Cluster.Strategy.Gossip — libcluster v3.5.0

krisleech

krisleech OP

Thanks for the example, the reason for choosing the gossip strategy was that we didn’t want to statically maintain a list of node names. We are using AWS ECS and will be employing auto-scaling in the future. So new instances will be spun on on demand and need to connect to the cluster.

krisleech

krisleech OP

In the meantime I tried the libcluster_postgres strategy and this works both locally and on AWS.

It’s perhaps overkill given the cluster will not span multiple regions, so I’ll have a look at the suggestion from @LostKobrakai about multicast support and see if I can get gossip protocol to work.

krisleech

krisleech OP

Apparently AWS Fargate does not support UDP multicast or broadcast, I’ve not verified this for certain, but it certainly should explain why the Gossip protocol doesn’t work.

Hermanverschooten

Hermanverschooten

If al the nodes are resolvable through a single dns name, you could use DNSCluster.

albydarned

albydarned

Seeing the exact same with EC2 instances. Works locally, on AWS must be connected manually. Seems VPC just doesn’t support multicast. I only need a couple nodes right now, So I guess I could use Epmd for now. Would like this to just be automatic though. Postgres would probably work, but as you said seems like overkill.

What solution did you end up going with?

krisleech

krisleech OP

We are using libcluster_postgres.

The only thing I have noticed is that when we do a deploy (to ECS, Fargate) it spins up new nodes and they join the same cluster as the existing nodes (prior to them being terminated), so we get double sized cluster for a 10ish mins. We could change the cookie value to have two cluster’s during deployment, but we’ve not seen any issues with the current setup yet.

Also when the old nodes are said to be terminated in the AWS UI they actually aren’t for a few more minutes, you can still connect to them and see them as part of the cluster.

albydarned

albydarned

Interesting, thanks for sharing. Thats helpful to know how the cookies work. I’m running on EC2 machines. Using iex with --name and --cookie options, I can get each node to autoconnect using libcluster_postgres. Most reliable seems to be when i set --name equal to app@ However, making an elixir release seems like the --name is forcing itself to ip-. These then don’t autoconnect, even though I see the “connected to postgres” message from libcluster. I can always call Node.connect and it will work.

Did you run into anything simliar? I’ve even gotten to the point where using env.sh in the release directory to successfully get the ./app start_iex to show the correct app name with the IP. But, in release mode the same settings don’t autoconnect.

albydarned

albydarned

Just tried EPMD, and it works flawlessly with the local DNS names I set up inside of AWS. For some reason I just cannot get Gossip or Postgres to connect automatically when in release mode.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews