Если вы активно используете контейнеры в своей повседневной жизни, вам однозначно стоит взглянуть на CoreOS. Эта ОС работает абсолютно во всех самых распространенных облаках (EC2, Rackspace, GCE, Облаке КРОК), платформах виртуализации (Vagrant, VMware, OpenStack, QEMU / KVM), а также голом железе (PXE, iPXE, ISO, Installer). С помощью любого из этих руководств всего за несколько минут у вас получится запустить свои контейнеры в специально предназначенной для них ОС.

Я настоятельно рекомендую устанавливать CoreOS не менее чем на 3 виртуальных сервера, чтобы сразу получить представление о том, как организовать кластер для ваших контейнеров. Для правильного запуска и последующей работы вашего кластера необходимо всего лишь правильно заполнить cloud-config при помощи пользовательских данных (user-data). Правильный cloud-config приводится в руководстве по запуску CoreOS для каждой платформы или Облака.

При использовании CoreOS вы получаете в свое распоряжение три основных инструмента: обнаружение сервисов (service discovery), управление контейнерами (container management) и управление процессами (process management).

За каждую из этих задач в CoreOS отвечает отдельный демон:

  • etcd — для обнаружения сервисов
  • Docker — для управления контейнерами
  • Fleet — для управление процессами

Далее я расскажу о каждом из них чуть подробнее, а пока запустим небольшой кластер.

Запуск CoreOS в Облаке КРОК

Т.к. для AWS, GCP, Rackspace или DigitalOcean уже выпущено достаточно много различных руководств детально описывающих процесс запуска, я расскажу о том, как запустить CoreOS в Облаке КРОК.

Предлагаю вам скачать и разархивировать стабильный образ CoreOS для OpenStack.

$ wget https://stable.release.core-os.net/amd64-usr/current/coreos_production_openstack_image.img.bz2
$ bunzip2 coreos_production_openstack_image.img.bz2

Загрузите полученный образ в наше объектное Файловое хранилище

Образ CoreOS в CROC S3

Создайте собственный шаблон на базе этого образа для запуска ваших виртуальных машин. Для этого необходимо выбрать загруженный вами образ и открыть диалог «Создать шаблон»

Задайте название для вашего шаблона, например, «CoreOS Stable» и нажмите на кнопку «Создать шаблон»

Через несколько минут можно будет воспользоваться вашим шаблоном.

Для получения токена etcd для вашего кластера CoreOS, перейдите по ссылке https://discovery.etcd.io/new?size=3.

Запустите 3 виртуальных сервера, нужного вам размера, указав в диалоге создания экземпляра виртуальной машины в поле «Пользовательские данные» следующий конфиг:

#cloud-config

coreos:
etcd2:
# generate a new token for each unique cluster from https://discovery.etcd.io/new?size=3
# specify the initial size of your cluster with ?size=X
discovery: https://discovery.etcd.io/c41cda8c66f2198faa4f27f4d9d9cc27
# multi-region and multi-cloud deployments need to use $public_ipv4
advertise-client-urls: http://$private_ipv4:2379,http://$private_ipv4:4001
initial-advertise-peer-urls: http://$private_ipv4:2380
# listen on both the official ports and the legacy ports
# legacy ports can be omitted if your application doesn't depend on them
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
listen-peer-urls: http://$private_ipv4:2380
units:
- name: etcd2.service
command: start
- name: fleet.service
command: start
ssh_authorized_keys:
- ssh-rsa AAAA...

Предварительно замените в нем в значение параметра discovery: на URL, полученный вами при переходе по ссылке https://discovery.etcd.io/new?size=3, а также значение укажите ваш публичный SSH-ключ в строчке - ssh-rsa.

Созданный вами шаблон будет доступен в списке «Собственные шаблоны»

Пример заполнения пользовательских данных

После запуска ваших виртуальных серверов, подключиться к любому из них можно будет следующим образом:

$ ssh core@c2.public.ip

Проверьте состояние кластера следующей командой:

$ etcdctl cluster-health
member e14dcba44c7da9b2 is healthy: got healthy result from http://192.168.2.13:2379
member e8baaa0420d6fd08 is healthy: got healthy result from http://192.168.2.14:2379
member f77be20fe67d8e1f is healthy: got healthy result from http://192.168.2.12:2379

Поздравляю, ваш минимальный кластер CoreOS запущен.

Обнаружения сервисов при помощи etcd

Основным строительным блоком для контейнерных приложений является служба обнаружения сервисов. В кластере CoreOS за эту задачу отвечает etcd (документация). По сути etcd — это распределенное хранилище пар ключ-значение, доступное по HTTP. Обычно в него записываются данные, которыми необходимо обмениваться контейнерам вашего приложения, чтобы знать что-то друг о друге. Например, backend-ы могут записывать в etcd свои IP-адреса, которые затем могут переодически вычитываться сервисом обновления конфигурации балансировщика nginx или haproxy. Использование etcd в качестве службы обнаружения сервисов позволяет вам автоматически масштабировать ваши контейнеры горизонтально.

Если вы запускали ваш кластер используя инструкции выше, etcd будет запущен и настроен на всех ваших серверах автоматически.

Для работы с etcd используется утилита etcdctl. Для записи значения «CROC Cloud» для ключа /message выполните команду:

$ etcdctl set /message "CROC Cloud"
CROC Cloud

Прочитать это значение ключа /message можно с любого узла вашего кластера командой:

$ etcdctl get /message
CROC Cloud

Для этих же операций вы можете использовать curl. Для установки значения:

$ curl -L http://127.0.0.1:2379/v2/keys/message -XPUT -d value="CROC Cloud"
"action":"set","node":"key":"/message","value":"CROC Cloud","modifiedIndex":175334,"createdIndex":175334,"prevNode":"key":"/message","value":"CROC Cloud","modifiedIndex":175208,"createdIndex":175208

Для получения

$ curl -L http://127.0.0.1:2379/v2/keys/message
"action":"get","node":"key":"/message","value":"CROC Cloud","modifiedIndex":175334,"createdIndex":175334

Управление контейнерами при помощи Docker

Второй строительный блок CoreOS — это Docker (документация), который обеспечивает возможность запуска контейнеров ваших приложений. Он установлен по умолчанию на каждой машине CoreOS. Основная идея запуска микросервисных приложений в CoreOS заключается в том, что вы упаковываете каждый из своих сервисов (веб-сервер, кеш, база данных и т.д.) в отдельный контейнер и соединяете их вместе при помощи etcd.

Работа с Docker в CoreOS осуществляется точно так же как и в других Linux дистрибутивах.

Управление процессами при помощи fleet

Третий строительный блок CoreOS — это fleet, распределенная система инициализации для вашего кластера. Fleet используется для управления жизненным циклом контейнеров Docker.

Fleet работает, получая на вход unit файлы systemd. Каждый сервис далее планируется на одном или нескольких узлах вашего в кластера на основе указанных зависимостей и других настроек, определенных в unit файле. Используя fleetctl, вы можете запрашивать статус unit-а, удаленно получать доступ к его логам и т.д.

В качестве примера давайте создадим и запустим простой systemd unit, который будет запускать контейнер Docker. Создайте в вашей домашней директории на одном из узлов кластера файл croc.service со следующим содержанием:

[Unit]
Description=CROC Example Service
After=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill croc_service
ExecStartPre=-/usr/bin/docker rm croc_service
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name croc_service busybox /bin/sh -c "trap 'exit 0' INT TERM; while true; do echo CROC Cloud; sleep 1; done"
ExecStop=/usr/bin/docker stop croc_service

Более подробно о том, как работает systemd в CoreOS можно прочитать в документации Getting Started with systemd. А сейчас я всего лишь скажу, что данный unit настраивает запуск сервиса с именем croc_service на основе Docker образа busybox, заставляя последний запуститься и печатать на стандартный поток вывода сообщение «CROC Cloud».

Для загрузки и старта этого сервиса выполните команды

$ fleetctl load croc.service
Unit croc.service inactive
Unit croc.service loaded on 27435eb0.../192.168.2.14
$ fleetctl start croc.service
Unit croc.service launched on 27435eb0.../192.168.2.14

Контейнер с вышеописанной задачей запустился где-то в вашем кластере. Проверить статус его работы можно командой:

$ fleetctl status croc.service
● croc.service - CROC Example Service
Loaded: loaded (/run/fleet/units/croc.service; linked-runtime; vendor preset: disabled)
Active: active (running) since Mon 2017-04-10 12:48:30 UTC; 6s ago
Process: 1051 ExecStartPre=/usr/bin/docker pull busybox (code=exited, status=0/SUCCESS)
Process: 1045 ExecStartPre=/usr/bin/docker rm croc_service (code=exited, status=0/SUCCESS)
Main PID: 1060 (docker)
Tasks: 5
Memory: 4.1M
CPU: 48ms
CGroup: /system.slice/croc.service
└─1060 /usr/bin/docker run --name croc_service busybox /bin/sh -c trap 'exit 0' INT TERM; while true; do echo CROC Cloud; sleep 1; done

Apr 10 12:48:30 i-4155a060 docker[1051]: Digest: sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f
Apr 10 12:48:30 i-4155a060 docker[1051]: Status: Image is up to date for busybox:latest
Apr 10 12:48:30 i-4155a060 systemd[1]: Started CROC Example Service.
Apr 10 12:48:30 i-4155a060 docker[1060]: CROC Cloud
Apr 10 12:48:31 i-4155a060 docker[1060]: CROC Cloud
Apr 10 12:48:32 i-4155a060 docker[1060]: CROC Cloud
Apr 10 12:48:33 i-4155a060 docker[1060]: CROC Cloud
Apr 10 12:48:34 i-4155a060 docker[1060]: CROC Cloud
Apr 10 12:48:35 i-4155a060 docker[1060]: CROC Cloud
Apr 10 12:48:36 i-4155a060 docker[1060]: CROC Cloud

Для остановки сервиса выполните команду

$ fleetctl stop croc.service
Unit croc.service loaded on 27435eb0.../192.168.2.14
$ fleetctl status croc.service
● croc.service - CROC Example Service
Loaded: loaded (/run/fleet/units/croc.service; linked-runtime; vendor preset: disabled)
Active: inactive (dead)

Apr 10 12:50:32 i-4155a060 docker[1385]: CROC Cloud
Apr 10 12:50:33 i-4155a060 docker[1385]: CROC Cloud
Apr 10 12:50:34 i-4155a060 docker[1385]: CROC Cloud
Apr 10 12:50:35 i-4155a060 docker[1385]: CROC Cloud
Apr 10 12:50:36 i-4155a060 docker[1385]: CROC Cloud
Apr 10 12:50:37 i-4155a060 docker[1385]: CROC Cloud
Apr 10 12:50:38 i-4155a060 docker[1385]: CROC Cloud
Apr 10 12:50:39 i-4155a060 systemd[1]: Stopping CROC Example Service...
Apr 10 12:50:40 i-4155a060 docker[1482]: croc_service
Apr 10 12:50:40 i-4155a060 systemd[1]: Stopped CROC Example Service.

Для удаления сервиса необходимо выполнить команду

$ fleetctl destroy croc.service
Destroyed croc.service
$ fleetctl status croc.service
Unit croc.service does not exist.