Хабрахабр

[Перевод] Перешел с Terraform на CloudFormation — и пожалел

За этой практикой закрепилось название — Infrastructure as Code, и пока что для ее осуществления, особенно в AWS, есть два популярных инструмента: Terraform и CloudFormation. Представлять инфраструктуру в виде кода в повторяемом текстовом формате — простая лучшая практика для систем, с которой не нужно мышевозить.


Сравниваю опыт работы с Terraform и CloudFormation

На новом месте я тоже вовсю использовал Terraform, а потом компания продавила переход на все а-ля Amazon, включая CloudFormation. До прихода в Twitch (он же Amazon Jr.) я трудился в одном стартапе и года три использовал Terraform. Позднее, вдумчиво взвесив последствия перехода с Terraform на CloudFormation, я убедился, что Terraform, наверное, — лучший выбор для организации. Я усердно разрабатывал лучшие практики и для того, и для другого, и оба инструмента использовал в очень сложных рабочих процессах в масштабах организации.

Terraform Ужасный

Бета-версия ПО

0, и это — веская причина им не пользоваться. У Terraform еще даже не вышла версия 1. Я бы сказал, что "сейчас-то все по-другому", но… так вроде все говорят, нет? С тех пор, как я сам его впервые опробовал, он сильно изменился, но тогда еще terraform apply часто ломался после нескольких обновлений или просто через пару лет эксплуатации. Инструмент как будто правда стал лучше, но… :-0 Есть изменения, несовместимые с предыдущими версиями, хотя они уместны, и даже чувство такое, что синтаксис и абстракции хранилищ ресурсов теперь что надо.

Все, наверное, потому, что их сервисы часто хорошенько тестируют внутри организации и лишь потом, переименовав, публикуют. С другой стороны, AWS хорошо постаралась, поддерживая совместимость с предыдущими версиями. Поддерживать совместимость с предыдущими версиями API для такой многовариантной и сложной системы, как AWS, невероятно тяжело. Так что "хорошо постарались" это еще слабо сказано. А вот поведение CloudFormation на моей памяти ни разу с годами не изменилось. Любой, кому приходилось поддерживать общедоступные API, используемые так же широко, должен понимать, как трудно это делать на протяжении стольких лет.

Знакомься, нога… это пуля

Примерно так же дело обстоит и с Terraform. Насколько я знаю, удалить ресурс постороннего стека CloudFormation из своего стека CF невозможно. Функция, можно сказать, потрясающая, но с большой силой приходит и большая ответственность. Он позволяет импортировать существующие ресурсы в свой стек. Однажды это аукнулось. Стоит только занести ресурс в стек и, пока ты работаешь со своим стеком, удалить или изменить этот ресурс нельзя. Ввел несколько команд и… группа безопасности (вместе со входящим трафиком) исчезла. Как-то на сайте Twitch кто-то, не замышляя ничего дурного, случайно импортировал чью-то группу безопасности AWS в свой собственный стек Terraform.

Terraform Великий

Восстановление из неполных состояний

При этом он постарается вернуться к предыдущему. Иногда CloudFormation не может полностью перейти из одного состояния в другое. Отлаживать потом то, что получилось, бывает страшноватенько — никогда не знаешь, обрадуется ли CloudFormation, что его взламывают — пусть и для починки. Жаль, это не всегда осуществимо. А получится или нет вернуться к предыдущему состоянию, он толком определять не умеет и по умолчанию часами висит в ожидании чуда.

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

Более ясные изменения в состояния документа

Но как?" "Ладно, балансировщик нагрузки, ты меняешься.

—обеспокоенный инженер, готовый нажать кнопку "принять".

ClouFormation изменения отображает слабо. Иногда мне нужно проделать кое-какие манипуляции с балансировщиком нагрузки в стеке CloudFormation — например, добавить номер порта или изменить группу безопасности. Я же, как на иголках, раз по десять перепроверяю файл yaml, чтобы убедиться, что ничего нужного не стер, а лишнего — не добавил.

Порой он даже слишком прозрачен (читай: достает). Terraform в этом плане куда прозрачнее. К счастью, в последнюю версию включили улучшенное отображение изменений — теперь точно видно, что изменяется.

Гибкость

Пишите ПО от обратного.

Любое ПО пишите от обратного. Говоря прямо, самая важная отличительная черта долгоживущего ПО — это способность адаптироваться к изменениям. И конечно же, спустя месяцы вскрывалось, что я все понял не так, и сервис-то на самом деле не простой! Я вот чаще всего прокалывался на том, что брал "простенький" сервис, а потом принимался впихивать все в единый стек CloudFormation или Terraform. Когда работаешь с CloudFormation, сделать это возможно, только предварительно воссоздав существующий стек, а этого я, со своими БД, не делаю. И вот мне нужно неким образом разбить большой стек на малые составляющие. Terraform же позволял препарировать стек и расчленить его на более понятные меньшие части.

Модули в git

С Terraform можно поместить код в репозиторий git и обращаться к нему, используя семантический контроль версий. Делиться кодом Terraform между многочисленными стеками гораздо проще, чем кодом CloudFormation. Эквивалент от CloudFormation — S3, но у него нет тех же преимуществ, и нет ни одной причины, по которой нам вообще стоит отказаться от git в пользу S3. Любой, у кого есть доступ в этот репозиторий, может заново использовать общий код.

С Terraform все это получается легко и естественно, тогда как CloudFormation заставит вас попрыгать через кольца, прежде чем у вас заработает нечто подобное. Организация росла и способность делиться общими стеками достигла критического уровня.

Operations as code

"Заскриптуем и ладно".

—инженер за 3 года до того, как изобрести велосипед Terraform.

Когда речь о разработке ПО, то Go или программа на Java — это не просто код.


Code as Code

Есть ведь еще инфраструктура, на которой она работает.


Infrastructure as Code

Как ее мониторить? Но откуда она там? Нужно ли разработчикам разрешение на доступ? Где обитает ваш код?


Operations as Code

Быть разработчиком ПО — это вам не просто код писать.

SignalFx, PagerDuty или Github. Не AWS единым: вы наверняка пользуетесь услугами других поставщиков. Infra as Code выбирают по разным причинам, и любая одинаково важна для всего, связанного с ПО. Может быть, у вас есть внутренний сервер Jenkins для CI/CD или внутренняя панель управления Grafana для мониторинга.

Мы штамповали и поддерживали множество микросервисов, увеличивая эксплуатационные издержки. Когда я работал в Twitch, мы ускоряли сервисы внутри смешанных встроенных систем и систем AWS Amazon'а. Обсуждения проходили примерно в таком ключе:

  • Я: Блин, многовато телодвижений для разгона одного микросервиса. Мне вот эту фигню придется использовать, чтобы создать AWS аккаунт (мы шли к 2 аккаунтам на микросервис), потом эту — для настройки оповещений, еще эту — для репозитория кода, и эту — для списка адресов электронной почты, ну и вот эту...
  • Лид: Заскриптуем и ладно.
  • Я: Лады, но сам скрипт изменится. Нужен будет способ, как проверить, что все эти встроенные штуковины amazon'а имеют актуальное состояние.
  • Лид: Звучит неплохо. И для это скрипт напишем.
  • Я: Отлично! А скрипту наверняка еще надо будет задать параметры. Примет он их?
  • Лид: Да примет, куда денется!
  • Я: Процесс может измениться, потеряется обратная совместимость. Потребуется какой-нибудь семантически контроль версий.
  • Лид: Отличная идея!
  • Я: Инструменты можно изменить вручную, внутри пользовательского интерфейса. Нам потребуется способ, как это проверять и исправлять.

3 года спустя: ...

  • Лид: И получился у нас terraform.

Мораль басни такова: даже если вы по уши во всем amazon'овском, вы все равно пользуетесь чем-нибудь не от AWS, и у этих сервисов есть состояние, которое использует язык для конфигурации, чтобы это состояние синхронизировать.

CloudFormation lambda vs git-модули terraform

С помощью lambda можно создавать макросы или пользовательский ресурс. lambda — это решение CloudFormation для вопроса пользовательской логики. Для меня самой насущной проблемой стало управление разрешениями для всех этих пользовательских lambda (а это десятки аккаунтов AWS). Такой подход представляет дополнительные сложности, которых нет в семантическом контроле версий модулей git у Terraform. Сама эта функция — инфраструктура и код, и она сама нуждается в мониторинге и обновлениях. Другой по важности стала проблема типа "что было раньше — курица или яйцо?": она была связана с кодом lambda. Последним гвоздем в гроб стала трудность в семантическом обновлении изменений кода lambda; еще нужно было сделать так, чтобы действия стека без прямой команды не менялись между запусками.

Проще всего было бы сделать второе развертывание для EB рядом с производственной средой, сделав еще шаг: объединив автоматически масштабируемую группу канареечного деплоя с LB развертывания в производственную среду. Помню, как-то захотелось мне создать канареечный деплой для среды Elastic Beanstalk с классическим балансировщиком нагрузки. Когда я поинтересовался, нет ли сопоставимого решения в CloudFormation, мне указали на целый репозиторий в git с конвейером развертывания и прочим: и все это — ради того, что могли бы сделать несчастные 4 строчки кода Terraform. А раз Terraform использует ASG beantalk как вывод, это потребует 4 лишние строки кода в Terraform.

Он лучше обнаруживает дрейф

Убедитесь, что реальность соответствует ожиданиям.

Она доступна и с CloudFormation и с Terraform. Обнаружение дрейфа — очень мощная функция operations as code, потому что помогает убедиться, что реальность соответствует ожиданиям. Но по мере роста рабочего стека поиск дрейфа в CloudFormation выдавал все больше ложных обнаружений.

Например, вы вводите команду ignore_changes прямо в определении задачи ECS, если хотите игнорировать изменения в определении какой-то конкретной задачи, не игнорируя при этом изменения во всем развертывании ECS. С Terraform у вас есть гораздо более продвинутые хуки жизненного цикла для обнаружения дрейфа.

CDK и будущее CloudFormation

Многие из этих трудностей признаны, и инструменту нужны такие вещи как aws-cdk, структура для определения облачной инфраструктуры в коде и проведения ее через AWS CloudFormation. CloudFormation трудно управлять в крупных, межинфраструктурных масштабах. Будет любопытно взглянуть, что ждет aws-cdk в будущем, но ему трудно будет состязаться с другими преимуществами Terraform; чтобы подтянуть CloudFormation, потребуются глобальные изменения.

Чтобы Terraform не разочаровал

Это же "инфраструктура как КОД", а не "как текст".

Думаю, я просто не понял подхода. Первое впечатление от Terraform у меня сложилось довольно дурное. НЕ НАДО ТАК. Почти все инженеры по первой невольно воспринимают его как текстовый формат, который надо преобразовать в желаемую инфраструктуру.

Прописные истины хорошей разработки ПО относятся и к Terraform

Вы годами учились, чтобы стать хорошим программистом. Я видел, как многие практики, принятые для создания хорошего кода, игнорируются в Terraform. Прописные истины хорошей разработки ПО относятся и к Terraform. Не отказывайтесь от этого опыта просто потому, что работаете с Terraform.

Как уж код и не задокументировать?

Как можно писать код страницами — совершенно без документации? Мне попадались огромные стеки Terraform совершенно без документации. Добавляйте документацию, в которой объясняется ваш код Terraform (ударение здесь на слово "код"), почему этот раздел так важен, и что вы делаете.

Как можно разворачивать сервисы, которые некогда были одной большой функцией main()?

Почему мы так не разворачиваем ПО? Мне встречались очень сложные стеки Terraform, представленные в виде единого модуля. Те же ответы справедливы и для Terraform. Зачем дробим крупные функции на более мелкие? Если модуль у вас слишком велик — надо его разбить на модули поменьше.

Разве ваша компания не пользуется библиотеками?

Вот вы у себя в компании стали бы работать так с "боевым" кодом? Я видел, как инженеры, раскручивая новый проект при помощи Terraform, тупо копи-пейстили громадные куски из других проектов в свои собственные, а потом ковыряли их, пока не начинало работать. Да, не все должно быть библиотекой, но куда мы без общих библиотек в принципе?! Мы же не просто так пользуемся библиотеками.

Разве вы не пользуетесь PEP8 или gofmt?

В Python это PEP8. В большинстве языков есть стандартная принятая схема форматирования. У Terraform есть свой: terraform fmt. В Go — gofmt. Пользуйтесь на здоровье!

Вы станете пользоваться React, не зная JavaScript?

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

Вы кодите синглтонами, или внедряя зависимости?

Как это пригодится в Terraform? Внедрение зависимостей — признанная лучшая практика для разработки ПО, которую предпочитают синглтонам. Вместо того, чтобы писать модули, извлекающие из удаленного состояния, напишите модуль, который принимает параметры. Мне встречались модули Terraform, зависящие от удаленного состояния. А потом передайте эти параметры в модуль.

Ваши библиотеки делают десять вещей хорошо или одну — отлично?

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

Как вы производите изменения в библиотеках без обратной совместимости?

Когда происходят такие изменения в библиотеках, это раздражает, и точно так же раздражает, когда изменения без обратной совместимости производятся в модулях Terraform. Общему модулю Terraform, как и обычной библиотеке, нужно как-то сообщать пользователям об изменениях без обратной совместимости. Рекомендуется применять git tags и semver при использовании модулей Terraform.

Производственный сервис запущен у вас на ноутбуке или в датацентре?

Эти централизованные сервисы облегчают управление, аудит и одобрение изменений terraform. У Hashicorp есть инструменты вроде terraform cloud для запуска вашего terraform.

Разве вы не пишете тесты?

Для инфраструктуры это чревато коварными моментами. Инженеры признают, что код нужно тестировать, но сами при этом часто забивают на проверки, работая с Terraform. Я советую "тестировать" или "создавать примеры" стеков с использованием модулей, которые можно корректно задеплоить для проверки во время CI/CD.

Terraform и микросервисы

Жизнь и смерть микросервисных компаний зависит от скорости, обновления и разрушения новых микросервисных рабочих стеков.

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть