0
0

More than 1 year has passed since last update.

Terraformで作るAWSシステムパターン① インスタンス最小構成

Last updated at Posted at 2021-08-21

本記事の目的

Terraformを用いて、AWS上でよく見るシステムパターンを作成し、アウトプットとして記録する。
今回はインスタンスに接続するための最小構成を作成してみる。

設計

システム要件

インターネットからssh経由で接続可能な単一のサーバーを構築する。

構成図

minimum_configuration.png

事前準備

ソフトウェア要件

※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キーペアの設定を定義する。

compute.tf
# ====================
#
# 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用セキュリティグループの設定を定義する。

firewall.tf
# ====================
#
# 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/サブネット/インターネットゲートウェイ/ルーティングの設定を定義する。

network.tf
# ====================
#
# 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ファイルを作成する。

variable.tf
# ====================
#
# 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.tf
# ====================
#
# Output
#
# ====================

output "public_ip" {
  value       = aws_instance.example_instance.public_ip
  description = "EC2インスタンスのパプリックIP"
}

configファイル

Terraformのプロバイダー及びバージョン設定を定義する。

config.tf
# ====================
#
# 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用ユーザデータの内容を記述する。

user_data.sh
#!/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リポジトリ

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0