Информация актуальна где-то на конец июля.
Вынесу сюда краткое summary по исследованию существующих систем оркестрации в формате “плюсы и минусы”, сделанному мной на стажировке в Экспресс42. В статью не вошла связка Mesos+Marathon, т.к. ее ставил не я, но остальное вроде все охватил. Статейка больше для себя, чтоб иметь краткое описание систем в одном месте.
Fleet
Fleet очень круто сделан идеологически - ты работаешь с целым кластером как с обычной системой, описывая обычные, в общем-то, юнит-файлы для systemd. В части эксплуатации лишних сущностей минимум, все они скрыты под капотом, под который лезть приходится не очень часто. Но с другой стороны, эта скрытость вызывает проблемы с пониманием логики системы, когда тебе надо не просто бездумно шлепать по мануалу, а делать что-то свое. Также, fleet бедноват на средства работы со сложными системами, у него урезанные зависимости, нет иерархий, окружений.
- Есть constraints (как на уровне “запусти на ноде с такими-то свойствами”, так и на уровне “запусти/не запускай сервис2 на ноде с сервис1”)
- Нет healthchecks ни в каком виде
- Есть нормальный DNS Service Discovery, хоть и за счет внешних сервисов
- Удобный способ описания всего кластера в одном файле cloud-init
- Зависимости есть, но в очень урезанном виде: они работают только в пределах одной ноды. То есть мы можем запустить Сервис2 после Сервиса1, но только если оба этих сервиса запущены на одной ноде. Более сложные зависимости будут “когда-нибудь”
- Есть изолированная оверлейная сеть, с которой легко вытащить контейнер наружу, при желании (через
--net=host
) - Поддерживается все множество docker-команд в юнитах
- По файлу на сервис. Намного удобнее, чем отслеживать изменения в огромном файле на несколько сотен строк.
- Сложно делать blue-green потому что сложно развернуть две инфраструктуры в пределах одного кластера. Неудобно делать partial deploy
- Зато rolling довольно безопасен за счет большого количества стадий. Хотя средств отката я не увидел, придется какой-то внешней системой назад катить
- Простой синтаксис. Ребята не изобретали свой формат, а взяли обычный systemd синтаксис.
Nomad
В Nomad есть то, чего нет в Docker - описание инфраструктуры в едином файле, healthchecks в том же описании, dry-run, но зато не хватает всего остального: нет нормальной работы ни с сетью, ни с персистентными данными. Для эксплуатации в наших условиях как-то совсем не годится.
- Важно: до сих пор нет поддержки Docker volumes! - https://github.com/hashicorp/nomad/issues/150 https://github.com/hashicorp/nomad/issues/62
- Важно: Номад не рестартит контейнеры с проваленными healthcheck. Просто помечает их в консуле как failed, но не перезапускает - https://github.com/hashicorp/nomad/issues/876
- Нельзя рестартануть таску через nomad cli. Надо идти на слейв и прибивать контейнер руками.
- Файл получается довольно объемный из-за JSON-подобного синтаксиса. Скобки-скобки-скобки. Но вполне читаемый.
- Номад не умеет в зависимости между сервисами, когда-нибудь обещают сделать - https://github.com/hashicorp/nomad/issues/419
- Номад не умеет биндить порты на все интерфейсы или на какой-то определенный для контейнера. Только на тот, который указан в параметре
network_interface
конфига слейва. Обещают пофиксить когда-нибудь - https://github.com/hashicorp/nomad/issues/646 - Зато healthcheck’и можно описывать прямо тут, что удобно. Поддерживаются http, tcp и script чеки.
- Некрасивые DNS-имена. Мало того что надо извращаться с dnsmasq/bind для того чтобы пробросить DNS консула на 53 порт, так еще и имена получаются некрасивые, по типу
datastore-zookeeper.service.consul
, вместо более цивильныхzookeeper.datastore.service.consul
- Можно передавать данные о private registry прямо в самом файле, удобно.
- Нет способов исключить повторяемость кода. Надо тебе передавать одни и те же переменные в 10 разных контейнеров - дублируй код 10 раз.
- Nomad умеет обновлять джобу через скармливание ему новой версии hcl-файла, при этом обновляя контейнеры с заданными интервалами и параллелизмом.
- Поддерживается dry-run режим запуска джобы.
Kubernetes
Kubernetes очень крутой, но документация, особенно для такой объемной и сложной системы, просто ужасна. Мануалы часто неактуальны, некоторые вещи вообще в ней отсутствуют и приходится рыться в огромных обсуждениях на Github. А так - в нем есть почти все, хоть и местами через жопу.
- Есть constraints, healthchecks, DNS Service Discovery, scaling, autoscaling, single tasks, rolling updates, кофеварка и триммер для волос в носу;
- Есть cli утилита, которая может работать через TLS;
- Есть какие-то политики безопасности, но я их не трогал. Вроде как можно авторизовать пользователей по ключу и позволять им разное;
- Есть богатые возможности по определению своих метаданных для сервисов/подов/и т.д. Очень удобно в больших инфраструктурах;
- Есть API, документировано тоже не прям супер;
- Есть красивенький Dashboard
- Нет cron tasks, но есть четкий milestone, когда их запилят - в следующей версии
- Удобный способ описания всего кластера в одном файле cloud-init
- Удобный способ дистрибуции всего кластерного добра в контейнере, все развертывание сводится к указанию этому контейнеру нужных ключей
- Есть изолированная оверлейная сеть, с которой можно вытащить контейнер наружу, при желании через load balancer
- Есть поддержка распределенных/сетевых ФС из коробки;
- По умолчанию все довольно сильно изолировано, как на уровне namespace’ов, так и вообще by design. С другой стороны - зато сложновато взаимодействие сервисов настраивать;
- Очень много сущностей на всех уровнях. Kubectl имеет довольно длинные команды (хотя есть completions). Искренне не понимаю, зачем нужно было городить 4 сущности: Pod, Service, ReplicaSet, Deployment там, где другие системы обходятся одной;
- Как следствие из предыдущего - очень многословные yaml-файлы. Описание 4 сервисов у меня заняло 300 строк там, где в Swarm можно было бы обойтись 4 командами;
- Помимо количества сущностей, они еще и плохо документированы. Ладно бы еще документация местами отсутствовала и приходилось лезть на Github, так она просто неправильная и неактуальная. Ты видишь мануал на официальном сайте, который призван решить твою проблему, а он неточный и устаревший. В итоге ты убиваешь кучу времени на этот мануал, а потом все равно в итоге лезешь на Github.
Swarm
Мне оркестрация от Docker’а очень понравилась. Реально не хватает только описания инфраструктуры как кода где-нибудь в одном файле, с зависимостями и переменными. А так: кластер развертывается быстро, никаких непонятных дополнительных сущностей, есть приватные сети, есть общие сети, есть балансировка, скейлинг, constraints, вот это вот все. Учитывая темпы развития Docker - все скоро будет совсем хорошо.
Aurora
-
Aurora не умеет запускать несколько джобов с зависимостями между ними (например, запусти zk, как только он запустится - запусти kafka и т.д.). Одновременно, впрочем, она тоже не умеет их запускать, только по одному за раз. http://mail-archives.apache.org/mod_mbox/aurora-user/201602.mbox/%3CEE9100CC-04FF-4C64-B479-D3DF68D8C0BE%40lensa.com%3E - тут и далее по треду предлагают городить свои скрипты или использовать что-то вроде Chronos или Airflow.
-
constraints работают на уровне параметра attributes mesos-slave. Т.е. определяем на слейве какие-то атрибуты и потом можем сказать авроре - запускай такой-то джоб только на слейве с таким-то атрибутом.
-
Healthchecks есть, http и shell, но я их не тестил еще.
-
Максимальное количество failures, timeout между попытками перезапуска есть.
-
Внутри aurora-файла полноценный питон, можно определять какие-то структуры, подсовывать их в таски, стрелять себе в ногу из револьвера, ружья, дробовика, пулемета. Мне оказалось удобно определить dict со всеми параметрами в шапке файла и обращаться к нему по ходу дела.
-
Целиком игнорируются ENV, ENTRYPOINT и COMMAND докерфайла. С одной стороны это плюс, можно один и тот же контейнер переиспользовать для разных тасок, плюс в ряде случаев можно обойтись и без пересборки контейнеров. С другой стороны - приходится все эти переменные и команды вытаскивать из докерфайла в аврорафайл, получается что-то вроде:
postgres_proc = env_proc(
name="postgres_daemon",
cmdline="""
export PGDATA='/pgdata'
export PG_MAJOR='9.3'
export PG_VERSION='9.3.13-1.pgdg80+1'
export PATH="/usr/lib/postgresql/$PG_MAJOR/bin:$PATH"
/docker-entrypoint.sh postgres
"""
-
Есть cronjobs, services (long-running jobs) и обычные “одноразовые” джобы. С учетом предыдущего пункта все три вида можно построить на базе одного контейнера, переопределяя
cmdline
. -
Через aurora-cli можно логиниться прямо в контейнер джобы и чего-нибудь херачить там руками.