Сеть в AWS — это не «галочки где-то в консоли», а то, что определяет главный вопрос: кто до кого может достучаться. От неё зависит и безопасность (не смотрит ли база наружу?), и работоспособность (видит ли приложение базу?). Хорошая новость: вся модель строится из нескольких понятных кирпичиков, и собрать её в голове можно за один заход.
Представьте, что AWS — это огромное здание дата-центра, а вы арендуете в нём собственный изолированный этаж со своей разводкой проводов. Никто чужой на ваш этаж не попадёт, а вы сами решаете, какие двери открыть наружу. Этот «личный этаж» и есть VPC. Если базовые понятия облака ещё не на руках, начните с основ AWS, а сюда возвращайтесь за сетевой моделью целиком.
Public-подсеть это просто маршрут на Internet Gateway, и в ней стоят только балансировщик и NAT Gateway. Приложение и база в private: снаружи их не достать, а наружу они ходят через NAT, который считает и часы, и гигабайты.
Что такое VPC
Две команды завели по сети и обе взяли 10.0.0.0/16 — теперь эти сети не связать: адреса совпадают, и маршрутизатор не поймёт, куда слать пакет. Поэтому диапазон адресов выбирают заранее. VPC (Virtual Private Cloud) — ваша изолированная виртуальная сеть внутри AWS; её диапазон задаётся через CIDR — запись вида 10.0.0.0/16. Цифра после слэша говорит, сколько адресов в диапазоне: /16 — это 65 536 адресов, /24 — ровно 256. Чем меньше число, тем больше адресов.
Внутри VPC ничего чужого нет: это ваше адресное пространство, и трафик между двумя VPC не ходит, пока вы это явно не разрешите. Создаётся VPC одной командой, а дальше вы наполняете её подсетями.
aws ec2 create-vpc --cidr-block 10.0.0.0/16
Размер тут не любой: VPC берут от /16 (самый крупный) до /28 (самый мелкий), и для подсетей рамки те же. Попытка выписать себе /8 или, наоборот, /30 просто не пройдёт — AWS ответит ошибкой.
Подсети: public и private
Большой диапазон VPC разрезают на куски поменьше — подсети (subnet). Каждая подсеть живёт ровно в одной зоне доступности (availability zone — отдельный физический дата-центр внутри региона). Это важно для надёжности: если положить всё в одну зону, авария в ней унесёт весь сервис.
Главное деление подсетей — на public и private. Разница только в одном: есть ли у подсети дорога в интернет.
- Public-подсеть имеет маршрут наружу. Сюда ставят то, что должно быть доступно из интернета: балансировщик нагрузки, иногда bastion-хост для входа по SSH.
- Private-подсеть прямого выхода в интернет не имеет. Сюда ставят приложения, базы данных, кэши — всё, до чего снаружи не должно быть доступа.
Аналогия: public-подсеть — это ресепшен в офисе, куда заходят посетители с улицы. Private-подсеть — кабинеты внутри, куда с улицы не попасть.
Ещё одна мелочь, которая портит расчёты: не все адреса подсети ваши. AWS забирает себе пять штук — сетевой адрес, адрес роутера VPC, адрес DNS, один про запас и широковещательный. То есть в /24 вместо 256 адресов у вас 251. Когда подсеть нарезают впритык под известное число машин, про эту пятёрку вспоминают уже после ошибки.
Типовая схема почти любого приложения выглядит так: балансировщик в public-подсети, приложение и база — в private, и всё это продублировано в нескольких зонах доступности ради отказоустойчивости.
aws ec2 create-subnet --vpc-id vpc-0abc --cidr-block 10.0.1.0/24 --availability-zone eu-central-1a
aws ec2 create-subnet --vpc-id vpc-0abc --cidr-block 10.0.2.0/24 --availability-zone eu-central-1b
Маршрутизация: куда уходит трафик
Подсеть сама по себе не «знает», public она или private. За это отвечает таблица маршрутов (route table) — простой список правил вида «пакеты на такие-то адреса отправляй туда-то». К каждой подсети привязана одна таблица маршрутов.
Internet Gateway — это дверь VPC в интернет. Подсеть становится public именно потому, что её таблица маршрутов содержит строку 0.0.0.0/0 (то есть «весь остальной интернет»), указывающую на Internet Gateway. У private-подсети такой строки просто нет — отсюда и нет выхода наружу.
Но часто private-сервису всё-таки нужен исходящий доступ: скачать обновление, дёрнуть чужой API, отправить событие в платёжку. Входящий при этом не нужен — никто снаружи не должен инициировать соединение. Для этого служит NAT Gateway.
NAT Gateway работает как односторонний турникет: трафик изнутри наружу — пожалуйста, снаружи внутрь по своей инициативе — нельзя. Важная деталь, которую часто путают новички: сам NAT Gateway стоит в public-подсети, потому что ему нужен выход в интернет. А таблица маршрутов private-подсети направляет исходящий трафик 0.0.0.0/0 не на Internet Gateway, а на этот NAT Gateway. Так сервис ходит наружу, оставаясь невидимым снаружи.
Про цену этого турникета стоит сказать сразу, потому что она удивляет в первом же счёте. Он тарифицируется дважды: почасово за существование (порядка четырёх-пяти центов в час — около тридцати долларов в месяц за штуку, независимо от нагрузки) и отдельно за каждый обработанный гигабайт (примерно столько же за гигабайт). Через него идёт и трафик к сервисам самого AWS: выгрузили терабайт из хранилища объектов — заплатили за терабайт обработки, хотя данные не выходили за пределы облака.
Отсюда практика, которая экономит заметные суммы: обращения к хранилищу объектов и к DynamoDB заворачивают мимо шлюза — бесплатной точкой доступа в таблице маршрутов (о ней ниже). А сам счёт за шлюз смотрят до того, как он станет неприятным: в разбивке затрат по сервисам строка NatGateway-Hours и NatGateway-Bytes видна отдельно.
И ещё одна деталь, про которую забывают при первом проектировании: обычный NAT Gateway живёт в одной зоне доступности. Откажет эта зона — выход в интернет пропадёт у всех подсетей, чей маршрут смотрит на этот шлюз, даже если сами подсети в живых зонах. Поэтому ради отказоустойчивости NAT ставят по одному на зону и каждой зоне прописывают свой маршрут (или берут региональный вариант NAT, который AWS сам разворачивает по зонам).
aws ec2 create-route --route-table-id rtb-public --destination-cidr-block 0.0.0.0/0 --gateway-id igw-0abc
aws ec2 create-route --route-table-id rtb-private --destination-cidr-block 0.0.0.0/0 --nat-gateway-id nat-0abc
DNS внутри VPC
Половина обращений «приложение не видит базу» оказывается не про маршруты, а про имена. Разбираться в этом надо отдельно, потому что инструменты другие.
Резольвер живёт внутри VPC. У каждой сети есть встроенный разрешитель имён по адресу «база сети плюс два»: для 10.0.0.0/16 это 10.0.0.2. Он отвечает и на внешние имена, и на внутренние имена AWS — адрес управляемой базы, точки доступа сервисов. Именно его адрес машины получают автоматически, и именно поэтому внутри VPC вообще работает разрешение имён.
Два переключателя, без которых не работает ничего. У VPC есть свойства enableDnsSupport (пользоваться встроенным резольвером) и enableDnsHostnames (выдавать машинам внутренние DNS-имена). Первое включено по умолчанию, второе — только в сети, созданной по умолчанию; в сети, созданной руками или кодом, его часто забывают. Симптом забытого второго: адрес управляемой базы не разрешается изнутри, а из консоли всё выглядит правильно. Для точек доступа к сервисам (interface endpoint) с их приватными именами нужны оба.
Свои имена — приватная зона Route 53. Если хочется обращаться к базе как db.internal, а не по выданному облаком длинному имени, заводят приватную зону: она привязывается к одной или нескольким VPC и видна только изнутри них. Это же способ держать одно имя в разных средах: db.internal в тестовой сети указывает на тестовую базу, в боевой — на боевую, а код одинаковый.
Как проверять. Разбор ведут изнутри той машины, которая жалуется:
dig +short orders-db.cluster-abc123.eu-central-1.rds.amazonaws.com
dig +short db.internal @10.0.0.2 # спросить именно встроенный резольвер
cat /etc/resolv.conf # какой резольвер вообще настроен
Имя не разрешается — дело в переключателях VPC или в приватной зоне; имя разрешается, а соединения нет — тогда уже сеть, и порядок разбора в следующем разделе.
Security groups против NACL
Когда трафик уже доехал до подсети и ресурса, его фильтруют. В AWS два уровня фильтрации, и их постоянно путают.
Security group — фаервол на уровне конкретного ресурса (виртуальной машины, контейнера, эндпоинта базы). У него две ключевые особенности:
- он stateful («с памятью»): если вы разрешили входящее соединение, ответ на него уйдёт автоматически — отдельное правило на выход писать не нужно;
- в нём бывают только разрешающие правила. Запретить что-то явно нельзя — всё, что не разрешено, и так закрыто.
Network ACL (NACL) — фаервол на уровне целой подсети. Его особенности противоположные:
- он stateless («без памяти»): правила нужны отдельно на вход и отдельно на выход. Разрешили входящий запрос — не забудьте разрешить и исходящий ответ, иначе соединение повиснет;
- в нём бывают и разрешающие, и запрещающие правила;
- стартовое поведение зависит от того, откуда NACL взялся: тот, что создаётся вместе с VPC, пропускает весь трафик в обе стороны, а созданный вами вручную по умолчанию запрещает всё — правила придётся выписывать с нуля.
На практике основной рабочий инструмент — security groups: они точечные и привязаны к ресурсу. NACL берут реже, для грубой блокировки на уровне подсети (например, забанить диапазон адресов целиком).
Очень удобный приём: ссылаться одной security group на другую. Вместо того чтобы прописывать IP-адреса (которые меняются), правило «приложению можно ходить в базу» формулируют так: security group базы принимает трафик от security group приложения.
aws ec2 authorize-security-group-ingress \
--group-id sg-database \
--protocol tcp --port 5432 \
--source-group sg-application
Как подключаться к базе в приватной подсети
Открывать порт базы на весь интернет «для разработчиков» нельзя — его начнут сканировать через минуты. Правильных способов три:
- бастион — маленькая машина в публичной подсети, через которую пробрасывают SSH-туннель к базе;
- Session Manager (AWS Systems Manager) — доступ к машине или порту через IAM, без открытых портов и ключей SSH вовсе;
- VPN в VPC для всей команды.
Для отладки с реальными данными — read-реплика или анонимизированный дамп на стенде, а не рабочая база.
Порядок разбора: «пакет не доходит»
Когда соединение не устанавливается, гадать не нужно — проверять надо по порядку, снизу вверх по вероятности. Четыре шага закрывают почти все случаи.
1. Группа безопасности получателя. Разрешён ли входящий трафик на нужный порт от источника? Источником может быть не адрес, а другая группа безопасности — так и правильнее. Здесь же самая частая ошибка: правило добавили в группу приложения, а не базы.
2. Группа безопасности отправителя. Исходящий трафик по умолчанию разрешён весь, но если кто-то сузил исходящие правила (а в строгих контурах сужают), проверять надо и их.
3. Списки доступа подсети (NACL). Они действуют на уровне подсети и, в отличие от групп, не помнят состояние: разрешив входящий запрос, надо отдельно разрешить исходящий ответ на высокие порты (1024–65535). Это классическая причина «запрос уходит, ответ не приходит». По умолчанию списки разрешают всё, поэтому шаг важен только там, где их настраивали.
4. Таблица маршрутов. Есть ли вообще маршрут до получателя — для другой сети через соединение или хаб, для интернета через нужный шлюз. Отдельно проверяют, что маршрут прописан в таблице той подсети, где стоит машина.
И инструмент, который отвечает на вопрос «дошёл ли пакет»: журнал сетевых потоков (VPC Flow Logs). Его включают на сети, подсети или сетевой карте, и он пишет строки о каждом соединении: адреса, порты, число пакетов и, главное, признак ACCEPT или REJECT.
2 123456789012 eni-0abc 10.0.2.15 10.0.10.7 51514 5432 6 12 3400 1700000000 1700000060 REJECT OK
Читается это так: соединение с 10.0.2.15 на 10.0.10.7:5432 отклонено. Дальше вывод однозначный: если отклонение видно на стороне получателя — виновата его группа безопасности или список доступа подсети; если записи нет вовсе — пакет не дошёл до сети получателя, и дело в маршрутах. Без этого журнала оба случая выглядят одинаково — «таймаут».
Включать его стоит заранее, хотя бы на боевую сеть: он пишется в хранилище логов и стоит денег за объём, зато в момент инцидента отвечает на главный вопрос за минуту. Есть и второй инструмент для разовой проверки — анализатор доступности (Reachability Analyzer): указываешь источник и получателя, и он сам проходит по правилам и говорит, что именно блокирует, не отправляя ни одного пакета.
Где это применяется
Сеть AWS — это фундамент, на котором стоит всё остальное. Балансировщик в public-подсети, приложение и база в private, NAT для исходящих вызовов, security groups, описывающие «кто до кого» — эту схему вы встретите практически в любом боевом развёртывании. Когда трафик распределяют между несколькими зонами доступности, как в материале про масштабирование и доступность, под капотом работает ровно эта сетевая модель.
Типичные ошибки новичков, которые стоит запомнить заранее:
- поставить базу в public-подсеть — она оказывается доступна из интернета, это прямая дыра в безопасности;
- ждать выхода наружу из private-подсети без NAT Gateway — исходящие вызовы будут молча зависать;
- поставить публичный NAT Gateway в private-подсеть — он сам не получит выход в интернет и работать не будет (приватный NAT тоже бывает, но он служит для связи с другими сетями, а не с интернетом);
- забыть про stateless-природу NACL — разрешить вход, но не разрешить ответный выход, и соединение не установится;
- прописывать IP-адреса вместо ссылок между security groups — адреса меняются, и правила ломаются.
Глубже: связь между сетямирасширенное
Реальные системы редко помещаются в одну VPC: разные команды, разные окружения, разные аккаунты. Связать сети можно несколькими способами.
- VPC peering — прямое соединение двух VPC. Два ограничения, о которые спотыкаются в этом порядке. Первое: диапазоны адресов не должны пересекаться. Две сети
10.0.0.0/16соединить нельзя вообще никак — маршрутизатор не сможет решить, куда отправлять пакет; поэтому диапазоны сетей планируют один раз на всю компанию, а не выбирают по умолчанию в каждом новом проекте. Второе: соединение не транзитивно. Если A связана с B, а B связана с C, это не значит, что A видит C; каждую пару нужно соединять отдельно, и при росте числа сетей это превращается в паутину связей. - Transit Gateway — центральный хаб, к которому подключают много VPC (и даже локальную сеть офиса). Вместо россыпи peering-связей все ходят через один узел. Это спасает, когда сетей становится много, и у спасения есть цена: почасовая плата за каждое подключение (порядка пяти центов в час, то есть около сорока долларов в месяц за каждую присоединённую сеть) плюс отдельная плата за каждый обработанный гигабайт. Для трёх сетей это дороже трёх соединений напрямую; выигрыш начинается, когда сетей около пяти и больше, а к ним добавляется офис или второй регион. Требование о непересекающихся диапазонах при этом никуда не уходит.
- PrivateLink и VPC endpoints — доступ к сервису по приватной сети, без выхода в интернет вообще. Трафик при этом не покидает сеть AWS. Механизма тут два, и путать их дорого: до объектного хранилища S3 и базы DynamoDB дотягиваются бесплатным gateway-эндпоинтом — это просто строчка в таблице маршрутов. До остальных сервисов (например, до Secrets Manager) — interface-эндпоинтом на базе PrivateLink: в каждой зоне поднимается сетевая карта, и за неё берут почасовую плату плюс деньги за каждый гигабайт.
VPC endpoints — почти всегда правильный ответ на вопрос «как private-сервису безопасно достучаться до управляемого сервиса AWS».
Глубже: как заходить внутрь: почему Session Manager, а не бастионрасширенное
К машине в закрытой подсети надо иногда подключиться — посмотреть журнал, выполнить команду, пробросить порт до базы. Исторически для этого держали бастион: маленькую машину в публичной подсети с открытым портом SSH, через которую заходят на остальные.
У бастиона три постоянные проблемы: открытый порт в интернет (его сканируют непрерывно), ключи SSH, которые надо кому-то выдавать и потом отзывать, и отсутствие следа — кто заходил и что делал, видно только в журналах самой машины, если их вообще собирают.
Session Manager (часть Systems Manager) решает все три. Агент на машине сам устанавливает исходящее соединение со сервисом, и подключение идёт через него:
- нет открытых портов вовсе — ни SSH, ни бастиона; группа безопасности машины может не иметь ни одного входящего правила;
- доступ управляется правами IAM — не ключами: отозвали право у сотрудника, и он больше не войдёт, без всякой работы с ключами на машинах;
- всё пишется в журнал — факт подключения в журнал вызовов API, а при желании и полная запись сессии в хранилище объектов; для аудита это решающий довод.
Работает это и для проброса порта, то есть привычный туннель до базы тоже получается:
aws ssm start-session --target i-0abc123 # консоль на машине
aws ssm start-session --target i-0abc123 \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["orders-db.cluster-abc.eu-central-1.rds.amazonaws.com"],"portNumber":["5432"],"localPortNumber":["15432"]}'
Что нужно, чтобы это заработало: агент на машине (в образах Amazon Linux он уже есть), роль машины с правами Systems Manager и исходящий доступ до сервиса — либо через тот самый NAT, либо, что правильнее в закрытом контуре, через точки доступа внутри сети.
Когда всё-таки нужен бастион или VPN: когда подключаться надо не к машине, а к чему-то без агента (сетевое устройство, чужая система), когда нужен привычный доступ по SSH со своими ключами по требованию безопасности, и когда сотрудникам нужен доступ к приватным адресам целыми пачками — тогда VPN до сети удобнее, чем сессия на каждую машину.
Коротко
- VPC это ваше адресное пространство: диапазон выбирают заранее, чтобы сети потом можно было соединить; подсеть живёт в одной зоне, и пять адресов в каждой забирает AWS.
- Public-подсеть отличается от private только маршрутом 0.0.0.0/0 на Internet Gateway; приложения и базы живут в private и наружу ходят через NAT Gateway, который стоит в public-подсети и тарифицируется почасово и за гигабайт.
- Половина случаев «не видит базу» про имена: резольвер VPC по адресу «база сети плюс два», переключатели enableDnsSupport и enableDnsHostnames, приватная зона Route 53 для своих имён.
- Security group помнит соединения и только разрешает, NACL без памяти и умеет запрещать; правила пишут ссылками на группы, а не адресами.
- «Пакет не доходит» разбирают по порядку: группа получателя, группа отправителя, NACL, таблица маршрутов; «дошёл ли» отвечает журнал сетевых потоков, который включают заранее.
- Сети соединяют peering без пересечения диапазонов или Transit Gateway как хабом за почасовую плату; до сервисов AWS дотягиваются VPC endpoints: gateway бесплатно для S3 и DynamoDB, interface за деньги.
- Внутрь заходят через Session Manager: без открытых портов, по правам IAM и с журналом; бастион и VPN оставляют для того, у чего нет агента.
Что почитать дальше
- IAM в AWS — кто что может делать поверх «кто до кого дойдёт».
- Вычисления в AWS — где именно живут сервисы в этих подсетях.
- Масштабирование и доступность — балансировщик и копии по зонам на этой сети.
- Сеть в облаке — та же модель без привязки к провайдеру.