Комментарии 22
github.com/pulumi/pulumi/releases?after=v0.9.2
Terraform — это Сloud Agnostic утилита.
Нет, это заблуждение. Cloud agnostic это если бы вы просто поменяли provider: aws на что-то другое и у вас все заработает. Но нет, при смене облака, вам придется переписать все.
Terraform вам дает лишь hcl (hashicorp configuration language), т.е. да не придется учить другой язык, но все равно придется изучить ньюансы другого облака, термины и как все это написать под другой провайдер. Правильный термин — multiple cloud support
Как у вас устроена структура репозитория? А стейтов? Использовали ли интеграцию с Atlantis? Пишете ли тесты?
Про структуру репозиториев — их много. По сути каждый модуль ( вернее то, что его реализует) — это репозиторий. Есть репозитории ресурсных модулей, есть инфраструктурных, есть проекты которые все это исмпользуют. Вас интересуют все они в каком-то «общем» виде или что-то конкретное? Напишите, я постараюсь пояснить.
Стейты у нас хранятся в S3 бакете с шифрованием и версионированием. Ну и конечно ограничением чрез IAM. 1 бакет на aws аккаунт, стейт каждого проекта имеет уникальное имя. Была сначала идея делать бакет под проект но отказались.
Интеграции с Atlantis как и самого Atlantis нет. Есть Gitlab + Gitlab CI, есть Ansible (как средство управления конфигурацией того, что было создано TF и мы сейчас все на него переводим), и немного легаси в виде puppet+foreman + RackTables с которыми ранее интегрировались при помощи самописных плагинов для TF.
Тесты пока не пишем и не понятно будем ли писать
module "AAA" {
source = "..."
count = "3"
github.com/hashicorp/terraform/issues/953
$ 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 как аргумент модуля не работает
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
}
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. Пришлось удалять ресурсы вручную.
Пока я не нашел достойного варианта защиты от таких неприятных ситуаций. Интересно, бывали ли у Вас подобные случаи, и есть ли у Вас алгоритм их предотвращения или исправления?
По вашему вопросу — мы храним 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 пока не работает, но надежда (и тикеты в гитхаб) есть.
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
Как мы переложили управление инфраструктурой на Terraform — и начали жить