Идея управления серверной инфраструктурой через код (Infrastructure as Code, IoC) не нова. Управление настройками через скрипты или файлы конфигурации позволяет стандартизировать настройку системы, масштабировать решение, снизить ошибки и исключить “человеческий фактор”. Shell-скрипты или их прототипы существовали с момента создания компьютеров, а с появлением виртуальных машин стало возможно заскриптовать настройку сервера с нуля. Однако сегодня я хочу сконцентрироваться на кодировании именно облачной инфраструктуры. Это интересно, потому что облака вывели фреймворки по управлению инфраструктурой на принципиально новый уровень.
Связано это, в первую очередь, с подходом по предоставлению облаком конечному пользователю единого API с помощью которого можно управлять любым ресурсом или сервисом в нем. Таким образом у пользователя появились возможность создания подобных фреймворков. Последующий же рост и популяризация самих облаков создали спрос и на системы управления ими, что стимулировало большой сегмент IT индустрии инвестировать в это направление.
Сегодня лидеры индустрии предоставляют 200+ сервисов которые работают на разных уровнях абстракции (IaaS, PaaS, SaaS), но все так же позволяют управлять всем через единый API. В данной статье я рассмотрю историю развития фреймворков для управления облачной инфраструктурой, выделив ключевые этапы и события, которые, по моему мнению, повлияли на их эволюцию.
Поскольку система управления облаком зачастую нераздельно связана с самим облаком и меня интересуют первопроходцы, я часто буду делать отсылку к AWS.
Эпоха CLI
Отсчет появления облаков, а также инструментов их кодирования логично вести с 2006 года с публичного релиза AWS SQS, S2, EC2.
В качестве инструмента управления на тот момент была доступна командная строка (CLI) и пакет для программирования (SDK). Управление через CLI/SDK тут же открыло возможности заскриптовать свои действия и сильно снизить количество рутинных операций, а также позволило создать библиотеки действий, делиться с коллегами и даже хранить в системе контроля версий. К сожалению, все это быстро превращалось в запутанное спагетти. Большое количество параметров и множество вариаций исходных условий приводило к тому, что то, что хорошо работало для демо примеров, было плохо применимо для решения реальных задач. Одним из важных факторов приводящих к этому была императивность работы с CLI/SDK. Например в псевдо коде можно сказать:
создай мне EC2 сервер размера Large
назови его ABC
Казалось бы все просто, но если вызвать эту команду 10 раз - получится 10 серверов с одинаковыми именами, за каждый придется платить и непонятно, какой из них надо удалять. В данном случае полагаться на имя сервера нельзя. Оно не должно быть уникально и создание будет работать пока не упрется в квоту. Также, если кто-то внесет изменения вручную, то синхронизировать состояние обратно не удасться. Для правильной идентификации надо хранить id созданной сущности, чтобы можно было обратиться к ней, а также атрибуты с ней связанные.
Хотя CLI/SDK являются основой, на которой базируются будущие поколения, использование их в чистом виде довольно ограничено и наиболее эффективно при выполнении разовых операций, не создающих постоянные сущности или инкрементальных действий.
Эпоха CloudFormation
Следующей большой вехой стало появление AWS CloudFormation в 2011 году. Это был первый серьезный подход к решению проблем идемпотентности и хранения состояния. Поскольку CloudFormation проприетарный инструмент, он получил отличную интеграцию и легкость использования в рамках AWS, но по тем же причинам не мог быть использован для других облаков. Инструмент получил декларативную нотацию и теперь, например, стало можно сказать:
должен быть один EC2 север размера Large
он должен быть назван ABC
CloudFormation создаст внутреннюю сущность - стек, к которому будут привязаны все созданные в результате него сущности. Таким образом, сколько бы раз мы не выполняли один и тот же стек, у нас всегда будет 1 сервер. Если же мы захотим 2-й - мы можем создать 2-й стек из той же конфигурации. Важно, что стек обеспечивает синхронизацию и даже если кто-то руками изменит настройки - выполнение CloudFormation приведет все в норму.
Решение одних проблем привело к другим - CloudFormation не предлагал специального языка для описания, а использовал JSON с расширенным синтаксисом. В результате, хотя была возможность установить базовую связь между объектами, гибкость и читаемость, присущая инструментам CLI/SDK, значительно утрачивалась. Даже внедрение базовых функций приводило к низкой читаемости кода, и можно только посочувствовать инженерам, которые вынуждены были отлаживать такие решения. Проблемой также становится и формирование библиотек, наследование, которое было полностью открыто ранее.
С ростом возникает новая задача - необходимость обеспечить еще более значительный рост и взаимосвязь между стеками, чтобы они могли ссылаться на ресурсы друг друга. Однако при увеличении масштабов становятся заметными медленная скорость выполнения и недостаточная прозрачность процессов, связанных с отладкой и пониманием того, над чем система фактически работает (debuggability).
Со временем CloudFormation перешел к использованию YAML, улучшил синтаксис, внедрил множество новых функций и стал фундаментом для следующих поколений платформы.
Эпоха Terraform
Эта эра для меня самая любимая, поскольку именно в этот момент я начал заниматься облаками.
В 2014 вышел Hashicorp Terraform. Этот инструмент, исправил множество недостатков, сохранив достоинства CloudFormation. Одним из ключевых изменений было удаление проприетарной составляющей, что позволило использовать инструмент для управления любым популярным облачным провайдером, сервисом или даже добавить собственную интеграцию в случае необходимости, поскольку он является open source.
Основой описания в Terraform стал собственный язык HCL (HashiCorp Configuration Language), который позволил создавать читабельный код, интегрировать встроенные функции и ссылаться на ресурсы без лишних проблем. Кроме того, Terraform работал с целыми папками, а не с отдельными файлами, что позволило разделить код на логические блоки и избежать создания огромных файлов с тысячами строк. Очень быстро была добавлена поддержка модулей и библиотек, а детализация планирования операций и логирование процесса выполнения были действительно на высоте. Отмечу также, что Terraform сразу использовал графовый движок и параллельно обрабатывал ресурсы, что значительно повышало его производительность по сравнению с CloudFormation того поколения.
Одной из основных проблем, связанных с "не проприетарностью", являлось управление состоянием и блокировками во время выполнения (когда несколько людей одновременно работают с одной и той же конфигурацией). Хотя эта проблема была оперативно решена с использованием ресурсов облачной инфраструктуры, она не стала настолько органично интегрированной, как в случае с CloudFormation. Кроме того, это добавляет ограничения при использовании вне облака, например только настроить PostgreSQL.
Далее возникали следующие сложности связанные с еще большим масштабированием:
Недостаток гибкости: требование большего количества функций, более удобного синтаксиса и поддержки циклов (для Terraform dсе это было реализовано с выходом HCL 2).
Потребность связывать между собой разные модули конфигурации и облачных провайдеров. То есть дать возможность настраивать multi cloud и писать инфраструктурный код с разбивкой по слоям
Высокий порог входа для разработчиков. Необходимо было изучить новый язык программирования, разобраться в устройстве облака, инфраструктурных компонентов и т.д.
Эпоха стабилизации
Здесь возникают 2 направления как вызовы уже имеющимся сложностям.
В конце 2015 года появилась первая версия Serverless фреймворка, которая была разработана с целью максимального упрощения жизни обычного разработчика. Он убрал детали и предоставил opinionated версию развертывания инфраструктуры. Это существенно упростило процесс написания небольших микросервисов. Serverless работал поверх AWS CloudFormation, поэтому движок выполнения был наиболее нативным, но сохранял все проблемы, о которых было упомянуто ранее. В случае, если простыми средствами не удавалось настроить конфигурацию, можно было обратиться к оригинальному CloudFormation и настроить через его. При дальнейшем усложнении системы, на каком-то этапе версия Serverless по сложности не сильно могла отличаться от чистого CloudFormation.
В 2016 вышел оркестратор над Terraform’ом - Terragrunt (уверен, были еще аналоги), цель которого повысить переиспользование кода, упростить поддержку больших конфигураций. С помощью него можно было еще раз шаблонизировать и параметризовать конфигурацию под разные окружения и больше переиспользовать имеющийся код (т.е. следовать принципу DRY), а также запускать выполнение сразу нескольких конфигураций.
Перечисленные инструменты существенно отличались своей целевой аудиторией. Serverless, в основном, нацелен на разработчиков бессерверных микросервисов на основе AWS Lambda, в то время как Terragrunt предназначен для DevOps-инженеров, работающих с большими конфигурациями. Однако, оба инструмента основаны на фундаменте уже существующих инструментов предыдущего поколения, что говорит о том, что эти исходные инструменты приобрели популярность и распространение, и у них есть четкая цель для дальнейшего развития.
Одним из главных вызовов в этот период стало стремление популяризировать эти инструменты и привлечь широкий круг инженеров, а также стирание границ между разработчиками и DevOps-инженерами.
Эпоха CDK
Я считаю, что следующую эпоху открыл выпуск AWS CDK (Cloud Development Kit) в 2019 году. Хотя на протяжении этого периода появилось множество новых инструментов, именно CDK совершил еще одну революцию, отвечая на потребности предыдущего периода - привлечение большего числа инженеров и разработчиков к написанию инфраструктурного кода. Он позволил описывать инфраструктуру с использованием знакомых программистам языковых конструкций, а затем преобразовывать результат в стек CloudFormation.
Таким образом, стало возможным избежать изучения нового синтаксиса и использовать всю мощь встроенных в язык функций, логических выражений и циклов. Хотя не все языки были сразу поддержаны, это был только вопрос времени. Теперь "Инфраструктура как Код" стала неотъемлемой частью процесса программирования, а не отдельной специализацией.
Были у AWS CDK и неоднозначные моменты. Во-первых, он работал поверх CloudFormation. Это означало, что он генерировал конфигурацию CloudFormation из кода и на этом его возможности заканчивались. Таким образом CDK сводился к красивой обертке над CloudFormation, а о его проблемах упоминалось выше. Во-вторых, мне, как человеку, который глубоко изучил синтаксис Terraform/HCL, Serverless и CloudFormation, показалось, что переход на обычный язык программирования, хоть и знакомый, скорее усложнял описание, чем помогал. Я считаю, что основной проблемой было необычное использование императивного языка в декларативном формате, в то время как специально разработанный язык HCL гораздо лучше подходил для таких операций. Однако, после наблюдения за реакцией разработчиков, которые ранее не работали с инфраструктурой, я понял, что для них AWS CDK гораздо более понятен, чем Terraform. Они быстро осваивались с использованием привычного языка программирования и легко создавали инфраструктурные ресурсы. Это доказало, что AWS CDK открывает двери для широкого круга разработчиков и делает процесс разработки инфраструктуры более доступным и интуитивным.
Спустя 3 года, в 2022 году Hashicorp пошел по тем же стопам и выпустил CDK для Terraform (CDKTF), что позволило разрабатывать инфраструктуру на привычном языке программирования, с дальнейшим преобразованием в Terraform, а не в CloudFormation. Такой подход предоставил разработчикам возможность использовать знакомый синтаксис и инструменты, но с преимуществами, которые предлагал Terraform для управления инфраструктурой.
В 2019 году также был выпущен open source продукт Pulumi, который, по моему мнению, является следующим этапом эволюции. Как и AWS CDK, он позволял описывать инфраструктуру на привычном императивном языке программирования, но не делал промежуточной трансформации в Terraform или CloudFormation. Это был свежий проект, не связанный с предыдущими итерациями. Кроме того, поскольку Pulumi являлся open source, он не был привязан к конкретному облаку, что добавляло гибкости и свободы в выборе платформы.
Эпоха AI
В 2023 году, все участники продолжают усиливать свой функционал и искать способы повысить эффективность разработки: писать код быстрее, выполнять отладку быстрее и понижать порог вхождения. Появляются и новые более экзотические подходы к описанию инфраструктуры. Например, продукт под названием IaSQL (Infrastructure as SQL) предлагает описывать всю инфраструктуру с помощью SQL запросов (на данный момент только для AWS). Лично я не являюсь фанатом SQL и даже не рассматривал такой подход, однако уверен найдется множество разработчиков, особенно DB-инженеров, которым это придется по душе. Кроме того, вопрос хранения состояния окружения в IaSQL надежно решен, так как основой этого продукта является Postgres, который его хранит.
Другое активное направление по ускорению разработки пришло из общего сектора - ChatGPT может помочь и здесь. Сейчас он в состоянии справляться с несложными конфигурациями Terraform некоторых провайдеров, а Pulumi уже выпустили AI модуль, который получил очень позитивные отзывы. Под капотом все тот же ChatGPT. Наиболее важная особенность бота здесь это возможность отредактировать изначально предложенную конфигурацию, что он и делает вполне грамотно.
Однако все же остается вопрос знаний автора: для редактирования необходимо иметь представление о том, что нужно изменить. То есть, требуются знания облачных технологий, при этом существенно снижается необходимость в знании конкретного инструмента. Больше нет необходимости заниматься рутинным написанием кода.
Заключение
Облачные платформы и инструменты автоматизации прошли несколько поколений, которые значительно ускорили процесс разработки и упростили его доступность. Однако, что остается неизменным и продолжает расти, так это сложность самих облачных систем. Еще ни один AI не предложил, как аккуратно вставить сгенерированную конфигурацию в имеющийся дизайн продакшн кодовой базы. Или как в этой кодовой базе настроить обратную связь для того, чтобы AI мог ее успешно оптимизировать. Таким образом текущие фичи по кодогенерации и AI перешли бы из категории начально уровня (снижение порога входа в программирование инфраструктуры) в профессиональную и стали бы настоящим подспорьем опытным инженерам.
Возможно, разработчики со временем и станут операторами ChatGPT, но вопрос о том, насколько результат будет оптимален, остается открытым. Освободившись от рутины, мы можем уделить больше времени изучению облачных платформ. Однако, будем ли мы стремиться к достижению оптимального результата или будем довольствоваться имеющимся кодогенератором и продолжать накапливать технический долг из-за необходимости действовать быстро или просто из-за лени? Ответ на этот вопрос зависит от ситуации, но ответить на него предстоит каждому конкретному инженеру.