参考 : https://developer.hashicorp.com/terraform/language
参考 : https://developer.hashicorp.com/terraform/tutorials/cli/plan
Terraform言語の特徴
TerraformはHCL(HashiCorp Configuration Language)という独自の宣言型言語を使用します。
Terraform言語の主な目的は、インフラストラクチャオブジェクトを表すリソースを宣言することです。 他のすべて言語機能は、インフラリソースの定義をより柔軟にするためにのみ存在します。
Terraformが宣言的な記述であるということは「Terraformの構成ディレクトリは、インフラリソースの完全なドキュメントである」という意味です。 Terraform言語の構文は、いくつかの基本要素のみで構成されています。
resource "aws_vpc" "main" { cidr_block = var.base_cidr_block } <BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" { # Block body <IDENTIFIER> = <EXPRESSION> # Argument }
{}
ブロックはコンテンツであり、通常インフラリソースのような何らかのオブジェクトの構成を表します。- インフラリソースには引数が存在し、値を割り当てることでインフラリソースの設定が可能です。それらはブロック内に書き込むことができます。
Terraform言語は宣言的であり、C言語プログラミングのように意図された目標への手段を説明するのではなく、 あるべき状態のみが記述されています。
リソース間の構成順序を決定するときでも、手続き型ではなく暗黙的に構成されます。
Terraform実行前
TerraformがAWSアカウントに対して変更を加えられるようにするためには、以前に取得したAWSアカウントの認証情報を、
AWS_ACCESS_KEY_ID
とAWS_SECRETACCESS_KEY
という環境変数として設定しておく必要があります。
それぞれのOSで、以下のようなコマンドを実行して環境変数を設定してください。
export AWS_ACCESS_KEY_ID=<あなたのアクセスキー> export AWS_SECRETACCESS_KEY=<あなたのシークレットアクセスキー>
- Windowsのコマンドターミナルでは次のように設定します。
set AWS_ACCESS_KEY_ID=<あなたのアクセスキー> set AWS_SECRETACCESS_KEY=<あなたのシークレットアクセスキー>
これらのコマンドは.bashrc
や$PROFILE
先のスクリプトに記述しておく必要があります。
AWSリソースの作成のためにはこれらの設定が必須となりますが、AzureやGCPなど別のプロバイダーを使用するためにはまた別の設定が必要になります。
ソースコード
以下のコードをmain.tf
として保存してください
# プロバイダの設定 provider "aws" { region = "us-west-2" } # EC2インスタンスの設定 resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI instance_type = "t2.micro" # セキュリティグループの設定 vpc_security_group_ids = [aws_security_group.example.id] } # セキュリティグループの設定 resource "aws_security_group" "example" { name = "example-sg" description = "Example security group" ingress { from_port = 8080 to_port = 8080 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
プロバイダの設定
provider "aws" { region = "us-west-2" }
このセクションでは、AWSプロバイダを設定しています。regionパラメータは、リソースがデプロイされるAWSリージョンを指定します。
EC2インスタンスの設定
resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" vpc_security_group_ids = [aws_security_group.example.id] tags = { Name = "example-instance" } }
resource "aws_instance" "example"
は、EC2インスタンスを作成するためのリソースブロックです。 amiやインスタンスタイプからEC2の設定がわかると思います。- vpc_security_group_idsは、このインスタンスに関連付けるセキュリティグループのIDを指定します。別のブロックで宣言しているセキュリティグループをここでは参照しています。
ターミナルを起動
terraform init
ターミナルを起動してmain.tf
を保存したファイルがあるフォルダーで以下のコマンドを実行してください。
terraform init
- 実行例
Initializing the backend... Initializing modules... - ec2-instance in modules/aws-ec2-instance Downloading registry.terraform.io/joatmon08/hello/random 6.0.0 for hello... - hello in .terraform/modules/hello Initializing provider plugins... - Reusing previous version of hashicorp/random from the dependency lock file - Reusing previous version of hashicorp/aws from the dependency lock file - Installing hashicorp/aws v5.7.0... - Installed hashicorp/aws v5.7.0 (signed by HashiCorp) - Installing hashicorp/random v3.5.1... - Installed hashicorp/random v3.5.1 (signed by HashiCorp) 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.
terraform init
コマンドはコードをスキャンして、どのプロバイダを使うのか判断し、そのプロバイダに関するコードをダウンロードする必要があります。
基本的にはスクラッチディレクトリである.terraform
フォルダにダウンロードされます。
このコマンド terraform init
コマンドは何度実行しても問題ないです。
ここまででプロバイダの情報がダウンロードされたので、次のコマンドを実行します。
terraform plan
以下のコマンドを使うと、実際に変更を加える前にTerraformが何を実行するのか、どのプロバイダーにどんなことをするのかの確認をします。
terraform plan
このコマンドを実行することで、AWSリソースの利用料の発生やサービスの更新など、現実の世界に変更が起きる前の確認ができます。
コマンドの表現はgit
の差分チェックと同じと考えて良いです。
$ terraform plan -out "tfplan" data.aws_ami.ubuntu: Reading... data.aws_ami.ubuntu: Read complete after 0s [id=ami-055744c75048d8296] 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: # random_pet.instance will be created + resource "random_pet" "instance" { + id = (known after apply) + length = 2 + separator = "-" } # module.ec2-instance.aws_instance.main will be created + resource "aws_instance" "main" { ## ... Plan: 4 to add, 0 to change, 0 to destroy. ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Saved the plan to: tfplan To perform exactly these actions, run the following command to apply: terraform apply "tfplan"
terraform apply
実際にインスタンスを作成するには、以下のコマンドを実行します。
terraform apply
applyコマンド実行時にはplan実行時と同じ確認画面が出力されます。
確認して問題なければyes
と入力しましょう。
ここまででAWSアカウント内にEC2、セキュリティグループの構築ができました。
Terraformコードに変更を加える
ここまではTerraformコードを使用してAWSリソースを構築する方法を紹介しました。
このあとはTerraformコードを変更してみたいと思います。 EC2インスタンスにタグがついていないので、タグをつけて名前を追加したいと思います。
# プロバイダの設定 provider "aws" { region = "us-west-2" } # EC2インスタンスの設定 resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI instance_type = "t2.micro" # セキュリティグループの設定 vpc_security_group_ids = [aws_security_group.example.id] tags = { Name = "terraform-example" } } # セキュリティグループの設定 resource "aws_security_group" "example" { name = "example-sg" description = "Example security group" ingress { from_port = 8080 to_port = 8080 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
ファイルの変更が済んだらterraform apply
を実行してみます。
Terraformはすでに作成されたリソースファイルの情報を保持しているため、terraform apply
を実行することで
リソースの変更が可能になります。
(実行した後は、Refreshing state...
と出力されます)
AWSコンソールからEC2を確認すると、Name
タグがついているのが確認できると思います。
EC2インスタンスの初期セットアップ
# プロバイダの設定 provider "aws" { region = "us-west-2" } # EC2インスタンスの設定 resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI instance_type = "t2.micro" # セキュリティグループの設定 vpc_security_group_ids = [aws_security_group.example.id] user_data = <<-EOF #!/bin/bash echo "Hello World" > index.html nohup busybox httpd -f -p 8080 & EOF user_data.replace_on_change = true tags = { Name = "terraform-example" } } # セキュリティグループの設定 resource "aws_security_group" "example" { name = "example-sg" description = "Example security group" ingress { from_port = 8080 to_port = 8080 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
<<- EOF
と EOF
は、\n
を入れなくても複数行に弥文字列を渡せる、Terraformのヒアドキュメントです。
user_data
属性に初期スクリプトを書き込むことができます。
今回のスクリプトはbusybox
と呼ばれるツールでポート8080でWebサーバを立ち上げ、index.html
を配信することができます。
暗黙的依存
現在、EC2とセキュリティグループの間には変数を使用した参照が行われています。
# セキュリティグループの設定 vpc_security_group_ids = [aws_security_group.example.id]
このように、あるリソースから他のリソースへ参照を追加すると、暗黙的依存が設定されます。 Terraformはこれらの依存をパースし、そこから依存グラフを作成してリソースをどの順番で作成するべきかを決めます。
今回だとEC2でセキュリティグループの設定を行なっているため、先にセキュリティグループを作成してその後にEC2インスタンスを立てる必要があるのです。
この依存グラフは以下のコマンドで表示させることができます。
terraform graph
グラフはコマンドラインインターフェース上に出現しますが、dot
コマンドを使用することで画像として出力することも可能です。
terraform graph -type=plan | dot -Tpng >graph.png
https://developer.hashicorp.com/terraform/language
page:https://minegishirei.hatenablog.com/entry/2024/06/04/175213