linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • База знаний
  • Шпаргалка
  • Capstone
  • Собеседование
Cluster

← все кластеры

Provider и resource: lifecycle, count/for_each

Provider-блок, alias, multi-region. Resource lifecycle (create_before_destroy, prevent_destroy, ignore_changes), count vs for_each, data vs resource, depends_on - когда честно нужен. Грамматика повседневной работы с Terraform.

6 вопросов · ~24 мин чтения

Questions

На этой странице

  1. 01В чём разница `count` и `for_each`? Что выбрать в новом коде?
  2. 02Чем data source отличается от resource? Когда что использовать?
  3. 03Что делает `alias` в provider-блоке? Зачем нужен?
  4. 04Что делает `create_before_destroy` и зачем он нужен?
  5. 05Когда `ignore_changes` действительно нужен, а когда это костыль?
  6. 06Когда `depends_on` нужен честно, а когда обходимо?

#count-vs-for-each

juniorчасто

В чём разница `count` и `for_each`? Что выбрать в новом коде?

Что отвечать

`count = N` создаёт N идентичных ресурсов с адресами `r[0]`, `r[1]`, `r[2]`. `for_each = set/map` создаёт по элементу с адресом `r["alpha"]`, `r["beta"]`. Главная разница в state. Удалишь элемент из середины count - все следующие переедут на индекс ниже и пересоздадутся. С for_each по map - удалишь ключ, удалится только тот ресурс. В новом коде - почти всегда `for_each`. Count оставляют для случаев «N однотипных без идентичности» (буквы алфавита, индексы массива).

Что хотят услышать

Кандидат должен: - объяснить почему for_each надёжнее по reindex'у: stable keys вместо позиционных - назвать что for_each требует set(string) или map; список нужно обернуть в `toset(list)` - сказать что ключи for_each должны быть known at plan time - нельзя `for_each = aws_subnet.x[*].id`, можно `for_each = var.subnets` - различить `each.key` и `each.value` для map: ключ + значение; для set - оба равны элементу - упомянуть `for_each = { for k, v in var.users : k => v if v.enabled }` как идиоматичный фильтр

Подводные камни

  • ✗ Использовать count с динамической длиной списка - удаление элемента из середины пересоздаст хвост
  • ✗ Передать в for_each список через `for_each = var.list` - ошибка типа, нужен `toset(var.list)` или map
  • ✗ Сделать for_each по computed-значению (`aws_subnet.x[*].id`) - plan упадёт «cannot use unknown value»

Follow-up

  • ? Что произойдёт при удалении 5-го элемента из списка в `count`?
  • ? Как сделать map-based for_each по computed-значениям?
  • ? Когда `count` всё-таки разумнее чем `for_each`?

Глубина в базе знаний

  • count и for_each: несколько ресурсов из одного блока
  • Блок resource: главный кирпич Terraform
  • Ссылки в HCL: как читать aws_s3_bucket.demo.bucket
tags: resources, count, for-each

#data-source-vs-resource

intermediateчасто

Чем data source отличается от resource? Когда что использовать?

Что отвечать

`resource` создаёт и владеет ресурсом - Terraform отвечает за его жизненный цикл (create, update, destroy). `data` только читает из провайдера, ничего не меняет, не появляется в state как «owned». Использование: data source для lookup существующего ресурса (айди VPC по тегу, последний Ubuntu AMI), для ввода данных через API провайдера. Resource - когда ты собираешься этот ресурс держать. Перепутаешь - либо случайно удалишь то, что не твоё, либо упустишь управление тем, что должен контролировать.

Что хотят услышать

Senior должен: - назвать data source как read-only lookup, всегда работает на plan-стадии (refresh) - сказать что data source плохо подходит для секретов через AWS Secrets Manager: значение попадёт в plan-вывод и state в plain - различить «свой» ресурс (resource) и «чужой» (data); чужой изменишь руками - не страшно, своего - drift - упомянуть что некоторые провайдеры дают write-data конструкции (`ephemeral` в Terraform 1.10+) для случаев когда значение не должно сохраняться в state

Подводные камни

  • ✗ Использовать data source для чтения собственного ресурса вместо direct reference - получаешь dependency через refresh, а не через граф
  • ✗ Думать что data source не пишет в state - пишет, refresh обновляет его каждый plan/apply, время съедается
  • ✗ Сделать data source на secret-значение и забыть - значение оседает в state и в plan-логах

Follow-up

  • ? Можно ли data source ссылаться на own resource в том же root?
  • ? Что делает `ephemeral` в 1.10+ и почему его придумали?
  • ? Чем поведение data source отличается на стадиях plan и apply?

Глубина в базе знаний

  • data-блок: читаем то, что уже есть в облаке
  • Блок resource: главный кирпич Terraform
  • Секреты и Terraform state: где хранить и как читать
tags: resources, data

#provider-alias-multi-region

intermediateиногда

Что делает `alias` в provider-блоке? Зачем нужен?

Что отвечать

Provider alias - второй (третий, ...) провайдер того же типа с другим конфигом. Канонический случай: AWS multi-region. Пишешь `provider "aws" { region = "us-east-1" }` и `provider "aws" { alias = "eu" ; region = "eu-west-1" }`. На ресурсе указываешь `provider = aws.eu` - он создастся в EU. Без alias всё ушло бы в default-провайдер. Same trick для кросс-аккаунт через `assume_role` или provider per environment.

Что хотят услышать

Кандидат должен: - объяснить семантику: `provider = aws.eu` - явная привязка ресурса к именованному провайдеру - назвать что модуль с multi-provider требует объявить provider configuration aliases в самом модуле (`required_providers` с `configuration_aliases`) - сказать что default-provider (`aws` без alias) - тоже именованный, просто без квалификатора. Если default не нужен - не объявляй - упомянуть что provider alias привязка известна на plan-стадии, нельзя выбирать провайдер динамически по computed-значению

Подводные камни

  • ✗ Забыть `provider = aws.eu` на ресурсе и получить создание в default-регионе вместо EU
  • ✗ Передать aliased provider в child-модуль без `configuration_aliases` объявления внутри - ошибка plan'а
  • ✗ Думать что `count` или `for_each` могут выбирать provider динамически - не могут, провайдер фиксирован на стадии plan

Follow-up

  • ? Как передать aliased provider в child-модуль правильно?
  • ? Зачем нужен `configuration_aliases` в `required_providers`?
  • ? Можно ли в одном root использовать два провайдера одного типа без alias?

Глубина в базе знаний

  • Блок provider: кому Terraform будет звонить
  • Как terraform init подтягивает модули
  • Ссылки в HCL: как читать aws_s3_bucket.demo.bucket
tags: provider, multi-region

#lifecycle-create-before-destroy

seniorиногда

Что делает `create_before_destroy` и зачем он нужен?

Что отвечать

По умолчанию Terraform при замене ресурса сначала destroy старый, потом create новый. `create_before_destroy = true` меняет порядок: сначала create нового, потом destroy старого. Используется когда простой недопустим: load balancer, ec2 в autoscaling group, RDS replica. Ловушка: имена и порты должны позволять одновременное существование двух экземпляров. Bucket с тем же именем нельзя создать - имя глобально уникально, придётся менять имя или принимать простой.

Что хотят услышать

Senior должен: - назвать что create_before_destroy полезен для zero-downtime replace, но требует чтобы имя/порт были unique или менялись - сказать что lifecycle блок один на ресурс, нельзя через for_each сделать его conditional - проектируй заранее - объяснить что зависимые ресурсы тоже под влиянием: если на ресурс ссылается LB target group, при replace она получит сначала новый target, потом старый исчезнет - упомянуть `precondition` и `postcondition` в lifecycle для assert'ов на values - в 1.2+

Подводные камни

  • ✗ Включить create_before_destroy на ресурсе с уникальным именем (S3 bucket без random-suffix) - apply падает с conflict
  • ✗ Думать что create_before_destroy решает проблему downtime для любого ресурса - не для всех; RDS major version, для примера, требует destroy+create независимо от lifecycle
  • ✗ Использовать create_before_destroy «на всякий» для всех ресурсов - некоторые провайдеры реагируют странно, читай документацию каждого resource

Follow-up

  • ? Что произойдёт при `create_before_destroy = true` для S3 bucket?
  • ? Чем `precondition` отличается от `validation` в variable?
  • ? Когда `prevent_destroy = true` уместен в проде?

Глубина в базе знаний

  • lifecycle: управляем поведением resource
  • Blue-green миграция legacy в Terraform
  • -replace и -target: точечные операции с одним ресурсом
tags: resources, lifecycle, zero-downtimebook: mastering.terraform.epub:ch6

#ignore-changes-tradeoffs

intermediateиногда

Когда `ignore_changes` действительно нужен, а когда это костыль?

Что отвечать

`ignore_changes = [tags["LastModified"]]` говорит Terraform: «не реагируй на изменение этого атрибута в drift'е». Нужен когда внешняя система автоматически меняет атрибут (auto-scaling adjustments, cloud-managed tags, lambda code если деплоится через CI отдельно от Terraform). Костыль когда: «у меня drift, но я не хочу разбираться» - ignore_changes маскирует проблему, не решает её. Раз поставил ignore_changes - этот атрибут больше не управляется Terraform'ом, его дрейф никто не видит.

Что хотят услышать

Senior должен: - назвать legitimate use cases: auto-scaling capacity, lambda code, ECS task definition revision, RDS engine_version при minor auto-upgrade - сказать что ignore_changes принимает list атрибутов, можно `ignore_changes = all` для полного «не трогай», но это уже знак что ресурс не нужно держать в Terraform - различить ignore_changes (drift на атрибуте) и lifecycle prevent_destroy (защита от случайного удаления) - упомянуть `ignore_changes` с computed-attributes: индексы list'ов тоже можно (`ignore_changes = [user_data]`), нельзя с map-ключом вычисляемым через интерполяцию

Подводные камни

  • ✗ Поставить `ignore_changes = all` и забыть - ресурс становится «привязанным к state, но не управляемым», drift не виден
  • ✗ Использовать ignore_changes для секретов в state - они всё равно там лежат, ignore_changes только UI
  • ✗ Не указать `description` рядом с ignore_changes - через полгода коллега не поймёт почему это ignored

Follow-up

  • ? Чем `ignore_changes = all` отличается от ситуации «не держать ресурс в Terraform вообще»?
  • ? Как ignore_changes реагирует на nested attributes (`tags.Owner`)?
  • ? Когда лучше data source чем ignore_changes на собственном ресурсе?

Глубина в базе знаний

  • lifecycle: управляем поведением resource
  • [[tf-drift-detection]]
tags: resources, lifecycle, drift

#depends-on-when-honestly-needed

intermediateиногда

Когда `depends_on` нужен честно, а когда обходимо?

Что отвечать

Terraform строит граф из явных references: видишь `aws_subnet.x.id` в HCL - получаешь implicit dependency. `depends_on` нужен когда зависимость есть, а references нет: IAM-роль с inline policy, которая должна быть привязана до того как EC2 её попробует использовать - связи через ARN может не быть в HCL. На большинстве ресурсов depends_on не нужен; писать его «на всякий случай» создаёт лишние рёбра в графе и может стать причиной cycle.

Что хотят услышать

Senior должен: - сказать что depends_on - escape hatch, использовать когда без него поведение неверное - назвать классический кейс: IAM policy attachment должна быть раньше использования роли; lambda permission раньше event source mapping - упомянуть что depends_on внутри модуля можно объявить через `depends_on` на уровне `module "x" { depends_on = [...] }` - предупредить что лишний depends_on делает граф плотнее и может замедлить plan на больших инфрах

Подводные камни

  • ✗ Добавить `depends_on = [aws_iam_role.foo]` там где уже есть implicit dep через `role = aws_iam_role.foo.name` - не нужно, иногда вредит
  • ✗ Использовать depends_on вместо «вынести зависимость в data source» - data source чище если ты не владеешь ресурсом
  • ✗ Сделать depends_on с обоих концов цепочки - получаешь cycle

Follow-up

  • ? Чем `depends_on` на уровне `module` отличается от внутри ресурса?
  • ? Какие провайдеры требуют explicit `depends_on` чаще других?
  • ? Что показывает `terraform graph` для лишнего `depends_on`?

Глубина в базе знаний

  • Зависимости ресурсов: явные и неявные
  • Ссылки в HCL: как читать aws_s3_bucket.demo.bucket
  • DAG в Terraform, как строится граф зависимостей
tags: resources, dependencies
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки