Я уже кратко упоминал о том, что в июльском релизе в Nutanix появилась фича, которую мы назвали Acropolis Container Services, и первое ее применение — поддержка инфраструктуры Docker на кластере Nutanix, в нашем собственно бесплатном гипервизоре AHV (Acropolis Hypervisor, форк и глубокая модификация KVM).
О том, что такое Docker я рассказывать не буду, на Хабре есть хорошая статья. А то, почему Nutanix занялся контейнерной виртуализацией лучше тысячи слов скажет одна картинка, которую я, пока писал эту статью, сделал в Google Trends.



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

Дело в том, что то, что после пары дней экспериментов и разборок работает для Test/Dev, крайне капризно при переносе в серьезный продакшн. И прежде всего это проблема со stateless data containers.

У новичков, знакомящихся с Docker, и раздумываюших о практическом применении контейнерной виртуализации «в бою», сразу возникает целая куча вопросов к Docker (и Docker-гуру):

  • Как обеспечить персистентность данных при использовании контейнеров?
  • Куда писать логи всех моих контейнеров?
  • Как развернуть образ Docker на сотни машин?
  • Как быстро откатиться, если очередной push на эти машины был неудачен?
  • Что с автоматическими билдами и тестами в контейнерах?
  • Как обеспечить взаимодействие между контейнерами?
  • Как собирать метрики приложений в контейнерах?

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

В отличие от уже привычных большинству «виртуальных машин», контейнеры являются transient объектами, равно как и хранилища, к ним относящиеся. При перезагрузке контейнера Docker вы теряете все данные, которые были изменены в ранее запущенном контейнере.
Почему это так — связано с тем, как архитектура Docker спроектирована. В основе его лежит так называемая «12-факторность», паттерн разработки, первоначально появившийся в Heroku, бывшем одном из первых PaaS-провайдеров. Эта схема декларирует, что состояние приложения должно находиться отдельно от самого приложения, в отдельном хранилище. Это отлично работает для front-end приложений, которым не проблема потерять свой state, так как они stateless по природе, но вот для остальных тут есть серьезная сложность. Как быть с логами приложений, с кэшем веб-сервера или ключами SSH?
Как совместно использовать данные между разными контейнерами, или между хостом и контейнерами?

Обычно во всех таких случаях принято применять сторонние монтируемые в контейнер дисковые тома, расположенные на хосте. Но в этом случае контейнеры становятся зависимыми от работы хоста, и, потенциально создается Single Point of Failure, так как потеря хоста автоматически означает потерю данных в примонтированном с этого хоста томе для всех использующих его приложений в контейнерах. Контейнеры-то перезапустить не проблема, а вот том с данными на хосте будет потерян.

Также следует помнить, что дисковая производительность ввода-вывода в контейнер довольно низкая, поэтому сам Docker рекомендует для высокопроизводительных приложений использовать тома (Volumes).
По умолчанию, контейнеры используют UnionFS, чтобы реализовать copy-on-write поведение для данных, то, что позволяет нам использовать git-подобное поведение для наших изменений в контейнере. Однако, если нам нужно получить максимальную производительность дискового ввода-вывода для приложений, и персистентность хранения данных, независимо от контейнера, вам нужно использовать Docker Volume.

Начиная с версии 1.8 в Docker появилась концепция volume plugin, с помощью которого можно осуществить взаимодействие между Docker и API хранилища. Это была первая попытка организовать интеграцию между Docker и хранилищем, но реализовано было все крайне спартански. Начиная с версии 1.9 появились так называемые named volumes, с которыми появилась возможность взаимодействовать с томами как отдельными именованными сущностями, вместо того, чтобы управлять ими изнутри контейнера.

Используя эти новые возможности Nutanix написал средства, позволяющие более удобно использовать системы Nutanix в качестве платформы для инфраструктуры Docker и вообще «контейнерной виртуализации» в боевом продакшне.

Для этого были созданы:

Docker Machine Driver – это инструмент «провижнинга», который позволяет создавать хосты Docker на вашем локальном компьютере, у облачного провайдера, или внутри вашего собственного датацентра. Он создает серверы, устанавливает на них Docker Engine и конфигурирует Docker client для работы с ними. The Docker Machine support enable end-users (both administrators and developers) to provision Docker engine on AHV VMs, and manage the VMs with docker-machine cli commands.

Docker Volume Plugin – позволяет средствам развертывания Docker Engine интегрироваться с внешней системой хранения и создавать персистентные тома для данных приложений.

Ну и раз уж тут ниже мы его упоминаем и используем:
Docker Datacenter (UCP) — это решение управления от Docker, позволяющее с помощью volume plugin пользователям использовать Nutanix DSF в качестве Persistent Storage.
В версии Acropolis OS 4.7 управление контейнерами реализовано пока только через CLI, но в релизе «Asterix» (4.8) оно будет интегрировано в Prism GUI.

Теперь у нас появилась возможность обеспечить высокодоступные, удобно монтируемые хранилища для контейнеров, которые расположены отдельно от контейнеров и хостов docker.

Начиная с версии Acrpolis OS 4.7 в DSF (Distributed Storage Fabric, наша распределенная кластерная файловая система, ранее мы называли ее NDFS) появилась поддержка этих перечисленных выше механизмов Docker.

Nutanix Acropolis DSF Volume driver написан на Go, и работает как Docker Volume extension. Он действует как промежуточный Sidekick-контейнер. Nutanix Acropolis DSF Volume plugin пробрасывает линк к DSF через механизм iSCSI Volume Groups, который обеспечивает доступ из контейнера в том DSF минуя гипервизор, и устраняя оверхеды доступа.



Следствием этого является то, что даже теряя контейнер или хост, вы не теряете доступ к данным тома. Более того, так как мы соблюдаем принцип data locality, при перемещении контейнера, вслед за ним переместятся по кластеру Nutanix и его данные.
Все перечисленное есть полностью нативная реализация на нашей платформе, не требующее сторонних решений.

Используя для развертывания инфраструктуры Docker платформу Nutanix с Acropolis DSF Volume plugin for Docker и Docker Machine Driver вы получаете нативную интеграцию платформы Nutanix с Docker API, вы можете воспользоваться всеми преимуществами хранения данных в хранилище Nutanix, такими как прозрачныq тиринг, дедупликация, компрессия, снэпшоты для данных, репликация, как синхронная, так и асинхронная. Вы получаете высочайшую производительность дисковых операций ввода-вывода для ваших приложений.
Наконец, что немаловажно, все это устанавливается и работает быстро и просто, включая поддержку нашими силами онлайн-техподдержки.

Вот как это работает в виде небольшого десятиминутного скринкаста (не забудьте включить HD в настройках Youtube!):



Кстати не исключено, что вы сможете попробовать это вживую уже на Nutanix CE.
Поделиться с друзьями
-->

Комментарии (3)


  1. SchmeL
    29.07.2016 11:20

    При перезагрузке контейнера Docker вы теряете все данные, которые были изменены в ранее запущенном контейнере.

    Это заблуждение — данные никуда не денутся, они останутся в последнем слое, полное их удаление произойдет если вручную удалить контейнер.
    Конечно, это не отменяет хранение важных данных вне контейнера на продакшене. Но в тестовой среде, у нас даже БД хранятся в контейнерах.


    1. shapa
      30.07.2016 17:46

      Мы вообще-то дословно пишем о продакшене. Неаккуратно читали статью? :)

      «Дело в том, что то, что после пары дней экспериментов и разборок работает для Test/Dev, крайне капризно при переносе в серьезный продакшн. И прежде всего это проблема со stateless data containers.»


  1. SchmeL
    01.08.2016 00:29

    Я именно прицепился к фразе

    При перезагрузке контейнера Docker вы теряете все данные, которые были изменены в ранее запущенном контейнере.

    Так как данное утверждение в корне не верно! Данные остаются в RW слое, даже после остановки и перезапуска контейнера.