AWS в глубину: от региона до Lambda
В краткой версии ты видел AWS как набор сервисов: EC2 — виртуалка, S3 — файлы, RDS — база. Здесь мы смотрим под капот: как физически устроено облако, почему один регион — это минимум три дата-центра, как IAM решает, кому что можно, и где именно в VPC «живёт» твоё приложение. Это знание отличает человека, который кликает в консоли, от инженера, который проектирует инфраструктуру.
Истории из практики начинаются одинаково: «приложение лежало, потому что мы запустили его в одной AZ, а AZ ушла на профилактику» или «счёт вырос в пять раз, потому что NAT Gateway обрабатывал трафик между двумя инстансами в одной подсети». Понимание устройства AWS — это страховка от обоих сценариев. Бесплатная инженерная классика от самих Amazon — AWS Builders’ Library: статьи о том, как устроены их распределённые системы внутри.
Глобальная инфраструктура: регионы и зоны доступности
Заголовок раздела «Глобальная инфраструктура: регионы и зоны доступности»AWS делит мир на регионы (Regions) — изолированные географические локации (eu-west-1 — Ирландия, eu-central-1 — Франкфурт). Внутри региона — зоны доступности (Availability Zones, AZ): это отдельные дата-центры с собственным питанием, охлаждением и сетью, соединённые между собой быстрыми каналами. Обычно в регионе 3 AZ, но их количество не раскрывается точно — ты видишь только eu-west-1a, eu-west-1b и т.д.
Ключевой принцип: AZ изолируют отказы. Дата-центр горит, страдает питание, режутся кабели — сбой одной AZ не должен уронить сервис. Поэтому production-архитектура всегда растянута минимум по двум AZ:
Регион eu-west-1├─ AZ-a ├─ AZ-b│ ┌──────────┐ │ ┌──────────┐│ │ EC2 app-1│ │ │ EC2 app-2││ └────┬─────┘ │ └────┬─────┘│ │ │ ││ ┌────▼─────┐ │ ┌────▼─────┐│ │ RDS (мастер, Multi-AZ)│ ◄┤ standby ││ └──────────┘ синхр. │ └──────────┘│ │ реплика в другой AZ,│ │ failover за минутыСверху над регионами — Edge Locations сеть CloudFront: сотни точек присутствия по миру, которые кэшируют статику ближе к пользователю. Регион выбирают по трём критериям: близость к пользователям (задержка), юрисдикция данные (GDPR: данные европейцев — в Европе) и наличие нужных сервисов (не всё появляется во всех регионах одновременно).
IAM: кто и что может
Заголовок раздела «IAM: кто и что может»IAM — фундамент безопасности AWS, и его ломают чаще всего. Модель сущностей и язык политик разобраны в IAM User Guide. Три сущности:
- Пользователи — люди. У каждого свой логин, пароль и (обязательно) MFA. Root-аккаунт запирается: MFA, длинный пароль, никакой повседневной работы из-под него.
- Роли (Roles) — не люди, а «должности». EC2-инстанс, Lambda-функция или GitHub Actions могут взять на себя роль и получить её временные ключи (автоматически ротируются). Никаких access key в коде.
- Политики (Policies) — JSON-документы, описывающие разрешения. Принцип минимальных прав: разрешаем только то, что нужно, только на те ресурсы, к которым есть доступ.
// Политика: приложение может читать и писать только один бакет{ "Version": "2012-10-17", "Statement": [{ "Sid": "AppAccessToUploadsOnly", "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"], "Resource": "arn:aws:s3:::myapp-uploads-prod/*" }]}ARN — единый идентификатор ресурса: arn:aws:s3:::myapp-uploads-prod/* читается как «все объекты внутри бакета». Можно сузить до конкретного префикса (.../tmp/*) или конкретного ключа.
# Привязать роль к инстансу при запуске — вместо ключей в кодеaws ec2 run-instances \ --image-id ami-0c02fb55956c7d316 \ --instance-type t3.micro \ --iam-instance-profile Name=app-role-profile
# Проверить, какие политики прикреплены к ролиaws iam list-attached-role-policies --role-name app-roleEC2: виртуальные машины с деталями
Заголовок раздела «EC2: виртуальные машины с деталями»EC2 — это KVM-виртуалки на серверах AWS. Три вещи, которые надо понимать глубже, чем «выбрал образ — запустил».
Типы инстансов. Буква в названии — семейство: t — burstable (дёшево, копит CPU-кредиты, всплески до 100% на короткое время), m — general purpose (сбалансировано), c — compute-optimized (много CPU на RAM), r — memory-optimized (большие кэши, БД), i/d — локальные NVMe-диски. Число — поколение: t3 старше и дешевле, t4g — на ARM Graviton (на ~20% дешевле x86 при той же производительности — проверяй совместимость бинарников). Полная таблица типов и семейств — в EC2 User Guide.
User-data — скрипт, который выполняется при первом старте. Это и есть «bootstrap» инстанса: обновить пакеты, поставить Docker, склонировать и запустить приложение.
# user-data.sh — передаётся через --user-data file://user-data.sh#!/bin/bashset -euo pipefailapt-get update && apt-get install -y docker.iousermod -aG docker ubuntudocker run -d --name app -p 80:3000 \ -e DATABASE_URL="$DATABASE_URL" \ ghcr.io/darkpix/petapp:latestДлинный user-data превращается в мусорку. Как только скрипт больше ~30 строк — собирай AMI (свой образ с предустановленным всем) через Packer или System Manager. Старт из готового AMI быстрее и воспроизводимее.
Security Groups — stateful-файрвол на уровне инстанса: разрешаешь входящее — ответы разрешены автоматически, обратные правила не нужны. Правило вида «вход с 0.0.0.0/0 на 22-й порт» — топ-1 причина взломанных инстансов. Доступ по SSH — только с твоего IP или через VPN/bastion в приватной подсети.
aws ec2 authorize-security-group-ingress \ --group-id sg-0abc123 \ --protocol tcp --port 22 \ --cidr 203.0.113.45/32 # только мой IP, не весь интернет
# Посмотреть, что сейчас разрешеноaws ec2 describe-security-groups --group-ids sg-0abc123S3: хранилище объектов и его жизненный цикл
Заголовок раздела «S3: хранилище объектов и его жизненный цикл»S3 хранит объекты (файл + метаданные) в бакетах с уникальным глобальным именем. Под капотом — это не диски, а распределённая система с 11 девятками доступности: твои объекты реплицированы минимум по трём AZ автоматически. Ты за это не платишь отдельно — в цену входит. Версионирование, lifecycle и классы хранения подробно описаны в S3 User Guide.
Три механизма, которые нужно знать до продакшена:
Версионирование — S3 сохраняет каждую версию объекта при перезаписи. Удалил файл — на самом деле поставил delete-маркер, старая версия на месте. Защита от «перезаписал бэкап сломанным архивом» и от ransomware, который шифрует и удаляет оригиналы.
Lifecycle-политики — автоматические правила перехода между классами хранения: через 30 дней объекты уходят в Standard-IA (редкий доступ, дешевле хранение, дороже чтение), через 90 — в Glacier, через 365 — в Deep Archive. Плюс правила удаления старых версий, иначе версионирование превратит бакет в свалку.
// lifecycle.json — горячие данные остывают сами{ "Rules": [{ "Id": "archive-backups", "Status": "Enabled", "Filter": { "Prefix": "backups/" }, "Transitions": [ { "Days": 30, "StorageClass": "STANDARD_IA" }, { "Days": 90, "StorageClass": "GLACIER" }, { "Days": 365, "StorageClass": "DEEP_ARCHIVE" } ], "NoncurrentVersionExpiration": { "NoncurrentDays": 30 } }]}Presigned URLs — временная подпись, дающая право скачать (или загрузить) объект без AWS-ключей. Классика: клиент просит у API ссылку «загрузить аватар», API вызывает generate_presigned_url с TTL 15 минут, клиент грузит файл напрямую в S3, минуя твой сервер.
# Python + boto3: выдать ссылку на загрузку на 15 минутimport boto3
s3 = boto3.client("s3")url = s3.generate_presigned_url( "put_object", Params={"Bucket": "myapp-uploads-prod", "Key": f"avatars/{user_id}.jpg", "ContentType": "image/jpeg"}, ExpiresIn=900,)# url — обычный HTTPS URL, работает без авторизации, живёт 15 минутRDS: база как сервис, Multi-AZ против реплик
Заголовок раздела «RDS: база как сервис, Multi-AZ против реплик»RDS — управляемый PostgreSQL/MySQL: AWS патчит, бэкапит (снапшоты + WAL-архивы, point-in-time recovery до 35 дней назад) и делает failover. Механики Multi-AZ и read replicas описаны в RDS User Guide. Но два механизма резервирования решают разные задачи, и путать их — классическая ошибка:
| Multi-AZ | Read Replica | |
|---|---|---|
| Цель | Отказоустойчивость | Масштабирование чтения |
| Репликация | Синхронная | Асинхронная (лаг секунды) |
| При failover | DNS-имя переключается на standby автоматически, 1–2 минуты | Не участвует, пока ты сам не промотишь |
| Читать с неё | Нельзя | Можно, с лага |
| Цена | ~2x инстанса | ~1x инстанса за реплику |
# Postgres 16, мультизона, шифрование, автообновление минорных версийaws rds create-db-instance \ --db-instance-identifier petdb \ --engine postgres --engine-version 16 \ --db-instance-class db.t4g.micro \ --allocated-storage 20 --storage-encrypted \ --multi-az \ --master-username appuser \ --manage-master-user-password \ # пароль в Secrets Manager, не в истории bash --backup-retention-period 7 \ --db-subnet-group-name private-subnetsLambda: функции и их подводные камни
Заголовок раздела «Lambda: функции и их подводные камни»Lambda запускает код по событию без серверов: HTTP (через API Gateway), загрузка объекта в S3, сообщение в SQS/Stream, расписание (EventBridge). Модель оплаты — за миллионы запросов и гигабайт-секунды памяти. Тысячи вызовов в день обойдутся в копейки; постоянно работающий API на Lambda обойдётся дороже, чем контейнеры. Лимиты и модель исполнения — в документации Lambda.
Лимиты, которые реально встречаются: память 128 МБ – 10 ГБ (CPU выдаётся пропорционально), максимум 15 минут выполнения (дольше — нельзя, задачу надо дробить), пакет кода 250 МБ, развёртывание 1000 одновременных инстансов по умолчанию (мягкий лимит, поднимается запросом).
Холодный старт — первый вызов после простоя (или при масштабировании) тратит время на подготовку окружения: сотни миллисекунд для Node.js, до нескольких секунд для Java или тяжёлых зависимостей. Митигация: держать функцию тёплой (пинг раз в 5 минут — костыль, но работает), Provisioned Concurrency (AWS сам держит N готовых окружений — стоит денег), миниатюрные рантаймы и ленивая загрузка зависимостей.
// index.mjs — Node.js 20, ленивая инициализация: тяжёлый импорт внутри обработчикаlet db; // коннект создаётся один раз и живёт между вызовами тёплого инстанса
export const handler = async (event) => { db ??= await createConnection(); // только при первом вызове const { key } = event.Records[0].s3.object; // обработка... return { statusCode: 200 };};VPC: сеть, в которой всё живёт
Заголовок раздела «VPC: сеть, в которой всё живёт»VPC — твой изолированный участок облака с выбранным адресным пространством (например, 10.0.0.0/16). Ты делишь его на подсети, каждая подсеть привязана к одной AZ и получает route table — таблицу маршрутизации. Подсеть с маршрутом 0.0.0.0/0 → Internet Gateway — публичная: из неё виден интернет (и интернет видит инстанс, если Security Group разрешает). Без этого маршрута — приватная: входящих извне нет, исходящих тоже, пока не добавить NAT.
Internet │ ┌───────▼────────┐ │ Internet Gw │ └───┬────────┬───┘ │ │ (только из публичной) ┌─────────▼───┐ │ │ Route: │ │ │ 0.0.0.0/0 │ │ │ → IGW │ │ └──────┬──────┘ │ ┌───────────────┼───────────┼───────────────────┐ │ VPC 10.0.0.0/16 │ │ │ ┌───▼────┐ │ │ ┌─────────────────┐ │ NAT │ исходящий │ │ │ Public subnet │ │ Gateway│ трафик из │ │ │ 10.0.1.0/24 │ └───┬────┘ приватной │ │ │ │ │ подсети │ │ │ ALB / bastion │ │ маскируется│ │ └────────┬────────┘ │ публичным │ │ │ │ IP NAT │ │ ┌────────▼────────┐ ◄────┘ │ │ │ Private subnet │ Route: 0.0.0.0/0 │ │ │ 10.0.2.0/24 │ → NAT Gateway │ │ │ │ │ │ │ EC2 (app) │ │ │ │ RDS (база) │ │ │ └─────────────────┘ │ └───────────────────────────────────────────────┘Почему это важно: база данных в приватной подсети не имеет публичного IP и физически недостижима из интернета — независимо от того, кто взломал твоё приложение. Приложение из приватной подсети ходит наружу (обновления, вызовы API) через NAT Gateway, который заменяет их частные IP на свой публичный.
CloudWatch: глаза и уши инфраструктуры
Заголовок раздела «CloudWatch: глаза и уши инфраструктуры»CloudWatch собирает метрики (CPU, сетевой трафик, латентность ALB), логи (агент на инстансе или встроенная интеграция Lambda) и алерты. Метрики базовые приходят бесплатно каждые 5 минут; детализация до 1 минуты — платная опция. Логи — отдельная строка расходов: один балбечущий сервис может писать гигабайты в день.
# Алерт: CPU выше 80% два периода подряд (10 минут) → SNS → email/Telegramaws cloudwatch put-metric-alarm \ --alarm-name high-cpu \ --metric-name CPUUtilization --namespace AWS/EC2 \ --dimensions Name=InstanceId,Value=i-0abc123 \ --statistic Average --period 300 \ --evaluation-periods 2 --threshold 80 \ --comparison-operator GreaterThanThreshold \ --alarm-actions arn:aws:sns:eu-west-1:123:alerts-topic
# Подписка топика на emailaws sns subscribe --topic-arn arn:aws:sns:eu-west-1:123:alerts-topic \ --protocol email --notification-endpoint oncall@example.com
# Греп по логам Lambda за последний часaws logs filter-log-events \ --log-group-name /aws/lambda/my-func \ --start-time $(($(date +%s%3N) - 3600000)) \ --filter-pattern "ERROR"Hetzner и DigitalOcean: прагматичная альтернатива
Заголовок раздела «Hetzner и DigitalOcean: прагматичная альтернатива»AWS — индустриальный инструмент: сотни сервисов, сложность, цена за гибкость. Для pet-проекта, MVP и большинства маленьких SaaS — избыточен.
| Критерий | AWS | Hetzner Cloud | DigitalOcean |
|---|---|---|---|
| VPS 2 CPU / 4 GB | ~$30–40/мес (t3.medium + трафик) | ~€5/мес, трафик 20 ТБ включён | ~$24/мес, трафик включён |
| Управляемая БД | RDS от ~$15/мес + storage | нет (поднимай сам) | Managed PG от $15/мес |
| Объектное хранилище | S3, $0.023/ГБ | нет | Spaces, $5/мес за 250 ГБ |
| Сложность | высокая: IAM, VPC, 200+ сервисов | низкая: проект → сервер → firewall | низкая: аналогично |
| Масштаб/фичи | бесконечный | до сотен серверов | до сотен серверов |
| Биллинг-сюрпризы | да (NAT, egress, логи) | почти нет: фикс цена | почти нет |
Прагматичная стратегия: учись на Hetzner/DO (концепции те же: виртуалка, снапшот, приватная сеть, firewall, managed БД), а AWS используй, когда проект перерос простое — нужны очереди, распределённые системы, соответствие требованиям Enterprise-клиентов или команда, которая уже живёт в AWS. Многие компании строят гибрид: вычисления на Hetzner, бэкапы в S3, CDN на CloudFront.
Типичные ошибки и грабли
Заголовок раздела «Типичные ошибки и грабли»- SSH открыт на весь интернет.
0.0.0.0/0:22в Security Group — боты подбирают пароли в течение часов после создания инстанса. Разреши только свой IP, лучше — вообще убери SSH наружу и ходи через AWS Systems Manager Session Manager (бастион без открытых портов). - Одна AZ для «экономии». Экономия в 50% стоимости инстанса оборачивается полным даунтаймом на время падения AZ (обычно 30–60 минут, бывали часы). Multi-AZ для базы — не опция, а норма.
- Версионирование S3 без lifecycle. Через год в бакете — сотни тысяч старых версий, и счёт за хранение вырос в десять раз. Всегда добавляй
NoncurrentVersionExpiration. - Ключи в коде вместо ролей. Access key в репозитории — это ключ от всего облака (если политика широкая). GitHub сканирует утечки, но сканирование — реакция, а не профилактика. На EC2 и Lambda — только IAM-роли.
- Холодные старты игнорируют. API на Lambda с p99 в 4 секундах из-за стартов — типичный результат. Меряй реальную латентность, а не среднюю; средняя спрячет проблему.
- CloudWatch-логи без retention. По умолчанию логи хранятся бесконечно. Один цикл с ошибками = десятки гигабайт = счёт за хранение. Ставь retention 7–30 дней:
aws logs put-retention-policy --log-group-name ... --retention-in-days 30.
Вопросы на собеседовании
Заголовок раздела «Вопросы на собеседовании»- Чем Multi-AZ отличается от Read Replica в RDS? Multi-AZ — синхронная standby-копия только для failover, читать с неё нельзя; Read Replica — асинхронная копия для разгрузки чтения с возможным лагом. Первое про доступность, второе — про масштабирование.
- Почему базу кладут в приватную подсеть? Чтобы у неё не было публичного маршрута вообще: защита не на уровне пароля, а на уровне сетевой топологии. Даже при компрометации приложения злоумышленник не может подключиться к БД извне.
- Как дать приложению на EC2 доступ к S3 без ключей? Создать IAM-роль с политикой на конкретный бакет, прикрепить к инстансу через instance profile. Ключи временные, ротируются, в коде ничего нет.
- Что такое холодный старт Lambda и как с ним бороться? Задержка первого вызова из-за инициализации окружения. Лечится миниатюрными рантаймами, ленивой загрузкой, Provisioned Concurrency и архитектурно — не кладя латентно-чувствительные пути на Lambda.
- Зачем NAT Gateway, если есть Internet Gateway? IGW даёт инстансам публичные IP и двусторонний доступ из интернета. Приватные подсети не должны быть видны снаружи, но им нужен исходящий доступ — его даёт NAT, подменяя частные адреса своим публичным.
- S3 реплицирует данные между AZ. Почему тогда нужно версионирование? AZ-репликация защищает от потери дата-центра, но не от человека: перезаписал или удалил файл — перезаписался везде. Версионирование защищает от ошибок и ransomware.
Практика
Заголовок раздела «Практика»- Заведи AWS-аккаунт (или используй учебный), первым делом настрой MFA для root, создай IAM-пользователя с правами администратора для работы, включи Budgets с алертами на $10. Только после этого создавай ресурсы.
- Собери VPC с нуля через CLI или Terraform:
10.0.0.0/16, по одной публичной и приватной подсети в двух AZ, NAT Gateway, route tables. Подними t3.micro в приватной подсети и докажи, что из интернета до него не достучаться, а она сама выходит наружу через NAT (curl ifconfig.meс неё покажет IP NAT). - Подними RDS Postgres с Multi-AZ в тех же приватных подсетях. Приложение — в публичной подсети за ALB (или хотя бы с Security Group, ограничивающим доступ к БД по группе приложения). Проверь failover:
aws rds reboot-db-instance --db-instance-identifier petdb --force-failoverи понаблюдай за DNS. - Создай S3-бакет с версионированием и lifecycle-политикой из примера выше. Напиши скрипт бэкапа:
pg_dump | gzip | aws s3 cp - s3://bucket/backups/$(date +%F).sql.gz. Затем «случайно» перезапиши бэкап пустым файлом и восстанови старую версию черезaws s3api list-object-versions. - Напиши Lambda на Node.js, триггер — загрузка файла в S3 (префикс
incoming/), функция копирует его вprocessed/и пишет лог. Замерь холодный и тёплый старт через CloudWatch Logs (добавьconsole.log(Date.now() - start)).
Что почитать
Заголовок раздела «Что почитать»- AWS Well-Architected Framework — шесть столпов: операционное совершенство, безопасность, надёжность, эффективность, оптимизация стоимости, устойчивость.
- AWS VPC Documentation — официальное описание сетевой модели.
- IAM Best Practices — рабочий чек-лист по правам.
- Hetzner Cloud Docs и DigitalOcean Docs — та же модель, проще изложенная.
- AWS CLI Command Reference — все команды из этой главы с полным списком параметров.