Циклы в Terraform: параметр count

Рейтинг: 68.5% · 14 голосов
Подробный курс по Terraform и OpenTofu на примерах Yandex Cloud: ресурсы и провайдеры, состояние и бэкенды, модули, циклы и условия HCL, секреты и Lockbox, тестирование, CI/CD и командная работа. С актуализацией на 2026 (Terraform 1.3-1.10, OpenTofu).
Ответить
Аватара пользователя
Vlad_DevOps
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Циклы в Terraform: параметр count

Сообщение Vlad_DevOps »

Оглавление курса (47)
  1. Что такое инфраструктура как код и зачем она нужна
  2. Категории инструментов IaC: чем отличаются Ansible, Packer, Kubernetes и Terraform
  3. Чем Terraform отличается от Ansible, Pulumi и CloudFormation
  4. Как работает Terraform под капотом и кто такой OpenTofu
  5. Установка Terraform и OpenTofu, подготовка Yandex Cloud
  6. Первый ресурс: разворачиваем виртуальную машину в Yandex Cloud
  7. Веб-сервер на ВМ: метаданные, user-data и группы безопасности
  8. Переменные ввода и выходные значения в Terraform
  9. Кластер ВМ: группа экземпляров Yandex Compute Instance Group
  10. Балансировщик нагрузки: Application Load Balancer в Yandex Cloud
  11. Состояние Terraform: что такое tfstate и чем опасен локальный файл
  12. Удалённое хранилище состояния: бэкенд на Yandex Object Storage
  13. Изоляция состояния: рабочие области против раскладки по папкам
  14. Источники данных и terraform_remote_state: связываем компоненты
  15. Модули Terraform: переиспользуем инфраструктуру
  16. Входные, локальные и выходные переменные модуля
  17. Версионирование модулей и подводные камни
  18. Циклы в Terraform: параметр count (вы здесь)
  19. Циклы в Terraform: for_each по множествам и картам
  20. Выражения for и строковые директивы
  21. Условная логика: count-трюк, for_each и директива if
  22. Встроенные функции, типы и выражения HCL
  23. Развёртывание без простоя: create_before_destroy
  24. Подводные камни Terraform и рефакторинг с блоком moved
  25. Управление секретами: основы и типы
  26. Инструменты управления секретами: Yandex Lockbox, Vault, SOPS
  27. Аутентификация провайдера и секреты: сервисные аккаунты и OIDC
  28. Секреты в ресурсах и состоянии, ephemeral-значения
  29. Провайдеры Terraform: установка, версии, required_providers
  30. Несколько копий одного провайдера: alias и мультизона
  31. Несколько провайдеров и аккаунтов: configuration_aliases
  32. Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud
  33. Код Terraform промышленного уровня: почему это долго
  34. Мелкие компонуемые модули вместо монолита
  35. Тестируемые модули и проверки: validation, precondition, postcondition
  36. Версионирование, публикация модулей и Terragrunt
  37. Ручное тестирование Terraform и очистка ресурсов
  38. Автоматические тесты на Terratest: модульные тесты
  39. Интеграционные и сквозные тесты, пирамида тестирования
  40. Нативный terraform test и статический анализ
  41. Внедрение Terraform в команде: процессы и культура
  42. Конвейер развёртывания прикладного кода
  43. Конвейер инфраструктурного кода и золотое правило Terraform
  44. Стиль, ревью и CI/CD-инструменты: Atlantis, TACOS, policy as code
  45. Что нового в Terraform 1.3-1.10: моды, импорт, провайдер-функции, Stacks
  46. OpenTofu в 2026: чем живёт форк и как мигрировать
  47. Сертификация HashiCorp Terraform Associate и карьера
Зачем тебе count и какую боль он лечит

Представь, что тебе нужно поднять не одну виртуалку, а три одинаковых - под кластер, под нагрузочное тестирование или просто три воркера для очереди. Самый прямолинейный путь - скопировать блок resource три раза, поменять имена и жить дальше. Через неделю прилетает задача "сделай пять штук", и ты снова идёшь копипастить, а потом ловишь опечатку в четвёртой копии и полдня дебажишь, почему одна ВМ не та.

Инфраструктура как код (iac) придумана ровно для того, чтобы такого не было. Если у тебя есть N одинаковых сущностей, описание должно быть ОДНО, а количество - параметром. В Terraform за это отвечает мета-аргумент count. Он работает с любым ресурсом и говорит коротко: "сделай вот этого добра ровно столько-то копий". Это первый и самый простой инструмент размножения ресурсов в terraform yandex cloud, и в этом уроке мы разберём не только как он создаёт копии, но и где он коварно подставляет.

Изображение

Механика: count, count.index и адресация копий

Идея простая. Ты добавляешь в блок ресурса строчку count = N, и Terraform создаёт N экземпляров этого ресурса. Внутри блока становится доступен объект count.index - это порядковый номер текущей копии, нумерация с нуля. То есть при count = 3 у тебя будут индексы 0, 1 и 2. Через count.index удобно генерировать уникальные имена, раздавать разные IP из подсети, тянуть значения из списка по позиции.

Когда ресурс размножен через count, Terraform хранит его уже не как одиночку, а как список экземпляров. Из-за этого меняется адресация:
  • resource_type.name[0] - обращение к конкретной копии по индексу. Например, yandex_compute_instance.worker[0] - первая виртуалка.
  • resource_type.name
  • - так называемый splat-оператор (звёздочка). Он разворачивает все копии в список значений. Например, yandex_compute_instance.worker
  • .id даст список из всех id созданных машин.
Splat особенно полезен в выводах и когда надо передать все адреса разом - скажем, список внутренних IP всех воркеров в группу безопасности или в шаблон конфига.

Практика: три одинаковые ВМ в Yandex Cloud

Соберём типовой пример - три одинаковые виртуалки. Сначала минимальный каркас провайдера и сеть, потом сами машины через count.

Код: Выделить всё

terraform {
  required_providers {
    yandex = {
      source = "yandex-cloud/yandex"
    }
  }
}

provider "yandex" {
  zone = "ru-central1-a"
}

resource "yandex_vpc_network" "net" {
  name = "demo-net"
}

resource "yandex_vpc_subnet" "subnet" {
  name           = "demo-subnet"
  zone           = "ru-central1-a"
  network_id     = yandex_vpc_network.net.id
  v4_cidr_blocks = ["10.10.0.0/24"]
}

resource "yandex_compute_instance" "worker" {
  count = 3

  name = "worker-${count.index}"
  zone = "ru-central1-a"

  resources {
    cores  = 2
    memory = 2
  }

  boot_disk {
    initialize_params {
      image_id = "fd8vmcue7aajpmeo39kk"
    }
  }

  network_interface {
    subnet_id = yandex_vpc_subnet.subnet.id
    nat       = true
  }
}
Тут count = 3 даёт три инстанса с именами worker-0, worker-1 и worker-2. Имя собираем через интерполяцию ${count.index}, так что копипаст не нужен в принципе. Обрати внимание: count.index подставляется автоматически в каждой копии своим значением.

Теперь вытащим результаты через splat. Выводы (outputs) - идеальное место показать, как разворачиваются все копии разом:

Код: Выделить всё

output "worker_names" {
  value = yandex_compute_instance.worker[*].name
}

output "worker_external_ips" {
  value = yandex_compute_instance.worker[*].network_interface.0.nat_ip_address
}

output "first_worker_id" {
  value = yandex_compute_instance.worker[0].id
}
В worker_names получишь список ["worker-0", "worker-1", "worker-2"], в worker_external_ips - список внешних адресов всех машин, а во first_worker_id - id только первой через индекс [0]. Запусти terraform plan apply и в плане увидишь три ресурса с суффиксами [0], [1], [2] - именно так Terraform их и подписывает в terraform state.

count хорошо ложится не только на ВМ. Тот же приём работает, например, для сервисных аккаунтов, когда нужно завести несколько одинаковых "пользователей-роботов":

Код: Выделить всё

resource "yandex_iam_service_account" "robot" {
  count = 3
  name  = "robot-sa-${count.index}"
}
Грабли: сдвиг индексов при удалении из середины

А вот теперь главная ловушка, ради которой стоило читать весь урок. count нумерует копии по позиции в списке, а не по имени или какому-то стабильному ключу. Привязка идёт жёстко к индексу: worker[0], worker[1], worker[2].

Допустим, у тебя три воркера, и ты решил убрать СРЕДНИЙ - worker-1. В нормальном мире ты ждёшь, что удалится одна машина, а две останутся на месте. В мире count происходит другое. Ты уменьшаешь count до 2, и Terraform думает так: раньше был список из трёх, теперь из двух, значит лишний элемент - тот, что в конце, [2]. Но содержимое-то сдвинулось. Машина, которая была worker[2], теперь должна стать worker[1]. И Terraform на полном серьёзе планирует:
  • worker[1] - изменить (потому что теперь там данные бывшего worker[2], имя поменяется на worker-1);
  • worker[2] - удалить.
По факту это значит пересоздание (destroy/create) одной целой машины просто потому, что ты тронул элемент в середине. На stateless-воркерах это переживаемо. А если в середине была ВМ с данными, базой или статичным внешним IP - получишь даунтайм и потерю состояния на ровном месте. Запомни как мантру: count безопасно растить и резать только с хвоста списка. Любое удаление из середины тянет за собой каскадный сдвиг и пересоздание всего, что было правее.

Второе ограничение тоньше. Значение count вычисляется на стадии планирования, ДО применения. Поэтому в count нельзя подставлять величину, которая зависит от ещё не созданных ресурсов. Классика - попытка сделать count одного ресурса равным количеству или атрибуту другого ресурса, который сам ещё не существует:

Код: Выделить всё

# Так Terraform упрётся: значение count неизвестно на этапе плана
resource "yandex_compute_instance" "vm" {
  count = length(yandex_vpc_subnet.subnet[*].id)
  # ...
}
Если subnet тоже создаётся в этом же прогоне, его id ещё не вычислен на момент планирования count, и ты получишь ошибку вида "value of count cannot be computed". count хочет знать число ЗАРАНЕЕ - из переменной, из длины статического списка, из локала, но не из атрибута ресурса, рождающегося в том же apply.
Если коротко: count - это про "сколько штук", а не про "какие именно". Когда тебе важна стабильная идентичность каждого элемента, count - не твой инструмент, и в следующих уроках мы возьмём for_each, который привязывает экземпляры к ключам, а не к позициям.
Когда count - это нормально

Не подумай, что count - зло. Он отлично подходит, когда выполнены два условия: копии действительно взаимозаменяемы (никому не важно, кто из них [0], а кто [1]) и ты не планируешь выдёргивать элементы из середины. Типичные хорошие сценарии:
  • пул одинаковых stateless-воркеров, который масштабируется только числом;
  • условное создание ресурса через count = var.enabled ? 1 : 0 (включить/выключить блок флагом);
  • N однотипных сервисных аккаунтов или ключей, где порядок не имеет значения.
Если же сущности именованные и живут долго (продакшен-ВМ с привязанными дисками, пользователи с конкретными ролями) - бери for_each. Это не догма, а инженерное решение под конкретный профиль изменений. Кстати, всё сказанное один в один работает и в opentofu - это форк с тем же языком HCL и той же семантикой count, так что навык переносится без правок.

Мини-лаба: повтори руками
  • Подними три ВМ через count = 3 с именами worker-0..worker-2, прогони terraform plan apply, найди в state суффиксы [0], [1], [2].
  • Добавь output со splat worker
  • .name и отдельный output с worker[0].id, сравни вывод list против одиночного значения.
  • Теперь самое важное: уменьши count до 2, сделай plan (НЕ apply, если жалко машин) и внимательно прочитай, что Terraform собирается пересоздавать. Убедись, что лишним он считает хвост, а не "среднюю" машину.
  • Поэкспериментируй: оберни ресурс в count = var.create ? 1 : 0 и переключи флаг - почувствуй count как условный выключатель.
Контрольные вопросы
  • С какого числа начинается нумерация count.index и где её удобно применять?
  • Чем отличается обращение worker[0] от worker
  • и что вернёт каждое?
  • Что произойдёт, если из списка ресурсов с count удалить элемент из середины, и почему это опасно для ВМ с данными?
  • Почему нельзя задать count, равный атрибуту другого ресурса, создаваемого в том же apply?
Итог: что запомнить

count = N штампует N копий одного ресурса, count.index (с нуля) даёт каждой копии уникальный номер для имён и адресов. Доступ к копиям - через индекс [0] или splat [*]. Главный подводный камень - привязка к позиции: удаление из середины сдвигает индексы и пересоздаёт всё правее, поэтому расти и режь только с хвоста. И помни: count хочет число заранее, на этапе плана, и не дружит со значениями, которые ещё не вычислены. Когда копии взаимозаменяемы - count идеален; когда важна стабильная идентичность - дождись урока про for_each.
👍3 ❤️1 🔥2 😄 🤔
Аватара пользователя
torveteran
Сообщения: 1
Зарегистрирован: 17 май 2026, 20:28

Re: Циклы в Terraform: параметр count

Сообщение torveteran »

Спасибо, наконец дошло зачем splot эта звездочка нужна. А правда что если я через count = 2 уберу первую вм а не последнюю то пересоздадутся обе? пробовал на тесте вроде так и было
👍 ❤️1 🔥1 😄 🤔
Аватара пользователя
Zoria
Сообщения: 1
Зарегистрирован: 11 май 2026, 09:53

Re: Циклы в Terraform: параметр count

Сообщение Zoria »

Поймал ровно эти грабли на проде месяц назад, дернул воркера из середины и terraform пересоздал внешний ip у соседней машины, прод лег на пару минут. Теперь только с хвоста режу, как тут и написано
👍 ❤️ 🔥1 😄 🤔
Ответить
← Предыдущая глава
Версионирование модулей и подводные камни
Следующая глава →
Циклы в Terraform: for_each по множествам и картам

Все главы курса «Terraform: инфраструктура как код на Yandex Cloud»

Поделиться темой: ✈ Telegram VK
Похожие запросы: terraform yandex cloud с чего начать новичкукак установить terraform и opentofu на linuxчто такое terraform state и tfstate простыми словамиудаленный backend terraform на object storage yandex cloudчто такое инфраструктура как код iac простыми словамиterraform plan и apply что делают и чем отличаются

Вернуться в «Terraform: инфраструктура как код на Yandex Cloud»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя