Удаление элемента списка пересоздаёт ресурсы: 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. Ревью становится точнее: ненужные замены нельзя спрятать внутри общего рефакторинга списка.

Ещё по теме

Продолжить изучение

Хотите управлять инфраструктурой через код и понимать последствия изменений? Plan, state, модули и работа с существующими ресурсами — темы программы «Terraform и OpenTofu: инфраструктура как код».

Продолжить на практике

  • Terraform и OpenTofu: инфраструктура как код ↗

    Описывайте инфраструктуру в коде, проверяйте изменения до применения и работайте со state без сюрпризов. HCL, модули, remote state, импорт, CI и различия Terraform/OpenTofu — на воспроизводимом учебном окружении.