terraformを使ってみる。

今までAWS案件しか関わったことがなく、AWSだけでも需要はそこそこあるものの、フリーランスとして食べていくには守備範囲は広いほうが良い。
前職の会社ではAWSを主軸にしてシステム構築していたので、terraformについては、AWS CLIやCloudFormation直接叩いたほうが早いので導入にも懐疑的であった。
しかし、フリーランスに転身したのでより柔軟なツールに対応しているほうが仕事にありつけそうなため、ここらで基本くらいは齧っておきたいと思った。

契約先の検証環境が使えることもあるが、たまに意味不明な使い方していて検証環境に触りたくないときもあるので、往々にして自前のアカウントで検証することがある。
お金はかけたくないので、IaaCどかんと基礎環境立てて潰すコードが欲しかったので、VPCとEC2の簡単な基本構成作成を目標とする。


構成

構成イメージ

なにかとAZは入用なのでこのベース構成を目指してコードを作成しよう。

環境構築

①インストール
https://releases.hashicorp.com/terraform/1.6.6/terraform_1.6.6_windows_386.zip よりzipファイルを落とす。
任意のパスに展開しパスを通す。
"terraform --version"コマンドが通ればひとまずOK

PS C:\Users\itsuki> $ENV:Path+=";C:\Program Files\terraform"
PS C:\Users\itsuki> terraform --version
Terraform v1.6.6
on windows_386

tfファイルを用意。
適当なディレクトリにmain.tfファイルとvariable.tfファイル等を準備する。

main.tf

プロバイダ、バージョン、tfstateファイルの管理方法などを記載する。

provider "aws"{
    access_key = "${var.access_key}"
    secret_key = "${var.secret_key}"
    region = "${var.region}"
}

variable.tf

変数を定義する。

variable "system_name" {
    type=string
    default="test"
    description="My System Name"
}
variable "secret_key" {
    default="<YOUR_SECRET_KEY>"
}
variable "access_key"{
    default="<YOUR_ACCESS_KEY>"
}
variable "region"{
    default="ap-northeast-1"
}
variable "az1"{
    default="ap-northeast-1a"
}
variable "az2"{
    default="ap-northeast-1c"
}
variable "vpc_cidr"{
    default="192.168.0.0/22"
}
variable "subnet_public1_cidr"{
    default="192.168.0.0/24"
}
variable "subnet_public2_cidr"{
    default="192.168.1.0/24"
}
variable "subnet_private1_cidr"{
    default="192.168.2.0/24"
}
variable "subnet_private2_cidr"{
    default="192.168.3.0/24"
}
variable "key_name"{
    default="test-key"
}
variable "ec2_instance_type"{
    default="t2.micro"
}
variable "myip" {
  default = "<YOUR_GLOBAL_IP>"
}

vpc.tf

VPCなどネットワークリソースをまとめて記載した。

# ---------------------------
# VPC
# ---------------------------
resource "aws_vpc" "vpc" {
    cidr_block="${var.vpc_cidr}"
    instance_tenancy="default"
    enable_dns_support="true"
    enable_dns_hostnames="true"
    tags={
        Name="${var.system_name}-${terraform.workspace}-vpc"
    }
}
# ---------------------------
# InternetGateway
# ---------------------------
resource "aws_internet_gateway" "igw" {
    vpc_id=aws_vpc.vpc.id
    tags={
        Name="${var.system_name}-${terraform.workspace}-igw"
    }
}
# ---------------------------
# Subnet
# ---------------------------
resource "aws_subnet" "public_subnet1" {
    vpc_id=aws_vpc.vpc.id
    cidr_block="${var.subnet_public1_cidr}"
    availability_zone="${var.az1}"
    tags={
        Name="${var.system_name}-${terraform.workspace}-public-subnet1"
    }
}

resource "aws_subnet" "public_subnet2" {
    vpc_id=aws_vpc.vpc.id
    cidr_block="${var.subnet_public2_cidr}"
    availability_zone="${var.az2}"
    tags={
        Name="${var.system_name}-${terraform.workspace}-public-subnet2"
    }
}

resource "aws_subnet" "private_subnet1" {
    vpc_id=aws_vpc.vpc.id
    cidr_block="${var.subnet_private1_cidr}"
    availability_zone="${var.az1}"
    tags={
        Name="${var.system_name}-${terraform.workspace}-private-subnet1"
    }
}

resource "aws_subnet" "private_subnet2" {
    vpc_id=aws_vpc.vpc.id
    cidr_block="${var.subnet_private2_cidr}"
    availability_zone="${var.az2}"
    tags={
        Name="${var.system_name}-${terraform.workspace}-private-subnet2"
    }
}
# ---------------------------
# RouteTable
# ---------------------------
resource "aws_route_table" "public_rt1" {
    vpc_id=aws_vpc.vpc.id
    route {
        cidr_block="0.0.0.0/0"
        gateway_id=aws_internet_gateway.igw.id
    }
    tags={
        Name="${var.system_name}-${terraform.workspace}-rt1"
    }
}

resource "aws_route_table" "private_rt1" {
    vpc_id=aws_vpc.vpc.id
    route {
        cidr_block="0.0.0.0/0"
        gateway_id=aws_nat_gateway.ngw1.id
    }
    tags={
        Name="${var.system_name}-${terraform.workspace}-rt1"
    }
}

resource "aws_route_table" "private_rt2" {
    vpc_id=aws_vpc.vpc.id
    route {
        cidr_block="0.0.0.0/0"
        gateway_id=aws_nat_gateway.ngw2.id
    }
    tags={
        Name="${var.system_name}-${terraform.workspace}-rt2"
    }
}

resource "aws_route_table_association" "public-rta1"{
    subnet_id=aws_subnet.public_subnet1.id
    route_table_id=aws_route_table.public_rt1.id
}

resource "aws_route_table_association" "public-rta2"{
    subnet_id=aws_subnet.public_subnet2.id
    route_table_id=aws_route_table.public_rt1.id
}

resource "aws_route_table_association" "private-rta1"{
    subnet_id=aws_subnet.private_subnet1.id
    route_table_id=aws_route_table.private_rt1.id
}

resource "aws_route_table_association" "private-rta2"{
    subnet_id=aws_subnet.private_subnet2.id
    route_table_id=aws_route_table.private_rt2.id
}
# ---------------------------
# NATGateway
# ---------------------------
resource "aws_eip" "eip1"{
    vpc="true"
    tags={
        Name="${var.system_name}-${terraform.workspace}-eip1"
    }
}

resource "aws_eip" "eip2"{
    vpc="true"
    tags={
        Name="${var.system_name}-${terraform.workspace}-eip2"
    }
}

resource "aws_nat_gateway" "ngw1" {
    allocation_id=aws_eip.eip1.id
    subnet_id=aws_subnet.public_subnet1.id
    tags={
        Name="${var.system_name}-${terraform.workspace}-ngw1"
    }
}

resource "aws_nat_gateway" "ngw2" {
    allocation_id=aws_eip.eip2.id
    subnet_id=aws_subnet.public_subnet2.id
    tags={
        Name="${var.system_name}-${terraform.workspace}-ngw2"
    }
}

ec2.tf

SGの作成と、パブリックサブネットにEC2を構築する。
本当はグローバルIP取りたかったのだけど、うまくいかなかったので、variable.tfに直書きした。
何やらごちゃごちゃすると実行PCのグローバルIP取ってSGに設定とかキーペア作ってダウンロードとかできるらしい。。。もう少し勉強が必要。


# ---------------------------
# Security Group
# ---------------------------
resource "aws_security_group" "test_ec2_sg"{
    name="test-ec2-sg"
    description="ssh from my ip"
    vpc_id=aws_vpc.vpc.id
    tags={
        Name="test-ec2-sg"
    }
    ingress{
        from_port=22
        to_port=22
        protocol="tcp"
        cidr_blocks=["${var.myip}"]
    }
    egress{
        from_port=0
        to_port=0
        protocol="-1"
        cidr_blocks=["0.0.0.0/0"]
    }
}
# ---------------------------
# EC2
# ---------------------------
# Amazon Linux 2 の最新版AMIを取得
data "aws_ssm_parameter" "amzn2_latest_ami" {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}
 resource "aws_instance" "test-ec2"{
    ami=data.aws_ssm_parameter.amzn2_latest_ami.value
    instance_type="${var.ec2_instance_type}"
    availability_zone="${var.az1}"
    vpc_security_group_ids=[aws_security_group.test_ec2_sg.id]
    subnet_id=aws_subnet.public_subnet1.id
    associate_public_ip_address="true"
    key_name="${var.key_name}"
    tags={
        Name="${var.system_name}-${terraform.workspace}-ec2"
    }
 }

output.tf

# 作成したEC2のパブリックIPアドレスを出力
output "ec2_global_ips" {
  value = "${aws_instance.test-ec2.*.public_ip}"
}

デプロイ

パワーシェルでデプロイしていく。

terraform validateで構文確認
terraform initでワークスペース初期化
terraform planで実行計画作成
terraform applyでリソース作成
terraform showでリソース確認
terraform plan -destroyで削除リソースの確認
terraform destroyで環境削除
となります。
とくにエラーが出なければ、コマンド一発で環境構築が完了。
いいですね~。IaC最高!
これでサクッといつでも検証環境立てれちゃうぜ。

手順の紹介は以上です。
これからももうちょいIaCやらなにやら環境構築勉強していきたいな~と思っている。気が向いた時やら、今の仕事関係の技術の整理でまた更新予定。
ありがとうございました。

この記事が気に入ったらサポートをしてみませんか?