# -replace и -target: точечные операции с одним ресурсом _Workflow · TerraformLab Knowledge Base_ **TL;DR:** Флаги `-replace=
` и `-target=` ограничивают apply одним ресурсом. `-replace` пересоздаёт ресурс (заменяет устаревший `terraform taint`). `-target` применяет только к указанному ресурсу, это аварийный инструмент, не повседневный. ## Зачем нужны точечные операции По умолчанию Terraform работает со всем проектом разом: один plan показывает все изменения, один apply их применяет. Но иногда нужно что-то конкретное: - Пересоздать один сломанный ресурс, не трогая остальное. - Применить только часть конфигурации, чтобы не цеплять unrelated изменения. - Обойти временный bag в провайдере на одном ресурсе. Для этого, `-replace` и `-target`. ## `-replace=`, пересоздать ресурс Заставляет Terraform добавить в plan действие «destroy + create» даже если код не менялся. Полезно когда ресурс в облаке сломался (повреждённый EC2, зависший cache), а HCL правильный. ```bash terraform apply -replace=aws_instance.web ``` Plan покажет: ``` # aws_instance.web will be replaced, as requested -/+ resource "aws_instance" "web" { ... } Plan: 1 to add, 0 to change, 1 to destroy. ``` Это **замена устаревшего `terraform taint`**. До TF 0.15.2 надо было делать `terraform taint aws_instance.web; terraform apply`, два шага и модификация state руками. Теперь, один флаг. ### Адресация для -replace Поддерживается полная адресация: ```bash # обычный ресурс terraform apply -replace=aws_s3_bucket.demo # элемент count terraform apply -replace='aws_instance.web[0]' # элемент for_each terraform apply -replace='aws_s3_bucket.regional["eu"]' # ресурс внутри модуля terraform apply -replace='module.networking.aws_vpc.main' ``` Заметьте кавычки в shell, `[`, `]`, `"` shell интерпретирует. Без кавычек, ошибка. ### Несколько -replace Можно указывать несколько раз, будут пересозданы все: ```bash terraform apply \ -replace=aws_instance.web \ -replace=aws_db_instance.main ``` ## `-target=`, применить только указанный Игнорирует ВСЁ кроме указанного ресурса (и его зависимостей): ```bash terraform apply -target=aws_s3_bucket.logs ``` Plan: ``` Warning: Resource targeting is in effect You are creating a plan with the -target option, which means that the result of this plan may not represent all of the changes requested by the current configuration. # aws_s3_bucket.logs will be created + resource "aws_s3_bucket" "logs" { ... } ``` Terraform **сам предупреждает** что это плохо. Это не повседневный инструмент, это аварийный. ### Когда -target оправдан - Срочно нужно создать/изменить один ресурс, а другие ломают plan. - Тестируете один модуль в большом проекте. - Bootstrap нового окружения по частям (сначала VPC, потом всё остальное). - Разбор циклической зависимости через временное удаление одной стороны. ### Когда -target, плохая идея - Регулярная работа. Если используете каждый день, что-то не так с структурой проекта. Лучше разбить на отдельные state-файлы. - В CI/CD. Не должно быть автоматизации, которая зависит от -target. - Чтобы «обойти» drift вместо его починки. - Для прода без явного incident-флага. Любой -target в проде, это отклонение от нормы, должно быть в runbook. ## Почему -target плох (по версии HashiCorp) Из docs Terraform: > Targeting is a powerful but disruptive feature, and so should be > used only in exceptional circumstances. Конкретно: 1. **Создаёт частично-консистентный state.** После `-target` state и реальность в облаке отличаются от того, что описано в HCL. Может быть так часами, если забыли потом сделать «полный apply». 2. **Скрывает реальные зависимости.** Если ресурс A неявно зависит от B через переменную или data, `-target=A` либо упадёт, либо втянет B неожиданно. 3. **Усложняет debugging.** «Почему ALB не работает?», потому что полтора месяца назад кто-то сделал `-target=alb` и не применил обновления security_group. Поэтому HashiCorp **намеренно** не убирают warning. Каждый раз напоминает что вы делаете что-то нестандартное. ## `-target` с зависимостями Если ресурс ссылается на другие, они **тоже** будут затронуты: ```hcl resource "aws_vpc" "main" { ... } resource "aws_subnet" "private" { vpc_id = aws_vpc.main.id } ``` ```bash terraform apply -target=aws_subnet.private ``` Применит и subnet, и VPC (потому что subnet зависит от VPC). Это делает `-target` чуть менее опасным, нельзя сослаться на несуществующее. ## Чем НЕ являются эти флаги - `-replace` ≠ destroy + create вручную. Это атомарная операция в одном apply, со всеми зависимостями. - `-target` ≠ workspace. Workspace, это отдельный state с тем же HCL. Target, кусок одного state. - `-target` ≠ модуль. `module.networking` через -target, это весь модуль, не «только networking», но не «изоляция модуля». ## Подводные камни - **`-target` принимается через запятую тоже:** `-target=A -target=B`, не `-target=A,B`. Если хотите много, повторяйте флаг. - **`-replace` не работает на data-блоках.** Data, это read-only, его нечего пересоздавать. Если хочется «перечитать», следующий plan/apply сам обновит data. - **После `-target` обязательно сделайте полный apply.** Иначе забудете и расхождение state и HCL останется навсегда. Привычка: `apply -target=X && apply` в одном скрипте. - **`-replace` помечает только в plan'е.** Сам state не меняется до apply. Если plan показался плохим, просто не делайте apply, ничего не сломается. - **`-target` не работает с `import` блоком.** Декларативный import из TF 1.5+ применяется к всему конфигу. ## Команды ```bash terraform apply -replace=aws_instance.web ``` Пересоздать конкретный ресурс. Замена устаревшей terraform taint. ```bash terraform apply -replace='aws_s3_bucket.regional["eu"]' ``` Пересоздать конкретный элемент for_each. Кавычки обязательны для shell. ```bash terraform plan -replace=aws_instance.web ``` Сначала plan c -replace: посмотреть что будет, прежде чем делать apply. ```bash terraform apply -target=aws_subnet.private ``` Применить только указанный ресурс и его зависимости. АВАРИЙНЫЙ инструмент. ```bash terraform plan -target=module.networking ``` Plan только для модуля. Полезно для bootstrap новых окружений по частям. ## См. также - [terraform apply: применить план в реальном облаке](/terraform/kb/tf-apply.md) - [terraform plan: посмотреть, что Terraform собирается сделать](/terraform/kb/tf-plan.md) - [lifecycle: управляем поведением resource](/terraform/kb/tf-resource-lifecycle.md) - [terraform destroy: снести всё, что было создано](/terraform/kb/tf-destroy.md)