Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Здавалося б, розробники Terraform пропонують досить зручні best practices для роботи з AWS-інфраструктурою. Лише є нюанс. Згодом кількість оточень збільшується, у кожному з'являються особливості. З'являється майже копія стека додатків у сусідньому регіоні. І Terraform-код потрібно акуратно скопіювати та відредагувати відповідно до нових вимог чи зробити сніжинку.

Моя доповідь про патерни в Terraform для боротьби з хаосом та ручною рутиною на великих та довгих проектах.

Відео:

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Мені 40, я 20 років у IT. 12 років працюю у компанії Ixtens. Ми займаємося ecommerce-driven-development. І 5 років практикую DevOps-практики.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Моя розповідь буде про досвід у проекті в компанії, назва якої я не говоритиму, прикриваючись угодою про нерозголошення.

Цифри на слайді вказані для того, щоб розуміти масштаб проекту. І все, що я далі говоритиму, пов'язане з Amazon.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Я приєднався до цього проекту 4 роки тому. І в самому розпалі проходив рефакторинг інфраструктури, бо проект зріс. І ті патерни, які використовувалися, вони вже не пасували. І з огляду на все заплановане зростання проекту, треба було щось вигадати нове.

Спасибі Матвієві, який учора розповів, що у них відбувалося у Додо Піца. Це те, що відбувалося у нас 4 роки тому.

Прийшли розробники та почали робити інфраструктурний код.

Найочевидніші моменти, чому це потрібно було потрібно time to market. Потрібно було зробити так, щоб DevOps-команда була вузьким місцем при викочуванні. І крім усього іншого на першому рівні використовувалися Terraform і Puppet.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Terraform - це open source проект компанії HashiCorp. І для тих, хто взагалі не знає, що це, наступні кілька слайдів.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Інфраструктура як код – це означає, що ми можемо описати нашу інфраструктуру і попросити якихось роботів зробити так, щоб ми отримали ресурси, які ми описали.

Наприклад, нам потрібна віртуальна машина. Ми опишемо, додамо кілька обов'язкових параметрів.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Після цього в консолі налаштуємо доступ до Amazon. І попросимо Terraform plan. Terraform plan скаже: «Ок, для вашого ресурсу ми можемо зробити такі штуки». І, як мінімум, один ресурс буде додано. І жодних змін не передбачається.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Після того, як вас все влаштувало, ви можете попросити Terraform apply і Terraform створить вам instance, і ви отримаєте віртуальну машину у вашій хмарі.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Далі наш проект розвивається. Ми додаємо туди якісь зміни. Ми просимо більше instances, ми додаємо 53 запис.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

І повторюємо. Просимо plan. Бачимо які зміни плануються. Застосовуємо. І в такий спосіб наша інфраструктура зростає.

Terraform використовує таку штуку як state-файли. Т. е. всі зміни, які йдуть на Amazon, він зберігає у файлі, де для кожного ресурсу, який ви описали, є відповідні ресурси, які були створені в Amazon. Таким чином, при зміні опису якогось ресурсу, Terraform точно знає, що саме потрібно поміняти в Amazon.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Ці state-файли спочатку були просто файлами. І ми їх зберігали у Git, що було вкрай незручно. Постійно хтось забував прокоммітити зміни і виникало багато конфліктів.

Зараз є можливість використовувати бекенд, т. е. Terraform вказується в який bucket, яким ключем потрібно зберегти state-файл. І Terraform сам подбає про те, щоб дістати цей state-файл, зробити всю магію та покласти назад фінальний результат.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Наша інфраструктура зростає. Ось наш код. І тепер ми не хочемо просто створювати віртуальну машину, ми хочемо мати тестове оточення.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Terraform дозволяє зробити таку штуку як модуль, тобто те саме описати в якійсь папці.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

І, наприклад, в тестингу викликати цей модуль і отримати те саме, що ми виконували Terraform apply в самому модулі. Для тестингу буде такий код.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Для production ми можемо послати туди якісь зміни, тому що в тестингу нам не потрібні великі instances, у production великі instances якраз знадобляться.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

І далі я повернуся назад до проекту. Було складне завдання, інфраструктура планувалась дуже великою. І потрібно було якось розмістити весь код, щоб це було зручно для всіх: і для тих, хто здійснює maintenance над цим кодом, і для тих, хто вносить зміни. А планувалося, що будь-який розробник може піти та поправити інфраструктуру так, як потрібно для його частини платформи.

Це дерево каталогів, яке рекомендується самим HashiCorp, якщо у вас великий проект і є сенс розділити всю інфраструктуру на якісь маленькі шматочки, і кожні шматочки описувати в окремій татці.

Маючи велику бібліотеку ресурсів можна в тестингу і в production викликати приблизно те саме.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

У нашому випадку це не зовсім підходило, тому що тестовий стек для розробників або для тестування потрібно було отримувати якось простіше. А ходити по таткам і застосовувати в потрібній послідовності, і турбуватися про те, що база підніметься, а потім підніметься instance, який використовує цю базу, не хотілося. Тому весь тестинг запускався із однієї папки. Там викликалися ті самі модулі, але проходило все за один прогін.

Terraform турбується про всі залежності. І завжди створює ресурси в тій послідовності, щоб можна було отримати IP-адресу, наприклад, від свіжоствореної instance, і отримати цю IP-адресу в route53 запис.

Окрім цього, платформа дуже велика. І запуск тестового стека, навіть якщо на годину, навіть якщо на 8:XNUMX – це досить дорога справа.

І ми автоматизували цю справу. І Jenkins job дозволяв запускати стек. У ньому потрібно було запускати pull request зі змінами, які хоче розробник протестувати, вказати всі необхідні опції, компоненти, а також розміри. Якщо він хоче ефективності тестування, то він може більше взаймах взяти. Якщо йому потрібно просто перевірити, що якась форма відкривається, то міг стартанути на мінімалках. А також вказати потрібний кластер або не потрібний і т.д.

І потім Jenkins штовхав shell-скрипт, який трохи модифікував код у папці Terraform. Забирав непотрібні файли, додавав потрібні файли. І потім одним прогоном Terraform apply стек піднімався.

А далі вже йшли інші кроки, в які я не хочу заглиблюватись.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Через те, що для тестингу нам потрібно трохи більше опцій, ніж у production, нам доводилося робити копії модулів, щоб у цих копіях можна було додати ті фічі, які потрібні тільки в тестингу.

І так вийшло, що в тестингу хочеться протестувати ті зміни, які в результаті підуть на production. Але насправді тестувалося одне, а в production застосовувалося трохи інше. І був невеликий розрив шаблону, що в production всі зміни застосовувалися operation командою. І іноді виходило так, що ті зміни, які мали з тестингу перейти до production, вони залишалися в іншій версії.

Крім цього була така проблема, що додавався новий сервіс, який трохи відрізнявся від якогось вже існуючого. І замість модифікувати існуючий модуль, доводилося робити його копію і додавати необхідні зміни.

По суті, Terraform – це справжня мова. Це декларація. Якщо нам потрібно щось задекларувати, ми це декларуємо. І все це працює.

Якогось моменту, коли обговорювався один із моїх pull request, один із колег сказав, що не потрібно плодити сніжинки. Я зацікавився, що він має на увазі. Є такий науковий факт, що у світі не існує двох однакових сніжинок, усі вони трохи та відрізняються. І як тільки я це почув, я відразу відчув весь тягар Terraform-коду. Тому що коли потрібно було перейти з версії на версію, Terraform вимагав breaking chain зміни, тобто код більше не був сумісний з наступною версією. І доводилося робити pull request, який покривав майже половину файлів в інфраструктурі, щоби привести інфраструктуру до наступної версії Terraform.

І після того, як з'явилася така сніжинка, весь Terraform-код, який у нас був, перетворювався на велику купу снігу.

Для зовнішнього розробника, який не працює, для нього це не має великого значення, тому що він зробив pull request, його ресурс запустився. І все, далі не його турбота. А команді DevOps, які стежать за тим, щоб все було Ок, потрібно робити всі ці зміни. І вартість цих змін дуже зростала з кожною додатковою сніжинкою.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Є така історія про те, як студент на семінарі малює крейдою на дошці два ідеальні кола. І викладач дивується, як йому вдалося так без циркуля намалювати. Студент відповідає: "Дуже просто, я два роки в армії крутив м'ясорубку".

І з тих чотирьох років, у яких я беру участь у цьому проекті, близько двох років я займаюся Terraform. І, звичайно, у мене є якісь фішки, деякі поради, як можна спростити Terraform-код, працювати з ним, як з мовою програмування та зменшити навантаження на розробників, які мають підтримувати цей код у актуальному стані.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Перше, з чого я хотів би почати, це Symlinks. Terraform має багато коду, що повторюється. Наприклад, виклик провайдера практично в кожній точці, де ми створюємо шматочок інфраструктури, один і той же. І логічно винести його в окрему татку. І скрізь, де потрібно провайдер робити Symlinks на цей файл.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Наприклад, у вас в production використовується assume role, який дозволяє отримати права доступу на якийсь зовнішній Amazon-акаунт. І помінявши один файлик, всі, що залишилися, які в дереві ресурсів, матимуть необхідні права, щоб Terraform знав до якого Amazon-сегменту звертатися.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Де Symlinks не працюють? Як і говорив, у Terraform є state-файли. І вони дуже класні. Але справа в тому, що Terraform ініціалізує бекенд у першому. І він не може використовувати в цих параметрах будь-які змінні, їх потрібно писати текстом.

І як результат, коли хтось робить новий ресурс, він копіює частину коду з інших папок. І він може помилитися з ключем чи з bucket. Наприклад, він з sandbox робить sandbox-штуку, а потім робить у production. І так може виявитися, що bucket у production буде використовуватися з sandbox. Звісно, ​​це швидко знайдуть. Можна буде це якось виправити, але це втрата часу і в якійсь мірі ресурсів.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Що ми можемо зробити далі? Перед тим, як працювати з Terraform, треба його проініціалізувати. У момент ініціалізації Terraform викачує всі плагіни. Вони рано чи пізно з моноліту розбилися на більш мікросервісну архітектуру. І завжди потрібно робити Terraform init, щоб він підтягнув усі модулі, усі плагіни.

І можна використовувати shell-скрипт, який по-перше зможе дістати всі змінні. Shell-скрипт нічим не обмежений. А, по-друге, шляхи. Якщо ми завжди використовуємо той шлях, який у репозиторії як ключ до state-файлу, то, відповідно, помилку тут буде виключено.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Звідки дістати дані? JSON файл. Terraform дозволяє записувати інфраструктуру не тільки у hcl (HashiCorp Configuration Language), а й у JSON.

JSON легко читається зі shell-скрипту. Відповідно, можна в якесь місце покласти конфігураційний файл із bucket. І використовувати цей bucket і в Terraform-коді, і в shell-скрипті для ініціалізації.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Чому важливо мати bucket для Terraform? Тому що є така штука, як remote state-файли. Т. е. коли я піднімаю якийсь ресурс, мені для того, щоб сказати Amazon: «Підніми, будь ласка, instance», потрібно вказати дуже багато обов'язкових параметрів.

І ці ідентифікатори зберігаються в якійсь іншій татку. І я можу взяти і сказати: "Terraform, збігай, будь ласка, в state-файл того самого ресурсу і дістань мені ці ідентифікатори". І таким чином з'являється певна уніфікація між різними регіонами чи природними середовищами.

Не завжди можна використовувати віддалений state-файл. Наприклад, ви створили VPC руками. І той Terraform-код, який створює VPC, створює настільки несхожий VPC, що дуже довго і потрібно вам доведеться підлаштовувати одне під інше, тому можна використовувати наступну фішку.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Т. е. зробити модуль, який робить VPC і як би видає вам ідентифікатори, а насправді просто є файлик з захардшкіреними значеннями, який можна використовувати для створення того ж instance.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Не завжди потрібно зберігати state-файл у хмарі. Наприклад, коли тестуються модулі, можна використовувати ініціалізацію бекенда, коли файл зберігатиметься просто на диску на момент тестування.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Тепер трохи для тестування. Що у Terraform можна тестувати? Напевно, багато можна, але я говоритиму про ось ці 4 штучки.

HashiCorp має розуміння, як потрібно форматувати Terraform-код. І Terraform fmt дозволяє вам відформатувати код, який ви редагуєте у відповідність до цієї віри. Відповідно, тести повинні обов'язково перевірити, чи відповідає форматування тому, що заповідав HashiCorp, щоб не доводилося змінювати розташування дужок і т.д.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Наступний це Terraform validate. Він робить трохи більше, ніж перевірку синтаксису - аля, чи всі дужки парні. Що тут важливе? У нас інфраструктура дуже розлога. У ній дуже багато різних папок. І в кожній потрібно запустити Terraform validate.

Відповідно, щоб прискорити тестування, ми запускаємо кілька процесів паралельно, використовуючи паралель.

Паралель – це класна штука, користуйтеся.

Але щоразу, коли відбувається ініціалізація Terraform, він йде на HashiCorp і запитує: «Які останні версії плагінів? А той плагін, який у мене кеше – він той чи не той?». І це щокроку давало своє уповільнення.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Якщо Terraform підказати, де лежать плагіни, то Terraform скаже: «Ок, напевно, це найсвіжіше, що є. Я не нікуди ходити, я відразу почну валідувати ваш Terraform-код».

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Для того, щоб наповнити татку потрібними плагінами, у нас є дуже простий Terraform-код, який потрібно просто проініціалізувати. Тут, звичайно, потрібно вказати всіх провайдерів, які беруть участь у вашому коді, інакше Terraform скаже: «Я не знаю якогось провайдера, тому що його немає в кеші».

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Наступне це Terraform plan. Як і казав, технологія – циклічна. Ми робимо код із змінами. І потім слід дізнатися, які зміни плануються на інфраструктуру.

І коли інфраструктура дуже велика, можна поміняти один модуль, полагодити якесь тестове оточення або який-небудь конкретний регіон і зламати якийсь сусідній. Тому Terraform plan має робитися на всю інфраструктуру та показувати, які зміни плануються.

Робити це можна по розумному. Ми, наприклад, написали скрипт на Python, який розрізняє залежності. І в залежності від того, що було змінено: Terraform-модуль або просто якийсь конкретний компонент, він планує всі залежні папочки.

Terraform plan повинні робити на запит. Принаймні це те, що робимо ми.

Тести, звичайно, добре робити на кожну зміну, на кожен коміт, але плани – це досить дорога штука. І ми в pull request говоримо: Будь ласка, дай мені плани. Запускається робот. І надсилає в коментарі або в attach всі плани, які передбачаються від ваших змін.

План – річ досить дорога. Вона займає час, тому що Terraform йде в Amazon і запитує: «А ця instance ще існує? А у цього autoscale такі параметри?». І щоб це прискорити, можна використовувати такий параметр, як refresh=false. Це означає, що Terraform викачає із S3 state. І буде вірити, що state точно відповідатиме тому, що знаходиться в Amazon.

Такий Terraform plan проходить набагато швидше, але state повинен відповідати вашій інфраструктурі, тобто десь колись повинен запуститися Terraform refresh. Terraform refresh робить саме те, щоб state відповідав тому, що знаходиться в реальній інфраструктурі.

І треба сказати про безпеку. Із цього й треба було починати. Там, де ви запускаєте Terraform і Terraform працює з вашою інфраструктурою, є вразливість. Т. е. Ви, по суті, виконуєте код. І якщо pull request містить якийсь шкідливий код, він може виконатися на інфраструктурі, яка має занадто багато доступу. Тому будьте уважні де ви запускаєте Terraform plan.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Наступне, що я хотів би розповісти, це тестування user-data.

Що таке user-data? У Amazon, коли ми створюємо instance, ми можемо з instance надіслати якийсь лист – мета-дані. Коли instance запускається, зазвичай cloud init завжди присутній на цих instances. Cloud init зчитує цей лист і каже: "Ок, сьогодні я - load balancer". І відповідно до цих завітів робить якісь дії.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Але, на жаль, коли ми робимо Terraform plan і Terraform apply, user-data виглядає, як ось така кашка із цифр. Т. е. він просто надсилає вам хеш. І все, що ви можете подивитися в плані, це будуть якісь зміни або хеш залишиться тим самим.

І якщо на це не звертати увагу, то на Amazon, на реальну інфраструктуру може піти якийсь побитий текстовий файл.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Як варіант, можна при виконанні вказати не всю інфраструктуру, а лише template. І в коді сказати: "Будь ласка, виведи мені на екран цей template". І в результаті можна отримати роздруківку, як виглядатиме ваші дані на Amazon.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Інший варіант – це використовувати модуль для створення user-data. Ви використовуєте цей модуль. Отримуєте файл на диску. Порівнюєте його з референсним. І таким чином, якщо якийсь джун вирішить поправити трохи user-data, то ваші тести скажуть: "Ок, ось тут і тут якісь зміни - це нормально".

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Наступне, про що я хотів би розповісти, це Automate Terraform apply.

Звичайно, досить страшно робити Terraform apply в автоматичному режимі, бо хто знає, які там прийшли зміни і наскільки вони можуть бути згубними для живої інфраструктури.

Для тестового оточення – це все гаразд. Т. е. job, який створює тестове оточення, це те, що потрібно всім розробникам. І такий вислів, як «у мене все працювало» — це не смішний мем, а доказ того, що людина заморочилася, підняла стек, запустила на цей стек якісь тести. І переконався, що там все нормально і сказав: «Ок, той код, який я випускаю, протестували».

У production, sandbox та інших оточеннях, які є більш важливими для бізнесу, можна застосовувати частково деякі ресурси досить безпечно, тому що це не призводить до того, що хтось помирає. Це: autoscale-групи, security-групи, roles, route53 та там список може бути досить великий. Але слідкуйте за тим, що відбувається, читайте звіти про автоматичне застосування.

Там, де застосовувати небезпечно або боязко, наприклад, якщо це якісь ресурси з persistent, бази даних, то отримуйте звіти про те, що в якомусь шматочку інфраструктури є не застосовані зміни. І інженер вже під наглядом запускає jobs, щоб застосувати чи робить це зі своєї консолі.

У Amazon є така штука як Terminate protection. І вона може захистити в деяких випадках від непотрібних вам змін. Т. е. Terraform пішов на Amazon і каже: «Мені потрібно вбити цей instance, щоб зробити інший». А Amazon каже: Sorry, не сьогодні. У нас стоїть Terminate protection».

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

І вишенька на торті – це оптимізація коду. Коли ми працюємо з Terraform-кодом, ми повинні передати в модуль дуже багато параметрів. Це ті параметри, які необхідні для того, щоб створити якийсь ресурс. І код перетворюється на великі списки параметрів, які потрібно передати з модуля в модуль, з модуля в модуль, особливо якщо вкладені модулі.

І це дуже складно читаємо. На це дуже складно робити review. І часто виходить так, що якісь параметри проходять review і вони не зовсім ті, які потрібні. А це коштує часу та грошей, щоб потім виправити.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Тому я вам пропоную використовувати таку штуку як складний параметр, який включає якесь дерево значень. Т. е. потрібна якась папка, де у вас вказані всі значення, які ви хотіли б мати на якомусь environment.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

І викликаючи цей модуль, можна отримати дерево, яке генерується в одному загальному модулі, тобто в загальному модулі, який працює однаково для всієї інфраструктури.

У цьому модулі можна зробити деякі обчислення, використовуючи таку нову фічу в Terraform, як місцеві організації. І потім одним output'ом видати якийсь складний параметр, який може містити в собі хеші масиви і т.д.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

На цьому всі найкращі знахідки, які я маю закінчилися. І хотів би розповісти байку про Колумба. Коли він шукав гроші на свою експедицію, щоб відкрити Індію (як він тоді думав), йому ніхто не вірив і вважали, що це неможливо. Тоді він сказав: Зробіть так, щоб яйце не впало. Усі банкіри, дуже багаті і, напевно, розумні люди, намагалися якимось чином поставити яйце, і воно весь час падало. Тоді Колумб узяв яйце, трошки на нього натиснув. Шкаралупа зім'ялася, і яйце залишилося нерухомим. Вони сказали: «О, це дуже просто!». І Колумб відповів: «Так, це дуже просто. І коли я відкрию Індію, всі використовуватимуть цей торговий шлях».

І те, що зараз я вам розповів, це, мабуть, досить прості та тривіальні речі. І коли ти про них дізнаєшся і починаєш використовувати, це гаразд. Тож користуйтеся. І якщо для вас це цілком собі нормальні речі, то принаймні ви знаєте, як поставити яйце, щоб воно не впало.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

Підведемо підсумки:

  • Намагайтеся уникати сніжинок. І чим менше сніжинок, тим менше ресурсів вам потрібно, щоб робити якісь зміни на всій великій інфраструктурі.
  • Постійні зміни. Т. е. коли в коді відбулися якісь зміни, потрібно якнайшвидше привести вашу інфраструктуру у відповідність до цих змін. Не повинно бути ситуації, коли хтось через два-три місяці приходить, щоб подивитися Elasticsearch, робить Terraform plan, а там купа змін, яких він не очікував. І витрачається дуже багато часу для того, щоб привести назад все до ладу.
  • Тести та автоматизація. Чим більше у вас код покритий тестами та фішками, тим більше у вас впевненість у тому, що ви все робите правильно. А автоматична доставка збільшить вашу впевненість багаторазово.
  • Код для тестового та production-оточення повинен бути практично однаковим. Практично, тому що все-таки production трохи інший і там все одно будуть якісь нюанси, які виходитимуть за рамки тестового оточення. Але плюс-мінус можна це забезпечити.
  • І якщо у вас дуже багато Terraform-коду і на підтримку цього коду в актуальному стані потрібно багато часу, то ніколи не пізно зробити refactoring і привести його в хорошу форму.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

  • Імутна infrastructure. Доставка AMI за розкладом.
  • Структура для route53, коли у вас дуже багато записів і вам хочеться, щоб вони були в узгодженому порядку.
  • Боротьба з API rate limits. Це коли Amazon каже: «Все-все, більше я не можу приймати запити, будь ласка, зачекайте». І половина контори чекає, доки вона зможе запустити свою інфраструктуру.
  • Spot instances. Amazon – недешеві заходи та spots дозволяють досить багато економити. І там можна розповісти цілу доповідь про це.
  • Безпека та IAM roles.
  • Пошук втрачених ресурсів, коли у вас в Amazone є instances незрозумілого походження, вони їдять гроші. Навіть якщо instances коштує 100-150 доларів на місяць - за рік це 1 з лишком. Пошук таких ресурсів – це вигідна справа.
  • І зарезервовані instances.

Паттерни в Terraform для боротьби з хаосом та ручною рутиною. Максим Кострикін (Ixtens)

На цьому маю все. Terraform – це дуже круто, користуєтесь. Дякую!

Питання

Дякую за доповідь! У вас state-файл лежить у S3, а як ви вирішуєте проблему, що кілька людей можуть взяти цей state-файл і спробувати розвернутися?

По-перше, ми не поспішаємо. По-друге, є flags, в якому ми повідомляємо про те, що ми працюємо над якоюсь ділянкою коду. Т. е. незважаючи на те, що інфраструктура дуже велика, це не означає, що постійно хтось щось застосовує. І коли була активна фаза – це була проблема, у нас state-файли в Git зберігалися. Це було важливо, інакше хтось зробить state-файл, і нам доводилося вручну їх збирати до купи, щоб усе продовжувалося. Нині такої проблеми немає. А взагалі, Terraform вирішив це завдання. І якщо постійно щось змінюється, то можна використовувати locks, які запобігають тому, що ви сказали.

Ви використовуєте відкриту версію чи enterprise?

Ніякого enterprise, тобто все, що можна піти та скачати безкоштовно.

Мене звуть Станіслав. Я хотів зробити невелике доповнення. Ви розповіли про фічу Amazon, яка дозволяє зробити instance неубиваемым. Це є і в самому Terraform, у блоці Life Second можна прописати заборону на зміну або заборону на знищення.

У часі був обмежений. Гарне зауваження.

Ще хотів спитати дві речі. По-перше, ви розповіли про тестування. Чи користувалися ви якимись інструментами для тестування? Я чув про плагін Test Kitchen. Можливо, є ще щось. І хотів би ще спитати про Local Values. Чим вони, в принципі, відрізняються від Input Variables? І чому я не можу налаштувати щось тільки через Local Values? Я намагався розібратися з цією темою, але сам не розібрався.

Ми можемо детальніше поговорити за цією залою. Інструменти для тестування – це повний самопал. Там нічого такого немає, щоби протестувати. А взагалі, є варіанти, коли автоматичні тести піднімають інфраструктуру десь, перевіряють, що вона Ок, а потім усі знищують зі звітом, що ваша інфраструктура все ще у добрій формі. У нас цього немає, тому що тестові стеки запускаються щодня. І цього достатньо. І якщо щось почало ламатися, воно почне ламатися без того, що ми ще десь це перевіримо.

З приводу Local Values ​​давайте продовжимо розмову за залом.

Вітання! Дякую за доповідь! Дуже пізнавально. Ти казав, що у вас багато однотипного коду для опису інфраструктури. Чи не розглядали ви варіант створення цього коду?

Відмінне питання, дякую! Справа в тому, що коли ми використовуємо інфраструктуру як код, ми припускаємо, що ми дивимося на код і розуміємо, яка інфраструктура за цим кодом лежить. Якщо код генерується, нам потрібно уявити, який код згенерується, щоб зрозуміти, яка інфраструктура там буде. Або ми генеруємо код, комити його і, по суті, виходить те ж саме. Тому ми пішли тим шляхом, як ми написали, ми це отримали. Плюс генератори з'являлися дещо пізніше, коли ми почали робити. І вже пізно було міняти.

Про jsonnet чув щось?

Ні.

Подивися, це класна штука. Я бачу конкретний кейс, де можна застосувати його та генерувати структуру даних.

Генератори – це добре, коли у вас, як у анекдоті про машину для гоління. Т. е. перший раз обличчя різне, але потім у всіх обличчя однакове. Генератори дуже класно заходять. Але у нас, на жаль, обличчя трохи різні. Це проблема.

Просто подивися. Дякую!

Мене звуть Максим, я зі Сбербанку. Ви трохи розповіли, що намагалися привести Terraform до аналога мови програмування. Чи не простіше користуватися Ansible?

Це дуже різні речі. Можна і Ansible створювати ресурси, і Puppet можна створювати ресурси в Amazon. Але Terraform прямо заточений.

У вас лише Amazon?

Справа не в тому, що у нас лише Amazon. У нас майже лише Amazon. Але ключова фіча у тому, що Terraform пам'ятає. У Ansible, якщо сказати: "Підніми мені 5 instances", то він підніме, а потім ти кажеш: "А тепер мені потрібно 3". І Terraform скаже: "Ок, 2 уб'ю", а Ansible скаже: "Ок, ось тобі 3". Разом 8.

Вітаю! Дякую за вашу доповідь! Дуже цікаво було послухати Terraform. Відразу хочу дати маленький коментар з приводу того, що Terraform таки не має стабільного релізу, тому з великою обережністю ставтеся до Terraform.

Гарна ложка на обід. Т. е. якщо вам потрібне рішення, то ви іноді відкладаєте те, що нестабільно і т. д., але воно працює і нам допомогло.

Питання таке. Ви використовуєте Remote backend, ви використовуєте S 3. Чому офіційний бекенд не використовуєте?

Офіційний?

Terraform Cloud.

Коли він з'явився?

Місяця 4 тому.

Якби він з'явився 4 роки тому, то, напевно, я відповів би на ваше запитання.

Там є вже вбудована функція та locks, і можна зберігати state-файл. Спробуйте. Але я також не тестував.

Ми їдемо великим поїздом, який рухається з великою швидкістю. І не можна просто взяти та викинути кілька вагонів.

Ви говорили про сніжинки, а чому не використовували branch? Чому не вдалося так зробити?

Ми маємо такий підхід, що вся інфраструктура в одному репозиторії. Terraform, Puppet, усі скрипти, які хоч якось до цього належать, вони усі в одному репозиторії. Таким чином, можемо гарантувати, що інкрементальні зміни протестовані одна одною. Якби це було купа branches, то такий проект практично неможливо обслуговувати. Минають півроку, і вони настільки розходяться, що це просто якесь покарання. Це те, чого захотілося втекти до рефакторингу.

Тобто це не працює?

Це взагалі не працює.

У branch я вирізав слайд папки. Т. е. якщо зробити на кожен тестовий стек, наприклад, у команди А - у неї своя татко, у команди Б своя татко, то це теж не працює. Ми зробили уніфікований код тестового оточення, який був досить гнучкий для того, щоб підходити всім. Т. е. ми один код обслуговували.

Вітання! Мене звати Юра! Дякую за доповідь! Питання про модулі. Ви кажете, що ви використовуєте модулі. Як вирішуєте питання, якщо в одному модулі внесли зміни, які не сумісні із зміною іншої людини? Якось версіонуєте модулі чи намагаєтеся навести вундервафлю, щоб відповідати двом вимогам?

Це проблема великої снігової купи. Це те, чому ми страждаємо, коли якась невинна зміна може зламати якусь частину інфраструктури. І це буде помітно лише через якийсь тривалий час.

Т. е. поки що ніяк не наважується?

Робите універсальні модулі. Уникайте сніжинок. І все вийде. Друга половина доповіді про те, як це уникнути.

Вітаю! Дякую за доповідь! Хотів би уточнити. За кадром залишилася велика купа, заради якої я прийшов. Як інтегровані Puppet та роздача ролей?

User-data.

Т. е. просто випльовувати файлик і по ньому якось виконуєте?

User-data – це записка, тобто коли ми робимо клон образу, там піднімається Daemon і намагаючись розібратися, хто він, читає записку, що він load balancer.

Т. е. це якийсь окремий процес, який віддається?

Не ми його винайшли. Ми ним користуємось.

Вітаю! У мене питання про User — data. Ви сказали, що є проблеми, що хтось може щось не туди передати. Є якийсь спосіб зберігання user-data у тому самому Git, щоб завжди було зрозуміло, на що посилається User-data?

Ми User-data генеруємо з template. Т. е. туди вдається якась кількість змінних. Та Terraform генерує фінальний результат. Тому не можна просто так подивитися на template і сказати, що вийде, тому що всі проблеми пов'язані з тим, що розробник думає, що він у цій змінній передає рядок, а там вдається масив. І в нього – бац і я – той, той, наступний рядок, і все зламалося. Якщо це новий ресурс і людина піднімає його, бачить, що щось не працює, це швидко вирішується. А якщо це autoscale-група оновилася, то в якийсь момент instances в autoscale-групі починають підмінюватися. І хлоп щось не працює. Це прикро.

Виходить, що єдине рішення це тестувати?

Так, ви бачите проблему, ви туди додаєте тестові кроки. Т. е. output'ом теж можна тестувати. Можливо, не так зручно, але теж можна якісь мітки поставити – перевіряйте, що User-data тут прибита цвяхами.

Мене звуть Тимур. Дуже класно, що є доповіді про те, як правильно організовувати Terraform.

Я навіть не починав.

Я думаю, що в наступній конференції, можливо, буде. У мене є просте запитання. Чому ви хардкодите значення в окремому модулі, а не використовуєте tfvars, тобто чим краще модуль зі значеннями, ніж tfvars?

Т. е. мені тут (слайд: Production/environment/settings.tf) написати: domain = змінна, domain vpcnetwork, змінна vpcnetwork і stvars - дістати те саме?

Ми ж так робимо. Посилаємося на модуль setting source, наприклад.

По суті, це такий tfvars. Tfvars дуже зручний у testing-оточенні. У мене є tfvars для великих instances, для невеликих. І я один файлик кинув у папку. І одержав те, що я хотів. Коли ми пилимо інфраструктуру, ми хочемо, щоб можна було подивитися і відразу все зрозуміти. А так виходить, що треба глянути сюди, потім глянути в tfvars.

Виходить, щоби все було в одному місці?

Так, tfvars це коли у вас один код. І він використовується у кількох різних місцях із різними нюансами. Тоді ви б tfvars кинули та отримали ваші нюанси. А ми – це інфраструктура як код у чистому вигляді. Подивився і зрозумів.

Вітаю! Зіткнулися з такими ситуаціями, коли хмарний провайдер втручається в те, що ви зробили Terraform? Припустимо, ми мета-цю правимо. Там ssh-ключі. А Google постійно туди підсовує свої мета-дані, свої ключі. І Terraform завжди пише, що він має зміни. Після кожного прогону, навіть якщо нічого не змінюється, він завжди каже, що він зараз це поле оновлюватиме.

З ключами, але так, частина інфраструктури вражена такою штукою, тобто Terraform поміняти нічого не може. Ми руками теж змінити нічого не можемо. Поки що живемо з цим.

Т. е. ви з таким стикалися, але нічого не вигадали, він як робить і робить сам?

На жаль так.

Вітаю! Мене звуть Старков Станіслав. Mail. ru Group. Як вирішуєте проблему з генерацією тега на …, як ви його передаєте усередину? Я так розумію, через User - data, щоб вказати host name, Puppet нацькувати? І друга частина питання. Як ви вирішуєте це питання в SG, тобто коли ви генеруєте SG, сотня однотипних instances, як їх правильно назвати?

Ті instances, які нам дуже важливі, ми найменуємо їх красиво. Ті, які не потрібні, там приписка, що це autoscale-група. І за ідеєю це можна прибити і отримати новий.

Щодо проблеми з тегом, то немає такої проблеми, а є таке завдання. І теги у нас дуже використовуються, тому що інфраструктура велика і дорога. І нам потрібно дивитися, на що йдуть гроші, тому теги дозволяють розшмагати, що й куди пішло. І, відповідно, пошук того, що щось тут багато грошей витрачається.

Про що ще питання було?

Коли SG створює сотню instances, їх треба якось розрізняти?

Ні не потрібно. На кожному місці є агент, який повідомляє, що у мене проблема. Якщо агент повідомляє, то про нього агент знає і, як мінімум, його IP-адреса існує. Вже можна втікати. По-друге, у нас використовується Consul для Discovery там, де не Kubernetes. І Consul теж показує IP-адресу instance.

Т. е. Ви орієнтуєтеся саме на IP, а не на host name?

Неможливо орієнтуватися по host name, тобто їх дуже багато. Є ідентифікатори instance - AE і т. д. Його можна де-небудь знайти, можна його в пошук кинути.

Вітання! Я зрозумів, що Terraform – це гарна штука, ув'язнена під хмари.

Не тільки.

Саме це питання мені й цікаве. Якщо ви вирішите переїжджати, припустимо, на Bare Metal масово з усіма своїми instances? Чи не буде жодних проблем? Або ж доведеться використовувати інші продукти, наприклад, той же Ansible, який був тут згаданий?

Ansible трохи про інше. Т. е. Ansible працює вже тоді, коли instance запустився. А Terraform працює до того, як instance запустився. Перехід на Bare Metal – ні.

Зараз ні, а прийде бізнес і скаже: Давай.

Перехід на іншу хмару - так, але тут трохи інша фішка. Потрібно писати так Terraform-код, щоб із меншою кров'ю можна було перейти на якусь іншу хмару.

Спочатку ставилося таке завдання, що у нас вся інфраструктура - агностик, тобто будь-яка хмара повинна підійти, але в якийсь момент бізнес здався і сказав: «Ок, у найближчі N років ми нікуди не підемо, можна використовувати сервіси від Amazon ».

Terraform дозволяє створювати у Front-End jobs, конфігурувати PagerDuty, data doc і т.д. У нього дуже багато хвостів. Він може контролювати весь світ.

Дякую за доповідь! Я вже теж 4 роки кручу Terraform. На етапі плавного переходу до Terraform, до інфраструктури, до декларативного опису, ми стикалися із ситуацією, коли хтось щось робив руками, а ти намагався зробити план. І отримував там якусь помилку. Як ви такі проблеми знаєте? Як знаходите втрачені ресурси, що були вказані?

Здебільшого руками та очима, якщо ми бачимо у звіті щось дивне, то ми аналізуємо, що там відбувається, або просто вбиваємо. А взагалі, pull requests – це звичайна справа.

Якщо є помилка, чи робите ви rollback? Чи пробували таке робити?

Ні, це рішення людини в моменті, коли вона бачить проблему.

Джерело: habr.com