Infrastructure as a Code: найкращі практики для DevOps-інженерів

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Привіт! Мене звати Ігор Канівець. Я працюю на позиції Advanced DevOps в Innovecs. Сьогодні хочу поділитися практиками, які використовуються в IAAC (Infrastructure as a Code). Частина з них для когось відома, а частина може стати новинкою. У будь-якому випадку ця стаття буде корисною як для DevOps-інженерів, які вже на власному досвіді знають, наскільки важливо покривати інфраструктуру кодом, так і початківцям, які тільки починають свою роботу з Terraform.

Infrastructure as a Code — це інфраструктура, яка описана кодом. У статті ми розглянемо IAAC Terraform, який може працювати як з хмарними, так з On-Premise середовищами, але ми сконцентруємося на хмарах.

Починати роботу над проєктом треба з ініціалізації, команда teraform init, котра завантажить усі необхідні провайдери, які своєю чергою дозволять працювати з різними платформами (AWS, GCP, Azure, Cloudflare...).

Провайдер — це певною мірою інструкція, згідно з якою Terraform розуміє, як взаємодіяти з тією чи іншою платформою.

Основні команди для роботи з Terraform наступні:

  1. terraform init (проводить ініціалізацію проєкту і завантажує провайдери, які необхідні для деплою у тому чи іншому середовищі (дивись схему вище);
  2. terraform plan (дозволяє побачити, які саме ресурси terraform хоче створити або змінити чи видалити);
  3. terraform apply\destroy (дозволяє задеплоїти\ видалити ресурси, які ви побачили на етапі terraform plan).

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

Використовуйте віддалені state files та lock-механізм

Для збереження змін варто використовувати віддалений state file, у якому є поточний стан інфраструктури. Terraform також підтримує локальний state-файл, але в цьому випадку ви не зможете працювати командою над одним terraform-проєктом, бо ваші тіммейти не будуть у курсі того, що робите ви, а ви не будете в курсі того, що роблять вони. Також це загрожує перезаписом або видаленням ресурсів один одного. Тобто під час першого запуску команди terraform plan ми створюємо remote state file (попередньо вказавши шлях у terraform), який відображує поточний стан інфраструктури.

Якщо в проєкті працюють двоє та більше людей, один з яких проводить Teraform plan\apply, то інший у цей же момент, якщо спробує зробити одну із зазначених команд, — отримає сповіщення про те, що його тіммейт вже працює з цим проєктом, і треба трохи почекати, доки закінчиться деплой\план та lock буде знятий. Lock-механізм дозволяє запобігти перетиранню ресурсів один одного. Детальніше дізнатися про lock-mechanism можна за посиланням.

Іноді буває так, що ви почали робити terraform plan\apply й у вас виникли проблеми з інтернетом. У такій ситуації state file залишається заблокованим, оскільки terraform plan\apply не завершився успішно, і state file не розблокувався. Для розблокування state file використовується команда terraform force-unlock <lock-id>, якщо саме ви заблокували state file. Якщо це зробили не ви — дочекайтесь завершення deploy, якщо state file залишається залоченим довгий час — запитайте у тіммейта, чи можете ви зробити unlock state file (в terraform-повідомленні буде видно, хто залочив state file).

Розділяйте terraform-файли, базуючись на логічному розподілі ресурсів:

Всі змінні зберіть в один variables.tf файл, провайдери — в providers.tf файл, data-ресурси — у data.tf файл, та використайте їх у main.tf файлі. Завдяки цьому тіммейти зможуть легко розібратися у terraform-коді, тому що усі будуть on the same page та швидко зрозуміють, де треба змінити код для зміни інфраструктури у тому чи іншому напрямку.

Terraform не вимагає логічного розподілу файлів. Що 20 файлів з розширенням .tf, а що 1 файл з розширенням .tf з тисячею рядків коду — на етапі terraform plan усе збирається в єдиний файл, якій пізніше використовується для деплою. Значно легше передивитися 10 файлів по 15 рядків, ніж один файл зі 150 рядками, тому я раджу розділяти файли.

Використовуйте змінні замість хардкоду

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

Уявімо ситуацію, де ми захардкодили певне значення у тисячі рядків коду. Якщо необхідно змінити значення, треба його переписати у всіх місцях, де ми його захардкодили. Аби уникнути цього довгого процесу, можемо вказати це значення один раз у variables .tf файлі — замість хардкоду використати змінну — і вуаля. Додавши змінну в одному місці variables.tf файлі, ми змінимо це у тисячі місцях.

Моя порада — об’єднувати variable у логічні ланцюжки. Для прикладу, якщо є три змінні: vpc_id, vpc_cidr, subnet_group, об’єднаймо їх в одну object змінну network, яка своєю чергою матиме три атрибути (vpc_id, vpc_cidr, subnet_group). Для чого нам це? Під час деплою terraform ми використовуємо API calls під капотом. Кожен окремий API call — це певний час, який витрачаємо на обробку. Що більше API calls — то більше часу на terraform plan\deploy. І все, наче, добре, якщо йдеться про деплой одного інстансу в хмару. Ми не помітимо великої різниці — у нас одна змінна з трьома атрибутами чи три різні змінні. Уявімо, що в проєкті 1000 ресурсів, час на plan і apply terraform зростає, якщо замість однієї object змінної ми будемо використовувати три окремі. Та і в коді це має кращий вигляд, коли ми об’єднуємо змінні у логічні об’єкти.

Таким чином ми розвантажуємо роботу з Terraform і зменшуємо час відклику. До об’єктної змінної ми можемо звернутися наступним чином: var.network.vpc_id, var.network.vpc_cidr, var.network.subnet_group.

Неймінг variable — важливий момент у роботі. Особливо це відчутно, якщо ви написали код, з яким буде працювати вся команда. Витратьте 5 хвилин на назву змінної, в майбутньому це може зберегти годину часу для команди.

Використовуйте модулі

Модуль — це логічне об’єднання ресурсів, котрі можуть використовуватися у різних проєктах. Зазвичай ресурси модуля є ідентичними для різних проєктів, відрізняються тільки значення змінних.

Використовуючи модулі, ми уникаємо дублювання коду. Якщо нам треба створити 15 однакових інстансів (які потребують security_group, security_group_rules, public_ip etc.) у різних проєктах, можемо написати один модуль і 15 разів його викликати. Замість 400 рядків коду матимемо лише 15. Таким чином ми створимо 15 різних ресурсів, але за допомогою одного модуля.

Завдяки модульності код легше менеджити. Уявімо, що ми створили bastion module, який використовується в 15 проєктах. Відкрився, до прикладу, новий офіс в компанії, і нам необхідно додати ще одну IP-адресу до bastion security_group. Якби ми не мали модуля, нам потрібно було б додати нову IP-адресу до кожного бастіону у 15 проєктах. Кожна зміна, яку ми робимо вручну в коді, може стати потенційною помилкою в силу людського фактора. Але ми використовуємо модуль, тому достатньо буде додати нову IP-адресу в одному місці (це допоможе уникнути людського фактора, про який згадували раніше й зменшити час на коригування змінної в одному місці замість 15), зробити деплой коду і все. Такі переваги модульності.

Використовуйте ‘count’ function для створення однакових ресурсів чи для рішення ‘if case’ для ресурсу

Функція ‘count’ може допомогти нам у створенні як однакових ресурсів з різними іменами, так і вирішити ‘if condition’ всередині ресурсу.

Призначення count функції ви можете переглянути в офіційній документації terraform, нижче — я хотів би розповісти, як функція ‘count’ може допомогти зробити наш модуль більш гнучким або ресурс, який вимагає if condition на основі тих чи інших даних. Наприклад, є два DNS-провайдери — це Cloudflare і Route53 в Amazon. Різні системи використовують різні провайдери. Але у нас є модуль, який створює вебсервер, і супровідні ресурси інстансу (security group, security_group_rule, public_ip й інші).

Якщо не використовувати функцію count з if condition, нам необхідно просто задублювати код і створити два модулі. У першому випадку це буде модуль з Cloudflare записом, у другому — модуль з Route53 записом. Але дублювати весь модуль, у якому 500 рядків загального коду і тільки 10 рядків, які відрізняються, — це не найкраща практика.

Щоб вирішити цю ситуацію, ми якраз і можемо використати функцію count за призначенням. Таким чином при виклику модуля вказуємо, що провайдер дорівнює Cloudflare. Якщо так, то функція поверне нам одиницю і таким чином створиться Cloudflare-запис у Cloudflare. Далі ми заходимо у наступний ресурс Route53 і так само завдяки count перевіряємо. Відповідно умова буде 0, і ми не будемо створювати запис у Route53. Якщо ми вкажемо провайдер Route53, то все відбудеться навпаки, на відміну від першої ситуації, створиться Route53 dns запис, а Cloudflare не буде. Це дуже важлива опція всередині Terraform, яка допомагає зробити модуль гнучким.

Data resources наявних ресурсів

Уявімо ситуацію, що terraform створює новий ресурс, і з’являється необхідність у певному атрибуті ресурсу, який ви створили вручну. Наприклад, ви хочете створити security_group inbound rule для вже наявного інстанса.

Для цього вам необхідна IP-адреса інстансу. У вас є декілька варіантів, як це зробити:

  1. Захардкодити (це не найкраща практика, і я не рекомендую її, але такий варіант все ще існує).
  2. Використати data_resource, який дозволить отримати IP-адресу інстансу (це найкраща практика, яку я рекомендую).

Чому хардкод — це погано, а використання data_resource — це добре? Уявімо ситуацію, що з певної причини IP-адреса інстансу змінена. Якщо ми використовуємо data_resource, то при кожному запуску terraform plan інформація про інстанс оновлюється, і terraform пропонує замінити старий IP на новий. Якщо ж ми використовуємо хардкод, тоді terraform нічого про це не знатиме, допоки ви не внесете зміни в код. А якщо у вас таких змін 100 на проєкті, це додасть роботи й забере багато часу. Щоб використовувати data_resource, треба вказати ID ресурсу, атрибут якого ви хочете отримати. Для кожного ресурсу ID відрізняється, перевіряйте terraform документацію. Цей підхід дієвий у випадку, якщо частина інфраструктури ще не описана кодом, а частина — у процесі покриття.

Якщо ж інфраструктура вже описана кодом, то замість того, щоб робити API-call в AWS (data_resource), ми можемо використовувати data resource до state file (terraform_remote_state), який зберігається в s3 bucket. Для цього робимо запит і отримуємо усі ресурси для створення поточної інфраструктури.

Підсумовуючи сказане, у нас є два варіанти:

1) складніший шлях, коли ми робимо 15 API-calls в AWS, збираємо усю необхідну інформацію і таким чином продовжуємо створювати інфраструктуру (це робочий варіант у ситуації, коли ми хочемо отримати певні атрибути ресурсів, які ще не покриті terraform);

2) простіший і зручніший — робимо один API-call в s3 bucket і дістаємо ці 15 ресурсів (terraform_remote_state), які нам необхідні (інфраструктура, покрита terraform). У цьому випадку важливо розуміти, що в state file проєкту, до якого ми звертаємося, повинні бути outputs для атрибутів, які нам необхідні. Таким чином ми знову ж таки розвантажуємо Terraform flow, спокійно збільшуючи продуктивність і зменшуючи час відклику. Відповідно, якщо у нас 700 таких ресурсів (data_resource), то час на їх отримання помножується. Якщо ж ми використовуємо data_remote_state, і в нас є всі 700 outputs, у такому випадку замість 700 API-call — ми робимо один.

Підсумовуючи, якщо у вас є можливість використовувати remote_state_file з іншого проєкту — використовуйте і розвантажуйте terraform. Якщо немає — використовуйте data_resource, але не хардкодьте значення.

Якщо використовуєте інфраструктуру коду — не робіть зміни вручну, але навіть якщо так сталося — позначте це у terraform

Жодних ручних змін, якщо вже почали використовувати Infrastructure as a Code.

Часто трапляється так, що terraform допомагає повернути інфраструктуру у робочий стан. Уявімо ситуацію, що хтось випадково допустився помилки, і ваш сайт не відкривається. Щоб зрозуміти, чому так сталося, треба провести дебагінг, який займає час. Замість цього ви можете зробити terraform plan, і він вже покаже вам, які зміни були зроблені до цього. У такому випадку terraform applу розв’яже вашу проблему за кілька хвилин.

Але коли впав продакшн, і terraform plan\apply не повернув до робочого стану інфраструктуру — не витрачайте часу на виправлення terraform коду, спочатку вирішіть проблему вручну, пізніше все вкажіть у terraform у спокійному режимі. Це зменшить час вашого даунтайму, що своєю чергою зменшить кількість втрат. Якщо ж зміни не пов’язані з production issue, то все необхідно робити через Terraform код.

Коли зміни вносяться вручну, то ситуація виглядає так: один зробив зміни в тегах в інстансах, інший — змінив data base retention period до 4 чи 8 днів. Коли ми зіштовхуємося з production issue, то замість однієї зміни, яка є root cause — ми побачимо, що terraform хоче зробити 4 зміни у різних місцях. У такому випадку замість одного ресурсу вам треба передивитися 4, а на це все піде час. А якщо ви змінювали не 4 ресурси, а 20, то це ще більше часу. Звичайно, з ручними змінами треба боротися. Хоча і я у своїй роботі з цим зіштовхуюся, і це забирає мій час та час моїх колег. Тому доцільніше інфраструктуру покривати кодом і все прописувати в Terraform.

Використовуйте import resources, якщо проєкт не є частиною terraform, а ви хотіли б покрити його кодом

Якщо ваш проєкт повністю покритий terraform або ж певна його частина — це дуже добре. Але є ситуації коли ресурси частково створені terraform, а частково — вручну. Якщо нам необхідно покрити усі ресурси terraform — у цьому випадку допоможе terraform import команда. У Terraform є детальний опис, як робити імпорт тих чи інших ресурсів. Terraform проводить команду import, і таким чином забирає на себе менеджмент інфраструктури. Алгоритм імпорту наступний:

  1. Написати terraform код для ресурсу, який будете імпортувати.
  2. Заранити команду terraform plan (команда повинна показати вам, що ресурс, який ви хочете імпортувати, створиться).
  3. Імпортуйте ресурс за допомогою команди terraform import resource_id (для кожного ресурсу resource_id є різним, перевіряйте terraform документацію).
  4. Знову зробіть terraform plan команду (якщо імпорт зробили коректно, terraform повинен показати повідомлення: ‘The infrastructure is up to date’).

У процесі покриття інфраструктури кодом ви крок за кроком імплементуєте terraform. Відповідно наступного разу усі зміни можна вносити за допомогою Terraform, а не руками.

Команду import можна використовувати, коли у нас є два або три проєкти — Backend, Frontend і DevOps, які вже покриті terraform. Вчора це могло належати Backend, а сьогодні — DevOps. Тому нам треба зробити імпорт з Backend в DevOps. Своєю чергою ми повинні видалити цей ресурс із Backend (terraform state remove), і таким чином ми можемо і там, і там менеджити Terraform. Дуже важливо, щоб один ресурс менеджився лише за допомогою одного terraform state file, інакше буде постійний перезапис. Уявімо ситуацію, що у вас ресурс менеджиться за допомогою двох terraform state file DevOps і Backend, і в кожному проєкті використовуються default_tags. Кожного разу під час terraform apply записуватимуться теги для DevOps-проєкту і для BackEnd. Задля уникнення подвійної роботи зберігаємо resourse тільки в одному Terraform state file.

Перш ніж працювати з remote tf.state, нам треба попередити про це команду, щоб ніхто не зачіпав state file, поки ви не завершили з ним працювати.

Після завершення роботи з remote tf.state теж необхідно повідомити, що ви завершили, й інші можуть працювати з файлом. Успішним завершенням при імпорті ресурсів є результат команди terraform plan «infrastructure is up to date».

Упевніться, що не припустилися помилки у форматуванні Terraform fmt та у синтаксисі Terraform validate

Коли ми пишемо Terraform код, це все може мати неструктуровану форму. Тоді можна скористатися командою terraform fmt —recursive і надати цьому впорядкованого вигляду. Особливо це зручно, якщо у тебе 30 файлів, які можна форматувати одночасно. Відстежити це все очима складно, особливо якщо проєкт складається із тисячі рядків коду, а код завжди хочеться бачити читабельним. Також зручною є команда terraform validate, яка при розробці terraform-коду дозволяє перевірити, чи вистачає terraform усіх атрибутів, аби виконати terraform plan\apply.

Використовуйте версію провайдера тільки в корені проєкту — тоді вам не доведеться змінювати його у різних місцях

Як я вже зазначав на початку статті, для роботи з різними платформами terraform використовує провайдери. Провайдер — це драйвер (інструкція), яка вказує terraform, як комунікувати з платформою. В одному terraform-проєкті може бути декілька провайдерів. Уявімо ситуацію, що вам необхідно створити вебсервер, який повинен бути доступним за адресою example.terraform-learn.com.

Щоб створити вебсервер, ви можете використовувати AWS\GCP\Azure etc. хмарні провайдери. Для кожної хмари написаний свій провайдер. Після створення сервера вам необхідно створити DNS-reсord, який буде направляти трафік на ваш вебсервер. Для створення DNS-reсord в CloudFlare необхідно використовувати Cloudflare Provider.

Якщо у вашому проєкті є багато додатків, найкраща практика — декларувати версію провайдера в корені проєкту.

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

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

Наступного дня ви робите ті ж команди:

  1. git clone;
  2. terraform init\terraform init -upgrade;
  3. terraform plan.

І у вас виникає помилка. Спочатку ви думаєте, що проблема з вашим кодом, йдете в GitHub, дивитеся, а там немає ніяких змін з учорашнього дня, коли у нас все працювало. І тут виникає запитання, що ж таке сталося. Йдете до колег, просите зробити terraform plan, і у них все виходить. Що ж це за магія? Ви продовжуєте робити дебагінг і не розумієте, у чому справа.

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

  1. Дійсно, код не змінювався з моменту, коли все працювало коректно.
  2. Дійсно, terraform plan працює на комп’ютері вашого колеги.

Уся справа полягає у провайдері. З моменту, коли у вас все працювало і до того моменту, коли перестало — версія провайдера, наприклад, CloudFlare) змінена, і сьогодні ви вже не можете зробити план на створення DNS-record. Добре, скажете ви, але чому це працює у вашого колеги?

Це хороше запитання. У вашого колеги це працює, тому що не запустили команди terraform init\terraform init-upgrade, і ваш колега використовує не останню версію провайдера. Ви ж своєю чергою клонували свіжий код й ініціалізували terraform, який взяв останній провайдер (учора він був 4.21.0, сьогодні він — 4.22.0), якщо, звичайно, ваш провайдер не закріплений в terraform. Якщо ваш колега зробить terraform init\terraform init -upgrade, у нього також з’явиться ця проблема.

Використовуйте default tags — тоді усі ресурси всередині проєкту матимуть default tags

Хороша практика — використовувати для ресурсів теги. У такому випадку ви завжди будете знати, кому належить ресурс і чи покритий він terraform. Також коли ви переглядаєте costs, за тегами легко визначити, кого треба запитувати, чому інфраструктура з’їла так багато грошей. Для покриття ресурсів тегами є два підходи:

  1. Додавати теги до кожного ресурсу (це хороша практика, але не найкраща).
  2. Використовувати default_tags у корені проєкту. Це найкраща практика. У цьому випадку усі ресурси, які знаходяться всередині проєкту будуть мати дефолтні теги. Якщо вам окрім дефолтних тегів, треба додати будь-які унікальні теги — використовуйте конструкцію merge. У цьому випадку навіть якщо ми пропустимо якийсь ресурс і не покриємо його тегами — terraform його не пропустить і покриє.

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

Робіть terraform plan з ключем —out=tfplan і тільки тоді застосовуйте

Під час створення або зміни інфраструктури ми використовуємо terraform plan команду. Ця команда показує нам, що terraform збирається зробити в інфраструктурі. Якщо ми робимо terraform plan, terraform показує нам, що буде зроблено безпосередньо в консолі. Якщо ж ми використовуємо ключ —out=tfplan, у такому випадку terraform запише всі зміни, які будуть зроблені в локальному файлі.

Ми можемо робити terraform plan як з ключем, так і без нього. Це буде працювати однаково. Різниця лише в тому, що з використанням ключа буде створений локальний файл зі всіма змінами, які будуть зроблені, а якщо ми не будемо використовувати вищезгаданий ключ, то всі зміни показуватимуться тільки в консолі. Якщо щось піде не так — ви завжди можете відкрити tfplan файли й подивитися, що планувалося зробити, а що фактично зроблено.

***

Підсумовуючи, скажу найголовніше — інфраструктуру треба покривати кодом. Дотримуйтеся Clean Code Principles під час написання коду. Уникайте дублювання коду — інколи значно швидше зробити Сopy\Paste і забути, але в такому випадку буде зростати кількість вашого коду, а не якість. При розробці коду і мережі в ‘main’ використовуйте PR Review, адже, як правило, істина народжується у процесі дискусії, і ваш колега, який вже зіштовхнувся з подібною ситуацією, може підказати вам оптимальніший варіант.

👍ПодобаєтьсяСподобалось24
До обраногоВ обраному14
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Можливо бiльш використовувати yaml для спрощення, дякую

Неплохая статья для новичков, про workspace не увидел, удобно для разделения енвов а также у терраформа уже есть своя тулза terraform cloud где просто куча фич: сикреты, переменные да и по сути свой ci/cd для терраформа)

workspace

Должны вообще умереть и быть вырезаны из терраформа. Чем меньше людей про это знает — тем лучше.

terraform классный, но вот state хранит уж слишком много sensitive данных.
Я бы еще добавил слой шифрования поверх. Даже/тем более что оно хранится в облаке.

Найцікавіша части Terraform’у полягає у тому, що план деплойменту це JSON структура із певною ступінню залежностей одних ресурсів від інших. І коли приходить розуміння цього, то вже й HCL вчити не треба, достатньо вже знати Java, Python, JS, golang. Бо еволюцією Terraform є проект моїх знайомих — www.pulumi.com

Pulumi це справжній infrastructure-as-code, (бо якщо бути відвертим, то HCL — це мова моделювання), бо задача полягає у тому, щоб із використанням вже існуючих інструментів досягти результату. З технічної точки зору, Pulumi вміє конструктуювати структури які розуміє Terraform, бо задача стояла не створити щось нове, а взяти від терраформу найкраще — ядро деплойменту на основі JSON-структур.

вже й HCL вчити не треба, достатньо вже знати Java, Python, JS, golang

Це у тому випадку, коли вже знаєш хоча б одну з цих мов, а робота з json ніколи не була простою. Тобто це погляд на IaC з точки зору готового розробника.
План деплойменту зручненько парситься за допомогою jq.

це справжній infrastructure-as-code

TF CDK же є

Terraform CDK також є декларативним, оскільки кінцевий стан — це маніфест, які TF потім деплоїть.

Pulumi також є декларативним. Кінцевий стан — це артефакт pulumi engine, який безпосередньо застосовується до cloud provider API.

Це дає вам кілька переваг з декларативної сторони:

* Є багато місць, де механізм графів Terraform в кінцевому підсумку не будується правильно, і вам доводиться запускати тераформу більше одного разу. У Pulumi немає такої проблеми, тому що ви можете з’єднати речі в ланцюжок в асинхронному циклі. Наприклад динамічні обʼєкти TF контент яких доступних лише після первинного деплою, такими ресурсами можуть бути мережеві маски або регіону, або новостворенної віртуальної мережі (VCN).

* Pulumi використовує мови як першокласний механізм авторства, де Terraform CDK трансполює компоненти, написані мовою, у проміжний стан. Мається наувазі, що TF CDK інтерполює граф написаний Java/Python/Go у проміжний стан, який вже після того виконується самим TF.

Ну й простіше сказати, що усі родинні проблеми TF наслідуються безпосередньо й TF CDK. Pulumi була ж створена із врахуванням тих проблем.

із врахуванням тих проблем

Але як завжди зі своїми новими )

Hcl декларативен , а пулуми можно нахерачить говнокода и свалить в закат оставив треш разгребать другим.
Удел пулуми -кодифицированные инфракостыли когда нужна логика динамическая.

Полумі може те, чого не может HCL — потужність усієї екосистеми певної мови програмування типу Java на додачу із нескінченною кількістю сторонніх бібліотек, а HCL може лише те, що Антон закладено, особливо те, що стосується функцій.

И это всё на фоне зоопарка поддерживаемых языков. Так что велики шансы не просто художества разбирать, так ещё и на чём-то всратом

Переїхали на pulumi з typescript. Політ нормальний. Набагато більше свободи.

Спасибі, мені лише не вистачає , наявних прикладів саме кодом , до тих чи інших тіпсів

Якраз активно вивчаю і практикую Terraform. Всі поради, як на мене, дуже доречні.
Автору подяка за статтю і величезний плюс в карму!
Можливо спільнота порадить якісь перевірені ресурси, окрім документації. Буду вдячний)

згоден. поради досить хороші. для вивчення є сенс пробувати створювати свої модулі заодно розбиратись що написано в опенсорсних модулях того самого aws, cloudposse і тд.
посилання:
— github.com/cloudposse
— github.com/terraform-aws-modules

а якщо покласти в гіт і запускати пайплайною замість вимирітися хто зараз залочи стейт файла?

Додав би що тестування з terratest допомагає особливо при частому оновленні провайдерів (модулів)

Також раджу використовувати статичні перевірки коду та автоматичне форматування у єдиному стилі — terraform validate, terraform fmt — як мінімум.

А краще — tflit, tfsec, checkov...

Ну і про документування вашого коду не забувайте — terraform-doc

;)

«Використовуйте ‘count’ function для створення однакових ресурсів чи для рішення ‘if case’ для ресурсу»

Ні. count можна використовувати виключно для «рішення ‘if case’ для ресурсу». Поясню чому. Коли ви працюєте з count — ви, фактично, працюєте зі списком. І при додаванні чи при виключенні його елементів (наприклад — додаткових дисків для віртуальних машин, мережевих інтерфейсів, правил firewall) можуть бути перестворенні (тобто — видалені та створені нові, такі-ж) інші елементи, яки ви ніби-то не міняли, і це, по ланцюжку, може привести до видалення та створення пов’язаних об’єктів. Тобто, можливі масивні зміни, і це точно не те, що ви хочете.

terraform також має іншу конструкцію для циклів — for_each, яка працює з map (тобто зі словарями, не зі списками). І це значно більш оптимальна конструкція, бо навіть при додаванні чи видаленні елементів зі словаря інші елементи змінюватись не будуть, бо їх індекс не зміниться, таким чином ви значно зменьшуєте вплив будь-яких змін на проект.

Загальне правило для змінних та внутрішніх структур даних ваших проектів та модулів — уникати використання списків (list) і всюди, де можна, використовувати словники (map) перетворюючі map->list безпосередньо там, де це потрібно для створення ресурсу. Таким чином ви мінімізуєте вплив можливих змін на створені у хмарі ресурсі.

Ще одна рекомендація — думати у функціональній парадигмі, коли пишете модулі та перетворення внутрішніх структур даних — значно спрощує написання коду ;)

І терраформ вміє працювати з YAML — я рекомендую розділяти код terraform («архітектура» вашого проекту) від конкретних налаштувань (YAML) — прописувати змінні у tf файлах, звісно, можна, але краще повністю їх розділяти, та й yaml має багато можливостей, таких, як багаторівнева структура, наслідування частини даних, що значно спрощує роботу і зменьшує розмір даних проекту — це треба не для комп’ютера, це треба для людини, для зменьшення помилок.

www.terraform.io/...​uage/functions/yamldecode

medium.com/...​s-extensions-a1e4105d70bd

Підписатись на коментарі