インフラの構成管理を自動化するTerraform入門
TerraformからAWSインスタンスの起動と停止を実行する
以降では、Terraformの基本的な使い方を見ていきます。ここではAWSを例に紹介しますが、Terraformは他にも様々なクラウド環境で利用できます。
事前準備
まずは、AWS上のEC2インスタンスを起動する方法を試してみます。ここでは、実際にAWSのアカウントが作成されていることに加えて、アクセスキーとシークレットキーの取得を前提としています。また、設定適用時にはインスタンスが稼働しますので、停止するまで課金対象となる点にご注意願います。
Terraformをインストールした環境上で、任意の名前のディレクトリを作成し、移動します。その中で「aws.tf」という名称のファイルを作成し、内容は次の通りにします。アクセスキーと、シークレットキーは自分のものを記入ください(なお、セキュリティ上、このファイルのパーミッションは他人から読めないように設定し、作業後はアクセスキー等の情報は削除するなど、ご注意願います)。
1つめのブロックは「プロバイダ」と呼ばれるもので、Terraformがアクセス可能なクラウドサービスごとに提供されています。今回はAWSを使うため「aws」と指定します。もし他のプロバイダを使う場合は、awsではなく各々のプロバイダ名を記入します(例:DigitalOceanのプロバイダ名は「digitalocean」)。
そしてAWSの場合は、どのリージョンで稼働させるかを記入します。この例では「us-east-1」としていますが、東京リージョンを使う場合は「ap-northeast-1」とします。
次のブロックは「リソース」と呼ばれるものです。EC2インスタンスを起動するために、リソース名「aws_instance」を使い、「terraform_example」という名称のインスタンスを起動するものです。ここではUbuntu 14.04 LTSのAMI(Amazon Machine Image)と、インスタンスの種類も指定しています。SSHログインに必要なキーは、マネジメントコンソール上で登録済みのキー名称を「key_name」に記述します。
なお、リソースには命名規則があります。例えばプロバイダが「aws」の場合、リソース名は「aws_」で始まります。
Terraformでインスタンス起動
それでは、実際にTerraformを使ってインスタンスを起動しましょう。aws.tfを作成したディレクトリで、「terraform plan」コマンドを実行します。シークレットキー等の情報が正しければ、次のように変更予定の情報が表示されます。
$ terraform plan Refreshing Terraform state prior to plan... (省略) + aws_instance.terraform_example ami: "" => "ami-408c7f28" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_type: "" => "t1.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>" subnet_id: "" => "<computed>" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "<computed>"
この段階では設定は適用されておらず、あくまで設定変更を確認するだけです。もしAMIの設定や認証情報が正しくなければ、事前に警告が表示されます。その場合は、エラー内容に従って、適切に記述されているかどうか、確認します。
エラーが出なければ、適用準備は完了です。実際にインスタンスを起動するには「terraform apply」を実行します。
$ terraform apply aws_instance.terraform_example: Creating... ami: "" => "ami-408c7f28" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_type: "" => "t1.micro" (省略) aws_instance.terraform_example: Creation complete Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
このように「1 added」と表示されていれば、正常に処理が完了しています。そして、割り当てられたIPアドレスの情報を確認するには「terraform show」を実行します。
$ terraform show aws_instance.terraform_example: id = i-4a60fc9c ami = ami-408c7f28 availability_zone = us-east-1e ebs_block_device.# = 0 ebs_optimized = false ephemeral_block_device.# = 0 instance_type = t1.micro private_dns = ip-10-232-98-201.ec2.internal private_ip = 10.232.98.201 public_dns = ec2-54-163-125-154.compute-1.amazonaws.com public_ip = 54.163.125.154 (省略)
ここで表示される情報は、AWSマネジメントコンソールで表示される情報と同一のものです。ブラウザでアクセスし、N.VirginiaリージョンのEC2インスタンス情報を確認すると、実際に作成されているものと同じ情報が表示されていることが分かります。
インスタンスの削除
起動したインスタンスを削除する場合も、再び「terraform plan」を実行しますが、削除の場合は「-destroy」オプションを使います。表示される内容から、削除対象のリソースや名称が相違ないことを確認します。
$ terraform plan -destroy Refreshing Terraform state prior to plan... aws_instance.terraform_example: Refreshing state... (ID: i-4a60fc9c) (省略) - aws_instance.terraform_example
最終的に削除するのは「terraform destroy」コマンドです。コマンドを実行すると、「本当に削除しても構いませんか?」と確認が表示されます。「Enter a value:」に「yes」と入力することで、次のように削除が進行します。
$ terraform destroy 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_instance.terraform_example: Refreshing state... (ID: i-4a60fc9c) aws_instance.terraform_example: Destroying... aws_instance.terraform_example: Destruction complete Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
通常、インスタンス起動前に作成予定のインスタンスIDは分かりませんが、Terraformであれば変数として利用できます。
まず、「aws_eip」というリソースに「ip」という名前を割り当てます。その次のインスタンス名に「${aws_instance.terraform_example.id}」を指定しているのは、リソース「aws_instance」の名称「terraform_example」のインスタンスIDを変数として割り当てるものです。
ファイルに追加後、再び「terraform plan」コマンドを実行します。すると今度は、リソースaws_eipに関する情報が追加されていることが分かります。
$ terraform plan Refreshing Terraform state prior to plan... + aws_eip.ip allocation_id: "" => "<computed>" association_id: "" => "<computed>" domain: "" => "<computed>" instance: "" => "${aws_instance.terraform_example.id}" network_interface: "" => "<computed>" private_ip: "" => "<computed>" public_ip: "" => "<computed>" (省略)
エラーがなければ準備完了です。設定を適用するため「terraform apply」コマンドを実行します。正常に処理が進むと、先ほどのインスタンス追加に加え、追加されたElastic IPの情報も参照できます。
aws_instance.terraform_example: Creation complete aws_eip.ip: Creating... allocation_id: "" => "<computed>" association_id: "" => "<computed>" domain: "" => "<computed>" instance: "" => "i-36f669e0" network_interface: "" => "<computed>" private_ip: "" => "<computed>" public_ip: "" => "<computed>" aws_eip.ip: Creation complete Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
作成後は、先ほどのインスタンス同様に「terraform plan -destroy」「terraform destroy」コマンドを実行し、破棄しておきます。
その他のリソース
Terraformが扱えるのは、今回の例で紹介したインスタンスとElastic IPだけに留まりません。セキュリティグループや、IAM関係の管理、キーペア関連、Route53、VPC関連など、様々なリソースを扱えます。ただし、まだ実装途中のものもあり、詳しい動作範囲や挙動はドキュメントをお読みいただくか、実際にお試しいただければと思います。
DigitalOceanをTerraformで操作するには
最後にAWS以外にも使える例として、DigitalOceanの仮想サーバ(ドロップレット)の構築・削除を行ってみます。DigitalOceanは1分以内に仮想サーバが起動できるだけでなく、課金が時間単位であるなど、使い勝手が手頃です。しかし、毎回ブラウザを通して起動・削除するのは面倒ではないでしょうか。Terraformであれば、AWSと同様にDigitalOceanでも迅速な環境構築を行えます。
digitalocean.tfファイルの用意
任意のディレクトリに「digitalocean.tf」ファイルを作成します。この時、先ほど作業したAWS用のディレクトリとは別の場所で作業をします。これは、Terraformが実行時に同一ディレクトリ内にある*.tfファイル全てを読み込むことに加え、Terraform内部で使用する中間ファイルをディレクトリ内に置いているためです。
ファイルの中身は、次のようにします。あらかじめDigitalOceanのアカウントと、APIトークンの作成が必要です。
1つめのブロックは「digitalocean」のプロバイダを指定しています。2つめのブロックで、「digitalocean_droplet」というドロップレットに対するリソースを指定しています。あとは仮想マシン・イメージにCentOSを指定し、ホスト名、データセンタ、メモリ、プライベート・ネットワークの有効化を指定しています。
AWSの場合はプロバイダ「aws」に対して、リソース名は「aws_」で始まるという命名規則がありました。DigitalOceanも同様で、プロバイダ「digitalocean」に対応する各種のリソース名は「digitalocean_」で始まります。これは、他のプロバイダでも同様です。
なお、あらかじめSSH鍵をDigitalOceanに登録している場合は、その鍵を割り当てることもできます。登録済みの鍵IDを確認するためには、次のコマンドを実行して確認できます。
$ curl -X GET -H 'Content-Type: application/json' \ -H 'Authorization: Bearer <DigitalOceanのAPIトークン>' \ "https://api.digitalocean.com/v2/account/keys"
ドロップレトの起動と破棄
「terraform plan」を実行し、マシン・イメージやホスト名やスペックが適切かどうか確認できます。
$ terraform plan + digitalocean_droplet.example image: "" => "centos-6-5-x64" ipv4_address: "" => "<computed>" ipv4_address_private: "" => "<computed>" ipv6_address: "" => "<computed>" ipv6_address_private: "" => "<computed>" locked: "" => "<computed>" name: "" => "terraform.example.jp" private_networking: "" => "1" region: "" => "sgp1" size: "" => "512mb" ssh_keys.#: "" => "1" ssh_keys.0: "" => "737302" status: "" => "<computed>"
内容に問題がなければ「terraform apply」を実行します。正常に処理されれば、図3のようにドロップレットが自動作成されていることが分かります。
作業後のドロップレット破棄も手軽です。
$ terraform plan -destroy $ terraform destroy 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 digitalocean_droplet.example: Refreshing state... (ID: 5195198) digitalocean_droplet.example: Destroying... digitalocean_droplet.example: Destruction complete Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
まとめ
これまで見てきたように、Terraformはインフラの状態をコードで管理することができるツールです。数台程度の利用環境であれば、その効果は実感しづらいかもしれませんが、管理対象の台数が多い場合や、繰り返し作業が多い環境では力を発揮するのではないでしょうか。
Terraformはまだ開発途上であり、多くのクラウド環境の全ての機能には対応できていません。しかしながら、機能追加やバグ修正の開発スピードは非常に速いです。バグ発見や機能追加を希望される場合は、GitHub上でissueやプルリクエストを送ってみてはいかがでしょうか。
次回は、Consulを使ったクラスタ管理の方法をご紹介予定です。
※本稿は、2015年7月現在のTerraform v0.6.0に対して確認を行っています。
【参考文献】
Terraform(アクセス:2015/07)
https://terraform.io/
TERRAFORM DOCUMENTATION(アクセス:2015/07)
https://terraform.io/docs/index.html
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- マシン・イメージを自動構築し、作業効率を高めるPacker入門
- Iacツール「Terraform」の基本的な使い方
- TerraformからPulumiへの移行
- Oracle Cloud Hangout Cafe Season7 #2「IaC のベストプラクティス」(2023年7月5日開催)
- 「Terraform」のコードを自分で書けるようになろう
- SecretもPulumiで使いこなしたい! PulumiのSecurityを試してみよう
- 「Pulumi Stack」とは ー Pulumiによるマルチステージ環境の構築方法
- Policy as Codeでインフラのコンプライアンスを自動実現! 「Pulumi CrossGuard」を活用してみよう
- PulumiでAWSリソースをデプロイしよう
- 既に存在するリソースをPulumiで管理してみよう