という発表があったので、さっそく使ってみました。
Terraform でいろいろ作る
Terraform で VPC やら EC2 インスタンスやらを作ります。ちょっと長いです。
////////////////////////////////////////////////////////////////////////////////
/// 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
おしまい。