Terraform構成をテストする方法は?


37

中程度の複雑さを持つTerraform構成がある場合、継続的インテグレーション/継続的デリバリーパイプラインの一部として実行できる構成に関するテストをどのように作成しますか?

例として、次の望ましい状態を指定するマルチクラウド構成がある場合があります。

  • AzureでDockerをホストするAzure Container Services
  • Azure Blob Storage
  • SQL Azure
  • AWSでDockerをホストするEC2 Container Service
  • Amazon S3ストレージサービス
  • Amazon RDS SQL Serverデータベース

terraform apply上記をゼロから作成したり、部分的に展開された状態から上記の望ましい状態に移行したりする可能性があります。

Terraformは、作業を実行計画段階と実際にターゲットアーキテクチャに変更を加えるアプリケーション段階に分割することを認識しています。これを使用して、実行計画に対するテストを作成できますか?もしそうであれば、これらを作成するのに役立つフレームワークはありますか?


役に立つかもしれません:github.com/hashicorp/terraform/issues/5059
Tensibai

確かに興味深い、おそらく価値のある答え。
リチャードスレーター

私は自分でテラフォームを使用していないので、実際の経験のある人に答えを書いてもらいました:)
天柴iba

回答:


20

現在、これをTerraformに統合するための完全なソリューションはありませんが、別のプログラミング言語でテストを作成するのに役立ついくつかのビルディングブロックがあります。

Terraformは、JSON形式の状態ファイルを生成します。これは、原則として、外部プログラムがTerraformが作成したものに関する特定のデータを抽出するために使用できます。この形式はまだ公式に安定しているとは見なされていませんが、実際にはあまり頻繁に変更されないため、Terraformをアップグレードする際に調整が必要になる可能性があります。

ここでどの戦略が適切かは、テストする内容によって大きく異なります。例えば:

  • 仮想サーバーを起動する環境では、Serverspecなどのツールを使用して、これらのサーバーの観点からテストを実行できます。これは、帯域外プロセスを使用してTerraformとは別に実行するか、remote-execプロビジョニングツールを使用してTerraformの一部として適用できます。これにより、「サーバーはデータベースに到達できますか?」などの質問を検証できますが、「インスタンスのセキュリティグループは十分に制限されていますか?」などの質問には適していません。

  • unittestTerraform状態ファイルから関連するリソースIDまたはアドレスを収集し、関連するプラットフォームのSDKを使用してリソースに関するデータを取得し、それをアサートする既存のテストフレームワーク(Ruby、Pythonなど)を使用してテストを記述することができます期待どおりに設定されています。これは、以前のアイデアのより一般的な形式であり、テスト対象のインフラストラクチャの外部のホストの観点からテストを実行するため、アサーションを行うためのより広範なデータセットを収集できます。

  • より控えめなニーズについては、Terraform状態が現実の正確な表現(多くの場合、有効な仮定)であると信頼し、単純にそれを直接主張することを選択できます。これは、コスト割り当てのために正しいリソースタギングスキームが守られていることを確認するなど、単純な「リントのような」場合に最も適しています。

関連するTerraform Githubの問題これに関するいくつかの議論があります。

Terraformの最新バージョンでは、玩具以外のアプリケーションにはリモートバックエンドを使用することを強くお勧めしますが、これは状態データがローカルディスクで直接利用できないことを意味します。ただし、terraform state pullコマンドを使用してリモートバックエンドからスナップショットを取得できます。このコマンドは、JSON形式の状態データをstdoutに出力し、呼び出し側プログラムでキャプチャおよび解析できるようにします。


12

この質問の更新として、本番環境を壊さずにTerraform構成ファイルをテストできるKitchen-Terraformが追加されました。リポジトリには、さまざまなTerraformプロバイダーのいくつかの例も含まれています。


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分かかります。これは、(使用しているが、高速ではありませんドッカーテストの段階を、あなたが高速化することができ、いくつかの物事を)、あなたがテストは信頼性を高めるために作業する必要がありますが、それは時間の価値があります。

チェックアウトTerratestレポドキュメントおよびインフラストラクチャコードの様々なタイプの多くの例とそれらに対応するテストのために。


1
また、Terratestを使用した私のサンプルプロジェクトの1つをより詳細にテストするブログ投稿を作成しました:brightfame.co/blog/…。それは誰にとっても価値があるかもしれません。乾杯、ロブ!
ロブモーガン

Terratestの大ファン!
jlucktay

7

言及された他のすべてのオプションに加えて、InSpec 2.0がクラウドプロバイダーAPIのサポートを追加したことに言及したいと思います。基本的に、TerraformでIaCを書き続け、クラウドリソースのInSpecでコンプライアンスチェックを書きます。さらに、InSpecは必要に応じて個々のマシンのテストの作成をサポートしています。

こちらは、InspecをTerraformで使用する方法に関するChristoph Hartmann(Inspecの共同作成者)からの記事です: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
目標は、テラフォーム構成の変更をテストし、予想されるニーズを壊さないことです。デプロイすると遅すぎます。せいぜいDBが削除されるはずですが、ターゲット環境を壊してしまったのを見て失敗するだけです。 ..問題は、テラフォームコードのテストであり、最終結果のテストではなく、単体テストと統合テストです。
テンシバイ

良い点...不変条件をテストするためのセクションを追加しました。
ジャーガー

0

GitHubの課題スレッドで明らかにsmartによって提案されたTerraformをテストするこのエレガントでローテクな方法をました。すべての状況に適しているわけではありませんが、モジュールロジックの検証には最適です。

テスト中のモジュールを含むルートモジュールを作成し、テスト中の出力を確認します。次に、2つのファイルを使用した簡単な例を示します。

  • 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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.