Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

これで猛暑を乗り越えよう!2024年真夏の最新トレンドTerraform Tips集

kuro
August 14, 2024

これで猛暑を乗り越えよう!2024年真夏の最新トレンドTerraform Tips集

社内のLT会でのスライドです。

参考リンク
Terraform Style Guide (https://developer.hashicorp.com/terraform/language/style)
Terraform Language Documentation (https://developer.hashicorp.com/terraform/language)
Terraform on Google Cloud - Best practices for general style and structure (https://cloud.google.com/docs/terraform/best-practices/general-style-structure)

kuro

August 14, 2024
Tweet

More Decks by kuro

Other Decks in Programming

Transcript

  1. 1. resource name Terraform 公式style guideによると、 スネークケース ダブルクォートで囲む resource typeを含めない

    ⭕️ ❌ 1 resource "aws_lambda_function" "super_hyper" { 2 function_name = super-hyper-function 3 description = "A super hyper function" 4 ... 5 } 1 resource aws_lambda_function super-hyper-lambda-function { 2 function_name = super-hyper-function 3 description = "A super hyper function" 4 ... 5 }
  2. 1. resource name Terraform 公式style guideによると、 For consistency and readability,

    use a descriptive noun and separate words with underscores. 一貫性と可読性のために、説明的な名詞を使用し、単語はアンダースコアで区切る。 引用)https://developer.hashicorp.com/terraform/language/style#resource-naming Googole Cloud公式ドキュメントのTerraform on Google Cloud - Best practices for general style and structureによると、 This practice ensures consistency with the naming convention for resource types, data source types, and other predefined values. この慣習は、resource type、data source type、その他の定義済みの値の命名規則との一貫性を保証します。 引用) https://cloud.google.com/docs/terraform/best-practices/general-style-structure#naming-convention
  3. 2. comment 1行でも複数行のコメントであっても、 # を使う。 // や /* */  は idiomaticではない。

    だが、以前のバージョンの後方互換性のためにサポートされている。
  4. 4. version constraints = :1つの正確なバージョンのみ許可 ! = :特定のバージョンを除外 > , >

    = , < , < = :指定されたバージョンとの比較 ~> :一番右の数字のみインクリメントできる範囲内のバージョンを許可。 例) version = "~> 1.2.0" : 1.2.xの範囲内のパッチバージョンを許可(1.2.0, 1.2.1, 1.2.9など) 、但し1.3.0 は許可されない。 version = "~> 1.2" : 1.xの範囲内のマイナーバージョンを許可(1.2.0, 1.3.0, 1.9.9など) 、但し2.0.0は 許可されない。
  5. 4. version constraints (provider) ルートディレクトリ(terrafrom applyをするディレクトリ)で、 ~> で範囲を指定する。 terraform {

    required_providers { mycloud = { source = "hashicorp/azurerm" version = "~> 3.1.0" } } } いろんな場所で使われているmoduleの場合、 > = で最小限のバージョンを指定するのもあり。 terraform { required_providers { mycloud = { source = "hashicorp/azurerm" version = "> = 1.0" } } } ※そもそもmoduleにバージョンの設定はあまりしないと思いますが、 、
  6. 4. lifecycle ②prevent_destroy 例えば、このdb instanceを削除しようとすると、エラーを返す。 resource "aws_db_instance" "example" { engine

    = "mysql" engine_version = "5.7" instance_class = "db.t3.micro" name = "mydb" lifecycle { prevent_destroy = true } }
  7. 4. lifecycle ③ignore_changes 例えば、AWSコンソールからtagを変更しても、Terraformがその変更を無視する。 resource "aws_instance" "example" { ami =

    "ami-a1b2c3d4" instance_type = "t2.micro" tags = { Name = "ExampleInstance" } lifecycle { ignore_changes = [ tags, ] } }
  8. 4. lifecycle ④replace_triggered_by 例えば、セキュリティグループを変更すると、このEC2インスタンスも置き換えられる。 resource "aws_instance" "example" { ami =

    "ami-a1b2c3d4" instance_type = "t2.micro" lifecycle { replace_triggered_by = [ aws_security_group.example.id ] } } resource "aws_security_group" "example" { name = "example" description = "Example security group" }
  9. 5. removed block Terraformのstateからリソースを削除する時、 terraform state rm を叩く or removed

    block を使う ←おすすめ terraform plan、applyを実行する。 removed { from = aws_s3_bucket.main lifecycle { destroy = false # falseにすると、stateから削除されるだけで、実際のリソースは削除されない。 } }
  10. 7. import block 既存のリソースをTerraformで管理したい時に使う。 terraform import を叩く or import block

    を使う ←おすすめ terraform plan、applyを実行する。 import { to = snowflake_grant_privileges_to_account_role.new_resource_role_a #idはimportしたいリソースを識別するためのもの。各providerによって形式は異なる。 id = "\"${snowflake_role.a.name}\"|false|false|USAGE|OnAccountObject|DATABASE|\"${snowflake_database.test.name}\"" } resource "snowflake_grant_privileges_to_account_role" "new_resource_role_a" { account_role_name = snowflake_role.a.name privileges = ["USAGE"] .... }
  11. 8. terraform plan -generate-config-out importブロックのtoの宛先となるリソースを生成する時でかつ大量にimportしたい時に便利。 import { to = snowflake_grant_privileges_to_account_role.new_resource_role_a

    id = "\"${snowflake_role.a.name}\"|false|false|USAGE|OnAccountObject|DATABASE|\"${snowflake_database.test.name}\"" } を記述した後に、 terraform plan -generate-config-out=generated.tf を叩くと、 generated.tf に to の宛先となるリソースが生成される。 ↓みたいな resource "snowflake_grant_privileges_to_account_role" "new_resource_role_a" { account_role_name = snowflake_role.a.name privileges = ["USAGE"] .... } ※ただし、Experimentalな機能で、ちょっと制約もある。 。 。
  12. 9. TF_LOG 環境変数の TF_LOG を使うと、Terraformのログの出力レベルを選べる。 TRACE , DEBUG , INFO

    , WARN , ERROR のレベルで。 OFF にすると、TF_LOGが設定されていない場合と同じ。 TF_LOG=DEBUG terraform plan みたいにしてもいいし、CIでログを出したいときにも使える。 例) 1 log_level: 2 description: "Log Level" 3 type: choice 4 default: "off" 5 options: 6 - "off" 7 - "debug" 8 ..... 9 steps: 10 - name: Terraform Plan 11 run: terraform plan 12 env: 13 TF_LOG: ${{ inputs.log_level }}
  13. 10. terraform test # テストの中でinputとして渡すvariables variables { env = "test"

    project = "fuga" } # テスト実行前にセットアップもできる。テスト実行後には、sample⇨setupの順で削除される。 run "setup" { module{ source = "./testing/setup" } } run "sample" { command = apply # planも指定できる。 module { source = "../../../modules/sample" } # 検証 assert { condition = data.http.index.status_code == 404 error_message = "error: not found" } }
  14. 参考 Terraform Style Guide Terraform Language Documentation Terraform on Google

    Cloud - Best practices for general style and structure