We hope you find this tutorial helpful. In addition to guides like this one, we provide simple cloud infrastructure for developers. Learn more →

Экосистема Docker: обзор контейнеризации

PostedJune 29, 2015 13.7k views Docker

Серия туториалов

Этот туториал является 2-ой частью из 5-ти в серии статей Экосистема Docker.

Введение

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

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

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

Краткая история контейнеризации в Linux

Контейнеризация и изолирование компонентов не новые концепции в мире вычислений. Некоторые Unix-подобные операционные системы используют "зрелые" контейнерные технологии уже более 10 лет.

Система LXC (Linux Containers) - основа последующих технологий контейнеризации - была добавлена в ядро Linux в 2008 году. LXC использует комбинацию таких функция ядра, как cgroups (позволяет изолировать и отслеживать использование ресурсов) и пространства имен (позволяют разделять группы так, чтобы они не могли "видеть" друг друга), для реализации легковесной изоляции процессов.

Docker, появившийся несколько позже, позиционировался, как инструмент для упрощения работы по созданию и управлению контейнерами. Изначально Docker использовал LXC в качестве драйвера исполнения по умолчанию (с тех пор для этих целей была разработана библиотека под названием libcontainer). Docker, не привнося большого количества новых идей, сделал контейнеры доступными для обычного разработчика и системного администратора путем упрощения процесса и стандартизации интерфейса. Это стимулировало возрождение интереса к контейнеризации среди разработчиков в Linux-мире.

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

Что привносит контейнеризация

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

Некоторые из наиболее заманчивых преимуществ перечислены ниже.

Абстрагирование хост-системы от контейнеризованных приложений

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

Простота масштабирования

Одним из преимуществ абстрагирования между операционной системой хоста и контейнерами является то, что при правильном проектировании приложения, масштабирование может быть простым и прямолинейным. Сервис-ориентированная архитектура (будет рассмотрена далее) в комбинации с контейнеризованными приложениями обеспечивает основу для лёгкого масштабирования.

Разработчик может запустить несколько контейнеров на своей рабочей машине, при этом та же система может быть горизонтально масштабирована, например, на тестовой площадке. Когда контейнеры запускаются в эксплуатацию (продакшн), они снова могут быть масштабированы.

Простота управления зависимостями и версиями приложения

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

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

Чрезвычайно легкие, изолированные среды выполнения

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

Совместно используемые слои

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

Возможность компоновки и предсказуемость

Docker-файлы позволяют пользователям задать конкретные действия, необходимые для создания нового образа контейнера. Это позволяет Вам задавать настройки среды исполнения так, как будто бы это код, при желании сохраняя эти настройки в системе контроля версий. Одинаковый Docker-файл, собранный в одном и том же окружении, всегда создаст идентичный образ контейнера.

Использование Docker-файлов для повторяемых, консистентных сборок (билдов)

Когда есть возможность создать образы контейнеров в интерактивном режиме, обычно лучше записать шаги конфигурации в Docker-файл. Docker-файлы это простые файлы сборки (build-файлы), которые описывают процесс создания образа контейнера с известной начальной точки.

Docker-файлы невероятно полезны и ими довольно легко начать пользоваться. Вот лишь некоторые из преимуществ, которые они предоставляют:

  • Простота работы с версиями: Docker-файлы могут быть сохранены в системе контроля версий для отслеживания изменений и "откатывания" ошибок.
  • Предсказуемость: Сборка образов из Docker-файла помогает избавиться от человеческих ошибок в процессе создания образов.
  • Контролируемость: Если Вы планируете делиться своим образом, обычно хорошим тоном является предоставление Docker-файла, который создает данный образ, чтобы другие пользователи могли проконтролировать процесс. Таким образом Вы, по сути, предоставляете историю предпринятых для построения образа шагов.
  • Гибкость: Создание образов из Docker-файла позволяет переопределить настройки, которые заданы по умолчанию в интерактивном режиме. Это значит, что Вам надо производить меньше действий, чтобы получить правильно функционирующий образ.

Docker-файлы являются отличным инструментом автоматизации построения образов контейнеров для создания повторяемого процесса их построения.

Архитектура контейнеризованных приложений

При проектировании приложений, которые будут разворачиваться в контейнерах, один из первых возникающих вопросов это архитектура приложения. Обычно, контейнеризованные приложения лучше всего работают при сервис-ориентированной архитектуре.

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

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

  • Они не должны полагаться на особенности хост-системы.
  • Каждый компонент должен предоставлять консистентный API, который пользователи могут использовать для доступа к сервису.
  • Каждый сервис должен принимать во внимание переменные окружения в процессе первоначальной настройки.
  • Данные приложения должны храниться вне контейнера на примонтированных томах или в отдельных контейнерах с данными.

Эти стратегии позволяют заменять или изменять каждый компонент независимо (до тех пор, пока поддерживается API). Они также фокусируются на горизонтальной масштабируемости, ввиду того, что каждый компонент может быть масштабирован в соответствии с выявленным узким местом.

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

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

Использование Docker-реестр (Docker Registry для управления контейнерами

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

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

Заключение

Docker обеспечивает фундаментальную основу, необходимую для распределённого развёртывания контейнеров. При помощи упаковки компонентов приложения в отдельные контейнеры, горизонтальное масштабирование становится просто задачей развертывания или остановки нескольких экземпляров каждого компонента. Docker предоставляет необходимые инструменты не только для построения контейнеров, но и для управления и разделения их с другими пользователями или хостами.

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

0 Comments

Creative Commons License