Прим. перев.: это перевод статьи о крутом инструменте под названием Terraformer, с помощью которого можно легко сгенерировать готовый код и стейт для Terraform.

Что если я вам скажу, что существует возможность просто взять и нарисовать инфраструктуру в веб-интерфейсе и сразу же получить для нее готовый код для Terraform? Возможно в это сложно поверить, но Антон Бабенко уже сделал это в своем проекте modules.tf. Вот так просто, рисуешь диаграмму и заодно генерируешь код. Звучит круто, да?

Но что делать с уже имеющейся инфраструктурой (например "накликанной когда-то кем-то руками") и хотелось бы легко сгенерировать для нее код?

Или например другой пример: мы все время делали "мониторы" для Datadog вручную, и теперь хочется ими управлять через код, хорошо бы их как-то импортировать в код. Тут-то нам и поможет Terraformer — консольный инструмент для генерации кода и стейта в форматах HCL и json для уже существующей инфраструктуры.

Давайте немного подробнее поговорим о Terraformer ниже.

Введение

Довольно редко вся инфраструктура описывается кодом с нуля. Обычно, что-то добавляется руками через веб-интерфейс или с помощью командной строки облачного провайдера и т.д.

По моему скромному мнению, Terraformer значительно облегчает процесс получения какой-либо информации об уже имеющейся инфраструктуре. Например, в случае миграции с Cloudformation на Terraform или же если хочется делать периодические проверки инфраструктуры на наличие новых ресурсов (например кем-то созданных руками).

О проекте Terraformer

Terraformer был создан @sergeylanz, SRE в Google/Waze. Первый релиз был опубликован 2 мая 2019 года, данный релиз поддерживал AWS и GCP.

На сегодняшний день инструмент поддерживает 15 облачных провайдеров и более 10 сторонних провайдеров, таких как Kubernetes, Datadog, Keycloak, и т.д. Перечень всех провайдеров можно найти тут.

Более 70 инженеров уже внесли свою лепту в развитие проекта, поэтому можно с уверенностью говорить о том, что проект жив и развивается с каждым днем.

https://github.com/GoogleCloudPlatform/terraformer/graphs/contributors
https://github.com/GoogleCloudPlatform/terraformer/graphs/contributors

Погодите, я слышал о terraforming, разве это не одно и то же?

Несмотря на большой функционал, пациент скорее мертв, чем жив. Архитектурные ошибки в terraforming не позволили далее развиваться проекту.

Terraforming получает все атрибуты из облачных API и создает файлы HCL и tfstate с шаблонами. Каждый атрибут в API сопоставляется с атрибутом в Terraform. Файлы, созданные с помощью шаблонов, могут быть повреждены с использованием недопустимого синтаксиса. Когда провайдер добавляет новые атрибуты, необходимо также обновить код terraforming.

Terraformer же использует Terraform-провайдеров для сопоставления атрибутов, библиотеку HCL от Hashicorp и код Terraform.

Ок, так как же все-таки Terraformer работает под капотом?

Прим. перев.: Около двух лет назад на Хабре уже была статья от создателя Terraformer, в которой описывает как это работает.

Terraformer использует уже существующие Terraform-провайдеры, которые уже содержат в себе все ресурсы и логику работы с API облачных провайдеров. Инструмент взаимодействует с этими API с помощью RPC, что позволяет использовать последние версии API провайдеров без изменения кода внутри проекта. Добавление нового ресурса никогда не было таким простым.

Давайте немного поиграемся с Terraformer.

Установка

Тут все просто, скачиваем бинарник и распаковываем его:

export PROVIDER=aws
export PROVIDER_VERSION=3.33.0
export OS=darwin

# terraformer
curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-${OS}-amd64
chmod +x terraformer-${PROVIDER}-${OS}-amd64
sudo mv terraformer-${PROVIDER}-${OS}-amd64 /usr/local/bin/terraformer

# AWS provider
mkdir -p ~/.terraform.d/plugins/${OS}_amd64
curl -L https://releases.hashicorp.com/terraform-provider-aws/${PROVIDER_VERSION}/terraform-provider-aws_${PROVIDER_VERSION}_${OS}_amd64.zip -o terraform-provider-aws.zip
unzip terraform-provider-aws.zip
mv terraform-provider-aws_v${PROVIDER_VERSION}* ~/.terraform.d/plugins/${OS}_amd64/

Проверка корректности установки:

$ terraformer version
Terraformer v0.8.10

Импортируем ресурсы

Давайте, к примеру, импортируем все SSL-сертификаты (ACM) и базы данных (RDS) из Северной Виргинии (us-east-1) из нашего аккаунта AWS.

В моем случае используется несколько аккаунтов AWS, поэтому я использую профили, которые Terraformer, кстати, также поддерживает.

Начинаем импорт ресурсов:

$ terraformer import aws --resources=acm,rds --regions=us-east-1 --profile=my-profile
2020/07/12 17:52:09 aws importing region us-east-1
2020/07/12 17:52:09 aws importing... acm
...
2020/07/12 17:53:27 aws importing... rds
...
2020/07/12 17:54:01 aws Connecting....
2020/07/12 17:54:01 aws save acm
2020/07/12 17:54:01 aws save tfstate for acm
2020/07/12 17:54:01 aws save rds
2020/07/12 17:54:01 aws save tfstate for rds

Terraformer сгенерировал множество файлов, давайте посмотрим, что за файлы, а заодно и структуру сгенерированных файлов и директорий:

$ tree generated/
generated/
L-- aws
    +-- acm
    ¦   +-- acm_certificate.tf
    ¦   +-- outputs.tf
    ¦   +-- provider.tf
    ¦   L-- terraform.tfstate
    L-- rds
        +-- db_instance.tf
        +-- db_parameter_group.tf
        +-- db_subnet_group.tf
        +-- outputs.tf
        +-- provider.tf
        L-- terraform.tfstate

3 directories, 10 files

Тут мы можем увидеть, что в каждой директории для ресурса появились файлы в формате HCL, а также стейт. Кстати, Terraformer поддерживает различные представления сгенерированных ресурсов, больше информации тут.

Давайте посмотрим вывод terraform plan:

$ cd generated/aws/acm/
$ terraform init
$ AWS_PROFILE=my-profile terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


aws_acm_certificate.tfer--a1b2c3d4-a1b2c3d4-a1b2c3d4-a1b2c3d4-a1b2c3d4_example-com: Refreshing state... [id=arn:aws:acm:us-east-1:1234567890:certificate/a1b2c3d4-a1b2c3d4-a1b2c3d4-a1b2c3d4-a1b2c3d4]
aws_acm_certificate.tfer--s1d2f3g4-s1d2f3g4-s1d2f3g4-s1d2f3g4-s1d2f3g4_example-org: Refreshing state... [id=arn:aws:acm:us-east-1:1234567890:certificate/s1d2f3g4-s1d2f3g4-s1d2f3g4-s1d2f3g4-s1d2f3g4]
aws_acm_certificate.tfer--o2k3l4p1-o2k3l4p1-o2k3l4p1-o2k3l4p1-o2k3l4p1_example-net: Refreshing state... [id=arn:aws:acm:us-east-1:1234567890:certificate/o2k3l4p1-o2k3l4p1-o2k3l4p1-o2k3l4p1-o2k3l4p1]
aws_acm_certificate.tfer--z5x6c7v8-z5x6c7v8-z5x6c7v8-z5x6c7v8-z5x6c7v8_example-edu: Refreshing state... [id=arn:aws:acm:us-east-1:1234567890:certificate/z5x6c7v8-z5x6c7v8-z5x6c7v8-z5x6c7v8-z5x6c7v8]


------------------------------------------------------------------------


No changes. Infrastructure is up-to-date.


This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

Тут видим, что состояние ресурсов описанное в конфигурации и в стейте совпадают. Круто.

По умолчанию, код генерируется для Terraform 0.12, однако я использую версию 0.14, поэтому столкнулся с такой ошибкой:

$ terraform init                                                                                                          (eks-dev-green/noam722)

Initializing the backend...

Error: Invalid legacy provider address

This configuration or its associated state refers to the unqualified provider
"aws".

You must complete the Terraform 0.13 upgrade process before upgrading to later
versions.

Это легко можно исправить с помощью команды:

$ terraform state replace-provider registry.terraform.io/-/aws hashicorp/aws

Данная команда обновляет стейт с версии 3 до 4 и обновляет код до совместимости с Terraform 0.14.

Личный опыт

С помощью Terraformer я импортировал более 50 000 строк кода для таких провайдеров AWS, Datadog, New Relic и GitHub.

Вот как это примерно выглядит
Вот как это примерно выглядит

В общем-то, у меня не возникло никаких проблем с обновлением стейта и конвертацией кода на более новую версию, а также с пушем стейта на S3-бекенд.

Terraformer все еще не поддерживает некоторые типы ресурсов, например AWS Redshift, поэтому я их импортировал с помощью Terraforming, так что он тоже может пригодиться, имейте ввиду.

Итоги

Terraformer — отличный инструмент для реверс-терраформинга. В то же время это легко расширяемый фреймворк, позволяющий очень быстро добавлять поддержку новых ресурсов и провайдеров. Основатель проекта и сообщество активно работают над его развитием. Некоторые мелкие вещи типа старой версии стейта или необходимость конвертировать код для новой версии Terraform могут быть решены вручную, да и мелочи это все, наверняка они будут исправлены в будущем.

Спасибо сообществу работающему над инструментом. Живи долго и процветай, Terraformer.