# Структура коду

Питання, пов’язані зі структурою коду Terraform, є найпоширенішими у спільноті. Кожен також думав про найкращу структуру коду для проекту.

## Як правильно організувати структуру моєї Terraform конфігурації?

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

* Яка складність вашого проекту?
  * Кількість супутніх ресурсів
  * Кількість Terraform провайдерів (див. примітку нижче про "*логічних провайдерів*")
* Як часто змінюється ваша інфраструктура?
  * **Від** раз на місяць/тиждень/день
  * **До** безперервно (щоразу, коли є новий коміт)
* Ініціатори зміни коду? Чи дозволяєте ви серверу CI оновлювати репозиторій, коли створюється новий артефакт?
  * Тільки розробники можуть пушати до репозиторію інфраструктури
  * Кожен може запропонувати змінити будь-що, відкривши PR (включаючи автоматизовані завдання, що виконуються на сервері CI)
* Яку платформу або сервіс для деплою ви використовуєте?
  * AWS CodeDeploy, Kubernetes, чи OpenShift вимагає дещо іншого підходу
* Як згруповані середовища?
  * За середовищем, регіоном, проектом

{% hint style="info" %}
*Логічні провайдери* працюють повністю в рамках логіки Terraform і дуже часто не взаємодіють з жодними іншими сервісами, тому ми можемо вважати їх складність як O(1). До найпоширеніших логічних постачальників належать [random](https://registry.terraform.io/providers/hashicorp/random/latest/docs), [local](https://registry.terraform.io/providers/hashicorp/local/latest/docs), [terraform](https://www.terraform.io/docs/providers/terraform/index.html), [null](https://registry.terraform.io/providers/hashicorp/null/latest/docs), [time](https://registry.terraform.io/providers/hashicorp/time/latest).
{% endhint %}

## Початок роботи зі структуруванням конфігурацій Terraform

Ведення всього коду в `main.tf` - гарна ідея, якщо ви починаєте роботу або пишете приклад коду. У всіх інших випадках вам буде краще, якщо декілька файлів розділити логічно так:

* `main.tf` - викликає modules, locals, а також data sources, щоб створювати всі ресурси
* `variables.tf` - містить оголошення змінних, які використовуються в `main.tf`
* `outputs.tf` - містить outputs з ресурсів, які були створені в `main.tf`
* `versions.tf` - містить вимоги до версії для Terraform і провайдерів

`terraform.tfvars` не слід використовувати ніде, крім [композиції](https://www.terraform-best-practices.com/uk/key-concepts#composition).

## Як думати про структуру конфігурацій Terraform?

{% hint style="info" %}
Будь ласка, переконайтеся, що ви розумієте ключові поняття - [ресурсний модуль](https://www.terraform-best-practices.com/uk/key-concepts#resource-module), [інтфраструктурний модуль](https://www.terraform-best-practices.com/uk/key-concepts#infrastructure-module), а також [композиці](https://www.terraform-best-practices.com/uk/key-concepts#composition)ю, так як вони використовуються в наступних прикладах.
{% endhint %}

Загальні рекомендації щодо структурування коду

* З меншою кількістю ресурсів працювати легше і швидше
  * `terraform plan` та `terraform apply` обидва здійснюють виклики хмарного API для перевірки стану ресурсів
  * Якщо у вас вся інфраструктура в одній композиції, це може зайняти деякий час
* Радіус вибуху менший при меншій кількості ресурсів
  * Ізоляція ресурсів, непов'язаних один від одного, шляхом розміщення їх в окремих композиціях, зменшує ризик, якщо щось піде не так
* Почніть свій проект, використовуючи віддалений стан, тому що:
  * Ваш ноутбук – це не місце для джерела ресурсів усієї інфраструктури
  * Управління файлом tfstate в git — кошмар
  * Пізніше, коли рівні інфраструктури почнуть зростати в кількох напрямках (кількість залежностей або ресурсів), буде легше тримати все під контролем.
* Практикуйте послідовну структуру і [умови найменувань](https://www.terraform-best-practices.com/uk/naming):
  * Як і процедурний код, код Terraform повинен бути написаний для того, щоб люди спочатку прочитали; узгодженість допоможе потім, коли будуть зміни через шість місяців
  * Можна переміщати ресурси у файлі стану Terraform, але це буде важче зробити, якщо у вас непослідовна структура та імена
* Робіть модулі ресурсів максимально простими
* Не "хардкодьте" значення, які можна передати через змінні або виявити за допомогою джерел даних
* Використовуйте джерела даних та `terraform_remote_state` спеціально як з'єднувальники між модулями інфраструктури у межах композиції

У цій книзі приклади проектів згруповано за *складністю* - від малих до дуже великих інфраструктур. Цей поділ не є суворим, тому перевірте також інші конструкції.

### Оркестровка інфраструктурних модулів і композицій

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

Існує принаймні 5 окремих груп рішень для оркестровки, які використовують розробники:

1. Лише Terraform. Дуже просто, розробники повинні знати тільки Terraform, щоб виконати роботу.
2. Terragrunt. Чистий інструмент оркестрування, який можна використовувати для оркестрування всієї інфраструктури, а також для обробки залежностей. Terragrunt працює з інфраструктурними модулями та композиціями, тому зменшує дублювання коду.
3. In-house скрипти. Часто це відбувається як відправна точка для оркестрування і перед відкриттям Terragrunt.
4. Ansible або подібний інструмент автоматизації загального призначення. Зазвичай використовується, коли Terraform адаптований після Ansible, або коли Ansible UI активно використовується.
5. [Crossplane](https://crossplane.io/) та інші Kubernetes-натхненні рішення. Іноді має сенс використовувати екосистему Kubernetes і використовувати функцію циклу узгодження для досягнення бажаного стану ваших конфігурацій Terraform. Перегляньте відео [Crossplane vs Terraform](https://www.youtube.com/watch?v=ELhVbSdcqSY) для додаткової інформації.

З огляду на це, у книзі розглядаються перші два з цих структурних проектів, тобто лише Terraform і Terragrunt.

Дивіться приклади структур коду для [Terraform](https://www.terraform-best-practices.com/uk/examples/terraform) чи [Terragrunt](https://www.terraform-best-practices.com/uk/examples/terragrunt) у наступних частинах.
