Казалось бы, разработчики Terraform предлагают достаточно удобные рекомендации по работе с инфраструктурой AWS. Есть только нюанс.
Со временем количество сред увеличивается, каждая из которых имеет свои особенности.
В соседнем регионе появляется почти копия стека приложения.
А код Terraform нужно аккуратно скопировать и отредактировать под новые требования или превратить в снежинку.
Мой разговор о шаблонах в Terraform для борьбы с хаосом и ручной рутиной в больших и длительных проектах.
Видео:
Мне 40, я в IT 20 лет. Я работаю в Ixtens уже 12 лет. Мы занимаемся развитием электронной коммерции.
А практику DevOps я практикую уже 5 лет.
Мой рассказ будет о моем опыте работы в проекте в компании, название которой я не буду называть, прикрываясь подпиской о неразглашении.
Цифры на слайде указаны для того, чтобы понять масштаб проекта.
И все, что я скажу дальше, связано с Amazon.
Я присоединился к этому проекту 4 года назад. А рефакторинг инфраструктуры шел полным ходом, потому что проект разросся.
И те шаблоны, которые использовались, уже не подходили.
А учитывая весь запланированный рост проекта, нужно было придумать что-то новое.
Спасибо Матвею, который вчера рассказал нам, что произошло в «Додо Пицца».
Вот что произошло здесь 4 года назад. Пришли разработчики и начали писать инфраструктурный код. Наиболее очевидной причиной, по которой это требовалось, было время выхода на рынок.
Необходимо было обеспечить, чтобы команда DevOps не была узким местом во время развертывания.
И кроме всего прочего, Terraform и Puppet использовались на самом первом уровне.
Terraform — проект с открытым исходным кодом от HashiCorp. А для тех, кто даже не знает, что это такое, следующие несколько слайдов.
Инфраструктура как код означает, что мы можем описать нашу инфраструктуру и попросить некоторых роботов убедиться, что мы получаем описанные нами ресурсы.
Например, нам нужна виртуальная машина.
Опишем и добавим несколько обязательных параметров.
После этого настроим доступ к Amazon в консоли.
И мы попросим план Терраформирования.
План Терраформирования скажет: «Хорошо, мы можем сделать это для вашего ресурса».
И как минимум один ресурс будет добавлен.
И никаких изменений не предвидится.
Если вас все устраивает, вы можете попросить Terraform подать заявку, и Terraform создаст для вас экземпляр, и вы получите виртуальную машину в своем облаке.
Дальше наш проект развивается.
Мы добавляем туда некоторые изменения.
Просим больше экземпляров, добавляем 53 записи.
И мы повторяем.
Пожалуйста, планируйте.
Мы видим, какие изменения планируются.
Мы подаем заявку.
И именно так растет наша инфраструктура.
Terraform использует так называемые файлы состояния.
То есть он сохраняет все изменения, которые идут на Амазон, в файл, где для каждого ресурса, который Вы описали, есть соответствующие ресурсы, которые были созданы в Амазоне.
Таким образом, когда описание ресурса меняется, Terraform точно знает, что нужно изменить в Amazon.
Эти файлы состояния изначально были просто файлами.
И хранили мы их в Git, что было крайне неудобно.
Кто-то всегда забывал зафиксировать изменения, и возникало множество конфликтов.
Теперь можно использовать бэкенд, т.е.
в Terraform указывается, в каком бакете и по какому ключу должен быть сохранен файл состояния.
И Terraform сам позаботится о получении этого файла состояния, проделает всю магию и вернет конечный результат.
Наша инфраструктура растет. Вот наш код. И теперь мы хотим не просто создать виртуальную машину, мы хотим иметь тестовую среду.
Terraform позволяет создать такую вещь, как модуль, то есть описать одно и то же в какой-то папке.
И, например, при тестировании вызываем этот модуль и получаем то же самое, как если бы мы выполнили Terraform apply в самом модуле.
Для тестирования будет этот код.
Для производства мы можем отправлять туда некоторые изменения, поскольку в тестировании нам не нужны большие экземпляры; в продакшене большие экземпляры просто полезны.
А потом я вернусь обратно в проект. Это была непростая задача, запланированная инфраструктура была очень большой.
И нужно было как-то разместить весь код так, чтобы было удобно всем: и тем, кто выполняет обслуживание этого кода, и тем, кто вносит изменения.
И планировалось, что любой разработчик сможет пойти и починить инфраструктуру по мере необходимости для своей части платформы.
Это дерево каталогов, которое рекомендует сама HashiCorp, если у вас большой проект и имеет смысл разделить всю инфраструктуру на несколько небольших частей и описывать каждую часть в отдельной папке.
Имея обширную библиотеку ресурсов, вы можете вызывать примерно одно и то же и в тестировании, и в продакшене.
В нашем случае это не совсем подходило, потому что тестовый стек для разработчиков или для тестирования нужно было получить как-то попроще.
Но мне не хотелось перебирать папки и применять их в необходимой последовательности, и переживать, что база поднимется, а потом поднимется экземпляр, использующий эту базу.
Поэтому все тестирование запускалось из одной папки.
Там вызывались те же модули, но все делалось за один прогон.
Terraform позаботится обо всех зависимостях.
И он всегда создает ресурсы в такой последовательности, чтобы вы могли получить IP-адрес, например, из вновь созданного экземпляра, и получить этот IP-адрес в записи маршрута53. Кроме того, платформа очень большая.
А запустить тестовый стек, хоть на час, хоть на 8 часов — достаточно затратное мероприятие.
И мы автоматизировали это дело.
А работа Дженкинса позволила нам управлять стеком.
В нем нужно было запустить пул-реквест с изменениями, которые хочет протестировать разработчик, указать все необходимые опции, компоненты и размерности.
Если ему нужно тестирование производительности, он может взять больше экземпляров.
Если ему просто нужно проверить, открывается ли какая-то форма, то он мог бы начать с минимальной заработной платы.
А также указать, нужен кластер или нет и т.д. А затем Дженкинс запустил сценарий оболочки, который немного изменил код в папке Terraform. Я удалил ненужные файлы и добавил необходимые.
А затем с помощью одного запуска Terraform стек был поднят. А потом были и другие шаги, в которые я не хочу вдаваться.
В связи с тем, что для тестирования нам требовалось немного больше возможностей, чем в продакшене, нам пришлось делать копии модулей, чтобы в эти копии можно было добавить те функции, которые были нужны только для тестирования.
И так получилось, что на тестировании я как бы хочу протестировать те изменения, которые со временем пойдут в производство.
Но по факту тестировалось одно, а в производстве использовалось немного другое.
И произошел небольшой разрыв в схеме, согласно которой на производстве все изменения применялись командой эксплуатации.
А иногда оказывалось, что те изменения, которые должны были перейти из тестирования в производство, остались в другой версии.
Кроме того, возникла такая проблема, что был добавлен новый сервис, который немного отличался от какого-то уже существующего.
И вместо того, чтобы модифицировать существующий модуль, нам пришлось сделать его копию и внести необходимые изменения.
По сути, Terraform — это не настоящий язык.
Это декларация.
Если нам нужно что-то заявить, то мы это заявляем.
И все это работает. В какой-то момент, когда обсуждался один из моих пул-реквестов, один из моих коллег сказал, что создавать снежинки не нужно.
Мне было интересно, что он имеет в виду.
Существует научный факт, что в мире не бывает двух одинаковых снежинок, все они немного разные.
И как только я это услышал, я сразу почувствовал всю тяжесть кода Terraform. Потому что когда нужно было переходить от версии к версии, Terraform требовал разрыва цепочки изменений, т. е.
код переставал быть совместимым со следующей версией.
И нам пришлось сделать pull request, который охватывал почти половину файлов в инфраструктуре, чтобы довести инфраструктуру до следующей версии Terraform. И после появления такой снежинки весь код Terraform, который мы превратили в большую-большую кучу снега.
Для внешнего разработчика, находящегося вне эксплуатации, для него это не имеет большого значения, потому что он сделал пулл-реквест, его ресурс запустился.
И все, это уже не его забота.
И внести все эти изменения обязана команда DevOps, которая следит за тем, чтобы все было в порядке.
И стоимость этих изменений очень и очень возрастала с каждой дополнительной снежинкой.
Есть история о том, как студент на семинаре рисует мелом на доске два идеальных круга.
И учитель удивляется, как ему удалось так ровно рисовать без циркуля.
Студент отвечает: «Очень просто, я два года в армии крутил мясорубку».
И из четырех лет, что я занимаюсь этим проектом, я занимаюсь Terraform около двух лет. И, конечно, у меня есть некоторые хитрости, несколько советов, как упростить код Terraform, работать с ним как с языком программирования и снизить нагрузку на разработчиков, которые должны поддерживать этот код в актуальном состоянии.
Первое, с чего я хотел бы начать, — это символические ссылки.
В Terraform много повторяющегося кода.
Например, обращение к провайдеру практически в каждой точке, где мы создаём кусок инфраструктуры, один и тот же.
И логично положить его в отдельную папку.
И везде, где провайдер обязан сделать симлинки на этот файл.
Например, в рабочей среде вы используете предполагающую роль, которая позволяет вам получить права доступа к какой-либо внешней учетной записи Amazon. И изменив один файл, все остальные в дереве ресурсов будут иметь необходимые права, чтобы Terraform знал, к какому сегменту Amazon обращаться.
Где символические ссылки терпят неудачу? Как я уже сказал, в Terraform есть файлы состояния.
И они очень, очень крутые.
Но дело в том, что Terraform в первую очередь инициализирует бэкенд. И он не может использовать в этих параметрах какие-либо переменные; они всегда должны быть записаны в виде текста.
И в результате, когда кто-то делает новый ресурс, он копирует часть кода из других папок.
И он может ошибиться с ключом или с ведром.
Например, он делает из песочницы вещь-песочницу, а потом делает ее в производстве.
А так может оказаться, что ведро в производстве будет использоваться из песочницы.
Конечно, они его быстро найдут. Это можно будет как-то исправить, но тем не менее это пустая трата времени и в какой-то степени ресурсов.
Что мы можем сделать дальше? Прежде чем работать с Terraform, вам необходимо его инициализировать.
При инициализации Terraform загружает все плагины.
В какой-то момент они перешли от монолитной архитектуры к более микросервисной.
И всегда нужно делать Terraform init, чтобы он подтянул все модули, все плагины.
А можно использовать скрипт оболочки, который, во-первых, может получить все переменные.
Сценарий оболочки ничем не ограничен.
И, во-вторых, пути.
Если в качестве ключа к файлу состояния мы всегда будем использовать тот путь, который есть в репозитории, то, соответственно, ошибка здесь будет устранена.
Где я могу получить данные? JSON-файл.
Terraform позволяет писать инфраструктуру не только в hcl (языке конфигурации HashiCorp), но и в JSON. JSON легко читается из сценария оболочки.
Соответственно, вы можете поместить файл конфигурации с Bucket в какое-нибудь место.
И используйте это ведро как в коде Terraform, так и в скрипте оболочки для инициализации.
Почему важно иметь ведро для Terraform? Потому что существует такая вещь, как файлы удаленного состояния.
То есть, когда я поднимаю какой-то ресурс, чтобы сказать Amazon: «Пожалуйста, поднимите экземпляр», мне нужно указать очень много обязательных параметров.
И эти идентификаторы хранятся в какой-то другой папке.
И я могу пойти и сказать: «Терраформ, пожалуйста, зайди в файл состояния того самого ресурса и принеси мне эти идентификаторы».
И таким образом возникает определенная унификация между различными регионами или средами.
Не всегда возможно использовать файл удаленного состояния.
Например, вы создали VPC вручную.
А код Terraform, создающий VPC, создаёт настолько разные VPC, что это займёт очень много времени и придётся подгонять одно под другое, поэтому можно использовать следующий трюк.
То есть сделать модуль, который вроде бы делает VPC и как бы выдает вам идентификаторы, но на самом деле есть просто файл с жестко закодированными значениями, с помощью которого можно создать тот самый экземпляр.
Не всегда необходимо сохранять файл состояния в облаке.
Например, при тестировании модулей вы можете использовать бэкэнд-инициализацию, при которой файл будет просто сохранен на диске во время тестирования.
Теперь немного о тестировании.
Что можно протестировать в Terraform? Наверное, многое возможно, но я расскажу об этих 4-х вещах.
HashiCorp понимает, как следует форматировать код Terraform. И Terraform fmt позволяет вам форматировать редактируемый вами код в соответствии с этим убеждением.
Соответственно, тесты должны обязательно проверять, соответствует ли форматирование тому, что завещал HashiCorp, чтобы не было необходимости менять расположение скобок и т.п.
Следующий — проверка Terraform. Он делает немногим больше, чем проверяет синтаксис — аля, все ли круглые скобки парные.
Что здесь важно? Наша инфраструктура очень обширна.
В нем много разных пап.
И в каждом нужно запустить Terraform validate. Соответственно, чтобы ускорить тестирование, мы запускаем несколько процессов параллельно с помощью Parallel. Параллельность — очень классная штука, пользуйтесь.
Но каждый раз, когда Terraform инициализируется, он обращается к HashiCorp и спрашивает: «Какие последние версии плагинов? А плагин, который у меня в кеше – правильный или неправильныйЭ» И это замедлялось на каждом шагу.
Если вы сообщите Terraform, где находятся плагины, то Terraform скажет: «Хорошо, это, наверное, самое последнее, что там есть.
Я никуда не пойду, сразу начну валидировать ваш код Terraform».
Для того, чтобы наполнить папку необходимыми плагинами, у нас есть очень простой код Terraform, который нужно просто инициализировать.
Здесь, конечно, нужно указать всех провайдеров, которые так или иначе участвуют в вашем коде, иначе Terraform скажет: «Я не знаю определенного провайдера, потому что его нет в кеше».
Далее идет план Терраформирования.
Как я уже сказал, развитие циклично.
Вносим изменения в код. А дальше нужно узнать, какие изменения планируются в инфраструктуре.
А когда инфраструктура очень и очень большая, можно поменять один модуль, починить какое-то тестовое окружение или какой-то конкретный регион и сломать какой-то соседний.
Поэтому план Terraform должен быть составлен для всей инфраструктуры и показывать, какие изменения планируются.
Вы можете сделать это с умом.
Например, мы написали скрипт Python, который разрешает зависимости.
И в зависимости от того, что было изменено: модуль Terraform или просто конкретный компонент, он строит планы для всех зависимых папок.
Планы терраформирования должны быть составлены по запросу.
По крайней мере, мы так делаем.
Конечно, хорошо делать тесты под каждое изменение, под каждый коммит, но планы — штука довольно дорогая.
И в запросе на включение мы говорим: «Пожалуйста, дайте мне планы».
Робот запускается.
И присылайте в комментариях или прикрепляйте все планы, которые ожидаются от ваших изменений.
План – это довольно дорогая вещь.
Это требует времени, потому что Terraform обращается к Amazon и спрашивает: «Этот экземпляр еще существуетЭ» У этого автомасштабирования точно такие же параметрыЭ» А чтобы ускорить этот процесс, вы можете использовать такой параметр, какrefresh=false. Это означает, что Terraform загрузит состояние из S3. И поверит, что состояние будет в точности соответствовать тому, что есть в Amazon. Такой план Terraform проходит гораздо быстрее, но состояние должно соответствовать вашей инфраструктуре, т.е.
где-то, когда-то должно начаться обновление Terraform. Обновление Terraform делает именно это: состояние соответствует тому, что находится в реальной инфраструктуре.
И нам нужно поговорить о безопасности.
Вот с этого нам и пришлось начать.
Там, где вы запускаете Terraform и Terraform работает в вашей инфраструктуре, существует уязвимость.
То есть вы по сути выполняете код. А если пул-реквест содержит какой-то вредоносный код, то он может быть выполнен в инфраструктуре, имеющей слишком большой доступ.
Так что будьте осторожны при запуске плана Terraform.
Следующее, о чем я хотел бы поговорить, — это тестирование пользовательских данных.
Что такое пользовательские данные? В Amazon, когда мы создаем инстанс, мы можем отправить с инстансом определенное письмо — метаданные.
При запуске экземпляра обычно на этих экземплярах всегда присутствует облачная инициализация.
Cloud init читает это письмо и говорит: «ОК, сегодня я балансировщик нагрузки».
И в соответствии с этими заветами он совершает какие-то действия.
Но, к сожалению, когда мы создаем план Terraform и применяем Terraform, пользовательские данные выглядят как мешанина чисел.
То есть он просто отправляет вам хэш.
А в плане можно посмотреть только, будут ли какие-то изменения или хеш останется прежним.
И если не обратить на это внимание, то какой-нибудь битый текстовый файл может оказаться на Amazon, в реальной инфраструктуре.
Альтернативно, при выполнении можно указать не всю инфраструктуру, а только шаблон.
И в коде написать: «Пожалуйста, отобразите этот шаблон на моем экране».
И в результате вы можете получить распечатку того, как будут выглядеть ваши данные на Amazon.
Другой вариант — использовать модуль для генерации пользовательских данных.
Вы примените этот модуль.
Вы получаете файл на диске.
Сравните его с эталонным.
И таким образом, если какой-то парень решит немного подправить user-данные, то ваши тесты скажут: «ОК, тут и там есть какие-то изменения — это нормально».
Следующее, о чем я хотел бы поговорить, — это применение Automate Terraform. Конечно, делать применение Terraform в автоматическом режиме довольно страшно, потому что кто знает, какие изменения там произошли и насколько разрушительными они могут быть для живой инфраструктуры.
Для тестовой среды это все нормально.
То есть работа по созданию тестовой среды — это то, что нужно всем разработчикам.
И такое выражение, как «у меня всё работало» — это не смешной мем, а доказательство того, что человек запутался, поднял стек и провёл на этом стеке какие-то тесты.
И он убедился, что там всё хорошо, и сказал: «Хорошо, код, который я выпускаю, протестирован».
В производственной среде, песочнице и других средах, которые более критичны для бизнеса, вы можете частично использовать некоторые ресурсы совершенно безопасно, поскольку это не приводит к гибели людей.
Это: группы автомасштабирования, группы безопасности, роли, маршрут53, и список там может быть довольно большим.
Но следите за происходящим, читайте автоматические отчеты по заявкам.
Там, где применять опасно или страшно, например, если это какие-то постоянные ресурсы из базы данных, то получайте отчеты о том, что в каком-то участке инфраструктуры есть непримененные изменения.
А инженер под присмотром запускает задания по применению или делает это со своей консоли.
У Amazon есть такая штука, как прекращение защиты.
И может защитить в некоторых случаях от изменений, которые вам не нужны.
То есть Terraform зашёл на Amazon и сказал: «Мне нужно убить этот инстанс, чтобы сделать ещё один».
А Amazon говорит: «Извините, не сегодня.
У нас есть защита от прекращения действия».
И вишенкой на торте является оптимизация кода.
Когда мы работаем с кодом Terraform, нам приходится передавать в модуль очень большое количество параметров.
Это параметры, которые необходимы для того, чтобы создать какой-то ресурс.
И код превращается в большие списки параметров, которые нужно передавать из модуля в модуль, из модуля в модуль, особенно если модули вложенные.
И это очень сложно читать.
Пересмотреть это очень сложно.
И очень часто оказывается, что какие-то параметры подвергаются проверке и они не совсем те, что нужны.
И это требует времени и денег, чтобы исправить это позже.
Поэтому я предлагаю вам использовать такое понятие, как комплексный параметр, включающий в себя определенное дерево значений.
То есть вам нужна какая-то папка, где у вас будут все значения, которые вы хотели бы иметь в той или иной среде.
И вызвав этот модуль, можно получить дерево, которое генерируется в одном общем модуле, то есть в общем модуле, работающем одинаково для всей инфраструктуры.
В этом модуле вы можете выполнить некоторые вычисления, используя такую недавнюю функцию Terraform, как локальные значения.
А затем используйте один вывод для создания некоторого сложного параметра, который может включать хэши массива и т. д.
На этом все лучшие находки у меня закончились.
И мне хотелось бы рассказать историю о Колумбе.
Когда он искал деньги на свою экспедицию по открытию Индии (как он тогда думал), ему никто не верил и считали это невозможным.
Тогда он сказал: «Смотри, чтобы яйцо не упало».
Все банкиры, очень богатые и, наверное, умные люди, пытались как-то разместить яйцо, а оно продолжало падать.
Тогда Колумб взял яйцо и немного сжал его.
Скорлупа смялась, и яйцо осталось неподвижным.
Они сказали: «О, это слишком просто!» А Колумб ответил: «Да, это слишком просто.
И когда я открою Индию, все будут использовать этот торговый путь».
И то, что я вам только что рассказал, это, наверное, довольно простые и тривиальные вещи.
А когда ты о них узнаешь и начнешь ими пользоваться, это в порядке вещей.
Так что воспользуйтесь.
И если для вас это совершенно нормальные вещи, то вы хотя бы знаете, как расположить яйцо, чтобы оно не упало.
Подведем итоги:
- Старайтесь избегать снежинок.
И чем меньше снежинок, тем меньше ресурсов вам понадобится для внесения каких-либо изменений в вашу большую инфраструктуру.
- Постоянные изменения.
То есть, когда в коде происходят какие-то изменения, вам нужно как можно быстрее привести свою инфраструктуру в соответствие с этими изменениями.
Не должно быть ситуации, когда кто-то приходит посмотреть на Elasticsearch через два-три месяца, составляет план Terraform, а там куча изменений, которых он не ожидал.
И нужно много времени, чтобы привести все в порядок.
- Тесты и автоматизация.
Чем больше ваш код покрыт тестами и функциями, тем больше у вас уверенности, что вы все делаете правильно.
А автоматическая доставка повысит вашу уверенность во много раз.
- Код для тестовой и производственной среды должен быть практически одинаковым.
Практически, потому что производство все же немного другое и все равно будут некоторые нюансы, выходящие за рамки тестовой среды.
Но тем не менее, плюс-минус, это можно обеспечить.
- А если у вас много кода Terraform и на поддержание этого кода в актуальном состоянии уходит много времени, то никогда не поздно провести рефакторинг и привести его в хорошую форму.
- Неизменяемая инфраструктура.
Доставка АМИ по графику.
- Структура для
-
Поймите Доступные Варианты Интернет-Услуг
19 Oct, 24 -
Что Делать После Создания Веб-Сайта
19 Oct, 24 -
Новый Подход К Древней Панграмме
19 Oct, 24 -
Среды Развертывания Программного Обеспечения
19 Oct, 24 -
Основы Безопасности Интернета Вещей
19 Oct, 24 -
Карты Google 4.1
19 Oct, 24 -
Используете Ли Вы Социальные Закладки?
19 Oct, 24 -
Репортаж С Игромира — 2009
19 Oct, 24 -
Генератор Прелоадера (Индикатора Загрузки)
19 Oct, 24