LoginSignup
5
2

More than 1 year has passed since last update.

作りながら覚えるTerraform入門(2) - 基本編

Last updated at Posted at 2021-06-04

作りながら覚えるTerraform入門シリーズの第2回です。
第1回の インストールと初期設定 でTerraformを使う準備ができたので、とりあえず動かしてみましょう。
最初はVPCの操作を通じてTerraformの基本的なコマンドを覚えるのが良いと思います。

作りながら覚えるTerraform入門シリーズ
  1. インストールと初期設定
  2. 基本編 => 今回はコチラ
  3. VPC編
  4. EC2編
  5. Route53 + ACM編
  6. ELB編
  7. RDS編

今回の学習ポイントは以下です。

  • Resourceブロックの書き方
  • terraform init / plan / apply / destroyの実行の流れ
  • Terraformの実行計画の見方

VPCの作成

まず、作業用のフォルダを作成しておきます。

mkdir terraform
cd terraform/

provider.tfというファイルを作成して、以下のコードを貼り付けます。
拡張子が.tfであればファイル名は任意で大丈夫です。

provider.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

provider.tfにはAWSにリソースを作成するための宣言を記述します。
デフォルトリージョンもここで指定しておきます。このあたりはお決まりの構文ですね。
公式ドキュメントのAWS Providerを参考にしています。

続いて、network.tfというファイルを作成して、以下のコードを貼り付けます。
ファイルを分ける必要はありませんが、リソースごとに分けたほうが管理がしやすくなります。

network.tf
# Resourceブロックで「aws_vpc」を指定してVPCを作成
resource "aws_vpc" "vpc" {
  cidr_block       = "10.0.0.0/16"
  instance_tenancy = "default"

  tags = {
    Name = "my-vpc"
  }
}

resourceから始まる箇所をResourceブロックと呼びます。
resourceに続けて以下の引数を与えて、波括弧{}で囲った中にパラメータを記述します。

①第1引数:リソースタイプ
②第2引数:任意の識別名

①はAWSのリソースタイプで、aws_*の形になっています。Azureであればazurerm_*といった形。
基本的には*の箇所にサービス名が入るので連想しやすいですが、公式リファレンスを参照しながら記述します。
aws_vpcであれば、Resource: aws_vpc です。

②は識別名なので自由に命名できますが、他のリソースと重複はできません。
ここの命名に意外と悩んだりしますが、最初はとりあえず動かすことを目的としてexamplemainとしておくのも一つの手です。

作成したコードを元にリソースを作成してみましょう。
リソースを作成するには、terraform applyを実行します。

terraform apply
╷
│ Error: Could not load plugin
│ 
│ 
│ Plugin reinitialization required. Please run "terraform init".
:

そうすると、プラグインが読み込めないのでterraform initを実行するようエラーが表示されます。Terraformのインストールによってコマンド自体は利用できるようになりますが、AWSやAzureなど各サービス(プロバイダー)を利用するためのプラグインは分離されているため、まず最初にterraform initを実行してダウンロード(初期化)する必要があります。

terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.44.0...
- Installed hashicorp/aws v3.44.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!
:

terraform initを実行すると、.terraformディレクトリと.terraform.lock.hclファイルが作成されます。.terraformディレクトリが「AWS」というプロバイダーを利用するためのもの、.terraform.lock.hclは依存関係をコントロールするためのロックファイル、くらいに考えておきましょう。

tree -a
.
├── .terraform
│   └── providers
│       └── registry.terraform.io
│           └── hashicorp
│               └── aws
│                   └── 3.44.0
│                       └── darwin_amd64
│                           └── terraform-provider-aws_v3.44.0_x5
├── .terraform.lock.hcl
├── network.tf
└── provider.tf

それでは、改めてterraform applyを実行してみます。
「Do you want to perform these actions?」と確認を求められるので「yes」と入力して進めます。

terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_vpc.vpc will be created
  + resource "aws_vpc" "vpc" {
      + arn                              = (known after apply)
      + assign_generated_ipv6_cidr_block = false
      + cidr_block                       = "10.0.0.0/16"
      + default_network_acl_id           = (known after apply)
      + default_route_table_id           = (known after apply)
      + default_security_group_id        = (known after apply)
      + dhcp_options_id                  = (known after apply)
      + enable_classiclink               = (known after apply)
      + enable_classiclink_dns_support   = (known after apply)
      + enable_dns_hostnames             = (known after apply)
      + enable_dns_support               = true
      + id                               = (known after apply)
      + instance_tenancy                 = "default"
      + ipv6_association_id              = (known after apply)
      + ipv6_cidr_block                  = (known after apply)
      + main_route_table_id              = (known after apply)
      + owner_id                         = (known after apply)
      + tags                             = {
          + "Name" = "my-vpc"
        }
      + tags_all                         = {
          + "Name" = "my-vpc"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_vpc.vpc: Creating...
aws_vpc.vpc: Creation complete after 2s [id=vpc-0e32cf9d1213b770d]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

最後の「Apply complete!」の行を見ると1 addedとなっていて、1つのリソースが追加されたことがわかります。コンソール画面を確認してみると、「my-vpc」のNameタグが付いたVPCが作成できていることがわかります。

C101998D-1A0B-4519-B21F-7FE053B66210.png

VPCの更新

続いて、更新の動きを見ていきましょう。
試しにnetwork.tfのNameタグを「my-first-vpc」に変更してみます。

network.tf
resource "aws_vpc" "vpc" {
  cidr_block       = "10.0.0.0/16"
  instance_tenancy = "default"

  tags = {
    Name = "my-first-vpc"
  }
}

もう一度terraform applyを実行して適用してみましょう。

terraform apply

aws_vpc.vpc: Refreshing state... [id=vpc-0e32cf9d1213b770d]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_vpc.vpc will be updated in-place
  ~ resource "aws_vpc" "vpc" {
        id                               = "vpc-0e32cf9d1213b770d"
      ~ tags                             = {
          ~ "Name" = "my-vpc" -> "my-first-vpc"
        }
      ~ tags_all                         = {
          ~ "Name" = "my-vpc" -> "my-first-vpc"
        }
        # (14 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_vpc.vpc: Modifying... [id=vpc-0e32cf9d1213b770d]
aws_vpc.vpc: Modifications complete after 2s [id=vpc-0e32cf9d1213b770d]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

1 changedと表示されて更新されたことがわかります。
コンソール画面からもNameタグが変更できていることを確認しておきましょう。

次はcidr_blockを「192.168.0.0/16」に変更してみます。

network.tf
resource "aws_vpc" "vpc" {
  cidr_block       = "192.168.0.0/16"
  instance_tenancy = "default"

  tags = {
    Name = "my-first-vpc"
  }
}

terraform applyを実行して適用してみましょう。

terraform apply

aws_vpc.vpc: Refreshing state... [id=vpc-0e32cf9d1213b770d]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # aws_vpc.vpc must be replaced
-/+ resource "aws_vpc" "vpc" {
      ~ arn                              = "arn:aws:ec2:ap-northeast-1:123456789012:vpc/vpc-0e32cf9d1213b770d" -> (known after apply)
      ~ cidr_block                       = "10.0.0.0/16" -> "192.168.0.0/16" # forces replacement
      ~ default_network_acl_id           = "acl-009e09c086ff9c692" -> (known after apply)
      ~ default_route_table_id           = "rtb-0b555443103cfbe0b" -> (known after apply)
      ~ default_security_group_id        = "sg-0af32faf28e1dfa87" -> (known after apply)
      ~ dhcp_options_id                  = "dopt-2489e243" -> (known after apply)
      ~ enable_classiclink               = false -> (known after apply)
      ~ enable_classiclink_dns_support   = false -> (known after apply)
      ~ enable_dns_hostnames             = false -> (known after apply)
      ~ id                               = "vpc-0e32cf9d1213b770d" -> (known after apply)
      + ipv6_association_id              = (known after apply)
      + ipv6_cidr_block                  = (known after apply)
      ~ main_route_table_id              = "rtb-0b555443103cfbe0b" -> (known after apply)
      ~ owner_id                         = "123456789012" -> (known after apply)
        tags                             = {
            "Name" = "my-first-vpc"
        }
        # (4 unchanged attributes hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_vpc.vpc: Destroying... [id=vpc-0e32cf9d1213b770d]
aws_vpc.vpc: Destruction complete after 0s
aws_vpc.vpc: Creating...
aws_vpc.vpc: Creation complete after 3s [id=vpc-05c92959157ff59d0]

Apply complete! Resources: 1 added, 0 changed, 1 destroyed.

今回のcidr_blockの変更のように既存リソースの変更では対応できないケースは削除→作成の置き換えの動作になります。

後述しますが、実行計画の中に「replaced」や「forces replacement」という文字が含まれている場合は、それが意図したものなのか十分に確認してから実行する必要があります。

VPCの削除

最後に、作成したVPCを削除してみましょう。
リソースを削除するには、terraform destroyを実行します。
applyの時と同じように「yes」を入力して実行してみましょう。

terraform destroy

aws_vpc.vpc: Refreshing state... [id=vpc-05c92959157ff59d0]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # aws_vpc.vpc will be destroyed
  - resource "aws_vpc" "vpc" {
      - arn                              = "arn:aws:ec2:ap-northeast-1:123456789012:vpc/vpc-05c92959157ff59d0" -> null
      - assign_generated_ipv6_cidr_block = false -> null
      - cidr_block                       = "192.168.0.0/16" -> null
      - default_network_acl_id           = "acl-0896f7ab7cd8e3bbd" -> null
      - default_route_table_id           = "rtb-0ba11eb799c733669" -> null
      - default_security_group_id        = "sg-0ddd72a743034c145" -> null
      - dhcp_options_id                  = "dopt-2489e243" -> null
      - enable_classiclink               = false -> null
      - enable_classiclink_dns_support   = false -> null
      - enable_dns_hostnames             = false -> null
      - enable_dns_support               = true -> null
      - id                               = "vpc-05c92959157ff59d0" -> null
      - instance_tenancy                 = "default" -> null
      - main_route_table_id              = "rtb-0ba11eb799c733669" -> null
      - owner_id                         = "123456789012" -> null
      - tags                             = {
          - "Name" = "my-first-vpc"
        } -> null
      - tags_all                         = {
          - "Name" = "my-first-vpc"
        } -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_vpc.vpc: Destroying... [id=vpc-05c92959157ff59d0]
aws_vpc.vpc: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

1 destroyedと表示されて削除されたことがわかりますね。

Terraformの実行計画

これまで見てきたように、terraform applyterraform destroyを実行すると、これから起こる変更差分を「実行計画」として表示してくれます。

実行したコマンドの中にあるTerraform will perform the following actionsの箇所を振り返ってみてください。それぞれこれから行われる処理を示してくれています。

  • aws_vpc.vpc will be created
  • aws_vpc.vpc will be updated in-place
  • aws_vpc.vpc must be replaced
  • aws_vpc.vpc will be destroyed

リソースやパラメータの頭にある記号からも判別できます。
なお、何も変更がない場合はNo changes.と表示されます。

  • 作成: +
  • 更新: ~
  • 削除: -
  • 置き換え: -/+

繰り返しになりますが、単なる更新で済む場合と、作り直しになる場合があります。このあたりの挙動はコンソール画面から実施する場合と同じですが、実行計画はよく確認するように心がけましょう。

Terraformの基本コマンド

この記事ではVPCの作成と削除を通じて、init → apply → destroyを実行して、初期化 → 適用 → 削除を行いましたが、その他のよく使うコマンドも確認しておきましょう。

validate

terraform validateを実行すると、構文に誤りがないか、パラメータが適切かチェックすることができます。

# valid
terraform validate

Success! The configuration is valid.

# invalid (cidr_blockの範囲が誤っている例)
terraform validate

Error: expected cidr_block to contain a valid network Value, expected 10.0.0.0/16, got 10.0.1.0/16
│ 
│   with aws_vpc.vpc,
│   on network.tf line 2, in resource "aws_vpc" "vpc":
│    2:   cidr_block       = "10.0.1.0/16"

plan

先に実践した例ではterraform applyをいきなり実行しましたが、terraform planを実行すると実行計画の確認のみ行うことができます。applyやdestroyはせずに実行計画だけ確認したい場合に利用します。

fmt

terraform fmtを実行するとインデントを整えて見た目をキレイにしてくれます。-recursiveのオプションを付け加えるとサブディレクトリ含めて再帰的にフォーマットしてくれます。(付けない場合はカレントディレクトリの.tfファイルのみ)
が、インストールと初期設定でご紹介したように、VSCode拡張機能を利用して自動フォーマットを有効にすることをオススメします。

console

terraform consoleを実行すると対話型のコンソールを起動することができます。変数の値や関数の評価結果を確認したい場合に便利です。コンソールを終了するにはexitを入力します。

terraform console

> max(5, 12, 9)
12

他にもありますが、とりあえずこのあたりの基本コマンドを覚えておけば困らないと思います。

コマンド実行の流れ

私の場合は、initのあとはvalidate → plan → applyを繰り返して、いらなくなったらdestoryするって形で学習を進めました。学習環境は作って壊すの繰り返しなので、インストールと初期設定でご紹介したように、applyとdestoryの時に「yes」を入力しなくて済むように-auto-approveを付け加えたエイリアス設定を利用してtf init → tfv → tfp → tfa → tfdの流れで実行しています。エイリアス設定を再掲しておきます。

~/.zshrc
alias tf="terraform"
alias tfp="terraform plan"
alias tfv="terraform validate"
alias tff="terraform fmt -recursive"
alias tfa="terraform apply -auto-approve"
alias tfd="terraform destroy -auto-approve"

今回は以上です。次回はVPC編ということで、サブネットやルートテーブルなど含め、改めてVPC関連のリソースを作成する方法について書いてみたいと思います!

参考リンク

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2