🌏

AWS TerraformでVPCを作ろう

2024/05/20に公開

概要

今回は、Terraformを使用してAWS上にVPCとEC2インスタンスを作成します。

Terraformの実行環境はAWS Cloud9で作成します。

また、おまけにはなりますがTerraformで作成したインフラコードをGitHubで管理できるようにもしたいと思います。

本記事は以下のような方を対象としています。
・Terraformを始めてみたい
・AWS Cloud9とGitHubを連携させたい
・GitHubを初めて使う

前提環境
・AWSアカウントの作成
・Admin権限を持ったIAMユーザー
・Amazon S3のバケット作成
・(GitHubのアカウント所持)

構成図

今回作成するVPCはこちら

*defaultVPC内のリソースを一部省略しています。

構築

AWS Cloud9でTerraformの環境作り

AWS Cloud9の環境作成

はじめにTerraformの環境を作っていきます。

Terraformはローカル環境でも実行できますが、今回は個人環境に左右されないクラウド上に準備していきます。

AWS Cloud9の[環境]から[環境を作成]をクリック

任意の名前を設定したら他はデフォルトのままで[作成]をクリック

設定を変えてなければdefaultVPCのパブリックサブネットに作成されます。
もしこの設定を変更している場合はVPC設定の項目から任意のVPCに配置してください。

また、今回はt2.microインスタンスを使用しますが、無料枠外の場合はt3.microの方が利用料金を抑えられます。

作成が完了したら環境の[開く]からCloud9にアクセスしましょう。

ターミナルの画面が開くのでコマンドを打っていきます。
*bash -"p-IPアドレス... と表記されるタブです。

Terraformの環境作り

まずは、Terraformのバージョン管理に使うtfenvをインストールします。

git clone https://github.com/tfutils/tfenv.git ~/.tfenv

tfenvをインストールしたパスを環境変数に追加

sudo ln -s ~/.tfenv/bin/* /usr/local/bin

これによりtfenvコマンドが使えるようになります。

次はいよいよTerraformのインストールです。

まずはインストール可能なTerraformのバージョンを確認します。

tfenv list-remote

すると、バージョンがずらりと表示されます。

x.x.xの後ろに-alpha20240131のような表記がなく数字が一番大きいのが最新バージョンです。

$ tfenv list-remote
1.9.0-alpha20240501
1.9.0-alpha20240404
1.8.3
1.8.2
1.8.1
1.8.0
1.8.0-rc2
1.8.0-rc1
1.8.0-beta1

当時では1.8.3が最新でしたので本記事では1.8.3のTerraformを使用していきます。

今確認したバージョンのterraformをインストールします。

tfenv install 1.8.3

tfenv listコマンドでインストールできたか確認しましょう。

$ tfenv list
* 1.8.3 (set by /home/ec2-user/.tfenv/version)

おそらく、インストール直後は上記のような「*」マークがないかと思います。

これは、現在使用中のバージョンを表すものでインストールしただけではバージョンが切り替わりません。

なので、利用するバージョンをtfenv useコマンドで指定します。

tfenv use 1.8.3

コマンド実行後に「*」マークがついているか確認してください。

*Terraformの利用バージョンはterraform -vコマンドでも確認できます。

これでTerraformのインストール作業は完了です。

ここからはTerraformでAWS環境を作成するための下準備をしていきます。

まずは、Terraformの各ファイルを格納するディレクトリを作成します。

#ディレクトリ名はお好みで
mkdir terraform
cd terraform

Terraformではtfファイルにコードを記述します。

今回はmain.tfと環境変数を定義するvariables.tfの2つで進めますが、

本番運用では以下のような考えのもとファイルを分離しましょう。

https://dev.classmethod.jp/articles/directory-layout-bestpractice-in-terraform/

tfファイルの作成

#先ほど作成したディレクトリから実行します
touch main.tf
touch variable.tf

コマンドを実行するとCloud9のページ左側に2つのファイルタブが生成されているのが確認できるはずです。

ここからファイルにコードを記述していきますが、ファイル名をダブルクリックして新しいタブから記述してもvimコマンドでエディタを開いて記述する方法でもどちらでもOKです。

main.tf
#terraformの設定だよ
#使用するクラウドやバージョンを指定
terraform {
    required_version = "~> 1.4"
    
    required_providers {
        aws = {
            source = "hashicorp/aws"
            version = "~> 5.01"
        }
    }
    backend s3 {
    #terraformの詳細状態を保存するtfstateファイルの場所を定義 
        bucket = "作成したS3バケット名(ARN名じゃないよ!)"
        region = "ap-northeast-1"
        key    = "任意のファイル名.tfstate"
    }
}

#AWSプロバイダーの設定だよ
provider aws {
    region = "ap-northeast-1"
}

環境変数を定義するvariable.tfファイルでは様々な変数を定義できますが、

今回はNameタグに使用するデフォルトの名前とAZを定義してみましょう。

variable.tf
variable "tagname" {
    type = string
    default = "handsonterraform"
}
variable "az" {
    default = "ap-northeast-1a"
}

記入が完了したらterraform initコマンドでディレクトリの初期化をします。
*編集したファイルの保存は忘れずに

このコマンドではTerraformの実行に必要なプラグインをインターネットから取得します。

terraform init
~
~
~
#途中こんな感じの表示が出れば成功
Terraform has been successfully initialized!
$

TerraformでVPC作成

ここからはAWS上にVPC、EC2インスタンスを作成していきます。

まずはVPCから

main.tf
#VPCの設定だよ
resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/24"
  enable_dns_support = true
  enable_dns_hostnames = true
  tags = {
    Name = "${var.name_tag}_vpc"
  }
}

#subnet作成
resource "aws_subnet" "public_subnet_1"{
    vpc_id            = aws_vpc.vpc.id
    cidr_block        = "10.0.0.0/26"
    availability_zone = "${var.az}"
    
    tags = {
        Name = "${var.name_tag}_public_subnet"
    }
}

resource "aws_subnet" "private_subnet_1"{
    vpc_id            = aws_vpc.vpc.id
    cidr_block        = "10.0.0.128/26"
    availability_zone = "${var.az}"
    
    tags = {
        Name = "${var.name_tag}_private_subnet"
    } 
}

#igwの設定だよ
resource "aws_internet_gateway" "tf_igw" {
  vpc_id = aws_vpc.vpc.id
  tags = {
    Name = "${var.name_tag}_igw"
  }
}

#route table作成
resource "aws_route_table" "tf_rt_1" {
  vpc_id = aws_vpc.vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.tf_igw.id
  }
  tags = {
    Name = "${var.name_tag}_public_rt"
  }
}

resource "aws_route_table" "tf_rt_2" {
  vpc_id = aws_vpc.vpc.id
  route {
    cidr_block = "10.0.0.0/24"
    gateway_id = "local"
  }
  tags = {
    Name = "${var.name_tag}_private_rt"
  }
}

#Subnetにルートテーブルを関連付ける
resource "aws_route_table_association" "public_route_associate" {
  subnet_id = aws_subnet.public_subnet_1.id
  route_table_id = aws_route_table.tf_rt_1.id
}

resource "aws_route_table_association" "private_route_associate" {
  subnet_id = aws_subnet.private_subnet_1.id
  route_table_id = aws_route_table.tf_rt_2.id
}

#EC2インスタンスにSSH接続するためのセキュリティグループ作成
resource "aws_security_group" "terraform_sg_ec2" {
  name = "tf_sg_ec2"
  vpc_id = aws_vpc.vpc.id
  tags = {
    Name = "${var.name_tag}-sg"
  }
  
  #インバウンドルール
  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"]
  }
}

これでVPC、サブネット2つ、ルートテーブル2つ、IGW、EC2用のSGが作れます。

他リソースの書式はTerraformの公式サイトから確認できます。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

次はEC2インスタンスです。

main.tf
#Amazon Linux 2023の最新AMI IDを取得
data "aws_ssm_parameter" "amazonlinux_2023" {
    name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64"
}

#EC2を作成
resource "aws_instance" "amazon_ec2" {
    ami = data.aws_ssm_parameter.amazonlinux_2023.value
    instance_type = "t2.micro"
    availability_zone = "${var.az}"
    subnet_id = aws_subnet.public_subnet_1.id
    vpc_security_group_ids =[aws_security_group.terraform_sg_ec2.id]
    associate_public_ip_address = "true"
    tags = {
        Name = "${var.name_tag}-ec2"
    }
    user_data = <<-EOF
    #!/bin/bash
    yum install -y httpd
    systemctl start httpd.service
    EOF
}

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

tfファイルへの記述が完了したら必ず変更を保存してください。

そしたら作成tfファイルがあるディレクトリ上でterraform planを実行

コードをTerraformがテストして実行後にどんなリソースが作成されるか教えてくれます。

記述に誤りがある場合はErrorで教えてくれます。

Errorがなければterraform applyコマンドでリソースを作成しましょう。

「Enter a Value:」と表示されたら「yes」と入力してください。

今回はEC2インスタンスを作るので数十秒かかりますが、「Apply Complete……」と表示されれば無事デプロイは成功です!

EC2インスタンスのIPアドレスにブラウザでアクセスして「It works!」と表示されればユーザーデータで指定したApacheが正常に動作しています。

以上でCloud9とTerraformを使用したVPC、EC2の構築手順は完了です。

GitHubに保存する。

今回作ったインフラコードをGitHubにプッシュ(アップロード)する手順をまとめておきます。

*参考に記載している記事の内容にほんの少し補足した程度の内容です。

公開鍵の作成(Cloud9)

Cloud9上でGitHubとやり取りする際の公開鍵を準備します。

# ssh鍵を管理するsshディレクトリへ移動
$ cd ~/.ssh

#公開鍵の生成
$ssh-keygen
#鍵の設定について聞かれますが今回は全てEnter押下で問題ないです。

#公開鍵の表示
$ cat ~/.ssh/id_rsa.pub
#表示された鍵をコピーしてください

生成した鍵の登録(GitHub)

GitHubにログインした所からです。

右上のプロフィールアイコンをクリック
→Setting
→SSH and GPG keys(左側ペイン)
→SSH Keysの「New SSH Keys」をクリック
→Add new SSH key画面に行くので以下の内容で登録
・Title:任意の文字列
・key type:そのまま
・Key:コピーした公開鍵を貼り付け

個人アクセストークンの生成(GitHub)

GitHubにプッシュする際のパスワードになります。

Setting
→Developer setting(左側ペイン)
→Personal access tokens
→Tokens(Classic)
→Generate new token
→Classic
トークンのパラメータ設定画面に行くので以下の内容で生成
・Note:トークンの名前になります
・Expiration:トークンの有効期限です
・Select scope:トークンの権限です。今回は全てチェックします

生成後にトークンのパスフレーズが表示されるので必ず保存してください

リポジトリの作成(GitHub)

Cloud9からのプッシュ先となるリポジトリを作成します。

GitHubのマイページなどから新しいリポジトリを作成します。

リポジトリの作成ページでは以下の内容で設定します。

Repository name:リポジトリ名(Cloud9上ではディレクトリ名となります)
公開設定:PublicかPrivate
Add a README file:一応チェック入れます
Add .gitignore:プルダウンから「Terraform」を選択します

作成したリポジトリのトップページ右上に「Code」ボタンがあるのでクリック
→HTTPSを選択した状態でClone URLをコピー

リポジトリをクローンする(Cloud9)

Cloud9で以下のコマンド操作をします。

#gitの初期設定
$ git config --global user.name <GitHubに登録したユーザー名>
$ git config --global user.email <Githubに登録したメールアドレス>

#リポジトリをClone
$ git clone <GitURL(HTTPS)> 

この時リポジトリの配下にCloud9上で作っていたTerraformフォルダを移動しましょう

mv 移動させるディレクトリ 移動先ディレクトリ

では、Terraformファイルをリポジトリにpushします。

#cloneしたリポジトリで実施します
#origin設定(masterで通らない場合はmainに置き換えてください)
$ git push -u origin master
Username for 'Git URL(HTTPS)': <GitHubのユーザー名>
Password for 'Git URL(HTTPS)': <GitHubにて作成した個人アクセストークンのパスフレーズ>

#pushファイルをステージング環境へ追加
$ git add ファイル名

#ファイルとをリポジトリにコミット
$ git commit -m "任意のコメント"

#リポジトリにpush
$ git push origin master(またはmain)

実行後にユーザー名とパスワード(アクセストークンのパスフレーズ)を要求されます。

無事プッシュが完了したらGitHub側で反映されているか確認してください。

お疲れ様でした。

参考

https://dev.classmethod.jp/articles/cloud9-terraform-al2023/

https://kacfg.com/terraform-vpc-ec2/#tf-2

https://chibinfra-techblog.com/aws-cloud9-github-env-web-code/

https://qiita.com/ucan-lab/items/d594404d0d2c64a85a38

https://dev.classmethod.jp/articles/retrieve-latest-ami-id-of-amazonlinux-2023/

Discussion