Все больше разработчиков выбирают микросервисную архитектуру уже на стадии проектирования, а монолиты методично распиливают. Это длительная и непростая работа, поэтому разработчики стараются еще на стадии проектирования определиться с архитектурой.
В этом материале мы поговорим об особенностях Cloud Native приложений и какую роль играет Kubernetes в этом подходе.
«Классический» цикл разработки монолитных приложений неизбежно сталкивается с рядом проблем:
- Сложно часто выпускать релизы из-за трудностей с компиляцией и добавлением в текущий билд. Это ведет к накоплению технического долга.
- Во время пиковых нагрузок приложениям не хватает вычислительной мощности или ширины канала, что сказывается на качестве сервиса и приводит к потере клиентов. Проблемы с балансировкой нагрузки заслуживают отдельного материала.
- Приложение написано на старой версии языка программирования или сам язык не подходит под актуальные задачи. Только часть команды понимает, как это поддерживать, поэтому сотрудники становятся незаменимыми.
Cloud Native предлагает другую парадигму создания и развития приложений. В ней приложение можно легко обновлять без ущерба для клиента.
По этой причине все больше компаний отказываются от монолита в процессе или изначально создают приложения с учетом особенностей облачной архитектуры. Это сложный процесс, поэтому некоторые зависают в процессе рефакторинга. О том, почему индустрия пришла к микросервисам и контейнерам, можно почитать здесь.
Путь к Cloud Native
В 2015 году на заре становления Cloud Native появилась классификация приложений по степени готовности к облаку.
- Cloud Ready. Приложению не требуется постоянный доступ к диску, оно контейнеризировано, а управление с внешними сервисами осуществляется за счет конфигов. Есть возможность подключить сторонние службы.
- Cloud Friendly. Приложение 12 факторов. Здесь появляется горизонтальное масштабирование за счет ресурсов облачной платформы.
- Cloud Resilient. Решения, построенные так, что увеличение нагрузки или отказ отдельных компонентов не приведет к недоступности сервиса.
- Cloud Native. Микросервисная архитектура, при проектировании используется принцип API-first.
Теперь за развитием нативного подхода к созданию приложений присматривает целое сообщество — Cloud Native Computing Foundation или CNCF.
Cloud Native как ландшафт
Сообщество определяет Cloud Native как подход для создания и запуска приложений в динамических средах (все типы облаков), который обязательно использует контейнеры, service mesh, микросервисы и неизменяемую IT-инфраструктуру (immutable infrastructure). В таком подходе к управлению развертыванием сервисов и ПО на IT-ресурсах компоненты заменяются, а не изменяются. Приложение или услуги фактически развертываются заново при каждом изменении.
Cloud Native — это больше, чем просто регистрация в облачных сервисах и запуск приложений.
Для эффективного деплоя, запуска и управления в облачном приложении должны быть реализованы несколько основных принципов Cloud Native.
Ключевые признаки облачных приложений
- Контейнеризация и оркестрация.
- Следование практикам CI/CD.
- Масштабируемость ресурсов в зависимости от нагрузки.
- Отказоустойчивость и быстрое автоматическое восстановление в случае глобального сбоя.
- Наличие систем мониторинга состояний и производительности.
Среди прочих признаков Cloud Native сообщество отмечает высокий уровень автоматизации и возможность вносить значительные изменения с минимальными усилиями. Это облегчает деплой и, как следствие, увеличивает количество релизов. Все эти вводные данные указывают на то, что CNCF пока доверяет работу с контейнерами только Kubernetes, который сочетает все вышеперечисленное.
Например, внедрение Kubernetes помогло Adidas проводить релизы 3-4 раза в день, вместо недельных запусков.
Впрочем, эксперты сообщества регулярно обновляют карту сервисов, в которой собраны все необходимые компоненты для использования в клиентских приложениях.
Большая часть проектов относится к OpenSource-решениям и маркируется разными статусами в зависимости от того, на какой стадии находится проект.
Получается, любое приложение может быть Cloud Native? На самом деле, нет. Чтобы разобрать этот момент, посмотрим на различные типы приложений.
Состояния и изоляция
В первую очередь, определим приложения по типу состояний.
→ Stateless. В приложениях такого типа ответ сервера не зависит от какого-либо состояния. Данные о прошлых операциях или ссылки на них не сохраняются. Каждая операция выполняется как первая и единственная.
Приложения без статического состояния предоставляют одну услугу или функцию. Они используют сеть доставки контента (CDN) и веб-серверы для обработки этих краткосрочных запросов: один запрос — один ответ.
→ Stateful. Приложения и процессы с состоянием — это те, к которым можно возвращаться снова и снова. Например, интернет-банкинг или электронная почта. Они выполняются в контексте предыдущих операций, а на текущую сессию может повлиять то, что происходило ранее. По этим причинам приложения с состоянием используют одни и те же серверы каждый раз, когда обрабатывают запрос от пользователя.
Если stateful-операция прерывается, то «контекст» и история сохраняются. Пользователь может продолжить работу с того места, на котором остановился. Приложения с состоянием отслеживают такие вещи, как расположение окон, настройки предпочтений и недавняя активность.
Большинство приложений, которые мы используем каждый день, являются stateful, но с развитием технологий микросервисы и контейнеры упрощают создание и развертывание приложений в облаке.
Во вторую очередь, важно разделять изолированные и связанные приложения.
→ Изолированные. Не взаимодействуют со сторонними сервисами, например, с платежными системами.
→ Связанные. Используют один или несколько внешних сервисов.
Определение того, является ли приложение Cloud Native, зависит от обоих этих факторов.
Обратите внимание, что изолированные приложения в состоянии stateful требуют логи для работы, но данные хранятся в самом приложении, а не снаружи. На практике не так много приложений попадают в эту категорию, поскольку они плохо переносят перезагрузку.
Есть еще связанные и не имеющие статичного состояния приложения, которые должны взаимодействовать с внешними сервисами для ответа на запросы. Этот тип приложений более распространен, поскольку включает в себя взаимодействие с базами данных, брокерами сообщений (например, Apache Kafka).
Cloud Native для всех
Любое изолированное приложение, будь то stateless или stateful, может придерживаться принципов Cloud Native. Такое приложение может быть развернуто в гибридном облаке от разных провайдеров. Приложения, требующие подключения к внешним сервисам, также можно считать Cloud Native, но можно ли развернуть такие приложения в гибридном облаке — уже зависит от ситуации.
Если внешний сервис — это база данных, размещенная в Kubernetes для использования приложением, то ответ положительный. Приложение не зависит от поставщика облачных услуг и может быть развернуто в гибридном облаке. Такой тип архитектуры накладывает большую нагрузку на операционную деятельность. Требуется установка и управление базой данных или другим хранилищем данных в среде Kubernetes.
Запасной вариант
Другой вариант — использовать ресурсы облачного провайдера для предоставления услуг базы данных. Это оптимизирует нагрузку, но появится привязанность к провайдеру. Так развернуть приложение в гибридном облаке с несколькими провайдерами не получится.
Каждый облачный провайдер имеет свои предпочтительные механизмы. Например, интерфейс командной строки (CLI), API, собственный Terraform-провайдер, который используется для деплоя. Эта проблема делает невозможным автоматизированное развертывание одного и того же приложения у разных провайдеров.
Для решения этой задачи стали появляться многочисленные механизмы оркестрации. Несмотря на сложность администрирования, Kubernetes оказался надежнее и удобнее конкурентных решений. Сравнительный анализ K8s и Docker Swarm можно посмотреть здесь.
Kubernetes Native
Внедрение контейнеров постоянно растет. Предприятия переносят свои рабочие нагрузки с физических или виртуальных машин в контейнеры для оптимального использования ресурсов. Однако управление несколькими контейнерами в облачной среде не самый простой процесс, а если контейнеров будет тысяча?
В 2018 году Kubernetes первым получил статус Graduated Project (завершенный проект) в терминологии CNCF. Процесс развития K8s во много повлиял и на саму среду, изменив способы масштабного развертывания программного обеспечения, методы работы и взаимодействие корпораций с крупными проектами с открытым исходным кодом.
Сейчас «выпускников» CNCF уже 18, а Kubernetes представляет собой основу для всего ландшафта, поэтому все чаще можно встретить понятие Kubernetes Native как ориентацию разработки на работу с контейнерами и микросервисами.
COSI и Kubernetes Native 1.25
Объектное хранение данных в последние годы набирает популярность в качестве альтернативы файловым системам и блочному устройству.
Рабочие нагрузки, которые используют тома CSI, получают преимущества при переносе между провайдерами и кластерами Kubernetes без необходимости изменять манифесты приложений. Аналогичного стандарта для объектного хранилища пока не существует.
Парадигма объектного хранения способствует дезагрегации вычислений и хранения. Это достигается за счет того, что данные доступны по сети, а не локально.
Дезагрегированные архитектуры позволяют рабочим нагрузкам быть без статических данных. Это облегчает управление, масштабирование и автоматизацию.
Цель COSI — стандартизировать использование объектного хранилища, чтобы обеспечить следующие преимущества:
- Самообслуживание — четкое разграничение между администрированием и операциями (DevOps) для обеспечения самообслуживания для DevOps-инженеров.
- Переносимость — нейтральность к поставщикам обеспечивается благодаря переносимости между кластерами Kubernetes и поставщиками Object Storage.
- Переносимость между поставщиками возможна только в том случае, если оба поставщика поддерживают общий datapath-API.
- Kubernetes Native — использование API Kubernetes для предоставления, конфигурации и управления бакетами.
Контроллер COSI определяет три API Kubernetes, предназначенных для управления данными в бакетах:
- Bucket,
- BucketClass,
- BucketClaim.
Кроме этого, есть еще два API для управления доступом к бакетам:
- BucketAccess,
- BucketAccessClass.
В двух словах, Bucket и BucketClaim можно считать аналогичными PersistentVolume и PersistentVolumeClaim соответственно. Аналогом BucketClass в мире файловых/блочных хранилищ является StorageClass. Более подробно об API.
По сути Kubernetes Native является специализацией Cloud Native. Между этими понятиями много общего, но основное различие заключается в возможности смены облачных провайдеров.
Почему это различие важно? Использование всех преимуществ гибридного облака и использование нескольких облачных провайдеров требует, чтобы приложения можно было развертывать у любого провайдера. Без этой возможности приложение привязано к одному поставщику услуг.
Как Kubernetes помогает Cloud Native приложениям
Непрерывная доставка CI/CD. Автоматическая сборка и доставка кода из Git в инфраструктуру. Непрерывность достигается за счет того, что разработчики делают это без участия администратора инфраструктуры.
Сокращение времени и усилий. С помощью K8s компания может добиться непрерывной интеграции CI/CD, оптимизации модульного тестирования и доставки с нулевым временем простоя за счет автоматизации внедрения кода.
Оптимизация расходов. Контейнерная архитектура на базе Kubernetes позволяет отказаться от дорогостоящей инфраструктуры и сосредоточиться на производстве собственного продукта. Нагрузка распределяется внутри группы нод, которые состоят из более доступных серверов.
Эта же система используется для мониторинга использования ресурсов и состояния контейнеров, а также для перезапуска и масштабирования по мере необходимости.
Заключение
Kubernetes можно считать сердцем всего подхода Cloud Native, поскольку технология аккумулирует все основные положения подхода.
Чтобы отладить процесс масштабирования и автоматизации, можно использовать Managed Kubernetes.
Почему в такой модели использовать K8s проще:
- Провайдер организует и отвечает за доступность кластера.
- Провайдер разрабатывает и предоставляет инструменты для работы с K8s (например, terraform-провайдер).
- Провайдер предоставляет экосистему сервисов, которые интегрированы друг с другом. Например, образы можно хранить в Container Registry.