TerraformでAWSインフラをコード管理する入門
TerraformでAWSのVPC・EC2・RDSを定義し、インフラをコードとして管理する基本的な手順を解説します。
TerraformはHashiCorpが開発したIaC(Infrastructure as Code)ツールです。AWSやGCPなどのクラウドリソースを .tf ファイルで宣言的に定義し、terraform apply でその状態に収束させます。手動でコンソールをポチポチするよりも、設定の再現性・変更履歴の管理・チームでのレビューが容易になります。
インストールと初期設定
1
2
3
4
5
| # macOS
brew install terraform
# バージョン確認
terraform version
|
AWSの認証情報は ~/.aws/credentials か環境変数で設定します。
1
2
3
| export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_DEFAULT_REGION=ap-northeast-1
|
ディレクトリ構成
infra/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
VPCの定義
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| # main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
# VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = {
Name = "${var.project}-vpc"
}
}
# パブリックサブネット
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.project}-public-${count.index}"
}
}
data "aws_availability_zones" "available" {}
# インターネットゲートウェイ
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
}
resource "aws_route_table_association" "public" {
count = 2
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
|
変数の定義
1
2
3
4
5
6
7
8
9
10
11
12
13
| # variables.tf
variable "aws_region" {
default = "ap-northeast-1"
}
variable "project" {
description = "プロジェクト名(リソースのタグに使用)"
type = string
}
variable "instance_type" {
default = "t3.micro"
}
|
1
2
3
| # terraform.tfvars
project = "myapp"
instance_type = "t3.small"
|
EC2インスタンスの定義
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| # セキュリティグループ
resource "aws_security_group" "web" {
name = "${var.project}-web-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
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"]
}
}
# 最新のAmazon Linux 2023 AMIを動的に取得
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.al2023.id
instance_type = var.instance_type
subnet_id = aws_subnet.public[0].id
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "${var.project}-web"
}
}
|
Outputsの定義
1
2
3
4
5
6
7
8
| # outputs.tf
output "web_public_ip" {
value = aws_instance.web.public_ip
}
output "vpc_id" {
value = aws_vpc.main.id
}
|
基本的なワークフロー
1
2
3
4
5
6
7
8
9
10
11
| # 初期化(プロバイダーのダウンロード)
terraform init
# 変更内容の確認(実際には何も変更しない)
terraform plan
# 適用
terraform apply
# 削除(注意:本番環境では使わない)
terraform destroy
|
terraform plan で変更内容を必ず確認してから apply するのが基本です。+ が新規作成、~ が変更、- が削除を意味します。
Stateファイルのリモート管理
デフォルトではStateファイルがローカルの terraform.tfstate に保存されますが、チーム開発ではS3とDynamoDBを使ってリモート管理します。
1
2
3
4
5
6
7
8
9
| terraform {
backend "s3" {
bucket = "myapp-terraform-state"
key = "infra/terraform.tfstate"
region = "ap-northeast-1"
dynamodb_table = "terraform-lock"
encrypt = true
}
}
|
DynamoDBによるロックにより、複数人が同時に apply して状態が壊れるのを防げます。
まとめ
| コマンド | 用途 |
|---|
terraform init | 初期化(プロバイダーのダウンロード) |
terraform plan | 変更内容のプレビュー |
terraform apply | インフラへの反映 |
terraform destroy | リソースの削除 |
terraform state list | 管理リソース一覧 |
Terraformを使うことでインフラの変更をGitでレビューでき、誰が何をいつ変更したかを追跡できるようになります。まずローカル環境の開発VPCから試してみるのがおすすめです。