blog-image

terraformの構文とかまとめ

2023-11-21

terraform

現場でterraformでのIaCを経験したのでざっくりメモです

複数アカウントの切り替え

AWS cliのconfigure登録でアカウントごとに--profileオプションをつけて作成する export AWS_DEFAULT_PROFILE=prodなどで切り替え

1$ aws configure --profile <YOUR_PROFIlE_ID>
2
3AWS Access Key ID [None]: <YOUR_ACCESS_KEY>
4AWS Secret Access Key [None]: <YOUR_SECRET_ACCESS_KEY>
5Default region name [None]: <YOUR_REGION>
6Default output format [None]:
1$ export AWS_DEFAULT_PROFILE=prod

他にもワークスペース機能を活用したり出来るらしい(まだ使用したことが無いです…)

terraformコマンド操作説明

初期化 Terraformで新しく設定を記述した場合、初期化を行う必要があります。

1$ terraform init

確認(所謂dry-run) 実行計画の確認ができます

1$ terraform plan

適用

1$ terraform apply

terraform管理下のリソースすべて消去する

1$ terraform destroy

リソースの閲覧

1$ terraform show

既存環境 import

※terraform varsion1.5から下記手順とは異なる方法でインポートできるようになりました

インポート手順 lambdaの例

必要最低限のtfファイルを作る

1resource "aws_lambda_function" "cognito_login" {
2}

Webコンソールで作成したリソースをimport

terraform import 取り込みたいサービス名.インポートしたい名前 AWSにあるリソース のような形で実行します lambdaの例だと下記のようになります

1$ terraform import aws_lambda_function.<インポートしたい名前> <すでにAWS上で作成されているLambda関数名>
インポートする際の注意点

一点注意して頂きたいのはリソースごとにインポートコマンドの書き方が異なります。 先ほどのlambdaの場合はコマンドの末尾にlambda関数の名前を入力していましたが、 例えばEC2インスタンスの場合は、以下のようにコマンドの末尾にはインスタンスのidを入力します<br>

1$ terraform import aws_instance.web i-12345678

参照:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#import <br> インポートのコマンドはリソースごとに調べて実行しましょう

import後にterraform state listコマンドで取り込んだリソースの名前を取得し、terraform state showコマンドでリソースの情報が見れる

1$ terraform state list
2
3aws_lambda_function.cognito_login
4
5$ terraform state show aws_lambda_function.cognito_login
1resource "aws_lambda_function" "cognito_login" {
2    architectures                  = [
3        "x86_64",
4    ]
5    arn                            = "arn:aws:lambda:ap-northeast-1:************:function:cognito"
6    function_name                  = "cognito"
7    handler                        = "lambda_function.lambda_handler"
8    id                             = "cognito"
9    invoke_arn                     = "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:************:function:cognito/invocations"
10    last_modified                  = "2025-11-09T00:00:00.000+0000"
11    layers                         = []
12    memory_size                    = 128
13    package_type                   = "Zip"
14    qualified_arn                  = "arn:aws:lambda:ap-northeast-1:************:function:cognito:$LATEST"
15    reserved_concurrent_executions = -1
16    role                           = "arn:aws:iam::************:role/service-role/cognito-role-n44l3fff"
17    runtime                        = "python3.9"
18    source_code_hash               = "qUoU5sSYPTtEdpRr456MYKgW4MOCSaedddKZj0ebKLkk="
19    source_code_size               = 2000
20    tags                           = {}
21    tags_all                       = {}
22    timeout                        = 3
23    version                        = "$LATEST"
24
25    timeouts {}
26
27    tracing_config {
28        mode = "PassThrough"
29    }
30}
31

こちらを上記の.tfファイルにコピペし、いらない箇所や環境によるものの値を修正していく

修正が終わったらterraform planを実行し、No changes.と出れば差分なくインポート完了です

Git BashでTerraform importしたときにパスが勝手に変換されてエラーになる場合の対処法

windowsのgitbashで作業していたら遭遇したバグ

tfstateについて

terraformには状態管理のためのtfstateというファイルがあります。 ローカルで管理するか、S3などのウェブ上で管理するか選べます。 下記の設定はローカルで保存。

1terraform {
2  backend "local" {
3    path = "./terraform.tfstate"
4  }
5}

s3保存にする場合の例 事前にs3バケットを作成する必要あり

1terraform {
2  backend "s3" {
3    bucket  = "test-terraform-tfstate"
4    region  = "ap-northeast-1"
5    key     = "terraform.tfstate"
6    encrypt = false
7    shared_credentials_file = "$HOME/.aws/credentials"
8  }
9}

s3バケット作成と同時にローカルのファイルアップロード

s3にバケット作成と同時にファイルアップロードをしたい時があります 下記のように書けます

1resource "aws_s3_bucket" "aws_s3_bucket" {
2  bucket              = "test_aws_s3_bucket"
3  object_lock_enabled = false
4  tags                = {}
5  tags_all            = {}
6  force_destroy       = null
7}
8
9resource "aws_s3_object" "test_file_upload" {
10  bucket = aws_s3_bucket.aws_s3_bucket.bucket_name
11  key    = "test.json"
12  source = "./test.json"
13}

リソースを作るかどうかを動的に制御したい

countを使ってtrue,falseの条件式が書けます 下記はapigatawayのリソースポリシーをつけるか付けないかの例 var.api_gateway_is_resource_policyの値がtrueならこのリソースは作られることになります

1resource "aws_api_gateway_rest_api_policy" "api_policy" {
2  count = var.api_gateway_is_resource_policy ? 1 : 0
3
4  rest_api_id = aws_api_gateway_rest_api.test_api.id
5  policy = jsonencode({
6    Statement = [
7      {
8        Action = "execute-api:Invoke"
9        Condition = {
10          NotIpAddress = {
11            "aws:SourceIp" = [for ip in var.ip_list : ip]
12          }
13        }
14        Effect    = "Deny"
15        Principal = "*"
16        Resource  = "arn:aws:execute-api:*:*:*"
17      },
18      {
19        Action    = "execute-api:Invoke"
20        Effect    = "Allow"
21        Principal = "*"
22        Resource  = "arn:aws:execute-api:*:*:*"
23      },
24    ]
25    Version = "2012-10-17"
26  })
27}

terraformで管理したくないけどリソースの情報が欲しい

importしてしまうと削除時に一緒に消えちゃってまずいとかのリソースを情報だけ引っ張りたい時に使います 下記の場合importしていない為、terraform destroyコマンドを実行してもroute53のリソースは消えません

1data "aws_route53_zone" "host_domain" {
2  name = var.domain_name
3}
4
5resource "aws_route53_record" "test_record" {
6  name    = var.sub_domain_name
7  type    = "A"
8
9  # ↓ 下記のような形でimportを行わなくても情報の参照ができる
10  zone_id = data.aws_route53_zone.host_domain.zone_id
11  alias {
12    name                   = aws_api_gateway_domain_name.api_gateway_domain_name.regional_domain_name
13    zone_id                = aws_api_gateway_domain_name.api_gateway_domain_name.regional_zone_id
14    evaluate_target_health = true
15  }
16}

依存関係を明示的に指定したい

あるリソースの方が先に作って欲しい時に使用します depends_onにリソースを書いておきます

1resource "aws_api_gateway_deployment" "test_api_deployment" {
2  depends_on = [
3    module.lambda_login
4  ]
5  rest_api_id = aws_api_gateway_rest_api.test_api.id
6  triggers = {
7    redeployment = filebase64("./api-gateway.tf")
8  }
9}