Terraform に入門してみる
Terraformを使うのでとりあえず入門記事を漁って見る。
- Terraform簡易チュートリアル on AWS - Qiita EC2の起動から削除までを一通り説明している最小構成のチュートリアルだと思う。一番最初にやるのがよいかな。内容は事前準備、Terraformの導入、TerraformでのEC2の起動・変更・確認・削除。
- terraform 独りハンズオン(1) - ようへいの日々精進XP 一人ハンズオン規模は中位
- AWSでTerraformに入門 | Developers.IO 一通りのチュートリアルがのっているので後で試す
- Terraform と CI で実現するインフラのコード化と構築の自動化 - Qiita TerrafromのCIについて。読んでおいたほうがいい。
- terraformを使ってAWS環境を構築する ハマったところなどの運用事例が紹介されている読めばOK。
- ヌーラボのインフラ運用最前線 2015 〜Terraform による AWS の構成の自動化〜 - ヌーラボ [Nulab Inc.]
導入事例など。これも読んでおいたほうがいい。
とりあえず、 Terraform簡易チュートリアル on AWS - Qiita をハンズオンしてみる。
事前準備
AWS アクセスキーの発行
公式ドキュメントを参照(アクセスキー ID と秘密アクセスキーの取得 )して、アクセスキーとシークレットアクセスキーを発行する。
また、 aws-cli
をインストールして aws configure
を実行しておく。
Terraformのインストール
brew update && brew install terraform
インストール出来た。
$ terraform -v Terraform v0.6.14 Your version of Terraform is out of date! The latest version is 0.6.15. You can update by downloading from www.terraform.io
AWSにEC2インスタンスを立ててみる
Terraform の設定ファイルを書く
「Terraform」の設定ファイルは「JSON」か「HCL」のどちらかで記述できる。
JSON の場合は *.tf.json
、 HCL の場合は *.tf
という拡張子をつける。
HCL は「HashiCorp Configuration Language」の略で、設定ファイルを記述するために HashiCorp が独自に設計したシンタックス。 JSON と比較して可読性がよいらしい(いちいち{}
でくくらなくてもよいのもメリット)。
- GitHub - hashicorp/hcl: HCL is a configuration language.
- Configuration Syntax - Terraform by HashiCorp
とりあえず、 git init
して書き始めよう。
provider "aws" { region = "ap-northeast-1" } resource "aws_instance" "hello-aws" { ami = "ami-a21529cc" instance_type = "t2.micro" }
この、 provider
とか resource
をブロックを呼ぶらしい。
まず、 provider
を記述する。今回は AWS に構築をしてみるので aws
を指定指定する。
プロバイダの一覧は公式ドキュメント参照。
access_key
と secret_key
は aws configure
で設定していない場合はここで記述する。
reagion
には対象のリージョンを指定する(リージョンとアベイラビリティーゾーン)。東京は ap-northeast-1
なので、これを指定。
resource
ブロックは引数を二つとり、第一引数に「作成するリソースのタイプ」を、第二引数に「リソース名」を指定する。プロバイダが AWS の場合に指定できるリソースは公式ドキュメント参照(AWS PROVIDER)。
とりあえずチュートリアルに習って、 EC2 のインスタンスを作成してみる。
リソースブロックの第一引数に aws_instance
、第二引数の名前に hello-aws
を記述(AWS: aws_instance - Terraform by HashiCorp)。
ドキュメントをみると、この aws_instance
には必須項目が二つある。
ami
: 作成するAMI(Amazon マシンイメージ)instance_type
: 作成する EC2 のインスタンスタイプ(インスタンスタイプ)
AMI はなんとなく ami-a21529cc
の Ubuntu (無料枠の対象)を指定してみる。
インスタンスタイプは t2.nano
が一番安いんだけど、無料枠の対象の t2.micro
を指定。
インスタンスを起動する
plan
で Dry Run してみる
terraform
のサブコマンドに plan
というのがある。このコマンドを実行することにより、どのような変更が適用されるか事前に確認することができる。
terraform 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_instance.hello-aws ami: "" => "ami-a21529cc" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_state: "" => "<computed>" instance_type: "" => "t2.micro" key_name: "" => "<computed>" placement_group: "" => "<computed>" private_dns: "" => "<computed>" private_ip: "" => "<computed>" public_dns: "" => "<computed>" public_ip: "" => "<computed>" root_block_device.#: "" => "<computed>" security_groups.#: "" => "<computed>" source_dest_check: "" => "1" subnet_id: "" => "<computed>" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "<computed>" Plan: 1 to add, 0 to change, 0 to destroy.
Note が表示された。
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.
これは、「 out
パラメータを指定してプランを保存しなかったら、 apply
呼ばれた時に何を実行するか保証できないよ!」ってことだと思う。多分、 plan
した後に別の人が別のところで apply
した場合は、今回行った plan
は意味なくなるから気をつけろよってことだと思う。
あとで、実験しよう。
あと、 terraform.tfstate
というファイルが作成される。これは、 Terraform が管理しているリソースを JSON で保存しておくファイルらしい。
いまは、何も適用してないから空っぽいファイルができてるね。
{ "version": 1, "serial": 0, "modules": [ { "path": [ "root" ], "outputs": {}, "resources": {} } ] }
apply
で適用する
apply
のサブコマンドを実行すると、 *.tf
ファイルの記述に従って処理が適用される。
$ terraform apply aws_instance.hello-aws: Creating... ami: "" => "ami-a21529cc" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_state: "" => "<computed>" instance_type: "" => "t2.micro" key_name: "" => "<computed>" placement_group: "" => "<computed>" private_dns: "" => "<computed>" private_ip: "" => "<computed>" public_dns: "" => "<computed>" public_ip: "" => "<computed>" root_block_device.#: "" => "<computed>" security_groups.#: "" => "<computed>" source_dest_check: "" => "1" subnet_id: "" => "<computed>" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "<computed>" aws_instance.hello-aws: 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
作成されたっぽい。 computed
の部分は特になにも指定してないので動的に作成される(っぽい)。
インスタンスの詳細を見るには show
を使えって書いてあるので実行してみる。
$ terraform show aws_instance.hello-aws: id = i-4a10aed5 ami = ami-a21529cc availability_zone = ap-northeast-1a ebs_block_device.# = 0 ebs_optimized = false ephemeral_block_device.# = 0 iam_instance_profile = instance_state = running instance_type = t2.micro key_name = monitoring = false private_dns = ip-172-31-4-134.ap-northeast-1.compute.internal private_ip = 172.31.4.134 public_dns = ec2-52-192-1-94.ap-northeast-1.compute.amazonaws.com public_ip = 52.192.1.94 root_block_device.# = 1 root_block_device.0.delete_on_termination = true root_block_device.0.iops = 24 root_block_device.0.volume_size = 8 root_block_device.0.volume_type = gp2 security_groups.# = 0 source_dest_check = true subnet_id = subnet-8b78affc tags.# = 0 tenancy = default vpc_security_group_ids.# = 1 vpc_security_group_ids.1967208828 = sg-9257fef7
なんかイロイロ表示されましたね。 ちゃんと起動してるかチェック。
$ aws ec2 describe-instances --instance-ids "i-4a10aed5" | jq '.Reservations[].Instances[] | {"Image ID": .ImageId, "Instance ID": .InstanceId, "Status": .State.Name}' { "Image ID": "ami-a21529cc", "Instance ID": "i-4a10aed5", "Status": "running" }
起動してるっぽい。
インスタンスを変更する
ためにしに、 AMI を Ubuntu から Amazon Linux に変更してみる。
diff --git hello-aws.tf hello-aws.tf index cbe294a..62aeca0 100644 --- hello-aws.tf +++ hello-aws.tf @@ -3,6 +3,6 @@ provider "aws" { } resource "aws_instance" "hello-aws" { - ami = "ami-a21529cc" + ami = "ami-f80e0596" instance_type = "t2.micro" }
terraform plan
を実行。
Refreshing Terraform state prior to plan... aws_instance.hello-aws: Refreshing state... (ID: i-4a10aed5) 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_instance.hello-aws ami: "ami-a21529cc" => "ami-f80e0596" (forces new resource) availability_zone: "ap-northeast-1a" => "<computed>" ebs_block_device.#: "0" => "<computed>" ephemeral_block_device.#: "0" => "<computed>" instance_state: "running" => "<computed>" instance_type: "t2.micro" => "t2.micro" key_name: "" => "<computed>" placement_group: "" => "<computed>" private_dns: "ip-172-31-4-134.ap-northeast-1.compute.internal" => "<computed>" private_ip: "172.31.4.134" => "<computed>" public_dns: "ec2-52-192-1-94.ap-northeast-1.compute.amazonaws.com" => "<computed>" public_ip: "52.192.1.94" => "<computed>" root_block_device.#: "1" => "<computed>" security_groups.#: "0" => "<computed>" source_dest_check: "true" => "1" subnet_id: "subnet-8b78affc" => "<computed>" tenancy: "default" => "<computed>" vpc_security_group_ids.#: "1" => "<computed>" Plan: 1 to add, 0 to change, 1 to destroy.
新しいリソースを作るみたいな表示になってる。
ami: "ami-a21529cc" => "ami-f80e0596" (forces new resource)
Plan: 1 to add, 0 to change, 1 to destroy.
terraform apply
を実行。
aws_instance.hello-aws: Refreshing state... (ID: i-4a10aed5) aws_instance.hello-aws: Destroying... aws_instance.hello-aws: Destruction complete aws_instance.hello-aws: Creating... ami: "" => "ami-f80e0596" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_state: "" => "<computed>" instance_type: "" => "t2.micro" key_name: "" => "<computed>" placement_group: "" => "<computed>" private_dns: "" => "<computed>" private_ip: "" => "<computed>" public_dns: "" => "<computed>" public_ip: "" => "<computed>" root_block_device.#: "" => "<computed>" security_groups.#: "" => "<computed>" source_dest_check: "" => "1" subnet_id: "" => "<computed>" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "<computed>" aws_instance.hello-aws: Creation complete Apply complete! Resources: 1 added, 0 changed, 1 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 show | grep " id =" id = i-1cd06883 $ aws ec2 describe-instances --instance-ids "i-4a10aed5" "i-1cd06883" | jq '.Reservations[].Instances[] | {"Image ID": .ImageId, "Instance ID": .InstanceId, "Status": .State.Name}'
{ "Image ID": "ami-a21529cc", "Instance ID": "i-4a10aed5", "Status": "terminated" } { "Image ID": "ami-f80e0596", "Instance ID": "i-1cd06883", "Status": "running" }
古い方は terminated
になってるし、新しい方は違う AMI ID で running
になってる。
インスタンスの削除
インスタンスの削除は plan
に -destroy
オプションをつけてプランファイルを作成し、 apply
実行時にプランファイルを指定して実行する。
プランファイルを作成して。
$ terraform plan -destroy -out=destroy.tfplan efreshing Terraform state prior to plan... aws_instance.hello-aws: Refreshing state... (ID: i-1cd06883) 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. Your plan was also saved to the path below. Call the "apply" subcommand with this plan file and Terraform will exactly execute this execution plan. Path: destroy.tfplan - aws_instance.hello-aws Plan: 0 to add, 0 to change, 1 to destroy.
削除。
$ terraform apply ./destroy.tfplan aws_instance.hello-aws: Destroying... aws_instance.hello-aws: Destruction complete Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
確認してみると両方とも terminated
になってた。
$ aws ec2 describe-instances --instance-ids "i-4a10aed5" "i-1cd06883" | jq '.Reservations[].Instances[] | {"Image ID": .ImageId, "Instance ID": .InstanceId, "Status": .State.Name}' { "Image ID": "ami-a21529cc", "Instance ID": "i-4a10aed5", "Status": "terminated" } { "Image ID": "ami-f80e0596", "Instance ID": "i-1cd06883", "Status": "terminated" }