なんとなくわかるインフラ構築 〜Terraform編
はじめに
Terraformの名前だけ知ってる人向けに、なんとなく分かるレベルでTerraformを説明していく。
今回書いたコードはこちら。
AWS IAMの認証情報の設定をして、READMEに記載されたコマンドを実行すれば本記事に記載された環境を構築することができる。
Terraformとは
HashiCorp社が提供する、インフラをコードで管理するためのツール。インフラをコードで管理することにより、効率よく且つ安全にインフラの管理をすることを目的としている。TerraformはAPIを介することで、AWS、Azure、GCPなどのクラウドプラットフォーム、GitHubやDockerなどのサービスの管理を行うことができる。
例えばAWSでインフラを構築する際、Terraformを使わない場合はAWSマネジメントコンソールにログインし、各サービスの画面まで移動して一つ一つのリソースを作成する必要がある。インフラを構築したあと、修正したい場合や作り直したい場合など、同様の手順で画面を移動してぽちぽちと操作を行う必要があるため、非常に手間がかかる上に、変更内容を記録しておかないと後々面倒になる。
Terraformを使ってAWSでインフラ構築する場合、設計した内容をコードに落とし込み、Terraformコマンドを時効するだけでAWS上にインフラが構築される。インフラを修正したい場合もコードを修正し、Terraformコマンドを実行するだけで差分がAWSインフラに反映される。
Terraformコマンドを実行して環境を全て消しさることもできるので、納得できる環境ができるまで作って壊してを繰り返すことができるため非常に便利。Terraformコマンドを実行してからAWSインフラに反映されるまで多少時間はかかるが、Dockerイメージを作るときと同じ感覚で進めることができるので良き。
Terraformでインフラをコード化する
なんとなくわかるインフラ構築 〜AWS編 で使用した下記の図の構成について、Terraformを用いてコード化していく。
プロバイダを指定する
まず初めに、Terraformでインフラを構築するプロバイダを設定する。
今回はインフラの構築先がAWSのため、AWSをプロバイダとして指定する。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.49.0"
}
}
}
この段階ではプロバイダ指定しているだけなので、実行しても何も作成はされない。
VPCとインターネットゲートウェイの作成
ネットワークの大枠となるVPCと、その入り口となるインターネットゲートウェイを作成する。
VPCの作成には aws_vpc
リソースを用い、CIDR( cidr_block
プロパティ)にIPアドレスを指定している。
インターネットゲートウェイの作成には aws_internet_gateway
リソースを用いる。このとき aws_internet_gateway
リソースブロック内の vpc_id
プロパティにはVPC( aws_vpc.this
)のIDを指定している。これにより、VPC( aws_vpc.this
)と紐づいたインターネットゲートウェイを作成することができる。
resource "aws_vpc" "this" {
cidr_block = "10.0.0.0/16"
}
resource "aws_internet_gateway" "this" {
vpc_id = aws_vpc.this.id
}
上述した resource "aws_vpc" "this"
の this
はTerraform上で作成したVPCリソースの管理をするための名前であり、実際にAWS上で作成されたリソースに使われる名前ではない。
余談だが、作成するリソースが一つしかない場合などは便宜上 this
と名前をつける方がいいとTerraform公式ドキュメントに記載されている( Terraform - Resource and data source arguments )ので、本記事でも this
としている。
なお aws_vpc
リソースに限った話ではないが、リソースブロック内のプロパティは必須のものと任意のものがあり、必須のものが入力されていない場合はTerraform実行時にエラーとなり、任意のものが入力されていない場合はそのプロパティのデフォルト値が使用される。
サブネットとルーティングの作成
VPCとインターネットゲートウェイを作成したことでネットワークの大枠ができたので、次は外部からのアクセスを許可するためのサブネットとルーティングを作成する。
サブネットの作成には aws_subnet
リソースを用い、 vpc_id
プロパティには先ほど作成したVPC( aws_vpc.this
)のID、サブネットを作成するアベイラビリティゾーン( availability_zone
プロパティ)には任意のアベイラビリティゾーン、サブネットのCIDR( cidr_block
プロパティ)にはVPC( aws_vpc.this
)で指定したCIDRの範囲内のCIDRを指定している。
サブネットに対してルーティングの設定を反映するためには、複数のリソースを用いる必要がある。
まずはルートテーブルの作成をするために aws_route_table
リソースを用い、 vpc_id
プロパティにVPC( aws_vpc.this
)のIDを指定する。
次にルートテーブルにルートの定義をするために aws_route
リソースを用い、VPC内部からの通信全て( 0.0.0.0/0
)をインターネットゲートウェイ( aws_internet_gateway.this
)経由で行わせるよう指定する。
最後に、サブネット( aws_subnet.this
)がサブネット内部からの通信をインターネットゲートウェイ( aws_internet_gateway.this
)経由で行うために aws_route_table_association
リソースを用い、サブネット( aws_subnet.this
)とルートテーブル( aws_route_table.this
)を関連づけている。
resource "aws_subnet" "this" {
vpc_id = aws_vpc.this.id
availability_zone = "ap-northeast-1a"
cidr_block = "10.0.128.0/24"
}
resource "aws_route_table" "this" {
vpc_id = aws_vpc.this.id
}
resource "aws_route" "this" {
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.this.id
route_table_id = aws_route_table.this.id
}
resource "aws_route_table_association" "this" {
route_table_id = aws_route_table.this.id
subnet_id = aws_subnet.this.id
}
EC2の作成
最後にEC2を作成し、外部インターネットからEC2の80番ポートにアクセス可能な状態にする。
このとき、EC2を作成するだけだと外部インターネットからアクセスができる状態にはならないので、先にセキュリティグループから作成し、通信の流れを制御する。
外部インターネットからEC2への80番ポートへのアクセスを可能にするために aws_security_group
リソースを用い、 ingress
ブロックには外部インターネットからEC2への通信を許可するための条件を指定し、 egress
ブロックにはEC2からアクセス元への返信を許可するための条件を指定する。ここでは外部インターネットからEC2への80番ポートへの通信を許可しており、EC2からアクセス元へレスポンスを返す際には全ての通信を許可するように指定している。
次にEC2を作成するために aws_instance
リソースを用いる。 ami
プロパティにはEC2で使用するAMI、 instance_type
プロパティには起動するEC2のインスタンスタイプ、 subnet_id
プロパティにはサブネット( aws_subnet.this
)のID、 private_ip
プロパティにはサブネットに割り当てたCIDRの範囲のIPアドレス、 security_groups
プロパティには作成したセキュリティグループ( aws_security_group.this
)のIDをそれぞれ指定する。
# EC2の設定
resource "aws_security_group" "this" {
vpc_id = aws_vpc.this.id
ingress {
from_port = 80
to_port = 80
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"]
}
}
resource "aws_instance" "this" {
ami = "ami-0bba69335379e17f8"
instance_type = "t2.micro"
subnet_id = aws_subnet.this.id
private_ip = "10.0.128.100"
associate_public_ip_address = true
security_groups = [aws_security_group.this.id]
}
ここまでコードを書いた後、Terraformコマンドを実行することで上図の構成でインフラが構築される。
なお、EC2に80番ポートでアクセス可能な状態にはしているが、EC2上でWebサーバが起動していなければアクセスできないので、EC2にログインするなりTerraform実行時にshellを操作してWebサーバを起動するなりする必要がある。今回はそこまではやらない。
おわりに
Terraformを用いてAWS上にインフラ構築する方法について説明した。
小規模であれば本記事のようにコードを一つのファイルにまとめるだけで十分だが、中規模・大規模になった場合にはモジュール化してテンプレートとして扱う方が良い。モジュール化の方法についてはまた次回以降に書いていく。
Discussion