2
votes

I have a PlayFramework (play-scala) application that I want to run in a cluster. So I might have several docker containers of this application image running. I don't know the IP addresses of these ahead of time, as the cloud services provider can start and stop them dynamically,so I cannot specify seed nodes. Also, all of the application.conf files should be the same fore each instance of the application?

How do I configure the play application to enable each instance of the application to discover and join the Akka cluster?

I have looked at: https://www.playframework.com/documentation/2.7.x/ScalaAkka#Akka-Cluster Akka cluster setup with play framework https://github.com/lregnier/play-akka-cluster-aws

Do I have to use Akka Cluster Bootstrap since I cannot specify seed nodes?

Is it enough to have the following in the application.conf file (taken from Cluster Usage:

akka {
  actor {
    provider = "cluster"
  }
  remote {
    log-remote-lifecycle-events = off
    netty.tcp {
      hostname = "127.0.0.1"
      port = 0
    }
  }

  cluster {
    seed-nodes = [
      "akka.tcp://[email protected]:2551",
      "akka.tcp://[email protected]:2552"]

    # auto downing is NOT safe for production deployments.
    # you may want to use it during development, read more about it in the docs.
    #
    # auto-down-unreachable-after = 10s
  }
}

But without the seed nodes? If so, how do node discover and join the cluster?

1

1 Answers

2
votes

Given the requirement, the best option might be to use Akka Cluster Bootstrap. To run container-based services, service discovery using AWS ECS or Kubernetes is probably closer to your need.

Akka Cluster Bootstrap addresses your need of not having pre-assigned seed nodes by means of an automatic cluster bootstrap mechanism. Each of the nodes probes each others through their exposed HTTP endpoints and if no seed nodes exist (i.e. no existing cluster), the node with the "lowest" address will make itself a seed node prompting other nodes to join the newly formed cluster. For more details, see this Akka doc re: cluster bootstrap.

As described in the Akka doc, Akka Cluster Bootstrap depends on modules Akka Discovery and Akka Management:

libraryDependencies ++= Seq(
  "com.lightbend.akka.management" %% "akka-management-cluster-bootstrap" % "1.0.1",
  "com.typesafe.akka" %% "akka-discovery" % "2.5.21"
)

For service discovery using ECS, assign aws-api-ecs or aws-api-ecs-async (for non-blocking IO) to akka.discovery.method in application.conf which might look something like the following:

akka {
  cluster {
    seed-nodes = []
    seed-nodes = ${?SEED_NODES}
  }
  # ...
  management {
    cluster.bootstrap {
      contact-point-discovery {
        required-contact-point-nr = 2
        required-contact-point-nr = ${?REQUIRED_CONTACT_POINTS}
      }
    }
    # ...
  }
  discovery {
    method = aws-api-ecs-async
    aws-api-ecs-async {
      cluster = "my-ecs-cluster"
    }
  }
}

For service discovery using Kubernetes, akka.discovery.method should be assigned kubernetes-api in application.conf which might look like below:

akka {
  cluster {
    seed-nodes = []
    seed-nodes = ${?SEED_NODES}
  }
  # ...
  management {
    cluster.bootstrap {
      contact-point-discovery {
        required-contact-point-nr = 2
        required-contact-point-nr = ${?REQUIRED_CONTACT_POINTS}
      }
    }
    # ...
  }
  discovery {
    method = kubernetes-api
    kubernetes-api {
      pod-namespace = "default"
      pod-namespace = ${?K8S_NAMESPACE}
      pod-label-selector = "app=akka-cluster"
      pod-label-selector = ${?K8S_SELECTOR}
      pod-port-name = "cluster-mgmt-port"
      pod-port-name = ${?K8S_MANAGEMENT_PORT}
    }
  }
}