Как стать автором
Обновить

Комментарии 22

Нет. Если честно вот только из Вашего комментария о нем узнал. Посмотрел их гихаб. Первый коммит в сентябре 17 года. Наш проект в то время уже жил в проде и управлялся TF, поэтому без шансов.
github.com/pulumi/pulumi/releases?after=v0.9.2
Terraform — это Сloud Agnostic утилита.

Нет, это заблуждение. Cloud agnostic это если бы вы просто поменяли provider: aws на что-то другое и у вас все заработает. Но нет, при смене облака, вам придется переписать все.
Terraform вам дает лишь hcl (hashicorp configuration language), т.е. да не придется учить другой язык, но все равно придется изучить ньюансы другого облака, термины и как все это написать под другой провайдер. Правильный термин — multiple cloud support
Спасибо, учту и внесу исправление!
Как вы отлаживаете ваш terraform код?
Поясните пожалуйста что Вы имеете ввиду, то есть конкретней. Если я сейчас правильно понял Ваш вопрос, тогда следующим образом — любой модуль, любое изменение проходит тестирование в Lab на тестовом окружении нашей команды. Потом оно «долетает» до других Lab окружений разработчиков где уже интегрируется с изменениями софта, настроек и тп. Когда мы считаем что изменение готово — оно идет в stage и после — в prod.
Прошу прощения, я немного другое имел в виду. При переходе на terraform 0.12 hashicorp основательно поломали обратную совместимость. В частности я столкнулся с большим количеством ошибок вызванных неправильными типами переменных. Я не нашел способа посмотреть на содержимое и тип переменных, исправлять приходилось буквально методом тыка. terraform 0.12upgrade помогал далеко не всегда. TF_LOG=TRACE тоже не сильно прибавил ясности. Может вы знаете какой-то другой способ отладки, который бы помог в этой ситуации?
Использовали ли для импорта что-то? Например terraformer или terraforming?
Как у вас устроена структура репозитория? А стейтов? Использовали ли интеграцию с Atlantis? Пишете ли тесты?
Используем terraforming. Сейчас уже почти нет, тк изначально все изменения совершаются через TF. Ранее приходилось применять довольно часто. Плюс мы достигли такого уровня «дзен» когда можем описать весь набор ресурсов в виде модуля, импортнуть все связанные AWS сущности внутрь и потом при помощи plan ( как тест/сравнение) довести конфигурацию до нужного вида. То есть миновать шаг «получили машинно сгеренированный код, надо его причесать»
Про структуру репозиториев — их много. По сути каждый модуль ( вернее то, что его реализует) — это репозиторий. Есть репозитории ресурсных модулей, есть инфраструктурных, есть проекты которые все это исмпользуют. Вас интересуют все они в каком-то «общем» виде или что-то конкретное? Напишите, я постараюсь пояснить.

Стейты у нас хранятся в S3 бакете с шифрованием и версионированием. Ну и конечно ограничением чрез IAM. 1 бакет на aws аккаунт, стейт каждого проекта имеет уникальное имя. Была сначала идея делать бакет под проект но отказались.

Интеграции с Atlantis как и самого Atlantis нет. Есть Gitlab + Gitlab CI, есть Ansible (как средство управления конфигурацией того, что было создано TF и мы сейчас все на него переводим), и немного легаси в виде puppet+foreman + RackTables с которыми ранее интегрировались при помощи самописных плагинов для TF.

Тесты пока не пишем и не понятно будем ли писать
Вы приводите ссылку на оооочень старый комит) Давно уже есть поддержка. Используем очень просто — count передается внутрь модуля, во все зависимые сущности, помогая 1 шаблоном создавать нужное число ресурсов. Плюс внутри модуля через связку count, element и еще ряда функций зашита логика связывания этих ресурсов. Так например мы передаем в модуль число хостов, которые должны быть развернуты и список подсетей. Модуль сделает указанное число EC2 инстансов, сетевых интерфейсов, дисков, rt53 записей и пр, свяжет их и раскидает по сеткам.
я вот даже прям сейчас пробую
$ terraform apply

Error: Reserved argument name in module block

on nodes.tf line 4, in module «nodes»:
4: count = 3

The name «count» is reserved for use in a future version of Terraform.

$ terraform -v
Terraform v0.12.6
+ provider.openstack v1.22.0
+ provider.random v2.2.0
+ provider.template v2.1.2

module «nodes» {
source = "./modules/create_server"

count = 3
// server_count = "${var.server_count}"

в моем случае я передаю другую переменную (server_count), которую потом подставляют в count ресурсов модуля, но вот именно count как аргумент модуля не работает
у вас версия 0.12, я в начале статьи указываю что у нас 0.11 (последняя из этой линейки) и на 0.12 мы пока не переходили. Да, возможно поведение изменилось. У нас это выглядит вот так. Вызываем мы вот так
module "test-ec" {
   count            = "1"
   count_offset     = "10"
   source           = "git::ssh://FQDN/terraform/modules/vm-general.git?ref=1.0.0"
   host_name_prefix = "${var.hostname_prefix}-srv"
   ami_id           = "${data.aws_ami.XXXXX-ami-al-2018.id}"
...


а внутри модуля оно выглядит вот так:
resource "aws_network_interface" "nic0" {
  count             = "${var.count}"
  subnet_id         = "${element(var.subnet_ids, count.index)}"
  security_groups   = ["${var.sgs_ids}"]
  source_dest_check = true
...

data "aws_subnet" "subnet" {
  count = "${var.count}"
  id    = "${aws_network_interface.nic0.*.subnet_id[count.index]}"
}


resource "aws_instance" "instance" {
  count      = "${var.count}"
....

resource "aws_ebs_volume" "ebs_volume" {
  count             = "${length(var.ebs_volumes) * var.count}"
...

resource "aws_volume_attachment" "ebs_attachment" {
  count       = "${length(var.ebs_volumes) * var.count}"
...



но мы еще дополнительно в input.tf ( мы разделяем модуль на 3 файла — описание модуля, input для входных данных и output для выходных) описываем cpunt как переменную, которая уже потом, как Вы видите выше обращается в count ресурса.
Возможно в 0.12 это слово внесли в список служебных и больше такой красивый хак не проходит
variable "count" {
  description = "Number of EC2 instances."
  default     = 0
}

variable "count_offset" {
  description = "Offset of instances. It uses for naming."
  default     = 0
}

понятно, спасибо. ну подход у вас тот же самый
В 0.13 наконец то таки завезли нативную поддержку count для модулей
Terraform не позволяет вам описать зависимость между модулями, если они логически на одном уровне.

Эту проблему успешно решает Terragrunt. Помимо проблем с зависимостями между модулями, Terragrunt содержит много других полезных фич, расширяющих Terraform, так что советую обратить внимание.


Основная проблема Terraform, на мой взгляд, — отсутствие полноценных rollback-ов и запись в state результатов apply только после окончания выполнения команды. State для Terraform – это все: если он будет испорчен, прощай инфраструктура. Я лично несколько раз наблюдал ситуации на проде, когда по разным причинам Terraform экстренно завершил свою работу и испортил state. И далеко не всегда его откат к предыдущей версии позволяет решить все проблемы. Однажды это привело к экстренному дестрою всей инфраструктуры приложения.


Немного деталей. Terraform успешно выполнил plan, после чего должен был добавить несколько новых ресурсов. В процессе применений изменений что-то произошло с сетью на раннере. Как результат, они не были применены в полном объеме; более того, в state не были отражены те изменения, которые уже были применены. Перезапуск пайплайна и откат state на предыдущую версию не помогли: Terraform ругался на то, что не может создать ресурсы с такими именами, которые уже есть в аккаунте.


В 90% случаев это фиксится мануальным удалением тех ресурсов, которые не были проиндексированы в state. Однако в один из деплоев в качестве "битого ресурса" оказалась security group, которая была связана правилами с Elastic Beanstalk, и у нас не получилось удалить ее. В итоге пришлось полностью дестроить инфраструктуру для приложения и раскатывать его заново. Благо у нас все равно был запланирован даунтайм для мажорных обновлений других сервисов, и на клиентах это никак не отразилось.


В моей практике бывали и другие случаи, когда state по каким-то причинам портился. Например, был случай, когда из-за проблем с управлением зависимостями между модулями Terraform ушел в панику и опять же испортил state. Пришлось удалять ресурсы вручную.


Пока я не нашел достойного варианта защиты от таких неприятных ситуаций. Интересно, бывали ли у Вас подобные случаи, и есть ли у Вас алгоритм их предотвращения или исправления?

Про Terragrunt читали но пока не дошло до практики его применения и не знаем дойдем ли. Пока просто своими силами поддерживаем конфигурации модулей и связи между ними.

По вашему вопросу — мы храним tfstate в s3 что дает его версионирование из коробки на любой чих, поэтому частично проблему это решает. И да, уже несколько раз это спасало правда не на проде.

Второй момент, как я уже упоминал это разделение проекта и соответственно разделение tfstate. У нас он вырос до неприличных размеров и сложности с тз построения плана, в итоге удалось разрезать его на несколько логически обособленных кусков, добившись во первых — более быстрого построения плана, во вторых — страхуя себя (опять же частично) от упомянутых проблем.

Ну и да, в случае если что-то идет не так — ручная работа с использованием terraform target, terraform taint

При проблемах во время создания ресурса зачастую помогает отметить его для пересоздания при следующем применении через taint.
Это работает, когда ресурс указан в tfstate.
Но, если пришлось откатить tfstate и нужного ресурса там нет — его можно вписать или скопировать, а затем также отметить для пересоздания.


PS: не пойму только, чем в этом случае поможет шаблонизатор terragrunt

Но, если пришлось откатить tfstate и нужного ресурса там нет — его можно вписать или скопировать, а затем также отметить для пересоздания.

Думаю, лезть в tfstate и менять его руками — плохая идея. Так можно много чего наворотить, особенно, если не до конца понимаешь, с чем имеешь дело. Рекомендации, изложенные в комментарии выше (версионирование tfstate с возможным откатом на предыдущие версии, разбивка инфраструктуры на небольшие блоки с отдельными tfstate и т.д.), я нахожу более прозрачными и безопасными.


не пойму только, чем в этом случае поможет шаблонизатор terragrunt

Как Вы правильно заметили, никак. Terragrunt — лишь расширение Terraform, позволяющее решить ряд его проблем (например, как упоминалось выше, управление зависимостями между модулями) и сделать его использование более гибким (например, управление инфраструктурой для разных окружений). Использование Terragrunt не решает проблему испорченного state.

И кстати если у вас только AWS и только 11 версия, попробуйте tflint, может понравится.
Для 12 пока не работает, но надежда (и тикеты в гитхаб) есть.

спасибо что подсказали, попробуем. Мы использовали дефолтные опции валидации, без сторонних линтеров. И судя по их репе они уже могут в 0.12
github.com/wata727/tflint
«TFLint is a Terraform linter focused on possible errors, best practices, etc. (Terraform >= 0.12)»

Тут такой нюанс приятный, tflint ходит в облако и проверяет что ресурс там имеется, например image или ещё какой.
Если проверять только синтаксис, он не намного лучше связки


terraform fmt & terraform validate

А насчет полной поддержки V0.12 ждем-с https://github.com/virtuald/pyhcl/issues/55

Зарегистрируйтесь на Хабре , чтобы оставить комментарий