Удаление элемента списка пересоздаёт ресурсы: count и стабильные ключи for_each
В списке было три сервера: alpha, beta и gamma. Удалили beta, но plan предлагает изменить или заменить gamma и ещё один экземпляр. Причина в адресах count: второй объект называется [1], а не beta. После удаления элемента значение по индексу [1] стало gamma, и инструмент сравнивает его с прежней beta.
Ресурс с count удобно применять к взаимозаменяемым экземплярам. Если у каждого есть собственная идентичность, стабильные ключи for_each обычно точнее описывают задачу. Переход требует сохранить связь со state, иначе новая форма адреса сама вызовет удаление и создание.
Увидим сдвиг на локальном ресурсе
Встроенный terraform_data позволяет изучить план без облака. Для Terraform нужна версия 1.4+; OpenTofu поддерживает этот тип. Создайте отдельный main.tf:
variable "names" {
type = list(string)
default = ["alpha", "beta", "gamma"]
}
resource "terraform_data" "node" {
count = length(var.names)
input = var.names[count.index]
triggers_replace = var.names[count.index]
}
Для воспроизведения в новом локальном каталоге выполните init, plan и подтверждённый apply своего инструмента. Triggers_replace добавлен намеренно: смена имени должна требовать замены, чтобы эффект сдвига был виден. Если оставить только input, terraform_data может обновиться на месте; у реального provider результат зависит от свойств ресурса.
Теперь удалите beta из default и посмотрите новый plan без применения. Индекс [1] получает gamma вместо beta, поэтому меняется его triggers_replace. Последний [2] больше не объявлен и удаляется. Удаление одного логического элемента затронуло адрес другого — именно это нужно исправить.
Сначала мигрируем все исходные элементы
Верните полный список alpha, beta, gamma и замените блок ресурса следующей конфигурацией. Ключи выводятся из уникальных имён, которые в этой модели считаются постоянными.
resource "terraform_data" "node" {
for_each = toset(var.names)
input = each.key
triggers_replace = each.key
}
moved {
from = terraform_data.node[0]
to = terraform_data.node["alpha"]
}
moved {
from = terraform_data.node[1]
to = terraform_data.node["beta"]
}
moved {
from = terraform_data.node[2]
to = terraform_data.node["gamma"]
}
Оставьте прежнюю variable names. Plan должен показать переносы трёх адресов без изменения их значений. Примените именно проверенный перенос на учебном состоянии, затем отдельной правкой удалите beta из списка и посмотрите следующий plan. Теперь должен удаляться только node["beta"], а alpha и gamma сохранят свои адреса.
Выберем ключ по смыслу
Toset подходит, если имена уникальны и переименование означает смену логического объекта. При дубликатах set объединит одинаковые значения, поэтому число экземпляров изменится. Если отображаемое имя разрешено менять независимо от идентичности, используйте map: ключом будет постоянный код, значением — изменяемые настройки.
Например, ключ worker_primary может хранить name=gamma. Тогда смена name не меняет адрес worker_primary, хотя provider всё ещё может потребовать физическую замену по правилам этого атрибута. Стабильный адрес устраняет случайный сдвиг, но не отменяет ограничения обновления конкретного ресурса.
Проверка начинается с фактического state
Перед составлением moved посмотрите state list и свойства каждого индекса. Порядок текущего списка в Git не всегда совпадает с историей применений. Если перепутать соответствие, перенос сохранит неверную привязку и дальнейший plan предложит неожиданные изменения.
Базовое различие count в Terraform и count в OpenTofu одинаково: индекс входит в адрес. Правила декларативного переноса следует сверять в руководствах Terraform и OpenTofu.
В рабочем модуле разделите миграцию адресов и удаление объекта на два проверяемых изменения. Так первый plan отвечает на вопрос сохранения идентичности, второй — на вопрос намеренного удаления beta. Ревью становится точнее: ненужные замены нельзя спрятать внутри общего рефакторинга списка.
Ещё по теме
- Invalid for_each argument: почему ключи ресурсов должны быть известны до apply
- Lock-файл Terraform и OpenTofu: фиксируем версии и проверяем обновление провайдера
Продолжить изучение
Хотите управлять инфраструктурой через код и понимать последствия изменений? Plan, state, модули и работа с существующими ресурсами — темы программы «Terraform и OpenTofu: инфраструктура как код».
Продолжить на практике
- Terraform и OpenTofu: инфраструктура как код ↗
Описывайте инфраструктуру в коде, проверяйте изменения до применения и работайте со state без сюрпризов. HCL, модули, remote state, импорт, CI и различия Terraform/OpenTofu — на воспроизводимом учебном окружении.
