AWS VPC с Terraform
ToC
Что такое VPC
Amazon Virtual Private Cloud (Amazon VPC) – это логически изолированный раздел облака AWS, в котором можно запускать ресурсы AWS в созданной пользователем виртуальной сети. Пользователь полностью контролирует свою среду виртуальной сети, в том числе может выбирать собственный диапазон IP-адресов, создавать подсети, а также настраивать таблицы маршрутизации и сетевые шлюзы. Для обеспечения удобного и безопасного доступа к ресурсам и приложениям в VPC можно использовать как IPv4, так и IPv6.
Настройка
Приступим к конфигурации VPC.
В файл variables.tf
добавляем блоки IP адресов, которые мы будем использовать внутри нашей VPC:
variable "vpc_cidr" {
description = "CIDR for the whole VPC"
default = "172.20.0.0/16"
}
variable "vpc_cidr_public" {
description = "CIDR for the Public subnet"
default = "172.20.0.0/24"
}
variable "vpc_cidr_private" {
description = "CIDR for the Private subnet"
default = "172.20.1.0/24"
}
- vpc_cidr - это блок для использования внутри всей VPC
- vpc_cidr_public - блок для публичных сервисов (например, для ssh proxy AKA bastion host или балансировщика)
- vpc_cidr_private - это блок для внутренних сервисов (например сервер БД или воркеры с приложениями)
Создаем файл vpc.tf
с содержимым:
resource "aws_vpc" "MyVPC" {
cidr_block = "${var.vpc_cidr}"
enable_dns_hostnames = true
tags {
Name = "TF:VPC",
Owner = "[email protected]",
Environment = "Production",
Description = "Custom VPC"
}
}
В cidr_block мы указываем переменную из variables.tf
vpc_cidr.
Ну и тэги - очень удобный инструмент для работы и выборки через АПИ нужных ресурсов.
Теперь нам необходимо описать конфигурацию сети и доступ в интернет из нашего VPC.
Сеть
Добавляем в vpc.tf
:
## Public subnet
resource "aws_subnet" "aws-subnet-public" {
vpc_id = "${aws_vpc.MyVPC.id}"
cidr_block = "${var.vpc_cidr_public}"
availability_zone = "${var.aws_region}a"
tags = {
Name = "Public subnet"
}
}
## Private subnet
resource "aws_subnet" "aws-subnet-private" {
vpc_id = "${aws_vpc.MyVPC.id}"
cidr_block = "${var.vpc_cidr_private}"
availability_zone = "${var.aws_region}b"
tags = {
Name = "Private subnet"
}
}
Тут переменных немного больше, но они практически все понятны. Опишу не самые очевидные вещи:
- availability_zone - зона доступности от региона отличается наличием индекса (a, b и т.п.)
После этого можно применить изменения и посмотреть, что будет:
$ terraform apply -var-file=terraform.tfvars
Гейт в большой Интернет
Добавляем в vpc.tf
:
## Internet gateway
resource "aws_internet_gateway" "gateway" {
vpc_id = "${aws_vpc.MyVPC.id}"
}
## Elastic IP for NAT GW
resource "aws_eip" "eip" {
vpc = true
depends_on = ["aws_internet_gateway.gateway"]
}
## NAT gateway
resource "aws_nat_gateway" "gateway" {
allocation_id = "${aws_eip.eip.id}"
subnet_id = "${aws_subnet.aws-subnet-public.id}"
depends_on = ["aws_internet_gateway.gateway"]
}
output "NAT_GW_IP" {
value = "${aws_eip.eip.public_ip}"
}
Итак, что тут происходит. Пройдем по блокам.
- первый блок создает тот самый виртуальный шлюз в интернет внутри VPC
- второй блок резервирует статический внешний IP адрес, чтоб наши сервера выходили в интернет всегда с одного адреса
- третий блок создает NAT шлюз, который будет NAT'ить исходящие соединения (идет привязка к публичной подсети и внешнему IP, он будет создан только после интернет шлюза из первого блока, о чем говорится в
depends_on
) - четвертый блок известен уже из прошлой статьи - вывод IP адреса для шлюза
Почти закончили. Остается настроить таблицы маршрутизации.
Роутинг
Здесь будет немного сложнее понять, но я надеюсь, что вы разберетесь.
Создаем файл routing.tf
с такими блоками:
## Default route to Internet
resource "aws_route" "internet_access" {
route_table_id = "${aws_vpc.MyVPC.main_route_table_id}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.gateway.id}"
}
## Routing table
resource "aws_route_table" "private_route_table" {
vpc_id = "${aws_vpc.MyVPC.id}"
tags {
Name = "Private route table"
}
}
resource "aws_route" "private_route" {
route_table_id = "${aws_route_table.private_route_table.id}"
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = "${aws_nat_gateway.gateway.id}"
}
resource "aws_route_table" "public" {
vpc_id = "${aws_vpc.MyVPC.id}"
tags {
Name = "Public route table"
}
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.gateway.id}"
}
}
## Route tables associations
# Associate subnet public_subnet to public route table
resource "aws_route_table_association" "public_subnet_association" {
subnet_id = "${aws_subnet.aws-subnet-public.id}"
route_table_id = "${aws_vpc.MyVPC.main_route_table_id}"
}
# Associate subnet private_subnet to private route table
resource "aws_route_table_association" "private_subnet_association" {
subnet_id = "${aws_subnet.aws-subnet-private.id}"
route_table_id = "${aws_route_table.private_route_table.id}"
}
Я предупреждал, что тут немного более запутано, но те, кто хорошо знает сети и маршрутизацию - легко заметит, что сначала мы создаем маршрут по умолчанию в таблице маршрутизации по умолчанию.
Дальше мы создаем внутреннюю таблицу маршрутизации и маршруты для приватной и публичной частей сети.
И наконец мы делаем привязку подсетей и таблиц маршрутизации.
Мой вам совет - перечитайте и нарисуйте связи на листе бумаги. Так будет проще понять. Расписывать подробно я тут не буду, оставлю это вам для домашнего задания.
Применяем, как мы делали это раньше.
Чтоб уничтожить все созданные ресурсы надо сделать destroy
:
$ terraform destroy -var-file=terraform.tfvars
Исходники, как всегда, на GitHub.
Комментарии: