頑張るときはいつも今

自称エンジニアのゴリラです。日々精進。

【AWS】TerraformでVPC構築からEC2を動作させてみた#1(VPC作成編)

何をやるか

  • 今まで手探りで動作させていたAWSを基礎から勉強しているのでそのメモ(Udemyで定番のあの教材です)
  • ただコンソールを触っていても少しつまらないので同じく勉強中のTerraformを使う
  • 今回はVPCとサブネット作成までやります。

    事前の予備知識

    Terraformって?

  • Vagrantを開発しているHashiCorp社が提供するインフラ構成管理ツール
  • .tf拡張子のファイルにインフラ構成を記述することで、構成通りのインフラが作成される(いわゆるIaC)

    何が嬉しい?

インフラをコードとして管理できるので下記のようなメリットがあるのかなって思います。

  • Gitなどと連携させて、バージョン管理やコードレビュー
  • 既存のインフラ構成の再利用
  • 人為的なミスを防ぐ

VPC(Virtual Private Cloud)

  • AWSクラウド内に論理的に分離された自分の仮想NW
  • 仮想NWをさらにサブネットで分けたり、ルートテーブルを作成してトラフィックを制御できる
  • AWSのサービスによっては、VPC内に作成できないものがあるため注意しておく
    • S3とかはVPC内に配置ができないためためVPC内のノードとの経路やセキュリティ設計が必要になる

      VPC内のサブネット

  • インターネットからアクセスを受けたいノード群とインターネットからアクセスを受けたくないノード群を分けたりする
    • インターネットからアクセスを受ける方をパブリックサブネット、反対にアクセスを受けない方をプライベートサブネット
    • パブリックサブネットにはIGW(インターネットGW)へルーティングできるようにしてあげる必要がある
      f:id:wa_football_1120:20191221132252p:plain
      サブネットの概要
  • VPC内のサブネットは/16 ~ /28から作成することができる
    • 予約アドレスは5個あるため、使えるIPアドレス2^サブネット - 5

      VPC内のルーティング

  • VPCを構築すると仮想的なSWが同時に構築される
  • ルートテーブルをサブネットと関連付けさせてサブネット間やインターネットへパケットを伝搬させる f:id:wa_football_1120:20191221134815p:plain

VPC内のセキュリティ

  • VPC内のリソースへのアクセス制限にはセキュリティグループネットワークACLがある
  • セキュリティグループはEC2などのインスタンスレベルでルールの作成ができる。
    • ステートフルのためアウトバウンドについてはルールが不要
  • ネットワークACLはサブネット単位でルールの作成をする
    • こちらはステートレスのため戻りの通信を含めてルールが必要
  • クラスメソッドさんのブログが参考になりました

実装

作成するインフラ構成

  • 単一AZにパブリックサブネットとプライベートサブネットを構築
  • プライベートサブネットのEC2にはMYSQLをインストールして、パブリックサブネットのEC2からのみアクセスできるようにする
    • RDSは別機会で
  • NAT GWをパブリックサブネットに配置して開発者がSSH接続できるようにする

    VPC作成

  • cidr_block: VPC内利用するIPアドレスの範囲
  • enable_dns_support: DNSによる名前解決を有効化するかどうか
  • enable_dns_hostnames: パブリックIPアドレスをもつインスタンスの名前解決を有効にする
resource "aws_vpc" "example_vpc" {
    cidr_block           = "10.0.0.0/16"
    enable_dns_support   = true # DNS名前解決をサポート
    enable_dns_hostnames = true # パブリックIPアドレスをもつインスタンスの名前解決を有効化

    tags = {
        Name = "Example"
    }
}

ネットワーク周り

パブリックサブネット

サブネット作成

  • vpc_id: 作成されたVPCのID(先ほど作成したVPCの出力値を利用する)
  • map_public_ip_on_launch: サブネット内で起動したインスタンスにパブリックIPアドレスを割り当てるかどうか
  • aveilability_zone: 作成するAZ
resource "aws_subnet" "example_public" {
    vpc_id                  = "${aws_vpc.example_vpc.id}"
    cidr_block              = "10.0.1.0/24"
    map_public_ip_on_launch = true
    availability_zone       = "ap-notrheast-1a"

    tags = {
          Name = "Example_Public_Subnet_northeast-1a"
    }
}

インターネットGW

  • vpc_idに作成したVPCのID
resource "aws_internet_gateway" "example_igw" {
    vpc_id = "${aws_vpc.example_vpc.id}"
}

ルートテーブル

  • aws_route_tableでルートテーブルを作成
    • vpc_idに作成したVPCのID
  • aws_routeで実際のルートを定義する
    • インターネットGWとのルートを作成する
  • aws_route_table_associationでルートテーブルをサブネットにアタッチする
resource "aws_route_table" "example_public" {
    vpc_id = "${aws_vpc.example_vpc.id}"
}
resource "aws_route" "example_public" {
    route_table_id         = "${aws_route_table.public.id}"
    gateway_id             = "${aws_internet_gateway.example_igw.id}"
    destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "example_public" {
    subnet_id      = "${aws_subnet.example_public.id}"
    route_table_id = "${aws_route_table.example_public.id}"
}

プライベートサブネット

サブネット作成

  • パブリックIPの付与は必要ないためmap_public_ip_on_launchfalseにする
resource "aws_subnet" "example_private" {
    vpc_id                  = "${aws_vpc.example_vpc.id}"
    cidr_block              = "10.0.2.0./24"
    map_public_ip_on_launch = false
    availability_zone       = "ap-northeast-1a"

    tags = {
        Name = "Exsample_Private_Subnet_ap-northeast-1a"
    }
}

Elastic IPを作成

  • NAT Gatewayに必要なElastic IPを作成する
  • aws_eipで作成が可能
  • IGW作成後にリソースの作成がされるようにdepends_onに指定する
    • 依存関係がある場合にはdepends_onを指定しておく

NAT Gateway作成

  • allocation_idに作成したElastic IPのIDを指定する
  • Elastic IP同様にIGWと依存関係があるためdepends_onに指定する
resource "aws_nat_gateway" "example_nat_gateway" {
    allocation_id = "${aws_eip.example_nat_gateway.id}"
    subnet_id     = "${aws_subnet.example_public.id}"
    depends_on    = ["${aws_internet_gateway.example_igw}"]
}

ルートテーブル

  • nat_gateway_idで作成したNATGWをアタッチしておく
resource "aws_route_table" "example_private" {
    vpc_id = "${aws_vpc.example_vpc.id}"
}

resource "aws_route" "example_private" {
    route_table_id         = "${aws_route.example_private.id}"
    nat_gateway_id         = "${aws_nat_gateway.example_nat_gateway.id}"
    destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route_table_association" "example_private" {
    subnet_id      = "${aws_subnet.example_private.id}"
    route_table_id = "${aws_route_table.example_private.id}"
}