Статьи

Акка Кластер с контейнерами Docker

Эта статья покажет вам, как создавать образы докеров, которые содержат одно кластерное приложение akka. Вы сможете запустить несколько начальных узлов и несколько узлов кластера. Код можно найти на Github и будет доступен как активатор Typesafe .

Если вы не знаете, докер или Акка

Докер — новая блестящая звезда в мире Devops. Он позволяет легко развертывать образы в любой операционной системе, в которой запущен Docker, обеспечивая при этом изолированную среду для приложений, работающих внутри образа контейнера.

Akka — это структура для создания параллельных, отказоустойчивых, распределенных и масштабируемых программных систем. Функция кластера позволяет распределять ваши актеры по нескольким компьютерам для достижения балансировки нагрузки, переключения при сбое и возможности масштабирования и уменьшения.

Большая картина

Вот как будет выглядеть запущенное приложение. Независимо от того, где ваши докеры будут работать в конце дня. Числа в левом верхнем углу описывают порядок запуска контейнеров.

Акка-докер-BigPicture

Сначала вы должны запустить свои начальные узлы, которые будут «склеивать» кластер вместе. После запуска первого узла все последующие начальные узлы должны знать IP-адрес начального начального узла, чтобы создать единый кластер. Описанный в этой статье подход очень прост, но легко настраивается, поэтому его можно использовать с другими технологиями предоставления, такими как chef, puppet или zookeeper.

Все последующие узлы, которые запускаются, нуждаются по крайней мере в одном seed-node-ip для присоединения к кластеру.

Конфигурация приложения

Мы развернем небольшое приложение akka, которое регистрирует только события кластера. Точка входа довольно проста:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
object Main extends App {
  
  val nodeConfig = NodeConfig parse args
  
  // If a config could be parsed - start the system
  nodeConfig map { c =>
    val system = ActorSystem(c.clusterName, c.config)
  
    // Register a monitor actor for demo purposes
    system.actorOf(Props[MonitorActor], "cluster-monitor")
  
    system.log info s"ActorSystem ${system.name} started successfully"
  }
  
}

Сложной частью является конфигурация. Во-первых, для конфигурации akka.remote.netty.tcp.hostname необходимо указать IP-адрес докера. Конфигурация порта не важна, так как у нас есть уникальный IP-адрес благодаря докеру. Вы можете прочитать больше о сети докеров здесь . Во-вторых, начальные узлы должны добавить себя в список akka.cluster.seed-node . И наконец, все должно быть настраиваемо с помощью системных свойств и переменных среды. Благодаря библиотеке Typesafe Config это достижимо (даже с небольшим количеством пота и слез).

  1. Сгенерируйте небольшой анализатор командной строки с помощью scopt и следующих двух параметров:
    –Seed флаг, который определяет, должен ли запуск этого узла действовать как начальный узел
    ([ip]: [port])… неограниченный список [ip]: [port], которые представляют начальные узлы
  2. Разделить конфигурацию на три файла
    1. application.conf, который содержит общую конфигурацию
    2. node.cluster.conf содержит только конкретную конфигурацию узла
    3. node.seed.conf содержит только специфическую для семенного узла конфигурацию
  3. Класс NodeConfig, который управляет всеми настройками и параметрами cli в правильном порядке и создает объект Typesafe Config.

Присмотритесь к классу NodeConfig . Основная часть такова:

01
02
03
04
05
06
07
08
09
10
// seed nodes as generated string from cli
(ConfigFactory parseString seedNodesString)
  // the hostname
  .withValue("clustering.ip", ipValue)
  // node.cluster.conf or node.seed.conf
  .withFallback(ConfigFactory parseResources configPath)
  // default ConfigFactory.load but unresolved
  .withFallback(config)
  // try to resolve all placeholders (clustering.ip and clustering.port)
  .resolve

Часть для определения IP-адреса немного хакерская, но должна работать в средах докера по умолчанию. Сначала ищется интерфейс eth0, а затем возвращается первый isSiteLocalAddress . IP-адреса в следующих диапазонах являются локальными : 172.16.xxx.xxx, 172.31.xxx.xxx, 192.168.xxx.xxx, 10.xxx.xxx.xxx.

Основная конфигурация кластера выполняется внутри секции кластеризации application.conf :

1
2
3
4
5
clustering {
  # ip = "127.0.0.1" # will be set from the outside or automatically
  port = 2551
  cluster.name = "application"
}

IP-адрес будет заполнен описанным выше алгоритмом, если ничего не установлено. Вы можете легко переопределить все настройки с помощью системных свойств. Например, если вы хотите запустить начальный узел и узел кластера внутри вашей IDE без докера, запустите оба варианта так:

1
2
3
4
# the seed node
-Dclustering.port=2551 -Dclustering.ip=127.0.0.1 --seed
# the cluster node
-Dclustering.port=2552 -Dclustering.ip=127.0.0.1 127.0.0.1:2551

Для SBT это выглядит так:

1
2
3
4
# the seed node
sbt runSeed
# the cluster node
sbt runNode

Сборка

Далее мы создаем наш образ докера. Плагин sbt-native-packager недавно добавил экспериментальную поддержку докера , поэтому нам нужно только настроить нашу сборку так, чтобы она была готова к докеру. Сначала добавьте плагин в ваш plugins.sbt .

1
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.7.4")

Теперь мы добавим несколько обязательных настроек в наш build.sbt . Вы должны использовать SBT 0,13,5 или выше.

1
2
3
4
5
6
7
8
// adds start script and jar mappings
packageArchetype.java_application
  
// the docker maintainer. You could scope this to "in Docker"
maintainer := "Nepomuk Seiler"
  
// Short package description
packageSummary := s"Akka ${version.value} Server"

И теперь мы настроены. Запустите sbt и запустите docker: publishLocal, и для вас будет создан образ docker. Dockerfile находится в target / docker, если вы хотите поближе взглянуть на то, что создано.

Запуск кластера

Теперь пришло время запустить наши контейнеры. Имя изображения по умолчанию имя: версия . Для нашего активатора это akka-docker: 2.3.4 . IP-адреса семян могут отличаться. Вы можете прочитать его из вывода консоли ваших начальных узлов.

1
2
3
4
docker run -i -t -p 2551:2551 akka-docker:2.3.4 --seed
docker run -i -t -p 2551:2551 akka-docker:2.3.4 --seed 176.16.0.18:2551
docker run -i -t -p 2551:2551 akka-docker:2.3.4 176.16.0.18:2551 176.16.0.19:2551
docker run -i -t -p 2551:2551 akka-docker:2.3.4 176.16.0.18:2551 176.16.0.19:2551

Как насчет ссылок?

Эта запись блога описывает другой подход к созданию кластера akka с помощью Docker. Я использовал некоторые из идей, но основная концепция заключается в компоновке соединения докера. Это позволяет вам получить информацию о ip и порте запущенных начальных узлов. Хотя этот подход подходит для компьютеров с одним хостом, он кажется более беспорядочным при работе с несколькими док-машинами.

Настройка в этом блоге требует только одного: центрального способа назначения IP-адресов хоста. Если ваши начальные узлы не меняют свои IP-адреса, вы можете настроить практически все, что уже есть в вашем application.conf.

Ссылка: Кластер Akka с контейнерами Docker от нашего партнера JCG Непомука Сайлера в блоге mukis.de .