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

Питання, пов’язані зі структурою коду 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` не слід використовувати ніде, крім [композиції](/uk/key-concepts.md#composition).

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

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

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

* З меншою кількістю ресурсів працювати легше і швидше
  * `terraform plan` та `terraform apply` обидва здійснюють виклики хмарного API для перевірки стану ресурсів
  * Якщо у вас вся інфраструктура в одній композиції, це може зайняти деякий час
* Радіус вибуху менший при меншій кількості ресурсів
  * Ізоляція ресурсів, непов'язаних один від одного, шляхом розміщення їх в окремих композиціях, зменшує ризик, якщо щось піде не так
* Почніть свій проект, використовуючи віддалений стан, тому що:
  * Ваш ноутбук – це не місце для джерела ресурсів усієї інфраструктури
  * Управління файлом tfstate в git — кошмар
  * Пізніше, коли рівні інфраструктури почнуть зростати в кількох напрямках (кількість залежностей або ресурсів), буде легше тримати все під контролем.
* Практикуйте послідовну структуру і [умови найменувань](/uk/naming.md):
  * Як і процедурний код, код 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](/uk/examples/terraform.md) чи [Terragrunt](/uk/examples/terragrunt.md) у наступних частинах.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.terraform-best-practices.com/uk/code-structure.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
