#本記事の目的
Terraformを用いて、AWS上でよく見るシステムパターンを作成し、アウトプットとして記録する。
今回はインスタンスに接続するための最小構成を作成してみる。
#設計
###システム要件
インターネットからssh経由で接続可能な単一のサーバーを構築する。
#事前準備
###ソフトウェア要件
※1 今回はTerraform用のAWS CLIプロファイルを、tf-demo
という名前で作成し使用する。
※2 Terraform実施時に出力されるjsonデータ加工用のコマンド。
###EC2キーペア用の公開鍵/秘密鍵の作成
$ ssh-keygen -t rsa -f ~/.ssh/minimum_configuration.pem
#ファイル構成
$ tree
minimum_configuration/
├── compute.tf
├── config.tf
├── firewall.tf
├── network.tf
├── output.tf
├── variable.tf
└── src
└── user_data.sh
#ファイル内容
###computeファイル
AMI、EC2インスタンス、EC2キーペアの設定を定義する。
# ====================
#
# AMI
#
# ====================
#
data "aws_ami" "test_ami" {
most_recent = true
owners = ["amazon"]
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "block-device-mapping.volume-type"
values = ["gp2"]
}
filter {
name = "state"
values = ["available"]
}
}
# ====================
#
# EC2 Instance
#
# ====================
resource "aws_instance" "example_instance" {
ami = data.aws_ami.example_ami.image_id
instance_type = var.instance_type
subnet_id = aws_subnet.example_subnet.id
associate_public_ip_address = true
vpc_security_group_ids = [aws_security_group.example_sg.id]
root_block_device {
volume_type = var.volume_type
volume_size = var.volume_size
delete_on_termination = true
}
key_name = aws_key_pair.example_key.id
user_data = file(var.user_data_file)
tags = {
Name = "${var.project}-${var.environment}-ec2"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Key Pair
#
# ====================
resource "aws_key_pair" "example_key" {
key_name = var.key_name
public_key = file(var.public_key_file)
tags = {
Name = "${var.project}-${var.environment}-keypair"
Project = var.project
Env = var.environment
}
}
###firewallファイル
EC2用セキュリティグループの設定を定義する。
# ====================
#
# Security Group
#
# ====================
resource "aws_security_group" "example_sg" {
name = "example_sg"
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-sg"
Project = var.project
Env = var.environment
}
}
# インバウンドルール(ssh接続用)
resource "aws_security_group_rule" "in_ssh" {
security_group_id = aws_security_group.example_sg.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
protocol = "tcp"
}
# インバウンドルール(ping疎通確認用)
resource "aws_security_group_rule" "in_icmp" {
security_group_id = aws_security_group.example_sg.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = -1
to_port = -1
protocol = "icmp"
}
# アウトバウンドルール(全開放)
resource "aws_security_group_rule" "out_all" {
security_group_id = aws_security_group.example_sg.id
type = "egress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
protocol = "-1"
}
###networkファイル
VPC/サブネット/インターネットゲートウェイ/ルーティングの設定を定義する。
# ====================
#
# VPC
#
# ====================
resource "aws_vpc" "example_vpc" {
cidr_block = var.vpc_cidr_block
enable_dns_support = true # DNS解決有効化
enable_dns_hostnames = true # DNSホスト名有効化
tags = {
Name = "${var.project}-${var.environment}-vpc"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Subnet
#
# ====================
resource "aws_subnet" "example_subnet" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = var.subnet_cidr_block
map_public_ip_on_launch = true #インスタンス起動時におけるパブリックIPアドレスの自動割り当ての有効化
availability_zone = var.availability_zone
tags = {
Name = "${var.project}-${var.environment}-subnet"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Internet Gateway
#
# ====================
resource "aws_internet_gateway" "example_igw" {
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-igw"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Route Table
#
# ====================
resource "aws_route_table" "example_rt" {
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-rt"
Project = var.project
Env = var.environment
}
}
resource "aws_route" "example_route" {
route_table_id = aws_route_table.example_rt.id
gateway_id = aws_internet_gateway.example_igw.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "example_subrt" {
subnet_id = aws_subnet.example_subnet.id
route_table_id = aws_route_table.example_rt.id
}
###variableファイル
Terraform実施時のグローバル変数を定義する。必要に応じてterraform.tfvarsファイルを作成する。
# ====================
#
# Variables
#
# ====================
variable "aws_region" {
default = "ap-northeast-1"
}
variable "project" {
default = "minimum"
}
variable "environment" {
default = "test"
}
# IAM #
variable "aws_profile" {
default = "tf-demo" # AWSプロファイル
}
# EC2 #
variable "instance_type" {
default = "t2.micro"
}
variable "volume_type" {
default = "gp2"
}
variable "volume_size" {
default = "8"
}
variable "user_data_file" {
default = "./src/user_data.sh"
}
variable "key_name" {
default = "minimum"
}
variable "public_key_file" {
default = "~/.ssh/minimum.pem.pub"
}
# VPC #
variable "vpc_cidr_block" {
default = "10.0.0.0/16"
}
variable "subnet_cidr_block" {
default = "10.0.1.0/24"
}
variable "availability_zone" {
default = "ap-northeast-1a"
}
###outputファイル
terraform apply
コマンド実行時の出力内容を定義する。
# ====================
#
# Output
#
# ====================
output "public_ip" {
value = aws_instance.example_instance.public_ip
description = "EC2インスタンスのパプリックIP"
}
###configファイル
Terraformのプロバイダー及びバージョン設定を定義する。
# ====================
#
# Terraform
#
# ====================
terraform {
required_version = ">=1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
# ====================
#
# Provider
#
# ====================
provider "aws" {
profile = var.aws_profile
region = var.aws_region
}
###user_dataファイル
EC2用ユーザデータの内容を記述する。
#!/bin/bash
yum update -y
#リソース作成
###Terraform実施
$ terraform init
$ terraform plan
$ terraform apply
###ping疎通確認
$ ping -c4 `terraform output -json | jq -r .public_ip.value`
###EC2インスタンスにssh接続
$ ssh -i ~/.ssh/minimum_configuration.pem ec2-user@`terraform output -json | jq -r .public_ip.value`
#感想
Terraformは作成もさる事ながら、削除するにも非常に便利なツールであり、作成と削除を簡単に繰り返せる事が利点であるように感じる。
次回は冗長性を意識したシステム構成を作ってみたい。
#Githubリポジトリ
https://github.com/kuraboshi/iac/tree/main/terraform/minimum_configuration
#参考文献