自動化ツールの一つである「Terraform」について、これから学ぼうという人、使っていきたい人に向けて基本的な使い方を紹介していきます。第4回はTerraformで複雑なリソースを一度に作成する方法として、リソースやデータソースの情報の活用方法を紹介します。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
第1回から第3回にかけて、Terraformを使用した基本的なリソース管理を解説してきました。これまでの解説だけでも十分にリソース管理を進めていくことは可能ですが、より実用的な、複雑なリソース管理をするには、まだまだ知っておくべき要素が幾つもあります。今回は、Terraformで複雑なリソースを一度に作成する方法として、リソースやデータソースの活用方法を紹介します。
Amazon Web Services(AWS)のリソースを作成するとき、通常は他のリソースと関連付けることがあります。「Amazon Elastic Compute Cloud」(Amazon EC2)インスタンスを作成する場合、本連載でこれまで紹介した手順ではセキュリティグループを指定しませんでしたが、一般的には用途にふさわしい既存のセキュリティグループを指定します。必要に応じて「Amazon Virtual Private Cloud」(Amazon VPC)のサブネットも指定することもありますし、ルートボリュームとは異なる「Amazon Elastic Block Store」(Amazon EBS)を作成し、アタッチすることもあります。
こういったことをTerraformで表現しようとすると、各リソースのIDやARN(Amazon リソースネーム)を指定する必要があります。ただ、IDやARNを知ることができるのはリソースを作成した後になるため、事前に必要なリソースを作成してからIDを調べ、IDを指定してもう一度目的のリソースを作成するというように、手間がかかってしまいます。
そこでTerraformにはそれぞれ依存するリソースを直接参照、指定する方法があります。実際には、前述のような手間がかかることなく、一度に複雑なリソースを作成することが可能です。
それでは早速、他のリソースを参照するようなリソースをTerraformで作成してみましょう。EC2インスタンスを作成する際に、別で作成したEBSをアタッチすることを表現してみます。まずは、新しくEBSを作成するTerraformのコードを作成します。
resource "aws_ebs_volume" "example" { availability_zone = "ap-northeast-1a" size = 20 }
上記は、サイズが20GiBのEBSボリュームを、アベイラビリティゾーンである「ap-northeast-1a」に作成することを表しています。試しに、この状態でterraform applyを実行してEBSボリュームを作成すると、以下のように指定した通りのEBSボリュームが作成されます。
では、試しに作成したEBSボリュームはterraform destroyでいったん削除し、本題であるEBSボリュームとEC2インスタンスの作成およびEBSボリュームのEC2インスタンスへのアタッチを同時に実行してみましょう。先ほどのTerraformのコードに内容を追加し、以下のような内容に変更します。
resource "aws_ebs_volume" "example" { availability_zone = "ap-northeast-1a" size = 20 } resource "aws_instance" "example" { ami = "ami-0f9816f78187c68fb" availability_zone = "ap-northeast-1a" instance_type = "t2.micro" } resource "aws_volume_attachment" "example" { device_name = "/dev/sdf" instance_id = aws_instance.example.id volume_id = aws_ebs_volume.example.id }
上記のように、EBSボリュームのEC2インスタンスへのアタッチは「aws_volume_attachment」リソースで表現することになりますが、インスタンスIDを指定するinstance_idと、ボリュームIDを指定するvolume_idにはIDを示す文字列を指定していません。それぞれ、EBSボリュームやEC2インスタンスを定義したリソース名のidという属性値を参照するようにしています。
これにより、まだ作成していないリソースのIDが分からなくても、リソース作成時に得られる情報を参照することで、一度にリソースを作成できるのはもちろん、Terraformのコード上でもどのリソースを参照しているのかが分かりやすくなります。
では、実際にこのTerraformコードを使用してterraform applyを実行してみましょう。
$ 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_ebs_volume.example will be created + resource "aws_ebs_volume" "example" { (中略) } # aws_instance.example will be created + resource "aws_instance" "example" { (中略) } # aws_volume_attachment.example will be created + resource "aws_volume_attachment" "example" { + device_name = "/dev/sdf" + id = (known after apply) + instance_id = (known after apply) + volume_id = (known after apply) } Plan: 3 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_ebs_volume.example: Creating... aws_instance.example: Creating... aws_ebs_volume.example: Still creating... [10s elapsed] aws_instance.example: Still creating... [10s elapsed] aws_ebs_volume.example: Creation complete after 11s [id=vol-xxxxxxxxxxxxxxxxx] aws_instance.example: Still creating... [20s elapsed] aws_instance.example: Still creating... [30s elapsed] aws_instance.example: Creation complete after 34s [id=i-xxxxxxxxxxxxxxxxx] aws_volume_attachment.example: Creating... aws_volume_attachment.example: Still creating... [10s elapsed] aws_volume_attachment.example: Still creating... [20s elapsed] aws_volume_attachment.example: Creation complete after 21s [id=vai-xxxxxxxxxx] Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
実行結果のログを見てみると、まずEBSボリュームとEC2インスタンスを作成し、それぞれのIDが判明してからEBSボリュームをEC2インスタンスにアタッチしていることが分かります。
このように、それぞれのリソースが相互に関係するような複雑な環境を用意する場合は、リソースの情報を参照する手法がほぼ必須の知識となります。
次に、リソースの情報とは異なり、既に存在する情報を参照することができる、データソースを参照する方法を紹介します。EC2インスタンスを作成する際に使用するAmazonマシンイメージ(AMI)を常に最新のAmazon Linuxにしておきたかったり、共通で使用するセキュリティグループを設定したかったりする場合に便利な方法となります。
まずは、AMIの情報を参照してEC2インスタンスを作成してみましょう。常に最新のAmazon Linux 2023を使うことを想定しますが、人力でやろうとすると毎回最新のAMI IDを探してTerraformのコードを修正する必要があります。手作業の部分を、データソースの参照に置き換えてみます。
data "aws_ami" "amzn-linux-2023-ami" { most_recent = true owners = ["amazon"] filter { name = "name" values = ["al2023-ami-2023.*-x86_64"] } } resource "aws_instance" "example" { ami = data.aws_ami.amzn-linux-2023-ami.id instance_type = "t2.micro" }
新しく、resourceではなくdataで始まる定義が登場しました。これがデータソースの定義で、上記の例では「al2023-ami-2023.*-x86_64」という名前にマッチする、Amazonが所有者の最新のAMI情報を取得する内容になっています。
これにより、このデータソースは最新のAmazon Linux 2023のAMI情報を持つようになります。続くEC2インスタンスのリソース定義で、このデータソースの情報のうちid属性を参照し、AMI IDとして利用しています。
一度、このTerraformのコードでterraform planを実行します。すると、最初にデータソースに持たせる情報を取得するような処理が実行されていることが分かります。
$ terraform plan data.aws_ami.amzn-linux-2023-ami: Reading... data.aws_ami.amzn-linux-2023-ami: Read complete after 1s [id=ami-0310b105770df9334] 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_instance.example will be created + resource "aws_instance" "example" { + ami = "ami-0310b105770df9334" (中略) } Plan: 1 to add, 0 to change, 0 to destroy. ─────────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
次に、既に作成してあるセキュリティグループを参照して、新たに作成するEC2インスタンスのセキュリティグループとして設定してみます。「example」という名前のセキュリティグループが既に存在していると仮定し、このセキュリティグループをデータソースとして定義します。
data "aws_security_group" "example" { name = "example" } resource "aws_instance" "example" { ami = data.aws_ami.amzn-linux-2023-ami.id instance_type = "t2.micro" vpc_security_group_ids = [data.aws_security_group.example.id] }
この内容でterraform planを実行すると、こちらも同様に、既に存在するセキュリティグループの情報を取得してデータソースに持たせる処理が実行され、作成するEC2インスタンスのセキュリティグループの設定として利用できるようになっていることが分かります。
$ terraform plan data.aws_ami.amzn-linux-2023-ami: Reading... data.aws_security_group.example: Reading... data.aws_security_group.example: Read complete after 1s [id=sg-xxxxxxxxxxxxxxxxx] data.aws_ami.amzn-linux-2023-ami: Read complete after 1s [id=ami-0310b105770df9334] 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_instance.example will be created + resource "aws_instance" "example" { + ami = "ami-0310b105770df9334" (中略) + vpc_security_group_ids = [ + "sg-xxxxxxxxxxxxxxxxx", ] } Plan: 1 to add, 0 to change, 0 to destroy. ─────────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
今回紹介したデータソース以外にも、AWSのリソース情報を参照できるものは非常にたくさんありますので、ぜひ一度公式ドキュメントを流し読みして、どのような情報が参照できるか探ってみるとよいでしょう。
第1回〜第4回で紹介した内容だけでも、かなり実用的なTerraformのコードを記述できるようになります。次回は、もっと便利にコードを記述する方法として、変数の使用方法を紹介します。
サイオステクノロジー所属。OSS よろず相談室でサポート対応をしているテクニカルサポートエンジニア。Ansibleに出会ってから自動化に取りつかれ、自身の業務やプライベートであらゆるものの自動化に取り組む。プライベートではJavaでちょっとしたツールの開発を趣味にしている。
Copyright © ITmedia, Inc. All Rights Reserved.