Что такое CoreOS?
CoreOS — это операционная система на базе Linux для построения легко и гибко масштабируемых кластеров. CoreOS — минималистичный дистрибутив. Установочный ISO образ объемом всего в 136Мб, а в памяти на конечной машине после установки и запуска она займет всего 114Мб. CoreOS основан на ChromeOS, который в свою очередь базируется на Gentoo.
Фактически, CoreOS можно условно можно разделить на следующие части:
- Systemd — управляет локальными службами на машинах кластера
- Docker — обеспечивает изоляцию служб, но его использование, в принципе, не обязательно
- Etcd — распределенно хранит конфигурацию кластера
- Fleet — обеспечивает распределенное управление службами («надстройка» над systemd)
CoreOS умеет запускать службы systemd на нужных машинах кластера, следить за их состоянием, хранить их конфигурацию.
Systemd
В CoreOS используется обычный systemd, который сейчас можно встретить во многих дистрибутивах Linux. Это система локального управления Linux-службами.
Docker
О Docker уже не раз писали на Хабре. Если коротко и по-простому — Docker берет ядро хостовой операционной системы Linux, монтирует к нему указанный вами образ файловой системы и позволяет работать внутри этого образа как будто вы находитесь в виртуализованном окружении.
Обратите внимание, что Docker не использует виртуализацию. Для изоляции процессов используются cgroups и namespaces, что позволяет избавиться от довольно серьезного оверхеда, который дают такие инструменты как KVM. Конечно, Docker можно использовать и на Mac и на Windows, но в этом случае хостовая операционная система должна будет работать внутри VirtualBox или любой другой системы виртуализации, поскольку Docker для работы необходимо ядро Linux (см. Boot2Docker)
Etcd
Etcd — распределенное Key-Value хранилище, которое запускается на каждой машине кластера CoreOS и обеспечивает общий доступ практически ко всем данным в масштабе всего кластера. Внутри etcd хранятся настройки служб, их текущие состояние, конфигурация самого кластера и т.д. Etcd позволяет хранить данные иерархически (хранилище древовидно), подписываться на изменения ключей или целых директорий, задавать для ключей и директорий ключей значения TTL (фактически, «экспирить» их), атомарно изменять или удалять ключи, упорядоченно хранить их (что позволяет реализовывать своеобразные очереди). Поскольку конфигурация сервисов, запущенных в масштабе кластера, хранится в etcd, узнать о запуске и остановке того или иного сервиса можно просто подписавшись на изменения соответствующих ключей в хранилище.
Etcd поддерживает REST HTTP интерфейс, поэтому для работы с ним достаточно curl. Из командной строки в CoreOS управляется с помощью утилиты etcdctl.
Fleet
Fleet — это «надстройка» над systemd, которая переносит управление службами с локальной машины на уровень кластера. Fleet хранит конфигурацию служб в виде юнитов systemd (в etcd), автоматически доставляет ее на локальные машины, запускает, перезапускает (при необходимости), останавливает службы на машинах кластера. Fleet умеет планировать запуск служб исходя из загруженности конкретных машин кластера. Ему можно сказать, что конкретную службу нужно запускать только на определенных машинах и т.д.
CoreOS — это очень просто
Для того, чтобы запустить службу hello в кластере CoreOS, нужно всего-навсего сделать следующее:
1. Зайти на любой из серверов кластера по SSH (они все равноправны)
2. Создать текстовый файл с описанием службы. Например, hello.service:
[Unit]
Description=My Service
After=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill hello
ExecStartPre=-/usr/bin/docker rm hello
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name hello busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"
ExecStop=/usr/bin/docker stop hello
3. Выполнить следующие команды:
fleetctl submit hello.service
fleetctl load hello.service
fleetctl start hello.service
4. Все! Получив последнюю команду, fleet, поскольку мы не дали ему никаких инструкций на этот счет, опеределит наименее загруженную машину кластера, возьмет наш юнит-файл, передаст его на выбранную машину, поместит туда, где systemd хранит свои службы и попросит systemd его запустить. А после запуска будет мониторить состояние. Если машина, на которой исполнялась служба, неожиданно «упадет», fleet перезапустит нашу службу на другой машине.
Рассмотрим наш пример поподробнее.
Файл конфигурации службы:
[Unit]
# Текстовое описание службы
Description=My Service
# Служба запускается только после старта службы docker.service
After=docker.service
[Service]
# Ждать старта службы бесконечное количество времени
# Полезно в том случае, если docker не обнаружит образа локально и начнет его скачивать
TimeoutStartSec=0
# Перед запуском службы последовательно выполнить указанные команды.
# Минус перед именем файла указывает на то, что код возврата команды можно проигнорировать.
ExecStartPre=-/usr/bin/docker kill hello
ExecStartPre=-/usr/bin/docker rm hello
# А тут код возврата игнорировать не нужно и если docker вернет ненулевой результат
# fleet поймет, что службу запустить не удалось и сообщит об этом
ExecStartPre=/usr/bin/docker pull busybox
# Это команда запуска службы. Мы просто выполняем бесконечный цикл Bash.
ExecStart=/usr/bin/docker run --name hello busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"
# Это команда остановки службы
ExecStop=/usr/bin/docker stop hello
Команды, которые необходимо выполнить:
# Читаем файл конфигурации службы с диска и помещаем его в хранилище для дальнейшей работы
fleetctl submit hello.service
# Определяем, на какой машине запустить службу и помещаем файл конфигурации в хранилище локального systemd на этой машине
fleetctl load hello.service
# Запускаем службу
fleetctl start hello.service
Посмотреть состояние служб можно командой fleetctl list-unit-files (короткая сводка по всем службам) либо fleetctl status hello.service (подробная информация о службе).
Установка CoreOS
CoreOS можно установить различными способами. Но если вы решили поэкспериментировать, рекомендую установку через Vagrant.
1. Установите Git, VirtualBox, затем Vagrant последних версий.
1а. Либо выполните в какой-нибудь папке git clone github.com/coreos/coreos-vagrant.git && cd coreos-vagrant
1б. Либо, если Git вам скачивать не захотелось, распакуйте куда-нибудь вот это.
2. Зайдите в папку, переименуйте там файл user-data.sample в user-data, config.rb.sample в config.rb. Зайдите на discovery.etcd.io/new, скопируйте в буфер появившийся URL, раскомментируйте строчку с инструкцией discovery в user-data и замените там URL.
3. Зайдите в папку и выполните там vagrant up
4. Дождитесь скачивания базового образа.
5. Выполните vagrant ssh.
Вы внутри :)
Ограничения, слабые стороны и неожиданности CoreOS
CoreOS не обеспечивает ничего, кроме того, что обеспечивает :) Иными словами, «из коробки», она не умеет ничего, кроме того, что мы обсудили. И, если вы собираетесь строить кластеры на базе CoreOS, вы столкнетесь как минимум со следующими проблемами:
Пакетный менеджер и обновления
В CoreOS отсутствует пакетный менеджер. И какая-либо система сборки или установки дополнительного ПО тоже (если не считать wget и curl :) ). В качестве альтернативы могу предложить использовать интегрированный toolbox контейнер Docker. Для его активации просто выполните /usr/bin/toolbox из командной строки. Будет запущен привилегированный контейнер с Fedora, где есть доступ к yum.
Обновления CoreOS выполняются для ОС целиком с помощью системы активных/пассивных разделов. Фактически, системных разделов в CoreOS два. Активен в каждый момент только один из них. Обновление всей ОС устанавливается на второй, после чего выполняется перезагрузка и смена активного раздела. Операционная система обновляется только целиком. Соответственно, достаточно легко можно выполнить откат к предыдущей версии ОС. Если вы, как и я ;), уже захотели заиметь пакетный менеджер в CoreOS из коробки, прочтите Developer Documentation.
Обнаружение служб
«Фишка» CoreOS в том, что она легко переносит службы между машинами кластера, самостоятельно останавливая и запуская их. Грубо говоря, это значит, что ваш веб-сервер, изначально запущенный на машине X, через пять минут может легко оказаться на машине Y, у которой совсем другой IP адрес во внутренней сети. Конечно, с помощью специальных инструкций для Fleet вы можете легко «приковать» сервис к конкретной машине, но… тогда зачем вам вообще CoreOS? :) Это создает проблему разрешения IP адресов для ваших служб. В принципе, достаточно легко запросить etcd и узнать, на какой машине сейчас выполняется служба. Но совсем автоматически этого не произойдет. Service Discovery вопрос достаточно серьезный и для его решения предлагается огромное количество ПО, из которого мне наиболее импонирует SkyDNS. Использовать SkyDNS можно с помощью sidekick-юнитов.
Персистентность контейнеров и данные как таковые
Если вы заметили, CoreOS фактически строится вокруг stateless docker-контейнеров, которые легко перенести на другую машину и там запустить. Действительно, довольно-таки легко контейнеризировать скажем, nginx и php-fpm. Файлы конфигурации для них тоже можно распространять в виде контейнера. Даже исходный код вашего приложения можно распространять в виде data-volume (это docker-контейнер, который содержит только данные) и подключать к различным службам. А что прикажете делать с базами данных?
Выходов несколько. Во-первых, сервисы вроде Flocker, которые мигрируют контейнеры с данными вслед за контейнерами со службами, которые эти данные используют. Во-вторых, запускать СУБД-подобные сервисы в режиме кластера. NoSQL решения умеют это очень хорошо, реляционные — заметно хуже, но все равно это возможно. В-третьих, можно поднять в рамках кластера любую распределенную файловую систему вроде GlusterFS или Ceph. Однако, подобное решение нужно оценить в точки зрения быстродействия. Эти вопросы обсуждались здесь.
Заключение
CoreOS сейчас переживает, не побоюсь этих слов, взрывной рост. Как и Docker, в общем-то. Количество различных проектов для CoreOS увеличивается с каждым днем. Так что, если сейчас вам чего-то не хватает для решения конкретной задачи, завтра эта возможность уже может появиться.
В рамках проекта CoreOS сейчас развивается альтернативный стандарт контейнеризациии Rocket. Однако… пока, видимо, лучше использовать Docker. Тем более, что CoreOS не собирается в будущем отказываться от Docker.
Что почитать?
Разумеется, можно почитать документацию. Однако мне больше всего понравился цикл статей на Digital Ocean о CoreOS. Собственно говоря, на его основе и под его влиянием и была написана данная статья :)