Terraformを試してみる
今日はTerraformを使ってみることにしました。
Terraform
TerraformはHashiCorp社が開発しているオーケストレーションツールです。
興味があって、少し試していたのですが、今回はそのときのメモです。
セットアップなど
セットアップはバイナリをダウンロードして展開するだけなので、簡単です。
$ wget https://dl.bintray.com/mitchellh/terraform/terraform_0.3.7_linux_amd64.zip $ unzip terraform_0.3.7_linux_amd64.zip Archive: terraform_0.3.7_linux_amd64.zip inflating: terraform inflating: terraform-provider-atlas inflating: terraform-provider-aws inflating: terraform-provider-cloudflare inflating: terraform-provider-cloudstack inflating: terraform-provider-consul inflating: terraform-provider-digitalocean inflating: terraform-provider-dnsimple inflating: terraform-provider-google inflating: terraform-provider-heroku inflating: terraform-provider-mailgun inflating: terraform-provider-null inflating: terraform-provisioner-file inflating: terraform-provisioner-local-exec inflating: terraform-provisioner-remote-exec
リソースを新規に作成してみる
まず、サンプルとして、以下のようなコンフィグを用意しました。
planディレクトリの下にコンフィグを用意しています。
「terraform plan dir」「terraform apply dir」で適用します。
$ cat plan/terraform_sample.tf provider "aws" { access_key = <your access key> secret_key = <your secret key> region = "ap-northeast-1" } resource "aws_vpc" "tf-vpc" { cidr_block = "10.0.0.0/16" tags { Name = "tf-vpc" } } $ terraform plan plan/ Refreshing Terraform state prior to plan... The Terraform execution plan has been generated and is shown below. Resources are shown in alphabetical order for quick scanning. Green resources will be created (or destroyed and then created if an existing resource exists), yellow resources are being changed in-place, and red resources will be destroyed. Note: You didn't specify an "-out" parameter to save this plan, so when "apply" is called, Terraform can't guarantee this is what will execute. + aws_vpc.tf-vpc cidr_block: "" => "10.0.0.0/16" default_network_acl_id: "" => "<computed>" default_security_group_id: "" => "<computed>" enable_dns_hostnames: "" => "<computed>" enable_dns_support: "" => "<computed>" main_route_table_id: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-vpc" $ terraform apply plan/ aws_vpc.tf-vpc: Creating... cidr_block: "" => "10.0.0.0/16" default_network_acl_id: "" => "<computed>" default_security_group_id: "" => "<computed>" enable_dns_hostnames: "" => "<computed>" enable_dns_support: "" => "<computed>" main_route_table_id: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-vpc" aws_vpc.tf-vpc: Creation complete Apply complete! Resources: 1 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: terraform.tfstate
現状の状態が、カレントディレクトリの「terraform.tfstate」に保存されます。
cat terraform.tfstate { "version": 1, "serial": 1, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": { "aws_vpc.tf-vpc": { "type": "aws_vpc", "primary": { "id": "vpc-1839f77d", "attributes": { "cidr_block": "10.0.0.0/16", "default_network_acl_id": "acl-c23befa7", "default_security_group_id": "sg-8d992ae8", "enable_dns_hostnames": "false", "enable_dns_support": "true", "id": "vpc-1839f77d", "main_route_table_id": "rtb-2ed3054b", "tags.#": "1", "tags.Name": "tf-vpc" } } } } } ] }
リソースを更新してみる
次に先ほどの設定にSubnetとInternetGatewayを追加します。
provider "aws" { access_key = <your access key> secret_key = <your secret key> region = "ap-northeast-1" } resource "aws_vpc" "tf-vpc" { cidr_block = "10.0.0.0/16" tags { Name = "tf-vpc" } } resource "aws_internet_gateway" "tf-internet-gateway" { vpc_id ="${aws_vpc.tf-vpc.id}" tags { Name = "tf-internet-gateway" } } resource "aws_subnet" "tf-subnet1" { vpc_id = "${aws_vpc.tf-vpc.id}" cidr_block = "10.0.1.0/24" availability_zone = "ap-northeast-1a" tags { Name = "tf-subnet1" } } resource "aws_subnet" "tf-subnet2" { vpc_id = "${aws_vpc.tf-vpc.id}" cidr_block = "10.0.2.0/24" availability_zone = "ap-northeast-1c" tags { Name = "tf-subnet2" } } resource "aws_route_table" "tf-public-route-table" { vpc_id = "${aws_vpc.tf-vpc.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.tf-internet-gateway.id}" } } resource "aws_route_table_association" "tf-subnet1-route-table-association" { subnet_id = "${aws_subnet.tf-subnet1.id}" route_table_id = "${aws_route_table.tf-public-route-table.id}" } resource "aws_route_table_association" "tf-subnet2-route-table-association" { subnet_id = "${aws_subnet.tf-subnet2.id}" route_table_id = "${aws_route_table.tf-public-route-table.id}" }
先ほど同様「terraform plan」を実行します。
$ terraform plan plan/ Refreshing Terraform state prior to plan... The Terraform execution plan has been generated and is shown below. Resources are shown in alphabetical order for quick scanning. Green resources will be created (or destroyed and then created if an existing resource exists), yellow resources are being changed in-place, and red resources will be destroyed. Note: You didn't specify an "-out" parameter to save this plan, so when "apply" is called, Terraform can't guarantee this is what will execute. + aws_internet_gateway.tf-internet-gateway tags.#: "0" => "1" tags.Name: "" => "tf-internet-gateway" vpc_id: "" => "${aws_vpc.tf-vpc.id}" + aws_route_table.tf-public-route-table route.#: "" => "1" route.~2206632460.cidr_block: "" => "0.0.0.0/0" route.~2206632460.gateway_id: "" => "${aws_internet_gateway.tf-internet-gateway.id}" route.~2206632460.instance_id: "" => "" route.~2206632460.vpc_peering_connection_id: "" => "" vpc_id: "" => "${aws_vpc.tf-vpc.id}" + aws_route_table_association.tf-subnet1-route-table-association route_table_id: "" => "${aws_route_table.tf-public-route-table.id}" subnet_id: "" => "${aws_subnet.tf-subnet1.id}" + aws_route_table_association.tf-subnet2-route-table-association route_table_id: "" => "${aws_route_table.tf-public-route-table.id}" subnet_id: "" => "${aws_subnet.tf-subnet2.id}" + aws_subnet.tf-subnet1 availability_zone: "" => "ap-northeast-1a" cidr_block: "" => "10.0.1.0/24" map_public_ip_on_launch: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-subnet1" vpc_id: "" => "${aws_vpc.tf-vpc.id}" + aws_subnet.tf-subnet2 availability_zone: "" => "ap-northeast-1c" cidr_block: "" => "10.0.2.0/24" map_public_ip_on_launch: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-subnet2" vpc_id: "" => "${aws_vpc.tf-vpc.id}" + aws_vpc.tf-vpc cidr_block: "" => "10.0.0.0/16" default_network_acl_id: "" => "<computed>" default_security_group_id: "" => "<computed>" enable_dns_hostnames: "" => "<computed>" enable_dns_support: "" => "<computed>" main_route_table_id: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-vpc" $ terraform apply plan/ aws_vpc.tf-vpc: Creating... cidr_block: "" => "10.0.0.0/16" default_network_acl_id: "" => "<computed>" default_security_group_id: "" => "<computed>" enable_dns_hostnames: "" => "<computed>" enable_dns_support: "" => "<computed>" main_route_table_id: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-vpc" aws_vpc.tf-vpc: Creation complete aws_subnet.tf-subnet1: Creating... availability_zone: "" => "ap-northeast-1a" cidr_block: "" => "10.0.1.0/24" map_public_ip_on_launch: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-subnet1" vpc_id: "" => "vpc-d839f7bd" aws_subnet.tf-subnet2: Creating... availability_zone: "" => "ap-northeast-1c" cidr_block: "" => "10.0.2.0/24" map_public_ip_on_launch: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "tf-subnet2" vpc_id: "" => "vpc-d839f7bd" aws_internet_gateway.tf-internet-gateway: Creating... tags.#: "0" => "1" tags.Name: "" => "tf-internet-gateway" vpc_id: "" => "vpc-d839f7bd" aws_internet_gateway.tf-internet-gateway: Creation complete aws_route_table.tf-public-route-table: Creating... route.#: "" => "1" route.3291085789.cidr_block: "" => "0.0.0.0/0" route.3291085789.gateway_id: "" => "igw-4cf80d29" route.3291085789.instance_id: "" => "" route.3291085789.vpc_peering_connection_id: "" => "" vpc_id: "" => "vpc-d839f7bd" aws_subnet.tf-subnet2: Creation complete aws_route_table.tf-public-route-table: Creation complete aws_route_table_association.tf-subnet2-route-table-association: Creating... route_table_id: "" => "rtb-fad3059f" subnet_id: "" => "subnet-0530c75c" aws_subnet.tf-subnet1: Creation complete aws_route_table_association.tf-subnet1-route-table-association: Creating... route_table_id: "" => "rtb-fad3059f" subnet_id: "" => "subnet-aa35e7dd" aws_route_table_association.tf-subnet1-route-table-association: Creation complete aws_route_table_association.tf-subnet2-route-table-association: Creation complete Apply complete! Resources: 7 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: terraform.tfstate
リソースを削除してみる
リソースを削除するために「terraform plan -destroy」コマンドを発行します。
$ terraform plan -destroy plan/ Refreshing Terraform state prior to plan... aws_vpc.tf-vpc: Refreshing state... (ID: vpc-d839f7bd) aws_subnet.tf-subnet2: Refreshing state... (ID: subnet-0530c75c) aws_subnet.tf-subnet1: Refreshing state... (ID: subnet-aa35e7dd) aws_internet_gateway.tf-internet-gateway: Refreshing state... (ID: igw-4cf80d29) aws_route_table.tf-public-route-table: Refreshing state... (ID: rtb-fad3059f) aws_route_table_association.tf-subnet2-route-table-association: Refreshing state... (ID: rtbassoc-9de538f8) aws_route_table_association.tf-subnet1-route-table-association: Refreshing state... (ID: rtbassoc-9ce538f9) The Terraform execution plan has been generated and is shown below. Resources are shown in alphabetical order for quick scanning. Green resources will be created (or destroyed and then created if an existing resource exists), yellow resources are being changed in-place, and red resources will be destroyed. Note: You didn't specify an "-out" parameter to save this plan, so when "apply" is called, Terraform can't guarantee this is what will execute. - aws_internet_gateway.tf-internet-gateway - aws_route_table.tf-public-route-table - aws_route_table_association.tf-subnet1-route-table-association - aws_route_table_association.tf-subnet2-route-table-association - aws_subnet.tf-subnet1 - aws_subnet.tf-subnet2 - aws_vpc.tf-vpc
その後、「terraform destroy」コマンドでリソースを削除します。
$ terraform destroy plan/ Do you really want to destroy? Terraform will delete all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes aws_vpc.tf-vpc: Refreshing state... (ID: vpc-d839f7bd) aws_subnet.tf-subnet1: Refreshing state... (ID: subnet-aa35e7dd) aws_subnet.tf-subnet2: Refreshing state... (ID: subnet-0530c75c) aws_internet_gateway.tf-internet-gateway: Refreshing state... (ID: igw-4cf80d29) aws_route_table.tf-public-route-table: Refreshing state... (ID: rtb-fad3059f) aws_route_table_association.tf-subnet2-route-table-association: Refreshing state... (ID: rtbassoc-9de538f8) aws_route_table_association.tf-subnet1-route-table-association: Refreshing state... (ID: rtbassoc-9ce538f9) aws_route_table_association.tf-subnet2-route-table-association: Destroying... aws_route_table_association.tf-subnet1-route-table-association: Destroying... aws_route_table_association.tf-subnet1-route-table-association: Destruction complete aws_subnet.tf-subnet1: Destroying... aws_route_table_association.tf-subnet2-route-table-association: Destruction complete aws_subnet.tf-subnet2: Destroying... aws_route_table.tf-public-route-table: Destroying... aws_subnet.tf-subnet1: Destruction complete aws_subnet.tf-subnet2: Destruction complete aws_route_table.tf-public-route-table: Destruction complete aws_internet_gateway.tf-internet-gateway: Destroying... aws_internet_gateway.tf-internet-gateway: Destruction complete aws_vpc.tf-vpc: Destroying... aws_vpc.tf-vpc: Destruction complete Apply complete! Resources: 0 added, 0 changed, 7 destroyed.
他
作成したリソース情報は、「terraform show」コマンドで確認できます。
$ terraform show aws_internet_gateway.tf-internet-gateway: id = igw-4cf80d29 vpc_id = vpc-d839f7bd aws_route_table.tf-public-route-table: id = rtb-fad3059f route.# = 1 route.3291085789.cidr_block = 0.0.0.0/0 route.3291085789.gateway_id = igw-4cf80d29 route.3291085789.instance_id = route.3291085789.vpc_peering_connection_id = vpc_id = vpc-d839f7bd aws_route_table_association.tf-subnet1-route-table-association: id = rtbassoc-9ce538f9 route_table_id = rtb-fad3059f subnet_id = subnet-aa35e7dd aws_route_table_association.tf-subnet2-route-table-association: id = rtbassoc-9de538f8 route_table_id = rtb-fad3059f subnet_id = subnet-0530c75c aws_subnet.tf-subnet1: id = subnet-aa35e7dd availability_zone = ap-northeast-1a cidr_block = 10.0.1.0/24 map_public_ip_on_launch = false tags.# = 1 tags.Name = tf-subnet1 vpc_id = vpc-d839f7bd aws_subnet.tf-subnet2: id = subnet-0530c75c availability_zone = ap-northeast-1c cidr_block = 10.0.2.0/24 map_public_ip_on_launch = false tags.# = 1 tags.Name = tf-subnet2 vpc_id = vpc-d839f7bd aws_vpc.tf-vpc: id = vpc-d839f7bd cidr_block = 10.0.0.0/16 default_network_acl_id = acl-913beff4 default_security_group_id = sg-1e982b7b enable_dns_hostnames = false enable_dns_support = true main_route_table_id = rtb-f9d3059c tags.# = 1 tags.Name = tf-vpc
また、リソース同士の関係を、「terraform graph」コマンドで確認できます。
terraform graph plan/ digraph { compound = true; subgraph { "0_aws_vpc.tf-vpc" [ label="aws_vpc.tf-vpc" shape=box ]; "0_aws_internet_gateway.tf-internet-gateway" [ label="aws_internet_gateway.tf-internet-gateway" shape=box ]; "0_aws_subnet.tf-subnet1" [ label="aws_subnet.tf-subnet1" shape=box ]; "0_aws_subnet.tf-subnet2" [ label="aws_subnet.tf-subnet2" shape=box ]; "0_aws_route_table.tf-public-route-table" [ label="aws_route_table.tf-public-route-table" shape=box ]; "0_aws_route_table_association.tf-subnet1-route-table-association" [ label="aws_route_table_association.tf-subnet1-route-table-association" shape=box ]; "0_aws_route_table_association.tf-subnet2-route-table-association" [ label="aws_route_table_association.tf-subnet2-route-table-association" shape=box ]; } "0_aws_vpc.tf-vpc" -> "0_provider.aws"; "0_aws_internet_gateway.tf-internet-gateway" -> "0_provider.aws"; "0_aws_internet_gateway.tf-internet-gateway" -> "0_aws_vpc.tf-vpc"; "0_aws_subnet.tf-subnet1" -> "0_provider.aws"; "0_aws_subnet.tf-subnet1" -> "0_aws_vpc.tf-vpc"; "0_aws_subnet.tf-subnet2" -> "0_provider.aws"; "0_aws_subnet.tf-subnet2" -> "0_aws_vpc.tf-vpc"; "0_aws_route_table.tf-public-route-table" -> "0_provider.aws"; "0_aws_route_table.tf-public-route-table" -> "0_aws_vpc.tf-vpc"; "0_aws_route_table.tf-public-route-table" -> "0_aws_internet_gateway.tf-internet-gateway"; "0_aws_route_table_association.tf-subnet1-route-table-association" -> "0_provider.aws"; "0_aws_route_table_association.tf-subnet1-route-table-association" -> "0_aws_subnet.tf-subnet1"; "0_aws_route_table_association.tf-subnet1-route-table-association" -> "0_aws_route_table.tf-public-route-table"; "0_aws_route_table_association.tf-subnet2-route-table-association" -> "0_provider.aws"; "0_aws_route_table_association.tf-subnet2-route-table-association" -> "0_aws_route_table.tf-public-route-table"; "0_aws_route_table_association.tf-subnet2-route-table-association" -> "0_aws_subnet.tf-subnet2"; subgraph { } subgraph { "0_provider.aws" [ label="provider.aws" shape=diamond ]; } }
色々試してみようと思います。
今日はこんなところで。
参考
- https://www.hashicorp.com/blog/terraform.html:Teraform
- AWS PROVIDER
- Terraform簡易チュートリアル on AWS
- http://qiita.com/zembutsu/items/85ed9061288cae11bc21:AWS Route53(DNS)をTerraformで操作
- http://qiita.com/zembutsu/items/5de875ed99ac8a56a998:TerraformでAWS(EC2)のセキュリティグループを管理
- HashiCorpの新オーケストレーションツールTerraformを試してみた
- Terraformを使う!「導入~AWSにインスタンスを作成・変更・削除」
- Terraformを使う!「TerraformからAWSインスタンスを操作する際のハマりどころ」