terraformで aws のいい感じの構成を作る (subnet編)
対象読者
terraformが何かを知っていて、 terraformを使おうと考えている人。
terraform version 0.9.1
subnet とは何なのか。
VPCのネットワーク内で更に細かくネットワークを分割したもの。 http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Subnets.html http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Scenario2.html ここらへんの話しになります。
今回は、イカ3つのsubnet構成を作ります。
- public
- nat-private
- private
public サブネット
public サブネットには、public ip アドレスを付与し、VPCの外からも見えるネットワークを作ります。 ELBを配置します。 また、nat-privateへの踏み台サーバーを建てたりします。
nat-private サブネット
外部ネットワークからアクセスは行えず、外のネットワークへ出る際に、nat を通るネットワーク おもに、自分で作ったアプリケーション(Railsアプリとか)を配置します。
private サブネット
外部ネットワークからアクセスは行えず、外のネットワークに出る必要のないネットワーク Database等のdatastoreを配置します。
multi-az
awsにはAvailabilityZoneと呼ばれる区分けがあります。 これは、物理的なインスタンスの位置の違いを示しており、片方のAZ(データセンター)が(天災とか)で壊れても、もう片方のAZにも配置しておくことでサービスが死なないようにするという手法に使います。
subnetはそれぞれAZごとに作ります。
東京リージョンでは a
, c
とAZがあるので2つ作ることになります。
subenet 作成のコード
resource "aws_subnet" "public1a" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 0)}" availability_zone = "ap-northeast-1a" tags { Name = "${var.service}-${var.envname}-public1a" } } resource "aws_subnet" "public1c" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 1)}" availability_zone = "ap-northeast-1c" tags { Name = "${var.service}-${var.envname}-public1c" } } resource "aws_subnet" "nat-private1a" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 4)}" availability_zone = "ap-northeast-1a" tags { Name = "${var.service}-${var.envname}-nat-private1a" } } resource "aws_subnet" "nat-private1c" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 5)}" availability_zone = "ap-northeast-1c" tags { Name = "${var.service}-${var.envname}-nat-private1c" } } resource "aws_subnet" "private1a" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 2)}" availability_zone = "ap-northeast-1a" tags { Name = "${var.service}-${var.envname}-private1a" } } resource "aws_subnet" "private1c" { vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 3)}" availability_zone = "ap-northeast-1c" tags { Name = "${var.service}-${var.envname}-private1c" } }
cidr_blockは、192.168.0.0/24
192.168.1.0/24
みたいになってます。
1つのsubnetで 256 アドレス使えます。ただ、AWSがいろいろ使うので実際にはこれよりちょっと少ないです。
subnet のネットワーク
subnet内でのネットワークの流れを定義する必要があります。 どうやって外と通信するか。という感じです。
public subnetでは、internet gateway を用意します。 これはVPCとしてのネットワークの出入り口でもあります。
nat-private subnetでは nat_gateway というものを用意します。 これは実態としてはEC2インスタンス(だとおもう)で、public ipアドレスを付与する必要があります。 以前は、AWSが用意したnat用のAMIを自身で起動して用意していましたが、nat_gatewayというマネージドなnatが利用できるようになりました。
イカ、コード
resource "aws_internet_gateway" "gw" { vpc_id = "${aws_vpc.vpc.id}" tags { Name = "${var.service}_${var.envname}_gateway" } } resource "aws_eip" "nat_gateway" { vpc = true } resource "aws_nat_gateway" "nat_gw" { allocation_id = "${aws_eip.nat_gateway.id}" subnet_id = "${aws_subnet.public1a.id}" depends_on = ["aws_internet_gateway.gw"] }
ルートテーブル
実際の、subnetのルーティングを設定します。
0.0.0.0/0
、つまりすべてのネットワークをgatewayに流しています。
resource "aws_route_table" "public" { vpc_id = "${aws_vpc.vpc.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.gw.id}" } tags { Name = "${var.service}_${var.envname}_public" } } resource "aws_route_table" "nat-private" { vpc_id = "${aws_vpc.vpc.id}" route { cidr_block = "0.0.0.0/0" nat_gateway_id = "${aws_nat_gateway.nat_gw.id}" } tags { Name = "${var.service}_${var.envname}_nat-private" } }
ルートテーブルを作っただけではダメで、それをどのsubnetで使うかを設定します。
resource "aws_route_table_association" "public1a" { route_table_id = "${aws_route_table.public.id}" subnet_id = "${aws_subnet.public1a.id}" } resource "aws_route_table_association" "public1c" { route_table_id = "${aws_route_table.public.id}" subnet_id = "${aws_subnet.public1c.id}" } resource "aws_route_table_association" "nat-private1a" { route_table_id = "${aws_route_table.nat-private.id}" subnet_id = "${aws_subnet.nat-private1a.id}" } resource "aws_route_table_association" "nat-private1c" { route_table_id = "${aws_route_table.nat-private.id}" subnet_id = "${aws_subnet.nat-private1c.id}" }
まとめ
正直、かなりハマりました。 というものの、terraformで作らないでAWSコンソールで作ると、最初からいい感じに設定されているんですよね。 自分で、terraformで細かく作って初めて知ったものは多かったです。 nat-privateのネットワークがハマりどころだと思います。