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!

First 10 of 12 Posts Switch mode

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

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
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
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
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New

We're in Beta

About us Mission Statement