banner banner banner
Программирование Cloud Native. Микросервисы, Docker и Kubernetes
Программирование Cloud Native. Микросервисы, Docker и Kubernetes
Оценить:
Рейтинг: 0

Полная версия:

Программирование Cloud Native. Микросервисы, Docker и Kubernetes

скачать книгу бесплатно

Программирование Cloud Native. Микросервисы, Docker и Kubernetes
Иван Портянкин

В этой книге мы взглянем на концепцию Cloud Native:– создание приложений, «рожденных» для облака— 12 факторов облачных приложений и микросервисы— история и краткий обзор виртуализации и масштабирования— контейнеры Docker— настройка и оркестровка KubernetesПриложения Cloud Native помогут развернуть систему любой сложности в любом облаке и мгновенно приспособить ее к растущим нагрузкам.

Программирование Cloud Native. Микросервисы, Docker и Kubernetes

Иван Портянкин

© Иван Портянкин, 2022

ISBN 978-5-4498-3387-7

Создано в интеллектуальной издательской системе Ridero

Введение

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

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

Актуальность и глубина информации. Онлайн-документация

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

Поэтому мы не стараемся максимально глубоко изучить все инструменты которыми пользуемся в данной книге, особенно это касается библиотек и программных сервисов API, предоставляемых известными публичными облаками (такими как Amazon AWS, Google Cloud, российскими Yandex и SberCloud). Основное – это понять процесс, который применяется при разработке в облаках, эффективно использовать базовые и главные возможности контейнеров Docker, и перейти «на ты» с Kubernetes.

Мы не станем перепечатывать массу документации из Интернета, прежде всего с сайтов docker.io и kubernetes.io. Большие компании, Google, Amazon и другие создают целый штаб качественных технических писателей, сопровождающих важные продукты, особенно если дело касается их коммерческих предложений и связанных с ними технологий, прежде всего Kubernetes. Хорошая документация, примеры, онлайн-лаборатории для мгновенных экспериментов прямо из браузера рядом с документацией – все это к вашим услугам, и чем лучше качество и скорость начала работы с облаком, тем быстрее и больше оно привлекает клиентов.

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

Аудитория книги

Эта книга прежде всего для программистов, которые на данный момент работают в привычной, не обязательно связанной с облаком среде – к примеру, запускают сервисы на собственных серверах или виртуальных машинах AWS, работают с базами данных, разрабатывают стандартные приложения для операционных систем (с интерфейсами командной строки CLI, классические графические приложения desktop, или вспомогательные приложения), или в основном сконцентрированы на пользовательских интерфейсах web и мобильных приложений. Подразумевается что вы знаете один или несколько языков программирования и основы сетей и протокола HTTP, но не более того.

Книга описывает, как применить классические знания о программировании в новой среде облачных вычислений (Сloud), где вместо ваших собственных настоящих физических серверов или управляемых вручную «тяжелых» мощных виртуальных вычислительных машин есть лишь эфемерная среда единого кластера (cluster), в которой будут исполняться сервисы, но среда эта способна практически мгновенно масштабировать приложение и сервисы для доступа миллионов пользователей, обеспечивать практически неограниченные ресурсы для вычисления и хранения данных, и эффективно обновлять приложения, используя множество полезных инструментов и сервисов Kubernetes, Docker и открытого сообщества вокруг них. При этом количество настроек самого приложения, изменений в нем будет не так велико – большая часть работы уже будет сделана для нас, особенно когда это касается непрерывного управления и масштабирования приложения.

По большому счету, это же относится и к программистам сервисов или больших монолитных (monolith) приложений, уже работающих на выделенных (dedicated) для этого серверах, виртуальных машинах публичных провайдеров облака, или же в собственных центрах вычислений, как часть частных облачных решений. Даже если большая часть всего, что касается контейнеров, микросервисов, архитектуры приложения как сервисов, уже вам отлично известно, то книга может быть полезна просто посмотреть на то, что дополнительно может предложить вам Kubernetes, и какова общая концепция Cloud Native (концепция приложений, созданных для облака).

Программирование и архитектура. Концепция Cloud Native

О чем именно эта книга? Мы попытаемся узнать большое количество связанных технологий, которые прекрасно сочетаются в единое целое, когда приложение или просто набор сервисов начинает работать в облаке. Связаны технологии, которые мы будем рассматривать, концепцией разработки приложений, созданных и приспособленных для работы в современном облаке (cloud native applications). Концепция эта больше высокого уровня, можно назвать это архитектурой или дизайном (будем считать, как и многие эксперты, что эти два слова означают для программистов примерно одно и то же). В общем случае приложение, созданное для облака, способно быстро запускаться на любом облаке с поддержкой основных технологий концепции (Docker и Kubernetes), и при правильном подходе быстро масштабироваться при пиковой нагрузке, непрерывно обслуживать пользователей даже во время обновлений и фатальных ошибок, и позволять программистам использовать любые нужные им технологии и инструменты и ускорить процесс разработки самых сложных систем.

На словах концепция звучит прекрасно, однако между архитектурой (дизайном) и непосредственной разработкой большая работа и множество деталей, в которых, как известно, заключается иногда самая большая загвоздка. В книге будет некоторое количество намеренно очень простых примеров, главная цель которых состоит в том, чтобы за минимальное количество шагов и настроек соединить теорию и историю изучаемого вопроса с практикой – непосредственным использованием довольно сложного рабочего инструмента (особенно когда речь идет о Kubernetes). После этого, уже зная основные детали, поняв их смысл, можно строить на этом уже реальную, сложную функциональность. Цельных, больших приложений «промышленного» уровня в книге мы рассматривать не будем – но вы всегда сможете найти их на GitHub, конференциях KubeCon, и разнообразных блогах.

Масштабирование на практике

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

Русскоязычные термины

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

Тем не менее, нет ничего более легкого для усвоения, чем структурированная и правильно поданная информация на родном языке, который просто «работает» на уровне глубокого подсознания, не требуя ни минуты задержки, впитываясь в память и сознание. Эта книга постарается максимально структурировать и постепенно ввести вас в мир облачных технологий на родном языке, и мы будет использовать максимально близкие по смыслу русскоязычные аналоги английских названий технологий. Правда, многие библиотеки, алгоритмы, компании, сайты, паттерны проектирования, процессы разработки настолько влились в нашу жизнь на английском языке, что чтение их названий на русском языке будет даже мешать. В этом случае мы будем использовать максимально нейтральное название и включать в скобках английское название, чтобы не перемешивать языки и шрифты, и не коверкать книгу и предложения не слишком звучным транслитом (Докер? Кубернетес? А может быть Кюбэрнэтис? «Нода» и «поды»? В любом случае подобное выглядит просто неприятно – мы будем писать английский термин и использовать наиболее верный перевод, без излишней смысловой нагрузки).

Пользовательские интерфейсы

В книге мы в основном рассматриваем технологии для облака, особенно подходящие для быстрой разработки, от идеи до минимального работающего продукта (minimal viable product, MVP), и его последующей миграции в полноценное, масштабируемое до глобального мирового сервиса приложение, или систему сервисов. Пользовательский интерфейс для любой системы это отдельная тема, чрезвычайно динамичная, вызывающая всегда горячие споры. Как и все, что свойственно вкусу и внешности, то, что вызывает восторг у одних, кажется совершенно ужасным другим. Конечно, у приложения будет web интерфейс, приложения для iOS и Android, возможно консоль администратора в дополнение ко всем диагностическим инструментам, которые мы затронем в этой книге. Тема чрезвычайно обширная и бесконечная, и изучения требует в отдельном разговоре. Будем считать что отличный пользовательский интерфейс у нас есть, и уделять внимания в данной книге мы ему не станем.

Примеры и их тестирование на GitHub

Все примеры и все команды, используемые нами для управления и экспериментов с Docker и Kubernetes, находятся в открытом репозитории ivanporty/cloud-docker-k8s на GitHub. Весь код примеров (включая команды, запускаемые нами из терминала) собирается и тестируется как часть непрерывной интеграции (CI) c помощью GitHub Actions – вы сможете увидеть их ежедневный запуск и результаты и сравнить со своими, если у вас что-то не получается. Ежедневная непрерывная сборка позволяет точно знать, что примеры книги работают и верны, и если новые версии Kubernetes или образов Docker что-то «ломают», я получаю уведомления об этом и быстро все обновляю, как в примерах, так и в электронных версиях книги.

Выбор Go и Java

Go как нельзя лучше подходит для микросервисов, особенно в качестве очень коротких, простых и быстрых процедур обработки данных. Этот язык специально был создан простым по синтаксису, в нем по сути не присутствует полноценная система объектно-ориентированного программирования, и он во всем приглашает к простому, короткому, быстрому коду.

Крайне полезно то, что Go компилируется в машинный код для целевой операционной системы, то есть работает так эффективно, как это возможно без специальных оптимизаций. Работая в облаке, где каждую минуту исполнения, мегабайт оперативной памяти, использованную энергию необходимо будет оплатить, любые промежуточные этапы, использующие ресурсы, могут быть чуть дороже, чем интерпретируемые языки, например Python, или языки на основе виртуальных машин Node. js и Java, даже если они быстро компилируются (just in time, JIT) в машинный код в процессе работы. Это «чуть дороже», помноженное на масштаб и количество пользователей (что в конечном итоге основной показатель успеха вашей идеи, стратегии и качества реализации), может вылиться в порядочные траты. Тем более что некоторые сложные участки программ на основе виртуальных машин оптимизировать крайне тяжело и они будут исполняться в разы медленнее.

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

Язык и платформа Java чрезвычайно популярны для классических корпоративных приложений, практически идеально переносятся между платформами и операционными системами, а количество фреймворков для веб-приложений, сервисов и микросервисов поражает воображение. Начать разработку может быть не так быстро и эффектно как на Go, но если у вас изощренный и сложный домен (domain) приложения (то есть описание области, в которой ваше приложение будет действовать), мощь объектного подхода, продуманный дизайн и стабильность языка, хорошо известные шаблоны проектирования и практики работы, и сотни разнообразных инструментов Java могут быть как нельзя кстати.

Вдобавок, главные игроки экосистемы Java и платформ для этого языка крайне заинтересованы оставить этот язык в лидерах разработки даже в мире микросервисов. Идет большая работа по уменьшению требований к оперативной памяти, размера виртуальной машины JRE, и разбиения платформы на модули, позволяющего исключить из приложения ненужные мегабайты библиотек JAR. Посмотрите на виртуальную машину GraalVM от Oracle, оптимизирующей запуск программы, и компилирующей байт-код в бинарный, или библиотеки Quarkus и Microprofile, создающие минимальные микросервисы.

Сторонние библиотеки и инструменты

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

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

Основные провайдеры облачных услуг – Amazon, Google, Microsoft

Основные технологии (контейнеризация, Docker, оркестрация сервисов Kubernetes) концепции приложений, созданных для облака Cloud Native, уже практически гарантированно работают на всех провайдерах облака, будь это три кита облачных вычислений Amazon Web Services (AWS), Google Cloud Platform (GCP), Microsoft Azure, российские #CloudMTS и SberCloud, или провайдеры меньших размеров, часто также предлагающих интересные цены и услуги (Digital Ocean). Для нас же это означает, что на данный момент концепция стала стандартом, который очень широко поддерживается, и будет поддерживаться на многие годы вперед, а значит изучение ее основ, и технологий в ней, даст нам ключи к эффективной работе с любыми облаками. Созданные же единожды приложения можно будет и переносить между облаками, и запускать в гибридном облаке, работающем на нескольких провайдерах одновременно.

Дополнительные форматы книги на ipsoftware.ru

Я намеренно создал книгу, используя современные независимые платформы для издания – LeanPub и российскую Ridero. Основная цель – снизить издержки классического издателя, в конечном итоге составляющие больше половины стоимости электронной книги, и особенно бумажной версий книги (в этом случае практически вся стоимость составляет траты на печать, хранение и распространения тиража). Книга также намеренно сделана короткой, учитывая огромную доступность справочной информации в Интернете, и цена ее будет минимально разрешенной электронными магазинами.

Различные платформы предоставляют разные уровень сервиса, форматы книги, и инструменты для работы с ней. База книги создана в формате Markdown на платформе LeanPub, сверстана для русских площадок с помощью Ridero. Вы можете найти и скачать все варианты и форматы книги на моем сайте www.ipsoftware.ru, особенно если вас не устроил изначально полученный вами вариант или формат. Более того, книга на сайте будет постоянно обновляться и меняться, в зависимости от найденных ошибок и необходимых добавлений. Обновить печатную версию к сожалению не так просто, но если вы уже купили и прочитали печатную версию, вы найдете историю изменений книги на сайте и можете прочитать обновленные главы в электронном виде.

Открытый текст. Благодарности

Эта книга создана открытой (free open source) и ее текст доступен на GitHub для обновлений и изменений (репозиторий ivanporty/cloud-docker-k8s-book). Если вы увидели ошибку, неточность, или чувствуете, что какого-то материала не хватает, открывайте запрос (pull request), я его проверю, и ваши изменения тут же появятся в электронных версиях книги. Я благодарю несколько человек, которые внесли исправления и изменения в книгу (это их учетные записи на GitHub):

– AdamPirson

– lex111 (Alexey Pyltsyn)

– alg (Aleksey Gureiev)

1. Приложения, созданные для облака – концепция Cloud Native

«Технологии Cloud Native позволяют создавать сложные системы в динамичной, современной среде частного, гибридного или коммерческого облака Cloud. Воплощают такой подход в жизнь контейнеры, сервисные сетки (service mesh), микросервисы, неизменная инфраструктура и декларативный способ управления ресурсами.»

    Устав фонда Cloud Native Foundation, управляющего стандартами и общим направлением концепции.

Современная разработка классических приложений, вспомогательных сервисов, мобильных приложений и их серверных компонентов, и программного обеспечения в целом подразумевает постоянные изменения функциональности. Часто новые функции появляются несколько раз в день. При этом обновления, исправления ошибок и перезапуски не должны останавливать сервис и доступ к его функциям ни на секунду. Практически весь мир объединен глобальным скоростным доступом в Интернет, и одновременный доступ не только миллионов, но сотен миллионов пользователей к удачному приложению и сервису больше не является прерогативой технических гигантов, таких как Google, Apple и Yandex, и вполне доступен маленькому стартапу и индивидуальному программисту. Приложение должно быть готово к пиковой нагрузке, не уменьшая качество своего сервиса. Именно таким и будет приложение, с самого начала созданное для работы в облаке.

Основные положения концепции Cloud Native

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

Реализовать это возможно с помощью так называемых «микросервисов» (microservices), слабо связанных между собой компонентов единой системы или приложения. Они обмениваются данными через сеть, используя стандартные сетевые протоколы, как правило это протокол HTTP и стандарт REST. Разработка и обновление одного микросервиса никак не затрагивает остальные части системы. Микросервисы связываются друг с другом через сетевые порты и абстрактные протоколы, и каждый из них может быть написан на любом подходящем языке и технологии. Обновляются и перезапускаются они также независимо. Микросервисы часто противопоставляются единому, большому серверному приложению, так называемому «монолиту» (monolith).

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

Одно из преимуществ приложения, разбитого на модули и микросервисы, работающие из собственных контейнеров – тонко настроенное горизонтальное масштабирование. Появляется возможность выделить наиболее нагруженную часть системы и запустить для ее сервисов и компонентов столько экземпляров, сколько необходимо для обработки текущей нагрузки. Для этого требуется практически неограниченная вычислительная мощность, растущая по требованию (ее еще называют эластичной) – эту мощь обеспечивают коммерческие провайдеры облака, такие как Google Cloud (GCP), Amazon Web Services (AWS), SberCloud, Yandex.Cloud.

Наконец, мощное, динамично меняющееся приложение, состоящее из сотен распределенных компонентов, соединенных между собой по сети, требует постоянного надзора и очень сложного управления, в том числе и для масштабирования и обновления компонентов. Здесь главную роль играет оркестратор контейнеров (orchestrator), самым популярным среди них без сомнения является Kubernetes. Для наблюдения трафика между компонентами, задержек, графиков исполнения запросов, и сбора и анализа журналов (logs) существуют целые комплексы программных решений, хорошо интегрированных с Kubernetes.

Первые выводы

Подводя краткий итог, мы поставили задачу создать максимально гибкое, устойчивое к отказам, всегда доступное приложение, способное выдержать пиковые нагрузки, и увидели, как эта задача может быть решена. Именно описанный подход и методы являются основой приложения, созданного для работы и развертывания в облаке (cloud native). Вот его ключевые атрибуты:

– Микросервисы (microservices) как способ максимально возможной слабой связи между подсистемами приложения. По сути это компонентная разработка, с прицелом на абсолютно независимый друг от друга процесс разработки, свободный выбор технологии, а также независимые выпуски новых версий и их развертывание на сервере.

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

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

– Оркестровка и управление контейнерами, внутри которых находятся микросервисы, в одном или множестве экземпляров. Основным инструментом управления является сейчас Kubernetes, мощный, расширяемый оркестратор, способный управлять, обновлять, масштабировать, настраивать взаимодействие для сотен микросервисов. Оркестратор работает с набором физических или виртуальных серверов в кластере.

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

Теперь давайте взглянем чуть подробнее, какие технологии, подходы и архитектура обеспечивают успех каждого из столпов концепции Cloud Native.

Микросервисы – быстрый цикл разработки и постоянный выпуск

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

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

Эластичность и практически неограниченная вычислительная мощность облака дает нам возможность разбить приложение на логические компоненты и запускать их и управлять ими индивидуально. При необходимости легко увеличить пропускную способность приложения, увеличив количество экземпляров компонентов (работающих в виде микросервисов), испытывающих наибольшую нагрузку. Это так называемое горизонтальное масштабирование (horizontal scaling или scaling out) – при работе в облаке его возможности практически безграничны, при условии выбора удачной архитектуры приложения, дающей возможность разбить его вычислительные потоки на независимые части. Вертикальное масштабирование же подразумевает рост мощности одного сервера и его аппаратных возможностей, что крайне ограничено, и более того, мощные серверы обычно очень дороги.

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

Гораздо меньший размер и менее связанная с другими компонентами функциональность позволяет программистам быстро проводить в жизнь новые идеи, рефакторинг кода, и пробовать новые подходы и процессы разработки. Разумный размер кода делает процесс разработки эффективным и удобным. Это же позволяет проще настроить системы постоянного контроля качества и развертывания сделанных изменений на сервере (CI/CD, continuous integration and delivery), и сделать их работу прозрачной и высокопроизводительной, позволяя программистам быстро проверить, было ли их последнее изменение удачным.

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

Мы подробнее рассмотрим некоторые аспекты дизайна и разработки микросервисов и похожих на них компонентов в отдельной главе.

Контейнеры – изоляция и гарантия неизменяемости версий

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

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

Все содержимое (файлы и зависимости приложения или его части), необходимое для запуска контейнеров, упаковывается в образы (image). Важным свойством образа является его неизменность (immutability), для каждой отдельной метки, или версии, этого образа. Поменять помеченный определенным способом образ с известной контрольной суммой уже невозможно. С практической точки зрения это означает, что созданная когда-то система, настроенная и работающая с определенным набором микросервисов, упакованных в образы для запуска в виде контейнеров, теперь всегда может быть заново воспроизведена в любой необходимый момент. Это важное качество воспроизводимости (reproducibility) гарантирует уверенность в текущем состоянии сложной, составной системы. Мы можем быть уверены в том, что работающая система не была запущена давно потерянным и никому больше не известным набором эзотерических скриптов.

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

Облако – неизменная эластичная инфраструктура. «Феникс» вместо «снежинки»

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

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

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

Гораздо проще восстанавливать и копировать сервер, если он представляет собой «феникса», способного быстро восстановиться из заранее подготовленного образа («пепла», если выражаться в терминах легенды). Еще лучше, если этот образ не бинарная копия диска, а список четких инструкций, по шагам восстанавливающих состояние сервера из известных проверенных компонентов. Эта инструкция хранится в системе контроля версий с историей всех изменений. Примеры – известные инструменты Terraform и Ansible. Сервер, созданный по инструкции, всегда будет одинаковым, и таким образом, обеспечит неизменяемую инфраструктуру приложения (immutable infrastructure).

Если и разработчики, и операторы имеют доступ к легко читаемой, легко восстанавливаемой конфигурации своих серверных систем и кластеров, процесс передачи выпущенных сервисов из разработки в эксплуатацию становится прозрачным и легко поддерживаемым. Восстановление среды для тестирования или эксплуатации не представляет собой проблем. Слияние процессов разработки и управления иногда еще называют процессом DevOps (девопс, development + operations).

Облачные сервера как нельзя лучше подходят для реализации упомянутых выше «фениксов», проверенных, неизменяемых серверов c прозрачной историей. Публичные провайдеры облака, такие как Amazon AWS, Google GCP или Yandex.Cloud, создают свои виртуальные или реальные сервера из тщательно проверенных, безопасных версий известных операционных систем, которые не будут внезапно меняться в процессе работы сервера. Ваша команда DevOps затем может использовать подготовленные заранее инструкции для дополнительной автоматической настройки этих серверов.

В мире контейнеров все становится еще проще. Провайдеры облака как правило предоставляют оптимизированную операционную систему для запуска контейнеров (чаще всего это особая версия Linux). Все зависимости и дополнительные настройки вы производите уже внутри самого контейнера, и указываете их при создании его образа, помечая его версией. Эта версия затем может многократно запускаться в виде контейнера и уже никогда не меняется. Управление сложными серверными конфигурациями значительно упрощается, и по сути, любой член команды, работающей в формате DevOps, способен без особого труда построить и восстановить любую конфигурацию системы, от тестирования до реальной эксплуатации, просто используя доступное в системе контроля версий описание развертывания и запуска системы.

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

Оркестровка Kubernetes – декларативное описание состояния

Получив неизменную, эластичную инфраструктуру, и все преимущества изоляции и быстрого запуска контейнеров, необходим инструмент, обладающий достаточной мощью и гибкостью для управления ими. Оркестратор Kubernetes, созданный на основе проверенной годами в компании Google системы управления контейнерами Borg, обладает всем необходимым для запуска и управления сложными системами, развернутыми в облаке. Все основные коммерческие провайдеры облака, Google Cloud, AWS, Azure, российские Yandex.Cloud, #CloudMTS и остальные, в обязательном порядке предоставляют сервисы на основе Kubernetes.

Исходный код Kubernetes открыт и находится на GitHub, это один из самых популярных проектов с огромным количеством программистов и компаний, работающих над ним. Запустить Kubernetes возможно на своем собственном, частном облаке и кластере, а начать эксперименты можно и вовсе на своем ноутбуке, используя совершенно полные локальные реализации, такие как Docker for Desktop, Kind и Minikube.

Как мы увидели в уставе фонда Cloud Native, декларативное описание является неотъемлемой частью этой концепции. В случае с Kubernetes это означает, что вместо развертывания и запуска приложений (упакованных в образы контейнеров) явными командами из скриптов и терминала, предпочтительным является желаемое состояние кластера (desired state). Состояние описывает все системы, микросервисы и сетевые настройки системы, а управляющая система Kubernetes заботится о том, чтобы кластер представлял собой именно желаемое состояние. Состояние описано в файлах YAML. В главах, посвященных Kubernetes, мы узнаем все детали о нем, и научимся описывать систему декларативным способом.

Инструменты для сбора журналов и наблюдения

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

Вокруг концепции Cloud Native сложилась огромная, динамичная экосистема решений и продуктов, помогающих решить неизбежные проблемы распределенных асинхронных систем. Прежде всего это «сервисные сетки» (service mesh), такие как Istio и Linkerd. Смысл термина «service mesh» состоит в упорядочении и управлении сетевыми переговорами микросервисов, но слово «сеть» уже давно и прочно занято, и мы используем «сетку», чтобы уменьшить путаницу. Сервисные сетки решают многие проблемы, дают возможность наблюдать за сетевыми вызовами, строить графы, получать задержки, и многое другое. Системы сбора метрик, такие как Prometheus, позволяют интегрировать метрики вашей системы в единые центры наблюдения (к примеру, на основе Grafana). Управление журналами, например Fluentd, справляется со сбором и упорядочением десятков разнообразных журналов, полученных от микросервисов. Мы еще раз вспомним эти инструменты, когда будем рассматривать микросервисы в следующей главе.

Разработка на практике – 12 факторов облачного приложения

Теория и концепция Cloud Native, то есть приложений, созданных для облака, пока выглядит стройно и логично, и остальную часть книги мы посвятим практическому применению ее основных частей. Однако всегда интересно узнать «выжимку» опыта компаний, команд и программистов, которые уже попробовали разработку таких приложений, и увидели всю подноготную проблем, с которыми придется столкнуться – как мы знаем, в программировании многие неприятности скрываются именно в мелких деталях.

Команда облачного сервиса Heroku, популярного выбора для небольших команд и микросервисных систем, собрала свои наблюдения в каталог из 12 факторов (12 factor app), наличие которых в дизайне и реализации системы резко повышает его шансы на успешную работу в облаке и простую поддержку готовой системы. Отсутствие этих факторов, или, что хуже, выбор противоположных решений, может впоследствии усложнить разработку и развертывание облачного приложения. Давайте посмотрим на эти факторы, и увидим, как они соотносятся с положениями концепции Cloud Native.