18
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

Organization

さっそく VPC NAT Gateway を使ってみた(terraform と awscli で)

【新機能】マネージドNATゲートウェイが利用可能に

という発表があったので、さっそく使ってみました。

Terraform でいろいろ作る

Terraform で VPC やら EC2 インスタンスやらを作ります。ちょっと長いです。

main.tf
////////////////////////////////////////////////////////////////////////////////
/// Variable

variable "ami_id" {
    default = "ami-b80b6db8" // CentOS 7 x86_64 (2014_09_29) EBS
}

////////////////////////////////////////////////////////////////////////////////
/// VPC

/// VPC

resource "aws_vpc" "test" {
    cidr_block = "10.9.0.0/16"
    tags { Name = "test" }
}

/// Internet Gateway

resource "aws_internet_gateway" "test" {
    vpc_id = "${aws_vpc.test.id}"
    tags { Name = "test-igw" }
}

/// Subnet

resource "aws_subnet" "front" {
    vpc_id = "${aws_vpc.test.id}"
    availability_zone = "ap-northeast-1a"
    cidr_block = "10.9.0.0/24"
    map_public_ip_on_launch = true
    tags { Name = "test-front" }
}

resource "aws_subnet" "back" {
    vpc_id = "${aws_vpc.test.id}"
    availability_zone = "ap-northeast-1a"
    cidr_block = "10.9.1.0/24"
    map_public_ip_on_launch = false
    tags { Name = "test-back" }
}

/// Route Table

resource "aws_route_table" "front" {
    vpc_id = "${aws_vpc.test.id}"
    tags { Name = "test-front" }
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = "${aws_internet_gateway.test.id}"
    }
}

resource "aws_route_table" "back" {
    vpc_id = "${aws_vpc.test.id}"
    tags { Name = "test-back" }
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = "${aws_internet_gateway.test.id}"
    }
}

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

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

/// Security Group

resource "aws_security_group" "main" {
    vpc_id = "${aws_vpc.test.id}"
    name = "test-main"
    description = "test-main"
    tags { Name = "test-main" }
    ingress {
        protocol = -1
        from_port = 0
        to_port = 0
        self = true
    }
    egress {
        protocol = -1
        from_port = 0
        to_port = 0
        cidr_blocks = ["0.0.0.0/0"]
    }
}

resource "aws_security_group" "devops" {
    vpc_id = "${aws_vpc.test.id}"
    name = "test-devops"
    description = "test-devops"
    tags { Name = "test-devops" }
    ingress {
        protocol = "tcp"
        from_port = 22
        to_port = 22
        cidr_blocks = ["192.0.2.123/32"]
    }
    egress {
        protocol = -1
        from_port = 0
        to_port = 0
        cidr_blocks = ["0.0.0.0/0"]
    }
}

/// Elastic IP

resource "aws_eip" "nat" {
    vpc = true
}

////////////////////////////////////////////////////////////////////////////////
/// EC2

resource "aws_instance" "bastion" {
    ami = "${var.ami_id}"
    instance_type = "t2.nano"
    key_name = "oreore"
    vpc_security_group_ids = [
        "${aws_security_group.main.id}",
        "${aws_security_group.devops.id}"
    ]
    subnet_id = "${aws_subnet.front.id}"
    associate_public_ip_address = true
    root_block_device = {
      volume_type = "gp2"
      delete_on_termination = true
    }
    tags {
        Name = "test-bastion"
    }
    user_data = <<EOS
        #cloud-config
        hostname: "bastion"
        timezone: "Asia/Tokyo"
EOS
}

resource "aws_instance" "server" {
    ami = "${var.ami_id}"
    instance_type = "t2.nano"
    key_name = "oreore"
    vpc_security_group_ids = [
        "${aws_security_group.main.id}"
    ]
    subnet_id = "${aws_subnet.back.id}"
    associate_public_ip_address = false
    private_ip = "10.9.1.10"
    root_block_device = {
      volume_type = "gp2"
      delete_on_termination = true
    }
    tags {
        Name = "test-server"
    }
    user_data = <<EOS
        #cloud-config
        hostname: "server"
        timezone: "Asia/Tokyo"
EOS
}

////////////////////////////////////////////////////////////////////////////////
/// Output

output "bastion.public_ip" {
    value = "${aws_instance.bastion.public_ip}"
}

output "subnet.front.id" {
    value = "${aws_subnet.front.id}"
}

output "route_table.back.id" {
    value = "${aws_route_table.back.id}"
}

output "eip.nat.id" {
    value = "${aws_eip.nat.id}"
}

インスタンスを2つ立ち上げています。

server インスタンスは InternetGateway が無いサブネットに属していて、PublicIP もないため、直接外部と通信できません。

bastion インスタンスはいわゆる中継サーバで、InternetGatewayのあるサブネットに属していて、PublicIP も付いています。server インスタンスに SSH でログインするためにはこのインスタンスを経由する必要があります。

実行します。

terraform plan
terraform apply

output で後の作業で必要になる項目を出力させているので、覚えておきます。

 :

Outputs:

  bastion.public_ip   = 52.12.34.56
  eip.nat.id          = eipalloc-12345678
  route_table.back.id = rtb-12345678
  subnet.front.id     = subnet-12345678

直接インターネットにでれないことを確認

bastion インスタンス経由で server インスタンスにログインします。

ssh centos@10.9.1.10 -o "ProxyCommand ssh centos@52.12.34.56 -W %h:%p 2>/dev/null"

curl で適当などこかのサイトにアクセスします。

curl -I qiita.com -m 3

server インスタンスは直接インターネットには出られないのでタイムアウトになります。

curl: (28) Connection timed out after 3153 milliseconds

VPC NAT Gateway を作る

Terraform はさすがにまだ対応していないので awscli で NAT Gateway を作ります。

ます awscli をアップデートします。

sudo pip install awscli --upgrade

最新版なら NAT Gateway に対応しています。

aws ec2 help | grep nat-gateway
       o create-nat-gateway
       o delete-nat-gateway
       o describe-nat-gateways

NAT Gateway を作ります。サブネットと Elastic IP を指定する必要があります。

aws ec2 create-nat-gateway --subnet-id "subnet-12345678" --allocation-id "eipalloc-12345678"

次のように結果が表示されました。

{
    "NatGateway": {
        "NatGatewayAddresses": [
            {
                "AllocationId": "eipalloc-12345678"
            }
        ],
        "VpcId": "vpc-12345678",
        "State": "pending",
        "NatGatewayId": "nat-1234567890abcdef",
        "SubnetId": "subnet-12345678",
        "CreateTime": "2015-12-18T02:26:01.524Z"
    }
}

バックエンドのサブネットの RouteTable のデフォルトゲートウェイを NAT Gateway に変更します。

aws ec2 replace-route \
  --route-table-id "rtb-12345678" \
  --destination-cidr-block "0.0.0.0/0" \
  --nat-gateway-id "nat-1234567890abcdef"

もう一度 server インスタンスにログインして curl してみると・・・

curl -I qiita.com -m 3

インターネット経由のアクセスができるようになりました!!!

HTTP/1.1 301 Moved Permanently
 :

全部削除する

もういらないので削除します。

NAT Gateway を削除します。

aws ec2 delete-nat-gateway --nat-gateway-id "nat-1234567890abcdef"

削除には少し時間がかかります。下記のように NAT Gateway の State を表示して・・・

aws ec2 describe-nat-gateways --nat-gateway-id "nat-1234567890abcdef" \
  --query 'NatGateways[0].State' --output "text"

deleting だと削除中です。これが deleted になれば削除完了です。

NAT Gateway の削除が完了したら Terraform で作ったもろもろも削除します。

terraform plan -destroy
terraform destroy -force

おしまい。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
18
Help us understand the problem. What are the problem?