Как проверить конфигурацию Terraform?

37

Если бы у вас была конфигурация Terraform, которая имела умеренную степень сложности, как бы вы написали тесты для конфигурации, которые могли бы выполняться как часть конвейера Continuous Integration / Continuous Delivery?

Например, у вас может быть конфигурация с несколькими облаками, которая задает следующее желаемое состояние:

  • Службы контейнеров Azure для размещения Docker в Azure
  • Хранилище BLOB-объектов Azure
  • SQL Azure
  • Контейнерный сервис EC2 для размещения Docker в AWS
  • Сервис хранения Amazon S3
  • База данных Amazon RDS SQL Server

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

Мне известно, что Terraform разделяет свою работу на этап плана выполнения и этап приложения, который фактически вносит изменения в целевую архитектуру. Может ли это быть использовано для написания тестов по плану выполнения, если да, существуют ли фреймворки, помогающие их написать?

Ричард Слейтер
источник
Может быть полезно: github.com/hashicorp/terraform/issues/5059
Tensibai
Действительно интересно, возможно, ответ достойный.
Ричард Слейтер
Я не использую terraform сам, поэтому я позволю кому-то с реальным опытом написать ответ :)
Tensibai

Ответы:

20

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

Terraform создает файлы состояний в формате JSON, которые, в принципе, могут использоваться внешними программами для извлечения определенных данных о том, что создал Terraform. Хотя этот формат еще не считается официально стабильным, на практике он меняется достаточно редко, чтобы люди успешно интегрировались с ним, признавая, что им может потребоваться внести изменения при обновлении Terraform.

Какая стратегия здесь подходит, во многом будет зависеть от того, что именно вы хотите проверить. Например:

  • В среде, которая раскручивает виртуальные серверы, такие инструменты, как Serverspec, могут использоваться для запуска тестов с точки зрения этих серверов. Это может быть либо запущено отдельно от Terraform с использованием какого-либо внеполосного процесса, либо как часть Terraform, применяемая с использованием remote-execпровайдера . Это позволяет проверять вопросы типа «может ли сервер связаться с базой данных?», Но не подходит для таких вопросов, как «достаточно ли ограничена группа безопасности экземпляра?», Поскольку надежная проверка требует доступа к данным извне самого экземпляра.

  • Можно написать тесты с использованием существующей тестовой среды (такой как RSpec для Ruby, unittestдля Python и т. Д.), Которая собирает соответствующие идентификаторы ресурсов или адреса из файла состояния Terraform, а затем использует SDK соответствующей платформы для получения данных о ресурсах и утверждает, что они настроены как ожидалось. Это более общая форма предыдущей идеи, когда тесты выполняются с точки зрения хоста за пределами тестируемой инфраструктуры, и, таким образом, они могут собирать более широкий набор данных для утверждения.

  • При более скромных потребностях можно полагать, что состояние Terraform является точным представлением реальности (во многих случаях допустимым предположением), и просто утверждать непосредственно об этом. Это наиболее подходит для простых «похожих на ворсин» случаев, таких как проверка того, что для целей распределения затрат используется правильная схема маркировки ресурсов.

Это обсуждается в соответствующем выпуске Terraform Github .

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

Мартин Аткинс
источник
12

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

PrestonM
источник
12

Недавно мы открыли исходный код Terratest , нашего швейцарского армейского ножа для тестирования кода инфраструктуры.

Сегодня вы, вероятно, тестируете весь код своей инфраструктуры вручную, развертывая, проверяя и отменяя развертывание. Terratest помогает вам автоматизировать этот процесс:

  1. Пишите тесты в Go.
  2. Используйте помощников в Terratest для выполнения ваших реальных инструментов IaC (например, Terraform, Packer и т. Д.) Для развертывания реальной инфраструктуры (например, серверов) в реальной среде (например, AWS).
  3. Используйте помощников в Terratest, чтобы проверить правильность работы инфраструктуры в этой среде путем выполнения HTTP-запросов, вызовов API, SSH-соединений и т. Д.
  4. Используйте помощников в Terratest, чтобы отменить все в конце теста.

Вот пример теста для некоторого кода Terraform:

terraformOptions := &terraform.Options {
  // The path to where your Terraform code is located
  TerraformDir: "../examples/terraform-basic-example",
}

// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)

// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)

// Run `terraform output` to get the value of an output variable
instanceUrl := terraform.Output(t, terraformOptions, "instance_url")

// Verify that we get back a 200 OK with the expected text
// It can take a minute or so for the Instance to boot up, so retry a few times
expected := "Hello, World"
maxRetries := 15
timeBetweenRetries := 5 * time.Second
http_helper.HttpGetWithRetry(t, instanceUrl, 200, expected, maxRetries, timeBetweenRetries)

Это интеграционные тесты, и в зависимости от того, что вы тестируете, это может занять 5 - 50 минут. Это не быстро (хотя, используя Docker и этапы тестирования , вы можете ускорить некоторые вещи), и вам придется потрудиться, чтобы сделать тесты надежными, но это того стоит.

В репозитории Terratest вы найдете документы и множество примеров различных типов кода инфраструктуры и соответствующих тестов для них.

Евгений Брикман
источник
1
Я также написал пост в блоге, в котором подробно описывается тестирование одного из моих примеров проектов с Terratest: brightfame.co/blog/… . Это может быть полезно для всех. Ура, Роб!
Роб Морган
Большой поклонник Терратеста!
jlucktay
7

В дополнение ко всем другим упомянутым опциям я хотел бы отметить, что в InSpec 2.0 добавлена ​​поддержка API-интерфейсов облачного провайдера. По сути, вы можете продолжить писать IaC с помощью Terraform, а затем писать проверки совместимости с InSpec для своих облачных ресурсов. Кроме того, InSpec поддерживает написание тестов для отдельных машин, если вам это когда-нибудь понадобится.

Вот статья Кристофа Хартманна (со-создателя Inspec) о том, как использовать Inspec с Terraform: https://lollyrock.com/articles/inspec-terraform/

Екта Леблебичи
источник
5

На Aws-Side есть https://github.com/k1LoW/awspec - должна быть возможность, подать в terraform.state и проверить, правильно ли применен terraform.

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

Мы обсуждаем эту идею здесь:

https://github.com/DomainDrivenArchitecture/dda-cloudspec/blob/development/README.md

Для тестирования инвариантов заранее, я не знаю готового решения ...

Мы провели несколько экспериментов, используя комбинацию terraform plan -out=plan.dumpи grepотсутствие названий элементов. Здесь обсуждается более доступный формат плана: github.com/hashicorp/terraform/issues/11883

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

Джергер
источник
4
Цель состоит в том, чтобы проверить, что изменения в конфигурации terraform не нарушат ожидаемых потребностей, после развертывания будет слишком поздно, в лучшем случае вы ошибетесь, увидев, что БД удалена там, где она не должна, но вы уже нарушили целевую среду. ... речь идет о тестировании кода terraform, а не о тестировании конечного результата, модульных тестах и ​​интеграционных тестах.
Тенсибай
Хороший вопрос ... добавлен раздел для тестирования инвариантов.
Джергер
0

Я видел этот элегантный, низкотехнологичный метод тестирования Terraform, предложенный, по- видимому, smartmart в ветке выпуска GitHub. Это не подходит для каждой ситуации, но отлично подходит для проверки логики модуля.

Создайте корневой модуль, который включает тестируемый модуль и проверяет результаты тестируемого теста. Вот простой пример использования двух файлов:

  • main.tf что будет запускать тесты
  • simple_module/outputs.tf представляющий тестируемый модуль

./main.tf

terraform {
  required_version = ">= 0.12"
}

module "simple_module" {
  source = "./simple_module"
}

locals {
  expected = 1
  got      = module.simple_module.module-returns-1
}

# Test Output
output "expect-1" {
  value = upper(local.expected == local.got)
}

output "expect-other" {
  value = "other" == local.got ? upper(true) : "FALSE. Got ${local.got}"
}

./simple_module/outputs.tf

output "module-returns-1" {
  value = 1
}

Запустите тесты

terraform init
terraform apply -auto-approve
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

expect-1 = TRUE
expect-other = FALSE. Got 1
mmell
источник