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://ClusterSystem@127.0.0.1:2551",
"akka.tcp://ClusterSystem@127.0.0.1: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?
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}
}
}
}