Взрывной рост использования контейнеров на предприятиях впечатляет. Контейнеры идеально совпали с ожиданиями и потребностями тех, кто хочет снизить затраты, расширить свои технические возможности и продвинуться вперед по пути agile и devops. Контейнерная революция открывает новые возможности и для тех, кто подзадержался с обновлением ИТ-систем. Контейнеры и Kubernetes – это абсолютно и принципиально новый способ управления приложениями и ИТ-инфраструктурой.



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

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

Тем не менее, OpenShift – это не волшебная палочка, которая решает все проблемы сама. Да, благодаря своим возможностям, эта платформа способна принести – и приносит своим заказчикам – массу пользы и быстро окупается, но при условии, что на момент ее запуска у вас есть хорошо продуманный план. Чтобы добиться успеха, надо тщательно проработать семь областей, прежде чем приступать к переносу каких-либо рабочих нагрузок на OpenShift.

1. Стандартизация правил именования и метаданных


В компьютерных науках есть только две трудные вещи: аннулирование кэша и именование сущностей.
– Фил Карлтон (Phil Karlton)

У всякой сущности в OpenShift и Kubernetes есть свое имя. И у каждого сервиса должно быть свое DNS-имя, единственное ограничение здесь – правила именования DNS. А теперь представьте, что монолитное приложение разложилось на 100500 отдельных микросервисов, каждый с собственной базой данных. И да, в OpenShift всё является либо иерархическим, связанным, либо должно соответствовать шаблону. Так что именовать придется массу и массу всего. И если заранее не подготовить стандарты, это получится настоящий Дикий Запад.

Вы уже распланировали схему реализации сервисов? Допустим, это будет одно большое пространство имен, например, «databases», в котором все будут размещать свои базы данных. OK, и даже допустим, что все так и будут делать, но потом-то они начнут размещать свои кластеры Kafka в своих собственных пространствах имен. Да, а нужно ли заводить пространство имен «middleware»? Или лучше назвать его «messaging»? И как обычно, в какой-то момент появляются ребята, которые всегда идут своим путем и считают себя особенными, и говорят, что им нужны собственные пространства имен. И слушайте, у нас же в организации 17 подразделений, может надо приделать ко всем пространствам имен наши стандартные префиксы подразделений?

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

Другая мегаполезная вещь – это метаданные. Стандартизируйте, какие активы хотите отслеживать, и убедитесь, что на соответствующих ресурсах прописаны нужные метаданные. Начните с рекомендованных меток. Например, аннотация «support_email» в метаданных пространства имен может сэкономить драгоценное время при выходе на техподдержку второго уровня в случае серьезного отказа. Кроме того, метаданные можно использовать, чтобы сократить имена ресурсов до вменяемой длинны, а не прописывать туда всю необходимую информацию через дефис. Привлеките всех, от архитекторов приложений до ИТ-эксплуатантов, устройте мозговой штурм и просчитайте наперед, что может здесь понадобиться, чтобы иметь продуманные стандарты к моменту запуска OpenShift.

2. Стандартизация корпоративных базовых образов


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

Возьмем, к примеру, базовое java-приложение. Ваши разработчики вряд ли ошибутся с выбором OpenJDK, а вот с управлением уязвимостями, обновлением библиотек и прочими вопросами ИТ-гигиены – вполне могут. Мы все знаем, что бизнес-задачи зачастую решаются ценой технических компромиссов, вроде намеренного использования старых версий Java. К счастью, такие задачи легко автоматизируются и управляются на уровне предприятия. Вы по-прежнему может использовать базовые образы вендора, но одновременно задавать и контролировать свои циклы обновления, создавая собственные базовые образы.

Возвращаясь к примеру выше, допустим, разработчикам нужна Java 11, а вам, соответственно, надо, чтобы они всегда использовали самую последнюю версию Java 11. Тогда вы создаете корпоративный базовый образ (registry.yourcompany.io/java11), используя в качестве отправной точки базовый образ от вендора ОС (registry.redhat.io/ubi8/openjdk-11). А когда этот базовый образ обновляется, вы автоматом помогаете разработчикам задействовать последние обновления. К тому же, таким образом реализуется уровень абстракции, позволяющий бесшовно дополнять стандартный образ необходимыми библиотеками или Linux-пакетами.

3. Стандартизация проверок работоспособности и готовности


Контроль исправности, он нужен практически везде. Считается, что для человека достаточно ежегодного медосмотра. Исправность приложений надо проверять, понятно, гораздо чаще, и контролировать две ключевые вещи:

  • Запущено ли приложение (health check – работоспособность).
  • Готово ли приложение (readiness check – готовность).

Существует масса и других метрик, чтобы облегчить мониторинг приложений, но вот эти две – это основа основ не только мониторинга, но и масштабирования. Работоспособность обычно определяется наличием сетевого подключения и способностью узла, на котором выполняется приложение, отозваться на запрос. Что касается готовности, то здесь уже каждое приложение должно реагировать на запросы по своим стандартам. Например, запуск приложения с очень низкими задержками может сопровождаться длительным обновлением кэша или прогревом JVM. И соответственно, пауза между ответами «Запущено» и «Готово» может достигать нескольких минут. А вот, например, для stateless REST API с реляционной базой данных эти ответы будут приходить одновременно.

Самое главное в этих проверках – не отходить от сугубо двоичной логики. Запущено – значит запущено, без всяких там «как бы запущено». Готово – значит готово, и никаких градаций, вроде «на такие запросы готово отвечать, а на такие – нет». Принцип простой: всё или ничего.

Второй аспект таких проверок– это стандартизация. Как проверить готовность? Если у вас нет стандартов, то даже такой простой вопрос может стать настоящим кошмаром для мониторинга. Просто сравните, как разошлись друг от друга стандарты Quarkus и стандарты Spring Boot. А ведь никто этого не хотел, но со стандартами всегда так. Единственная разница в том, что теперь ваша организация сама имеет власть разрабатывать и вводить стандарты.
Примечание на полях. Не изобретайте свои стандарты. Просто найдите и используйте какой-нибудь готовый.

4. Стандартизация логов


Продолжая тему мониторинга, отметим, что сочетание недорогих хранилищ и решений класса big data породило на предприятиях нового монстра – тотальное журналирование. Раньше это были неструктурированные и архаичные консольным логи, которые жили недолго и создавались от случая к случаю. Теперь норовят запротоколировать всё подряд и выстроить датасайнс с машинным обучением, чтобы самым революционным образом оптимизировать операции и мониторинг. Увы, надо признать очевидное: любые попытки начать собирать логи сотен приложений, не имея при этом абсолютно никаких стандартов и даже не задумываясь о них, неизменно приводят к бессмысленным и непомерным тратам на инструменты для управления логами и трансформации данных лишь для того, чтобы только начать работу. То есть еще до того, как вы поймете, что сообщения «Выполнен переход» или «Этот блок сработал» вряд имеют хоть какое-то отношение к вашим операциям.

Стандартизировать надо структуру. Повторимся: целостность стандартов важнее их правильности. Вы должны быть способы написать отдельный лог-парсер для каждого приложения, которое есть на предприятии. Да, это будут сугубо штучные, не тиражируемые вещи. Да, у вас будет куча исключений, которые нельзя контролировать, особенно для коробочных приложений. Но не выплескивайте ребенка вместе с водой, уделите внимание деталям: например, временная метка в каждом логе должна отвечать соответствующему стандарту ISO; сам вывод должен быть в формате UTC с точностью до 5-го знака в микросекундах (2018-11-07T00:25:00.07387Z). Уровни журнала должны быть оформлены CAPS-ом и там должны быть элементы TRACE, DEBUG, INFO, WARN, ERROR. В общем, задайте структуру, а уже затем разбирайтесь с подробностями.

Стандартизация структуры заставит всех придерживаться одних правил и использовать одни и те же архитектурные шаблоны. Это верно для логов как приложений, так и платформ. И не отклоняйтесь от готового решения без крайней нужды. EFK-стек (Elasticsearch, Fluentd и Kibana) платформы OpenShift должен быть в состоянии обработать все ваши сценарии. Он ведь вошел в состав платформы не просто так, и при ее обновлении это еще одна вещь, о которой не надо беспокоиться.

5. Переход на GitOps


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

В частности, традиционную схему на основе тикетов можно полностью заменить на модель с pull-запросами git. Допустим, владелец приложения хочет подкорректировать выделяемые приложению ресурсы после реализации в нем новых функций, например, увеличить память с 8 до 16 ГБ. В рамках традиционной схемы разработчику для этого надо создать тикет и ждать, пока кто-то другой выполнит соответствующую задачу. Этим кем-то другим чаще всего оказывается ИТ-эсплуатант, который лишь вносит ощутимую задержку в процесс реализации изменений, никак не повышая ценность этого процесса, или хуже того, навешивая на этот процесс лишние дополнительные циклы. В самом деле, у эсплуатанта есть два варианта действий. Первое: он рассматривает заявку и решает ее выполнить, для чего входит в продакшн-среду, вносит затребованные изменения вручную и перезапускает приложение.
Помимо времени на проведение самой работы здесь возникает и дополнительная задержка, поскольку у эксплуатанта, как правило, всегда есть целая очередь заявок на выполнение. Кроме того, возникает риск человеческой ошибки, например, ввод 160 ГБ вместо 16 ГБ. Второй вариант: эксплуатант ставит заявку под сомнение и тем самым запускает цепную реакцию по выяснению причин и последствий запрашиваемых изменений, да так, что иногда уже приходится вмешиваться начальству.

Теперь посмотрим, как это делается в GitOps. Запрос на изменения попадает в репозиторий git и превращается в pull-запрос. После чего разработчик может выставить этот pull-запрос (особенно, если это изменения в продакшн-среде) для утверждения причастными сторонами. Таким образом, специалисты по безопасности могут подключиться уже на ранней стадии, и всегда есть возможность отследить последовательность изменений. Стандарты в этой области можно внедрять программно, используя соответствующие средства в инструментальной цепочке CI/CD. После того, как его утвердили, pull-запрос версионируется и легко поддается аудиту. Кроме того, его можно протестировать в среде pre-production в рамках стандартного процесса, полностью устранив риск человеческой ошибки.

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

6. Схемы приложений (Blueprints)


Переход от монолитных приложений к микросервисам усиливает роль шаблонов проектирования (паттернов) приложений. В самом деле, типичное монолитное приложение не особо поддается классификации. Как правило, там есть и REST API, и пакетная обработка, и событиями оно управляется. HTTP, FTP, kafka, JMS и Infinispan? Да пожалуйста, а еще оно одновременно работает с тремя разными базами данных. И как прикажете создавать схему, когда здесь намешана целая куча шаблонов интеграции корпоративных приложений? Да никак.

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

  • REST API для управления данными в СУБД.
  • Пакетная обработка, которая проверят FTP-сервер на предмет обновления данных и отправляет их в топик kafka.
  • Camel–адаптер, берущий данные из этого kafka-топика и отправляющий их в REST API
  • REST API, которые выдают обобщенную информацию, собираемую из Data Grid, которая действует как конечный автомат.

Итак, теперь у нас есть схемы, а схемы уже можно стандартизировать. REST API должны отвечать стандартам Open API. Пакетные задания будут управляться как пакетные задания OpenShift. Интеграции будут использовать Camel. Схемы можно создавать для API, для пакетных заданий, для AI/ML, для multicast-приложений, да для чего угодно. А затем уже можно определять, как развертывать эти схемы, как их конфигурировать, какие шаблоны использовать. Имея такие стандарты, не надо будет каждый раз изобретать колесо, и вы сможете лучше сфокусироваться на действительно важных задачах, вроде создания нового бизнес-функционала. Проработка схем может показаться пустой тратой времени, но затраченные усилия сторицей вернутся в будущем.

7. Подготовьтесь к API


Вместе с микросервисной архитектурой приходят и API. Ими тоже придется управлять и лучше подготовиться к этому заранее.

Во-первых, здесь опять понадобятся стандарты. В качестве отправной точки можно взять стандарты Open API, но придется углубиться в дебри. Хотя здесь важно соблюсти баланс и не впасть в чрезмерную зарегламентированность с кучей ограничений. Посмотрите на эти вопросы: когда новая сущность создается с помощью POST, что надо возвращать, 201 или 200? разрешается ли обновлять сущности с помощью POST, а не PUT? В чем разница между 400-ми и 500-ми ответами? – примерно такой уровень детализации вам нужен.

Во-вторых, понадобится сервисная сетка service mesh. Это реально сильная вещь и со временем она станет неотъемлемой частью Kubernetes. Почему? Потому что трафик рано или поздно превратится в проблему, и вам захочется управлять им как внутри дата-центра (т.н. трафик «восток-запад»), так и между дата-центром и внешним по отношению к нему миром («север-юг»). Вам захочется вытащить из приложений аутентификацию и авторизацию и вывести их на уровень платформы. Вам понадобятся возможности Kiali по визуализации трафика внутри service mesh, а также сине-зеленые и канареечные схемы развертывания приложений, или, к примеру, динамический контроль трафика. В общем, service mesh без вопросов входит в категорию задач первого дня.

В-третьих, вам понадобится решение для централизованного управления API. Вам захочется иметь «одно окно» для поиска и повторного использования API. Разработчикам понадобится возможность зайти в магазин API, найти там нужный API и получить документацию по его использованию. Вы захотите единообразно управлять версиями и deprecation-ами. Если вы создаете API для внешних потребителей, то такое решение может стать конечной точкой «север-юг» во всем, что касается безопасности и управления нагрузкой. 3Scale даже может помочь с монетизицией API. Ну и рано или поздно ваше руководство захочет получить отчет, отвечающий на вопрос «Какие у нас есть API?».

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

Однако, надежда есть, и она заключается в автоматизации. Любой из перечисленных выше стандартов можно внедрить с помощью автоматизации. Процесс GitOps может проверять, что во всех соответствующих yaml-файлах присутствуют все требуемые метки и аннотации. Процесс CI/CD может контролировать соблюдение стандартов на корпоративные образы. Все может быть кодифицировано, проверено и приведено в соответствие. Кроме того, автоматизацию можно доработать, когда вы вводите новые стандарты или меняете существующие. Безусловное преимущество стандартизации через автоматизацию заключается в том, что компьютер не избегает конфликтов, а просто констатирует факты. Следовательно, при достаточной проработанности и инвестициях в автоматизацию, платформа, в которую вы вкладываете столько средств сегодня, может принести гораздо больший возврат инвестиций в будущем в виде повышения производительности и стабильности.