Контейнеры являются одной из основных тенденций в размещении приложений в общедоступных и частных облаках. Но что такое контейнеры, почему они стали популярным механизмом размещения, и как нужно изменить приложения, чтобы оптимизировать их для контейнерной среды?
Что такое контейнеры?
Технологии, лежащие в основе контейнеров, имеют долгую историю, начиная с SELinux в 2000 году и Solaris zones в 2005. Контейнеры сегодня – это комбинация характеристик нескольких базовых компонентов, включая SELinux, Linux namespaces и контрольные группы, обеспечивающие изоляцию процессов конечных пользователей, сети и пространства файловой системы.
Почему контейнеры пользуются таким успехом?
Недавнее широкое внедрение контейнеров происходит в основном за счет разработки стандартов, направленных на упрощение их использования, например, docker image (или образ) и модель распределения. Этот стандарт требует использования неизменяемых образов, которые являются отправной точкой для загрузки контейнера. Неизменяемый образ гарантирует, что выпущенный командой разработчиков образ является тем самым, что был протестирован и внедрен в производственную среду.
Легкая изоляция, предоставляемая контейнерами, создает лучшую абстрактность для компонента приложения. Действующие компоненты в контейнерах не будут прерывать работу друг друга, т.к. они могут работать непосредственно с виртуальной «машиной».
Также, компоненты можно лишить возможности забирать друг у друга системные ресурсы, и, если они не используют постоянный объем, не будет блокироваться попытка записи в одни и те же файлы.
Контейнеры помогли стандартизировать такие практики, как регистрация данных и метрические коллекции, и они позволяют увеличить плотность многопользовательских транзакций на физических и виртуальных машинах, и все это приводит к снижению затрат на развертывание.
Как вам создать подготовленное к контейнеру приложение?
Преобразование приложения под его работу внутри контейнера не является обязательным условием. Основные дитсрибутивы Linux имеют базовые образы, которые могут запускать все, что работает на виртуальной машине. Но общей тенденцией в контейнерных приложениях является следование нескольким отличным методам:
- Шаблоны являются одноразовыми
Любой шаблон вашего приложения не должен нуждаться в осторожной работе. Если система, управляющая несколькими контейнерами, перестает работать, Вы захотите привести в действие новые контейнеры, разбросанные в других доступных системах.
- Повторное выполнение операции вместо сбоя
При зависимости одного сервиса приложения от другого, один из них не должен давать сбой, если второй находится вне доступа. Например, API сервис запускается и обнаруживает, что база данных находится вне доступа. Вместо падения и отказа запуска, вы проектируете его повторное подключение. Во время отсутствия связи базы данных, API выдает код ошибки 503, сообщая клиенту о том, что сервис недоступен в данный момент. Приложения уже должны следовать данному указанию, но, если вы работаете в контейнерной среде, в которой шаблоны являются одноразовыми, необходимость в этом очевидна.
- Постоянные данные – имеют специальную направленность
Запуск контейнеров основан на совместных образах, используя файловую систему копирования при записи (COW). Если процессы, работающие в контейнере, записывают в файлы, тогда эти записи будут существовать столько же, сколько и контейнер. При удалении контейнера, удаляется и тот уровень в файловой системе COW. Направляя контейнер по установленному пути файловой системы, который будет сохранен после окончания срока службы контейнера, необходимо учитывать, что для его физического хранения потребуются дополнительные настройки и затраты. Четкое определение абстракции, для которой хранение является постоянным, выдвигает идею о том, что шаблоны являются одноразовыми. Наличие абстрактного уровня дает возможность механизму согласования контейнера справиться с тонкостями монтирования и демонтирования постоянных объемов для контейнеров, нуждающихся в них.
- Использование stdout лог-файлов.
Вы, должно быть, думаете, что если постоянные данные являются особенными, тогда для чего нужны log файлы? Подход предпринятого проекта по работе и согласованию контейнера заключается в том, что процессы должны писать в stdout/stderr и использовать инфраструктуру для архивирования и регистрации данных контейнера.
- Скрытые данные (и другие настройки) тоже очень важны.
Не следует жестко кодировать в образах такие скрытые данные, как пароли, ключи и сертификаты. Скрытые данные обычно не являются такими же, когда ваше приложение идет в службы разработки, проверки или производства. Большинство разработчиков не имеют доступ к скрытым данным продукции, поэтому если они введены в образ, нужно создать новый уровень образа, который заблокирует скрытые данные разработки. С этого момента, вы используете не тот образ, который был создан вашей командой разработчиков и протестирован высококачественной технологией (QE). Более того, данный образ теряет преимущество постоянных образов. Вместо этого, данные ценности должны быть абстрагированы в показатели среды или в файлы, введенные в запуск контейнера.
- Не допускайте совместное размещение сервисов
В согласованной среде контейнера вы хотите, что бы организатор отправлял вам контейнеры в соответствии с узлом, лучше всего подходящим в данный момент. Быть наиболее подходящим означает несколько моментов: в основе данного понятия может лежать узел, который обладает в данный момент наибольшей используемой памятью; качество службы, необходимое контейнеру; необходимы ли контейнеру постоянные объемы и т.д. Это может также означать, что ваши frontend, API и база данных в контейнере принимают на себя разные узлы. Хотя возможно принудить API работать на каждом узле (см. DaemonSets в Kubernetes), однако лучше сохранить его для контейнеров, выполняющих такие задачи, как мониторинг самих узлов.
- Планирование избыточности / высокой доступности.
Даже если вам не хватает нагрузки для требования на установку в HA режиме, не следует записывать сервис так, что потом вы не сможете запустить несколько его копий. Данное действие позволит использовать скользящее внедрение, упрощающее передачу данных с одного узла, на другой или улучшение версии сервиса без простоя.
- Реализация проверки готовности и жизнеспособности.
Часто приложения запускаются до того, как они смогут ответить на запросы, например, сервер API, которому нужно заполнить кэш в памяти данных. Механизму согласования контейнера необходим способ проверить, готов ли контейнер обслуживать запросы. Предоставление проверки готовности для новых контейнеров позволяет скользящему внедрению поддерживать работу старого контейнера до истечения его надобности, предотвращая простой. Подобно этому, проверка жизнеспособности – это способ механизма согласования продолжать проверку контейнеров на нормальное функционирование. Решение, что для контейнера означает нормально функционировать или быть «живым», остается за разработчиком приложения. Нефункционирующий контейнер будет удален, а на его месте создан новый.
Хотите узнать больше о контейнерах и использовать их, обращайтесь в контакты.
About The Author
Виктор Карабедянц
ИТ директор (CIO), руководитель нескольких DevOps команд. Профессиональный руководитель проектов по внедрению, поддержке ИТ систем и обслуживанию пользователей.