Skip to content

とりあえず触ってみる

vpc

まずはTerraformを使ってみましょう。
この章ではVPCの起動することを目標に、よく使用されるシンタックスを学んでいきます。

準備

新しいTerminalを立ち上げ、以下のコマンドでこの章用のディレクトリを作成し、作成したディレクトリに移動してください。

$ cd ~/Desktop/terraform-handson
$ mkdir vpc-handson
$ cd vpc-handson

Terraformを立ち上げているTerminalにもディレクトリが作成されていることを確認します。

# ls
vpc-handson

HCLを書く

VPCを立ち上げるためのコードを書きます。
以下のコードを main.tf の命名で vpc-handson/ 配下に作成してください。

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

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

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

今回は providerresource の2つを定義しました。

provider

providerはその名の通りプロバイダの定義を行います。
今回はAWSを使用したいため aws と宣言していますが、他にも gcpazure など様々なプロバイダが用意されています。

また、providerブロック内で region = "ap-northeast-1" と定義しています。
ここで指定したリージョンにVPCやEC2などの各種リソースを作成します。
今回は"ap-northeast-1"(東京リージョン)を指定します。

resource

resourceはVPCやEC2のような起動したいリソースを定義します。
今回はコードへVPCを定義しました。これを実行することで 「vpc-handsonという名前でCIDRが10.0.0.0/16のVPC」 が作成されます。

記述したコードがどのような意味を持つか、1つずつ見ていきましょう。

1行目から見ていきましょう。

resourceの定義と命名

resource "aws_vpc" "main" {

ここでは 「"aws_vpc"というリソースを"main"という名前」 で作成しています。
resource "aws_vpc" まではAWSのVPCを作成するという意味で、 "main" はTerraformで定義する他のリソースから参照する際に使用します。

例として「VPCを作成し、作成したVPC内にSubnetを作成する」コードを載せます。

# AWSプロバイダの定義
provider "aws" {
  region = "ap-northeast-1"
}

# VPCを作成する
resource "aws_vpc" "main" { # "main" という命名を行う
  cidr_block = "10.0.0.0/16"

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

# Subnetを作成する
resource "aws_subnet" "main" { # 別のリソースであれば命名が被っていても問題ないです
  vpc_id     = "${aws_vpc.main.id}" # aws_vpc.mainでmainと命名されたVPCを参照し、そのVPCのIDを取得する
  cidr_block = "10.0.1.0/24"
}

リソースのプロパティ

話を戻して、ブロック内のプロパティについて説明します。
今回作成するVPCは以下の通り、「"vpc-handson"という名前を付け、CIDRを10.0.0.0/16に設定する」ように記述されています。

  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "vpc-handson"
  }

これはVPCやEC2などのリソース毎にプロパティが異なります。
実際にTerraformのコードを記述する際はTerraformのリファレンスを見ながら記述していきます。

AWS: aws_vpc - Terraform by HashiCorp

Terraformリファレンスの先へ

TerraformはGolangでできており、AWSプロバイダはAWS SDK のAPIを叩いています。
実際にどのような値がどのようなバリデーションになっているのか、より詳細を知りたい場合はAWSのAPIリファレンスを見てみるのもありでしょう。
CreateVpc - Amazon Elastic Compute Cloud

Terraformの実行

初期化

Terraformで新しく設定を記述した場合、初期化を行う必要があります。
素のTerraformはプロバイダーが内部に組み込まれていないので、今回であればAWSプロバイダーのダウンロードが行われます。

初期化を行ってみましょう。

# terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "aws" (2.6.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 2.6"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

適用

コードの状態をAWS上へ適用しましょう。

# terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + aws_vpc.main
      id:                               <computed>
      arn:                              <computed>
      assign_generated_ipv6_cidr_block: "false"
      cidr_block:                       "10.0.0.0/16"
      default_network_acl_id:           <computed>
      default_route_table_id:           <computed>
      default_security_group_id:        <computed>
      dhcp_options_id:                  <computed>
      enable_classiclink:               <computed>
      enable_classiclink_dns_support:   <computed>
      enable_dns_hostnames:             <computed>
      enable_dns_support:               "true"
      instance_tenancy:                 "default"
      ipv6_association_id:              <computed>
      ipv6_cidr_block:                  <computed>
      main_route_table_id:              <computed>
      owner_id:                         <computed>
      tags.%:                           "1"
      tags.Name:                        "vpc-handson"


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:

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

新しく1つのリソースが追加されることが確認できました。
ログを見て問題なければ yes で実行を継続しましょう

  Enter a value: yes

aws_vpc.main: Creating...
  arn:                              "" => "<computed>"
  assign_generated_ipv6_cidr_block: "" => "false"
  cidr_block:                       "" => "10.0.0.0/16"
  default_network_acl_id:           "" => "<computed>"
  default_route_table_id:           "" => "<computed>"
  default_security_group_id:        "" => "<computed>"
  dhcp_options_id:                  "" => "<computed>"
  enable_classiclink:               "" => "<computed>"
  enable_classiclink_dns_support:   "" => "<computed>"
  enable_dns_hostnames:             "" => "<computed>"
  enable_dns_support:               "" => "true"
  instance_tenancy:                 "" => "default"
  ipv6_association_id:              "" => "<computed>"
  ipv6_cidr_block:                  "" => "<computed>"
  main_route_table_id:              "" => "<computed>"
  owner_id:                         "" => "<computed>"
  tags.%:                           "" => "1"
  tags.Name:                        "" => "vpc-handson"
aws_vpc.main: Creation complete after 7s (ID: vpc-028d784cfaa5ca479)

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

コンソールを確認して実際にVPCが起動できていることを確認してみましょう

https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#vpcs:sort=desc:VpcId

describe-vpcs

リソースの変更を行う

VPCの名前を "vpc-handson" から "vpc-handson-hoge" に変更してみましょう。
main.tf を以下の通り編集し、VPCの命名を変更します。

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

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
-    Name = "vpc-handson"
+    Name = "vpc-handson-hoge"
  }
}

Terraformではコードを適用する前に、どのような変更がかかるのか確認(所謂dry-run)を行うことができます。
実際にどのような変更がかかるのか確認してみましょう。

# terraform plan
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_vpc.main: Refreshing state... (ID: vpc-001c076e2cd2e79af)

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  ~ aws_vpc.main
      tags.Name: "vpc-handson" => "vpc-handson-hoge"


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

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

変更の差分が検出でき、その差分を出力した後にコマンドが終了しました。
Terraformを実行する際はオペミスを防ぐためにも terraform apply で実行する前に、 terraform plan でどのような変更がかかるのか確認してから実行するのが定石です。

どのような変更が行われるか検出できたので、実際に変更の適用を行いましょう。

# terraform apply
  :

適用が完了したらVPCのコンソールから変更が適用できたか確認してみましょう。

Terraformが管理しているリソース

Terraformが管理しているリソースは terraform show コマンドで閲覧することが出来ます。

まずはコマンドを打って確認してみましょう。

# terraform show
aws_vpc.main:
  id = vpc-07be0a5e024877c48
  arn = arn:aws:ec2:ap-northeast-1:856925507022:vpc/vpc-07be0a5e024877c48
  assign_generated_ipv6_cidr_block = false
  cidr_block = 10.0.0.0/16
  default_network_acl_id = acl-0a00c5fa26f28e853
  default_route_table_id = rtb-0681966791d3ad652
  default_security_group_id = sg-0a5a4b4a19b9d4240
  dhcp_options_id = dopt-23aa3947
  enable_classiclink = false
  enable_classiclink_dns_support = false
  enable_dns_hostnames = false
  enable_dns_support = true
  instance_tenancy = default
  ipv6_association_id =
  ipv6_cidr_block =
  main_route_table_id = rtb-0681966791d3ad652
  owner_id = 856925507022
  tags.% = 1
  tags.Name = vpc-handson-hoge

Terraformが管理しているリソースは terraform.tfstate というJSONファイルに格納されます。
Terraformコードの適用を行う際はこのファイルを参照し、差分の確認を行っています。

# ls
main.tf                  terraform.tfstate        terraform.tfstate.backup
# cat terraform.tfstate
{
    "version": 3,
    "terraform_version": "0.11.13",
    "serial": 5,
    "lineage": "40f395d7-8d59-b14c-f92f-e836258630af",
    "modules": [
        {
            "path": [
                "root"
            ],

Terraformは インフラをコードで宣言する ためのツールです。
そのため、コードで定義された状態になるように動作します。

現在のapplyが完了した状態で terraform plan コマンドを打っても差分が検出されないことを確認しましょう

# terraform plan

terraform.tfstateをクラウドで管理する

前提として terraform.tfstate をローカル上で管理するのは危険です。
Terraformはこのファイルを参照してコードの状態を適用するので、このファイルが存在しないと差分が検知できずに新しくリソースが作成されてしまいます。
もし「ローカルマシンが壊れた場合」「複数人で開発したい場合」など、プロダクション開発で使用する場合はバックアップを行う必要があります。
そのバックアップの機能としてTerraformは "backend" という terraform.tfstate をS3などのオブジェクトストレージに保管する機能が存在するので、本番でTerraformを使用する場合は検討しましょう。

削除する

Terraformで管理されているリソースを削除しましょう。
ワンコマンドで管理しているリソースを削除できます。

実際に削除してみましょう。

# terraform destroy
aws_vpc.main: Refreshing state... (ID: vpc-001c076e2cd2e79af)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - aws_vpc.main


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 と入力します

  Enter a value: yes

aws_vpc.main: Destroying... (ID: vpc-001c076e2cd2e79af)
aws_vpc.main: Destruction complete after 1s

Destroy complete! Resources: 1 destroyed.

WebコンソールでTerraformで作成したVPCが削除されていることを確認しましょう。