はじめに
Terraformを使ったAWS環境構築をやることになったため、
最低限実行環境や使用するファイル等を抑えておくために
とりあえず触ってみたという記事になります。
Terraformに関する私の知識としてIaCツールでサーバや
各社のパブリッククラウドのインフラ環境をコードで
自動構築できるツールだという認識はあるものの実際に使用したことはありません。
ドキュメント
公式サイトのAWS向けチュートリアルをなぞっていきます。
実行環境構築
環境
接続元端末
- OS:Windows 11
- SSHクライアント:TeraTerm 5.0
Terraform実行用サーバ
- EC2インスタンス(Linux):AmazonLinux2023
AMI:ami-0dfa284c9d7b2adad
インスタンスサイズ:t2.micro
AWS CLI:2.14.5
(Terraformで構築する環境とは別VPC上のパブリックサブネット上に作成済み)
Terraformインストール
# yum-utilsの導入
sudo yum install -y yum-utils
# リポジトリ追加
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
# Terraformインストール
sudo yum -y install terraform
# 確認
terraform -version
[ec2-user@ip-192-168-0-5 ~]$ terraform -version
Terraform v1.6.6
on linux_amd64
AWS環境構築のためTerraformの他AWS CLIが必要です。(今回はAL3利用のためデフォルトで導入済み)
AWS CLIの実行ユーザーには権限周りで躓くのを防ぐため、とりあえずPowerUserAccessを付与しています。
ディレクトリ・ファイル準備
# チュートリアル用ディレクトリ作成
mkdir learn-terraform-aws-instance
cd learn-terraform-aws-instance
# チュートリアル用ファイル作成
touch main.tf
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ pwd
/home/ec2-user/learn-terraform-aws-instance
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ ll
total 0
-rw-r--r--. 1 ec2-user ec2-user 0 Dec 23 05:08 main.tf
作成したmain.tf
に公式ドキュメント記載の内容を貼り付けます。
ドキュメント内のTipsに下記記載があるのでリージョン指定を東京(ap-northeast-1)、
AMI IDを東京リージョンのAL3のAMI IDに変更しておきます。
The AMI ID used in this configuration is specific
to the us-west-2 region. If you would like to use a different region,
see the Troubleshooting section for guidance.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_instance" "app_server" {
ami = "ami-0dfa284c9d7b2adad"
instance_type = "t2.micro"
tags = {
Name = "ExampleAppServerInstance"
}
}
Terraform作業ディレクトリ初期化
Terraform作業ディレクトリの準備
リソースファイルが配置されたディレクトリをTerraformに読み込ませます。
terraform init
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ pwd
/home/ec2-user/learn-terraform-aws-instance
# terraform initの実行
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 4.16"...
- Installing hashicorp/aws v4.67.0...
- Installed hashicorp/aws v4.67.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
(省略)
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$
Terraform作業ディレクトリの初期化が完了するとterraform init
を実行したディレクトリ配下に
.terraform
ディレクトリと.terraform.lock.hcl
ファイルが生成されます。
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ ls -al
total 8
drwxr-xr-x. 3 ec2-user ec2-user 66 Dec 23 05:28 .
drwx------. 6 ec2-user ec2-user 158 Dec 23 05:19 ..
drwxr-xr-x. 3 ec2-user ec2-user 23 Dec 23 05:28 .terraform
-rw-r--r--. 1 ec2-user ec2-user 1407 Dec 23 05:28 .terraform.lock.hcl
-rw-r--r--. 1 ec2-user ec2-user 367 Dec 23 05:19 main.tf
チェック
記載したファイルのフォーマットと構文チェックを実施します。
# フォーマットチェック
terraform fmt
# 構文チェック
terraform validate
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ terraform fmt
main.tf
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ terraform validate
Success! The configuration is valid.
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$
Terraformの実行
Terraformの実行(1回目)
実際に記載したコードをもとに環境を作ってもらいます。
# Terraformの実行
terraform apply
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ 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:
(変更内容が記載される)
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
最終確認としてEnter a value:
でyse/noを入力する必要があります。
aws_instance.app_server: Creating...
Error: creating EC2 Instance: VPCIdNotSpecified: No default VPC for this user. GroupName is only supported for EC2-Classic and default VPC.
status code: 400, request id: 7f3344e0-4f94-4326-a6b4-e23188d58076
with aws_instance.app_server,
on main.tf line 16, in resource "aws_instance" "app_server":
16: resource "aws_instance" "app_server" {
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$
main.tf
作成した段階で「これVPC指定してないけどいけるの?」と思っていましたが、案の定エラーになりました。
公式ドキュメントでは、オレゴンリージョン(us-west-2)にデフォルトVPC一式が存在することが前提となっているため、リソースとしてはEC2だけ作成すれば自動でオレゴンのデフォルトVPCに配置される流れでした。
オレゴンのデフォルトVPC以外の既存VPCにデプロイする場合は
main.tf
内にSGとサブネットのIDを入れれば良いという記載があるのでそれに従います。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_instance" "app_server" {
ami = "ami-0dfa284c9d7b2adad"
instance_type = "t2.micro"
vpc_security_group_ids = ["<SG ID>"]
subnet_id = "<subnet ID>"
tags = {
Name = "ExampleAppServerInstance"
}
}
Terraformの実行(2回目)
修正完了後、再度構文チェックと実行します。
# 変更後の構文チェック
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ terraform validate
Success! The configuration is valid.
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$
# 実行
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ terraform apply
(省略)
aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Still creating... [30s elapsed]
aws_instance.app_server: Creation complete after 32s [id=i-xxxxxxxxxxxxxxxx]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$
Apply complete!と表示され、マネジメントコンソール上からも指定したサブネット上に
EC2インスタンスが起動していることが確認できました。
Terraformで構築したリソースの削除
Terraformで作成したEC2インスタンスを削除します。
terraform destroy
[ec2-user@ip-192-168-0-5 learn-terraform-aws-instance]$ terraform destroy
aws_instance.app_server: Refreshing state... [id=i-xxxxxx]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
(変更内容が記載される)
Destroy complete! Resources: 1 destroyed.
正常に削除されました。
変数の利用などまだ公式チュートリアルの内容はまだありますが、
Terraformでの構築の流れを理解することができました。
VPC周りを含めた環境の構築
公式チュートリアルの中では既存VPC上にEC2インスタンスをデプロイしましたが、
VPCも含めたEC2インスタンスの新規構築をやってみます。
構成
以下のような形でリソース種別にファイル分割します。
TF-WORK
|-- ec2.tf
|-- main.tf
`-- network.tf
完成図としては以下の通り
SGは作成せずVPCデフォルトのものをアタッチさせます。
providerのリファレンスを参考に各種パラメータを記載していきます。
main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "ap-northeast-1"
}
network.tf
# ======VPC======
resource "aws_vpc" "tf-vpc-01" {
cidr_block = "192.168.0.0/16"
instance_tenancy = "default"
enable_dns_hostnames = "true"
tags = {
Name = "TF-VPC-01"
Env = "TF-WORK"
}
}
# ======Subnet======
resource "aws_subnet""tf-vpc-01-pub-01-a" {
vpc_id = aws_vpc.tf-vpc-01.id
cidr_block = "192.168.0.0/24"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = "true"
tags = {
Name = "TF-VPC-01-Pub-01-a"
Env = "TF-WORK"
}
}
resource "aws_subnet" "tf-vpc-01-pri-01-a" {
vpc_id = aws_vpc.tf-vpc-01.id
cidr_block = "192.168.1.0/24"
availability_zone = "ap-northeast-1a"
tags = {
Name = "TF-VPC-01-Pri-01-a"
Env = "TF-WORK"
}
}
# ======IGW======
resource "aws_internet_gateway" "tf-vpc-01-igw-01" {
vpc_id = aws_vpc.tf-vpc-01.id
tags = {
Name = "TF-VPC-01-IGW-01"
Env = "TF-WORK"
}
}
# ======RouteTable======
resource "aws_route_table" "tf-vpc-01-rtb-pub-01" {
vpc_id = aws_vpc.tf-vpc-01.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.tf-vpc-01-igw-01.id
}
tags = {
Name = "TF-VPC-01-RTB-Pub-01"
Env = "TF-WORK"
}
}
resource "aws_route_table" "tf-vpc-01-rtb-pri-01" {
vpc_id = aws_vpc.tf-vpc-01.id
tags = {
Name = "TF-VPC-01-RTB-Pri-01"
Env = "TF-WORK"
}
}
resource "aws_route_table_association" "tf-vpc-01-rtb-at-pub" {
subnet_id = aws_subnet.tf-vpc-01-pub-01-a.id
route_table_id = aws_route_table.tf-vpc-01-rtb-pub-01.id
}
resource "aws_route_table_association" "tf-vpc-01-rtb-at-pri" {
subnet_id = aws_subnet.tf-vpc-01-pri-01-a.id
route_table_id = aws_route_table.tf-vpc-01-rtb-pri-01.id
}
ec2.tf
resource "aws_instance" "tf-ec2-01" {
ami = "ami-0dfa284c9d7b2adad"
instance_type = "t2.micro"
subnet_id = aws_subnet.tf-vpc-01-pub-01-a.id
key_name = "TF-AWS-KEY"
tags = {
Name = "TF-EC2-01"
Env = "TF-WORK"
}
}
実行
# 構文チェック
[ec2-user@ip-192-168-0-5 TF-WORK]$ terraform validate
Success! The configuration is valid.
[ec2-user@ip-192-168-0-5 TF-WORK]$
# 実行プラン確認
[ec2-user@ip-192-168-0-5 TF-WORK]$terraform plan
(省略)
Plan: 9 to add, 0 to change, 0 to destroy.
[ec2-user@ip-192-168-0-5 TF-WORK]$
# 適用
[ec2-user@ip-192-168-0-5 TF-WORK]$terraform apply
(省略)
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
[ec2-user@ip-192-168-0-5 TF-WORK]$
問題なくデプロイされたことが確認できました。
まとめ
Terraform知識ゼロ状態でTerraformを使ったAWS環境構築を試してみました。
実行環境の構築も簡単にでき、Terraformファイルの記述自体や指定するパラメータ等も
個人的にはCloudFormationより感覚的に書けると思いました。
リソースの依存関係も自動で分析されて良い感じに作ってくれるのが素晴らしい。
変数のマッピング等の機能もいろいろあるようなのでまた触って理解していきます。