Архитектор облачной инфраструктуры
Проектирует масштабируемую, безопасную и экономичную облачную архитектуру в AWS, Azure или GCP с IaC и дорожной картой.
Пример запуска
Сгенерировано Claude Opus 5.5, 23 сентября 2026 г.
Значения переменных
- Cloud provider
- AWS (основной регион — eu-central-1, Франкфурт; DR-регион — eu-west-1, Ирландия)
- Workload type
- Backend маркетплейса товаров ручной работы (handmade e-commerce): каталог, корзина, заказы, платежи, уведомления — микросервисы на Go и Node.js, REST + GraphQL API, веб- и мобильный клиенты
- Expected scale
- ~250 000 активных пользователей в месяц, обычная нагрузка 150–300 RPS, пиковая (Чёрная пятница, декабрьские распродажи) до 1200 RPS; каталог ~2 млн товарных позиций, БД заказов растёт на ~500 тыс. записей/год; ожидаемый рост общего трафика x3 в течение ближайших 12 месяцев
- Availability requirements
- Целевой SLA для внешнего API — 99.95% (допустимый простой ~22 минуты в месяц). RTO (Recovery Time Objective) — не более 1 часа для полного восстановления сервиса после отказа региона, RPO (Recovery Point Objective) — не более 15 минут потери данных заказов и платежей. Архитектура должна быть отказоустойчивой минимум в пределах 3 зон доступности (AZ) внутри основного региона eu-central-1, с возможностью ручного или автоматического переключения (failover) на резервный регион eu-west-1 в случае катастрофического отказа. Для критичных данных (заказы, платежи, пользователи) требуется синхронная репликация в пределах региона и асинхронная межрегиональная репликация с лагом не более 5 минут. Плановые технические работы должны проводиться без простоя (zero-downtime deployments, blue/green или canary). Требуется автоматизированное тестирование disaster recovery не реже одного раза в квартал.
- Budget constraints
- $10 000–12 000 в месяц на облачную инфраструктуру (без учёта ФОТ), допустимо кратковременное превышение до $15 000 в пиковые месяцы (ноябрь–декабрь); приоритет — предсказуемость расходов и возможность прогнозирования на 6 месяцев вперёд
- Compliance requirements
- Обязательное соответствие GDPR (обработка персональных данных граждан ЕС: имена, адреса доставки, история заказов, email) — требуется хранение и обработка персональных данных исключительно в дата-центрах ЕС, реализация права на удаление данных («право на забвение») с полным удалением из всех бэкапов и логов в течение 30 дней по запросу, ведение журнала доступа к персональным данным сроком не менее 1 года, назначенный DPO (Data Protection Officer). Платежи обрабатываются через Stripe как процессинговый партнёр, поэтому требуется соответствие PCI DSS уровня SAQ A — компания не хранит, не обрабатывает и не передаёт номера карт напрямую, вся чувствительная платёжная информация остаётся на стороне Stripe (используется Stripe Elements/Checkout). Требуется шифрование персональных данных в состоянии покоя (at rest) и при передаче (in transit, TLS 1.2+), а также регулярный (не реже раза в год) внешний аудит безопасности инфраструктуры.
- Current state
- Монолитное приложение на Ruby on Rails 7, развёрнуто на одном выделенном сервере Hetzner (32 GB RAM, 8 vCPU); PostgreSQL 14 работает на том же сервере без репликации и без автоматических бэкапов, кроме еженедельного ручного дампа; деплой производится вручную через Capistrano разработчиками с локальных машин; CI/CD отсутствует, тесты запускаются локально; мониторинг ограничен базовым UptimeRobot без алертинга по метрикам и без централизованного логирования; команда — 6 инженеров (4 backend, 1 frontend, 1 DevOps на part-time), опыта работы с облачными провайдерами в команде минимальный
Архитектура AWS для handmade-маркетплейса: eu-central-1 (основной) + eu-west-1 (DR)
0. Уточняющие вопросы и принятые допущения
Часть вводных влияет на архитектуру и стоимость, но не указана. Ниже вопросы, а в скобках допущение, с которым я проектирую. Если допущение неверно, скорректируйте его, и я пересчитаю соответствующие разделы.
| # | Вопрос | Допущение [ДОП] |
|---|---|---|
| 1 | Переписывание Rails → Go/Node.js уже идёт или это целевое состояние? | [ДОП-1] Это целевое состояние. Сейчас в продакшене Rails-монолит, миграция поэтапная (strangler fig). |
| 2 | Объём медиа (фото товаров) и исходящий трафик? | [ДОП-2] ~8 ТБ изображений в S3 и ~8 ТБ/мес исходящего трафика через CDN. Это самая неопределённая статья затрат. |
| 3 | География пользователей? | [ДОП-3] Преимущественно ЕС, мобильные и веб-клиенты. |
| 4 | Git-хостинг и CI? | [ДОП-4] GitHub + GitHub Actions. Их стоимость не входит в облачный бюджет. |
| 5 | Как устроен фронтенд (SPA или SSR)? | [ДОП-5] SPA/статическая сборка в S3 + CloudFront. Если нужен SSR (Next.js), он выносится отдельным ECS-сервисом. |
| 6 | Есть ли юридическая обязанность хранить счета и заказы (для Германии: HGB/AO, 6–10 лет)? | [ДОП-6] Есть. Финансовые записи заказов при запросе на удаление анонимизируются, но не удаляются (исключение по ст. 17(3)(b) GDPR). Решение за DPO и юристом. |
| 7 | Провайдер email и push-уведомлений? | [ДОП-7] Email через Amazon SES (eu-central-1), push через FCM/APNs без персональных данных в payload. |
| 8 | Что входит в «внешний API 99.95%»? | [ДОП-8] SLA измеряется на входе (CloudFront/ALB) по успешным ответам API, без учёта деградации внешних зависимостей (Stripe, SES). |
| 9 | Уровень поддержки AWS? | [ДОП-9] Business Support. При целевом SLA 99.95% это обязательно. |
1. Краткое резюме решения
Предлагаю контейнерную архитектуру на ECS Fargate (Graviton/ARM64) в 3 AZ региона eu-central-1. Данные размещаются так:
- транзакционные данные — в Aurora PostgreSQL (синхронный кворум 4/6 копий в 3 AZ) с Aurora Global Database в eu-west-1 (типичный лаг меньше 1 с при требовании до 5 мин);
- корзины, сессии и ключи идемпотентности — в DynamoDB Global Tables;
- кэш — в ElastiCache (Valkey);
- поиск по каталогу из 2 млн позиций — в OpenSearch.
DR-регион работает в режиме warm standby: минимальная копия сервисов запущена и масштабируется по runbook. Это закрывает RTO 1 ч и RPO 15 мин примерно за 8% бюджета, тогда как active-active обошёлся бы в 1.8–2 раза дороже и был бы на порядок сложнее для команды из 6 человек.
ECS Fargate выбран вместо EKS осознанно. В команде минимальный облачный опыт и один DevOps на part-time, поэтому сопровождение Kubernetes (обновления control plane, add-on'ы, CNI, Karpenter) создаёт операционный риск выше, чем экономия от гибкости K8s. При этом ECS поддерживает нативные blue/green и canary-деплои.
GDPR реализуется через четыре механизма:
- Service Control Policy (SCP), разрешающие работу только в двух регионах ЕС;
- отсутствие персональных данных в логах;
- удержание бэкапов не более 28 дней в сочетании с реестром удалений;
- оркестратор «права на забвение» на Step Functions.
PCI DSS SAQ A обеспечивается тем, что данные карт никогда не касаются нашей инфраструктуры: используются Stripe Checkout/Elements, а в нашей системе хранятся только токены и идентификаторы Stripe.
Ориентировочная стоимость — ~$11.3K/мес по on-demand ценам и ~$10.2K после покупки обязательств (Savings Plans/RI), в пиковые месяцы — ~$12.8–13.5K.
⚠️ Важно по срокам. Сегодня 23.09.2026, а Чёрная пятница 27.11.2026. Не переносите продакшен в AWS до пика. Перенос для команды без облачного опыта за 2 месяца до максимальной нагрузки — главный риск всего проекта. План на Q4 2026 — укрепить Hetzner (раздел 8, этап 0), а прод-cutover в AWS провести в январе–феврале 2027.
2. Диаграмма архитектуры
2.1 Структура аккаунтов (AWS Organizations + Control Tower)
AWS Organization (management account — только биллинг и Organizations, без нагрузок)
├── OU: Security
│ ├── security-tooling ← делегированный админ GuardDuty, Security Hub, Config, Macie, Inspector
│ └── log-archive ← org CloudTrail, VPC Flow Logs, audit-логи доступа к ПДн (S3 Object Lock, 13 мес)
├── OU: Infrastructure
│ └── shared-services ← ECR (+репликация в eu-west-1), Route 53 hosted zones, роль CI через OIDC
├── OU: Workloads
│ ├── prod (eu-central-1 = primary, eu-west-1 = DR)
│ ├── stage (eu-central-1; раз в квартал — DR-учения в eu-west-1)
│ └── dev (eu-central-1)
└── SCP: запрет регионов вне eu-central-1/eu-west-1, запрет отключения CloudTrail/GuardDuty/Config,
запрет выхода из организации, запрет создания IAM-пользователей и ключей доступа
2.2 Прод-топология
Пользователи (Web SPA / iOS / Android)
│ HTTPS, TLS 1.2+ (предпочтительно 1.3)
┌───────────────────┴──────────────────────┐
▼ ▼
┌─────────────────────────────────┐ ┌─────────────────────────────────────┐
│ CloudFront #1: static.example │ │ CloudFront #2: api.example │
│ SPA, изображения (S3 + OAC) │ │ AWS WAF (managed rules, rate-limit, │
│ Долгий кэш, WebP/AVIF │ │ Bot Control), Shield Standard │
│ Без ПДн │ │ Кэш только для публичного каталога │
└───────────────┬─────────────────┘ │ (persisted GraphQL queries, GET) │
│ └───────────────┬─────────────────────┘
▼ │ origin: origin-api.example
S3 media (eu-central-1) ▼
──CRR+RTC──► S3 (eu-west-1) Route 53 failover record + health checks
PRIMARY → ALB euc1 │ SECONDARY → ALB euw1
│
╔═════════════════════════════════════════════════════════════════╪══════════════════════════════╗
║ eu-central-1 (PRIMARY) — VPC 10.10.0.0/16 — AZ a / b / c ▼ ║
║ ┌─ Public /22 ×3 ──────────────────────────────────────────────────────────────────────────┐ ║
║ │ ALB (HTTPS 443, TLS13-1-2 policy, SG разрешает только CloudFront prefix list) │ ║
║ │ NAT Gateway ×3 (по одному на AZ) │ ║
║ └──────────────────────────────────────────────────────────────────────────────────────────┘ ║
║ ┌─ Private-app /19 ×3 ─── ECS Fargate (ARM64), задачи в 3 AZ, min 3 на критичный сервис ───┐ ║
║ │ graphql-gateway (Node.js) ──┬─► catalog-svc (Go) ──► search-indexer (Go worker) │ ║
║ │ REST /v1/* ├─► cart-svc (Go) ──────► DynamoDB carts/sessions │ ║
║ │ ├─► order-svc (Go) ───┐ │ ║
║ │ ├─► payment-svc (Go) ─┼──► Stripe API (egress через NAT) │ ║
║ │ │ ▲ webhooks /stripe (проверка подписи) │ ║
║ │ ├─► user-svc (Node.js) ← PII vault (шифрование ПДн) │ ║
║ │ └─► legacy-rails (на период strangler fig) │ ║
║ │ notification-svc (Node.js worker) ◄── SQS ◄── EventBridge ◄── Transactional Outbox │ ║
║ │ gdpr-erasure (Step Functions + Lambda) │ ║
║ └──────────────────────────────────────────────────────────────────────────────────────────┘ ║
║ ┌─ Private-data /22 ×3 (без маршрута в интернет) ──────────────────────────────────────────┐ ║
║ │ RDS Proxy ──► Aurora PostgreSQL 16: writer (AZ-a), reader (AZ-b), autoscale-readers │ ║
║ │ общий storage: 6 копий в 3 AZ, кворумная синхронная запись │ ║
║ │ ElastiCache Valkey: primary + 2 replica (3 AZ), TLS + AUTH, Multi-AZ auto-failover │ ║
║ │ OpenSearch: 3 data-ноды (3 AZ) + 3 dedicated masters │ ║
║ └──────────────────────────────────────────────────────────────────────────────────────────┘ ║
║ Региональные сервисы (через VPC endpoints): S3/DynamoDB (gateway, бесплатно), ECR, Secrets ║
║ Manager, KMS, SQS, STS, CloudWatch Logs (interface). SES, EventBridge, Step Functions. ║
╚══════════════════════════╤═════════════════════════════════════════════════════════════════════╝
│ асинхронная репликация (цель ≤ 5 мин, факт обычно < 1 с)
│ • Aurora Global Database (storage-level)
│ • DynamoDB Global Tables
│ • S3 CRR + Replication Time Control (SLA 15 мин)
│ • OpenSearch Cross-Cluster Replication (индекс каталога)
│ • ECR replication, Secrets Manager replica, KMS multi-region keys
│ • AWS Backup cross-region copy (снапшоты, 28 дней)
╔══════════════════════════▼═════════════════════════════════════════════════════════════════════╗
║ eu-west-1 (DR, WARM STANDBY) — VPC 10.20.0.0/16 — 3 AZ ║
║ ALB + ECS Fargate: по 1 задаче на сервис (прогрето, проходит health checks) ║
║ Aurora secondary cluster: 1× db.r7g.large (read-only, при failover становится writer) ║
║ Valkey: 1 нода (холодный кэш допустим); OpenSearch: 2 ноды (follower-индекс) ║
║ NAT ×1 (при failover → ×3 через Terraform), тот же набор VPC endpoints ║
╚════════════════════════════════════════════════════════════════════════════════════════════════╝
Наблюдаемость: ADOT/OpenTelemetry → CloudWatch (метрики, логи, X-Ray/Application Signals),
SLO-дашборды, CloudWatch Alarms → SNS → PagerDuty (on-call). Sentry — для ошибок клиентов.
Почему API за CloudFront, а не напрямую на ALB. Это даёт WAF и Shield на edge, TLS-терминацию ближе к пользователю и кэширование публичного каталога. Кэш CloudFront физически распределён в том числе вне ЕС, поэтому ответы с персональными данными отдаются с Cache-Control: private, no-store и никогда не кэшируются. Транзит через edge-локации покрывается AWS DPA. Это решение нужно зафиксировать в реестре обработки (RoPA) и согласовать с DPO. Консервативная альтернатива: регионный ALB с WAF для запросов с ПДн и CloudFront только для каталога. Она безопаснее с юридической точки зрения, но медленнее для пользователей и сложнее в эксплуатации.
3. Таблица ключевых сервисов AWS
| Слой | Компонент | Сервис AWS | Назначение / обоснование |
|---|---|---|---|
| Edge | CDN статики и медиа | CloudFront + S3 (OAC) | Снимает 80–90% трафика с origin, отдаёт изображения в WebP/AVIF |
| Edge | CDN и защита API | CloudFront + AWS WAF + Shield Standard | OWASP- и bot-правила, rate limiting, защита от L3/L4 DDoS |
| DNS | DNS и failover | Route 53 (failover routing, health checks) | Переключение origin между регионами, TTL 60 с |
| Вход | Балансировка | ALB (3 AZ) | L7-маршрутизация на ECS, blue/green через два target group'а. API Gateway при 150–1200 RPS стоил бы около $2K/мес против ~$150 |
| Compute | Микросервисы | ECS on Fargate (ARM64/Graviton) | Нет серверов и control plane, оплата за vCPU/GB, нативный blue/green и canary |
| Compute | Асинхронные задачи | ECS Fargate (частично Fargate Spot), Lambda | Воркеры уведомлений, индексации, GDPR-джобы |
| Данные | Заказы, платежи, пользователи, каталог | Aurora PostgreSQL 16 + Global Database | Синхронный кворум в 3 AZ, межрегиональный лаг меньше 1 с, managed failover |
| Данные | Пул соединений | RDS Proxy | Node.js создаёт много соединений; прокси ускоряет failover writer'а |
| Данные | Корзина, сессии, идемпотентность | DynamoDB (on-demand) + Global Tables | Синхронная репликация в 3 AZ, асинхронная в DR, не требует администрирования |
| Данные | Кэш | ElastiCache for Valkey | Карточки товаров, счётчики, rate limits. Valkey примерно на 20% дешевле Redis OSS |
| Данные | Поиск | Amazon OpenSearch Service | Полнотекстовый поиск и фасеты по 2 млн товаров |
| Данные | Медиа, бэкапы, логи | S3 (+CRR, Intelligent-Tiering, Object Lock для audit) | Хранение с опциональной неизменяемостью |
| Интеграция | События | EventBridge + SQS (+DLQ), transactional outbox | Слабая связность сервисов, надёжная доставка событий заказов |
| Интеграция | Оркестрация | Step Functions | Сага оформления заказа, workflow удаления данных по GDPR, DR-runbook |
| Коммуникации | Amazon SES (eu-central-1) | Транзакционные письма, обработка данных в ЕС | |
| Безопасность | Идентификация | IAM Identity Center + permission sets | SSO, без IAM-пользователей, MFA обязательна |
| Безопасность | Ключи и секреты | KMS (CMK, multi-region keys), Secrets Manager | Шифрование at rest, ротация паролей БД, ключи Stripe |
| Безопасность | Детекция и соответствие | GuardDuty, Security Hub, Config, Inspector, Macie, CloudTrail (org) | Непрерывный контроль, поиск ПДн в S3, доказательная база для аудита |
| Безопасность | Периметр | Security Groups, NACL, VPC endpoints, VPC Flow Logs | Сегментация на уровне сети |
| Надёжность | Бэкапы и DR | AWS Backup (cross-region copy), FIS, Resilience Hub | Ежеквартальные автоматизированные DR-учения |
| Наблюдаемость | Метрики, логи, трейсы | CloudWatch, X-Ray/Application Signals (через ADOT) | Единый стек без отдельной эксплуатации Prometheus/Grafana |
| FinOps | Контроль затрат | Cost Explorer, Budgets, Cost Anomaly Detection, CUR 2.0 | Прогноз на 6 месяцев вперёд, алерты об аномалиях |
4. Проектирование по направлениям
4.1 Топология, HA и DR
Сеть. В каждом окружении и регионе своя VPC, диапазоны не пересекаются: prod-euc1 10.10/16, prod-euw1 10.20/16, stage 10.30/16, dev 10.40/16. Это заложено на будущее под Transit Gateway или peering. В каждой VPC три уровня подсетей по 3 AZ:
- public — только ALB и NAT;
- private-app — ECS-задачи, большие /19 с запасом IP под масштабирование Fargate;
- private-data — без маршрута в интернет.
Высокая доступность внутри региона (закрывает 99.95%):
- ECS: у критичных сервисов минимум 3 задачи,
availability_zone_rebalancingвключён, на ALB настроен cross-zone. - Aurora: при отказе writer'а reader (promotion tier 0) становится writer'ом примерно за 30 с. RDS Proxy сокращает видимый для приложения простой.
- Valkey: Multi-AZ с автоматическим failover, 2 реплики.
- OpenSearch: zone awareness на 3 AZ, 1 реплика на шард.
- Синхронная репликация в регионе для заказов, платежей и пользователей обеспечивается архитектурой хранилища Aurora: запись подтверждается кворумом 4 из 6 копий в 3 AZ. Для DynamoDB синхронная запись в 3 AZ работает по умолчанию.
Композитный SLA только самих AWS-сервисов (CloudFront 99.9% × ALB × ECS × Aurora) формально ниже 99.95%. На практике фактическая доступность этих сервисов значительно выше контрактной. Однако 99.95% — это 22 минуты в месяц, и основной риск здесь не AWS, а собственные деплои, миграции БД и инциденты. Поэтому сильнее всего SLA защищают canary-деплои, миграции по схеме expand/contract, SLO-алертинг и on-call.
DR (warm standby) — как выполняются RTO ≤ 1 ч и RPO ≤ 15 мин:
| Этап failover | Механизм | Время |
|---|---|---|
| Обнаружение | Route 53 health checks, CloudWatch composite alarms, AWS Health events | 5–10 мин |
| Решение | Ручное подтверждение дежурным и CTO. Автоматический межрегиональный failover не делаем — ложное срабатывание при split-brain опаснее самого простоя | 5–10 мин |
| БД | Aurora Global Database: managed failover (unplanned) → secondary становится writer'ом | 1–5 мин |
| Compute | Step Functions/SSM runbook: desired_count DR-сервисов → прод-значения, NAT ×3, Valkey +реплики |
5–15 мин |
| Трафик | Route 53: переключение origin-записи (TTL 60 с), CloudFront сам начинает ходить в DR-ALB | 1–5 мин |
| Проверка | Синтетические тесты (CloudWatch Synthetics), сверка платежей со Stripe | 5–10 мин |
| Итого | ~25–50 мин (цель < 60) |
RPO. Лаг Aurora Global обычно меньше 1 с, DynamoDB Global Tables — секунды, S3 RTC — до 15 мин. Для платежей дополнительно работает reconciliation-джоб: после failover он забирает из Stripe Events API все события с последнего checkpoint'а и восстанавливает статусы. Даже гипотетически потерянные в лаге записи о платежах восстанавливаются из источника истины (Stripe).
Риск ёмкости в DR. При региональной аварии многие клиенты AWS одновременно масштабируются в соседних регионах. Задачи, которые уже запущены в режиме warm standby, частично снимают этот риск. Для критичных сервисов можно дополнительно держать в DR 2 задачи вместо 1.
Ежеквартальное DR-тестирование:
- Ежемесячно (stage): AWS FIS-сценарии: остановка задач, потеря AZ (сценарий «AZ Availability: Power Interruption»), failover Aurora.
- Ежеквартально (stage): полный региональный switchover (Aurora Global switchover → DR → обратное переключение). Выполняется автоматическим Step Functions runbook'ом с замером RTO/RPO и отчётом в S3 (артефакт для аудиторов).
- Раз в полгода (prod): плановый switchover в низкий трафик после двух успешных stage-прогонов.
- Отдельно: тест восстановления бэкапа (point-in-time restore в изолированный аккаунт) — проверяет, что бэкапы действительно восстанавливаются.
4.2 Безопасность
IAM и наименьшие привилегии:
- Нет IAM-пользователей и долгоживущих ключей (запрещено через SCP). Люди входят через IAM Identity Center с обязательной MFA.
- Permission sets:
ReadOnly— все инженеры, prod;Developer— полный доступ в dev, ограниченный в stage;ProdOperator— 2–3 человека, с временным повышением прав через TEAM или ручной approval;BreakGlass— хранится в сейфе, любое использование вызывает алерт.
- CI работает через GitHub OIDC → IAM role с условием на
repo:org/repo:environment:prod. Статические ключи не используются. - У каждого ECS-сервиса свой task role с доступом только к своей таблице, очереди и секретам. Например,
payment-svcчитает только секретstripe/*. Execution role отделён от task role. - Доступ к БД: IAM auth и отдельные роли PostgreSQL на каждый сервис (схема = сервис). Прямой доступ людей к prod-БД возможен только через SSM Session Manager с записью сессии, без bastion-хостов с SSH.
Сегментация сети:
- SG ALB разрешает 443 только из managed prefix list
com.amazonaws.global.cloudfront.origin-facing. Дополнительно CloudFront передаёт секретный заголовок, который проверяется на ALB. - SG приложений разрешает вход только от ALB и сервис-к-сервису по нужным портам. SG данных разрешают вход только от SG конкретных сервисов.
- Data-подсети не имеют маршрута в интернет. Egress из app-подсетей идёт через NAT к Stripe, APNs/FCM и прочим внешним API. На следующем этапе можно добавить AWS Network Firewall с allow-list доменов (~$300+/мес, отложено по бюджету).
- VPC Flow Logs направляются в log-archive.
Шифрование:
- At rest: KMS CMK отдельно для доменов
pii,orders,logs,backupsс ежегодной автоматической ротацией. Для S3 CRR и прикладного шифрования используются multi-region keys. Шифруются Aurora, DynamoDB, S3 (SSE-KMS + Bucket Keys ради экономии запросов к KMS), EBS, OpenSearch, Valkey, SQS и бэкапы. - Дополнительно для ПДн (email, телефон, адрес) — прикладное envelope-шифрование в
user-svc(AWS Encryption SDK). Администратор БД видит только шифротекст, а дампы и логи не раскрывают ПДн. - In transit:
- CloudFront:
TLSv1.2_2021; - ALB:
ELBSecurityPolicy-TLS13-1-2-2021-06; - Aurora:
rds.force_ssl=1; - Valkey: in-transit encryption;
- OpenSearch: enforce HTTPS;
- внутри VPC ALB ходит в задачи по HTTPS. Service Connect с TLS — опция, на старте её можно отложить: трафик и так остаётся в изолированных подсетях.
- CloudFront:
Управление секретами. Все секреты хранятся в Secrets Manager: пароли БД с автоматической ротацией, секретные ключи Stripe, webhook signing secret. В задачи они попадают через secrets в task definition. Секреты реплицируются в eu-west-1. В git и переменных CI секретов нет, это проверяют gitleaks в pre-commit и secret scanning в GitHub.
GDPR:
| Требование | Реализация |
|---|---|
| Хранение и обработка только в ЕС | SCP с deny для всех регионов, кроме eu-central-1 и eu-west-1 (с исключениями для глобальных сервисов IAM, CloudFront, Route 53, Support). Все субпроцессоры (SES, Stripe, провайдер push) проверяются и вносятся в реестр. CloudFront не кэширует ПДн. |
| Разделение ПДн | «PII vault» в user-svc: ПДн хранятся только там и в зашифрованном виде. Остальные сервисы (заказы, аналитика) оперируют user_id и снапшотом адреса доставки, который тоже зашифрован ключом пользователя. |
| Право на забвение за 30 дней | Step Functions workflow:<br>1) запрос → верификация личности;<br>2) событие UserErasureRequested в EventBridge;<br>3) каждый сервис удаляет или анонимизирует свои данные и отвечает ErasureCompleted: S3 — удаление всех версий в обоих регионах (CRR не переносит удаления версий автоматически); OpenSearch, DynamoDB и Valkey — удаление записей и сброс кэша; Stripe — DELETE /v1/customers/{id};<br>4) заказы анонимизируются, финансовые поля остаются по [ДОП-6];<br>5) удаляется per-user ключ шифрования (crypto-shredding);<br>6) формируется отчёт-доказательство для DPO. |
| Удаление из бэкапов | Хранение PITR и снапшотов — 28 дней (меньше 30), поэтому бэкапы с удалёнными данными истекают естественным образом. Реестр удалений (хэши user_id) лежит в отдельной таблице и автоматически применяется скриптом при любом восстановлении из бэкапа. Если бизнесу нужны долгосрочные архивы, они хранятся только с прикладным шифрованием per-user ключами: удаление ключа делает данные в архиве нечитаемыми. |
| Удаление из логов | Правило «никаких ПДн в логах»: структурированный логгер с redaction-фильтром плюс проверки в code review и тестах. Macie сканирует лог-бакеты на утечки. Retention прикладных логов — 30 дней. |
| Журнал доступа к ПДн от 1 года | Каждый доступ к ПДн через user-svc и админку пишет событие (кто, когда, чей user_id, цель) → Firehose → S3 в log-archive с Object Lock на 13 месяцев. Дополнительно используются pgaudit по таблицам ПДн и CloudTrail (management + S3/KMS data events для PII-ресурсов). В журнале только псевдонимные идентификаторы, иначе Object Lock вступит в конфликт с правом на удаление. |
| DPO и процессы | Организационная сторона: DPO, RoPA, DPIA для маркетплейса, DPA с AWS (входит в AWS Service Terms) и Stripe, процедура уведомления о breach за 72 часа, опирающаяся на алерты GuardDuty и Security Hub. |
PCI DSS SAQ A:
- Используется Stripe Checkout (redirect) или Payment Element в iframe Stripe. PAN никогда не проходит через наш бэкенд, логи или CloudFront.
- В
payment-svcхранятся толькоcustomer_id,payment_intent_idи статусы. - Webhooks проверяются по подписи (
Stripe-Signature), для защиты от повторов обрабатываются идемпотентно через DynamoDB и допуск по времени. - Для страниц, встраивающих платёжную форму: строгий CSP, SRI для собственных скриптов, минимум сторонних скриптов, контроль изменений фронтенда через CI. Критерии пригодности SAQ A в PCI DSS v4.0.1 требуют, чтобы сайт мерчанта был защищён от атак через скрипты.
- Ежегодно заполняется SAQ A и проводятся ASV-сканы по требованию эквайера.
Детекция и аудит:
- GuardDuty (включая ECS Runtime Monitoring и RDS Protection);
- Security Hub с AWS Foundational Security Best Practices и CIS;
- AWS Config с conformance pack;
- Inspector для сканирования образов в ECR;
- Macie на S3;
- IAM Access Analyzer.
Результаты агрегируются в security-tooling. Ежегодный внешний аудит и пентест покупается у стороннего подрядчика (не входит в облачный бюджет, ориентировочно €15–30K в год). Для него готовятся артефакты: Config compliance history, отчёты DR-тестов, IaC и журналы доступа.
4.3 Масштабируемость и производительность
Расчёт ёмкости. Сейчас пик 1200 RPS. С ростом ×3 через 12 месяцев получается ~3600 RPS в пике и 450–900 RPS в обычном режиме. Архитектура спроектирована под 4000+ RPS без переделки, растёт только число задач и реплик.
-
ECS autoscaling:
- target tracking по
ALBRequestCountPerTargetи CPU 60%; - scale-out быстрый (cooldown 60 с), scale-in медленный (300 с);
- scheduled scaling перед Чёрной пятницей: min × 3 за 48 часов до пика, потому что Fargate поднимает задачи 1–2 минуты;
- для ALB — LCU Reservation (резервирование ёмкости) на пиковые дни.
- target tracking по
-
Aurora:
- read/write splitting: writer для транзакций, reader endpoint для каталога и истории заказов;
- Aurora Replica Auto Scaling от 1 до 3 readers по CPU и соединениям;
pg_stat_statementsи CloudWatch Database Insights для поиска тяжёлых запросов;- 2 млн товаров и 500 тыс. заказов в год — малый объём для Aurora. Партиционирование заказов (pg_partman по месяцам) понадобится не раньше чем через 2–3 года, на старте достаточно корректных индексов.
-
Кэширование (многоуровневое):
- CloudFront: статика (TTL в днях, versioned assets) и публичный каталог через persisted GraphQL queries по GET (TTL 60–300 с);
- Valkey: cache-aside для карточек, категорий и цен, инвалидация по событиям
ProductUpdated; - in-process LRU в Go-сервисах для справочников.
Цель — cache hit ratio каталога выше 90%.
-
Поиск. Индекс OpenSearch строится через CDC/outbox →
search-indexer. Поиск по 2 млн документов со всеми фасетами укладывается в 3 data-ноды r7g.large. -
Изображения. Ресайз и конвертация в WebP/AVIF выполняются при загрузке (Lambda) или on-the-fly (CloudFront + Lambda). Это главный рычаг снижения стоимости egress: минус 30–50% трафика.
-
Устойчивость к перегрузке:
- rate limiting в WAF (по IP) и в gateway (по пользователю);
- circuit breakers и таймауты во всех клиентах;
- очереди SQS как буфер для уведомлений и индексации;
- «деградация по плану»: при перегрузке отключаются рекомендации, а поиск откатывается на PostgreSQL FTS.
-
Нагрузочное тестирование (k6 или Distributed Load Testing on AWS) на stage перед каждым сезоном, профиль — 1.5 × ожидаемого пика.
4.4 DevOps и IaC
Организация окружений: dev, stage и prod — отдельные AWS-аккаунты. Это даёт изоляцию blast radius, раздельный биллинг и чистый периметр для аудита. Stage повторяет prod по топологии (3 AZ, Aurora Global в eu-west-1 для DR-учений), но с меньшими инстансами. Dev использует одну Aurora без реплики, единственный NAT и автоостановку вне рабочих часов.
CI/CD-пайплайн (GitHub Actions + OIDC):
PR: lint → unit-тесты → SAST (Semgrep) → gitleaks → build image (ARM64) → Trivy scan
→ integration-тесты (testcontainers: Postgres, Valkey, LocalStack)
→ terraform fmt/validate/tflint/checkov + terraform plan в комментарий PR
merge в main:
→ push в ECR (shared-services, immutable tags = git SHA, cosign-подпись)
→ auto-deploy в dev → smoke tests
→ auto-deploy в stage → e2e + contract tests (Pact) + миграции БД (expand)
→ manual approval (GitHub Environment "prod", 2 approvers)
→ prod: ECS native BLUE/GREEN или CANARY (10% → bake 10 мин → 100%)
автоматический rollback по CloudWatch alarms (5xx, p99 latency, SLO burn rate)
→ post-deploy synthetic checks
Infra: Terraform plan в PR → apply через CI после approve (никаких apply с ноутбуков)
Zero-downtime миграции БД. Строго по паттерну expand → migrate → contract:
- добавить колонку или таблицу, при необходимости включить двойную запись;
- задеплоить код, работающий с обеими схемами;
- сделать backfill батчами;
- удалить старое в следующем релизе.
Инструменты: golang-migrate или Atlas с проверкой опасных операций (lock-heavy ALTER, индексы без CONCURRENTLY).
Структура Terraform описана в разделе 5. Ключевые принципы:
- модули переиспользуются, root-модули разделены по слоям (network → data → services → edge), чтобы уменьшить blast radius и время
plan; - state хранится в S3 с нативной блокировкой (
use_lockfile, DynamoDB для блокировок больше не нужен); - версии модулей и провайдеров зафиксированы.
4.5 Оптимизация затрат (сводка, подробности в разделе 6)
- Graviton везде: Fargate ARM64, r7g/m7g для Aurora, Valkey и OpenSearch дают −20% к стоимости compute.
- Обязательства покупаются только после 2–3 месяцев стабильного прода, по фактической базовой линии, а не по прогнозу.
- Fargate Spot — для воркеров (индексация, email) и stage/dev.
- Расписание dev/stage: остановка ночью и в выходные экономит 60–65% на этих окружениях.
5. IaC-скелет (Terraform)
5.1 Структура репозитория infra/
infra/
├── modules/ # переиспользуемые, версионируются git-тегами
│ ├── network/ # VPC, подсети, NAT, endpoints, flow logs
│ ├── security-baseline/ # KMS, GuardDuty, Config, Security Hub (per account)
│ ├── aurora-global/ # global cluster + primary + secondary
│ ├── ecs-cluster/
│ ├── ecs-service/ # task def, service, ALB TG/rules, autoscaling, alarms
│ ├── elasticache-valkey/
│ ├── opensearch/
│ ├── edge/ # CloudFront, WAF, Route 53 failover
│ └── observability/ # dashboards, SLO alarms, SNS
├── live/
│ ├── org/ # Organizations, SCP, Identity Center, log-archive
│ ├── shared-services/ # ECR + replication, GitHub OIDC roles, Route 53 zones
│ ├── prod/
│ │ ├── eu-central-1/{network,data,platform,services,edge}/
│ │ └── eu-west-1/{network,platform,services}/ # DR
│ ├── stage/ (та же структура)
│ └── dev/
└── .github/workflows/terraform.yml
5.2 Провайдеры и backend (live/prod/eu-central-1/data/versions.tf)
terraform {
required_version = ">= 1.10" # нужен для use_lockfile в S3 backend
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0" # зафиксировать конкретную минорную версию в .terraform.lock.hcl
}
}
backend "s3" {
bucket = "acme-tfstate-prod" # отдельный bucket на аккаунт, versioning + SSE-KMS
key = "prod/eu-central-1/data/terraform.tfstate"
region = "eu-central-1"
encrypt = true
use_lockfile = true # нативная блокировка S3, без DynamoDB
}
}
locals {
tags = {
Project = "handmade-marketplace"
Environment = "prod"
Owner = "platform"
ManagedBy = "terraform"
DataClass = "pii" # переопределяется на ресурсах: public | internal | pii | financial
}
}
provider "aws" {
alias = "primary"
region = "eu-central-1"
default_tags { tags = local.tags }
}
provider "aws" {
alias = "dr"
region = "eu-west-1"
default_tags { tags = merge(local.tags, { Role = "dr" }) }
}
5.3 Сеть (live/prod/eu-central-1/network/main.tf)
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 6.0" # проверьте актуальную мажорную версию модуля
name = "prod-euc1"
cidr = "10.10.0.0/16"
azs = ["eu-central-1a", "eu-central-1b", "eu-central-1c"]
public_subnets = ["10.10.0.0/22", "10.10.4.0/22", "10.10.8.0/22"] # ALB, NAT
private_subnets = ["10.10.32.0/19", "10.10.64.0/19", "10.10.96.0/19"] # ECS tasks
database_subnets = ["10.10.160.0/22", "10.10.164.0/22", "10.10.168.0/22"]
enable_nat_gateway = true
one_nat_gateway_per_az = true # отказ AZ не ломает egress в других AZ
create_database_subnet_group = true
create_database_internet_gateway_route = false
create_database_nat_gateway_route = false # data-подсети полностью изолированы
enable_dns_hostnames = true
enable_dns_support = true
enable_flow_log = true
flow_log_destination_type = "s3"
flow_log_destination_arn = var.log_archive_flowlogs_bucket_arn
flow_log_max_aggregation_interval = 600
}
# Gateway endpoints (бесплатно) + ключевые interface endpoints, чтобы не гонять трафик через NAT
module "endpoints" {
source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints"
version = "~> 6.0"
vpc_id = module.vpc.vpc_id
security_group_ids = [aws_security_group.endpoints.id]
subnet_ids = module.vpc.private_subnets
endpoints = {
s3 = { service = "s3", service_type = "Gateway", route_table_ids = module.vpc.private_route_table_ids }
dynamodb = { service = "dynamodb", service_type = "Gateway", route_table_ids = module.vpc.private_route_table_ids }
ecr_api = { service = "ecr.api", private_dns_enabled = true }
ecr_dkr = { service = "ecr.dkr", private_dns_enabled = true }
logs = { service = "logs", private_dns_enabled = true }
secrets = { service = "secretsmanager", private_dns_enabled = true }
kms = { service = "kms", private_dns_enabled = true }
sqs = { service = "sqs", private_dns_enabled = true }
sts = { service = "sts", private_dns_enabled = true }
}
}
5.4 KMS и Aurora Global Database (live/prod/eu-central-1/data/aurora.tf)
# Multi-region CMK: один логический ключ в обоих регионах (удобно для S3 CRR и прикладного шифрования)
resource "aws_kms_key" "core_data" {
provider = aws.primary
description = "prod core data (orders, payments, users) - PII/financial"
enable_key_rotation = true
multi_region = true
deletion_window_in_days = 30
}
resource "aws_kms_replica_key" "core_data_dr" {
provider = aws.dr
primary_key_arn = aws_kms_key.core_data.arn
}
resource "aws_rds_cluster_parameter_group" "core" {
provider = aws.primary
name = "prod-core-apg16"
family = "aurora-postgresql16"
parameter {
name = "rds.force_ssl"
value = "1" # только TLS-подключения
}
parameter {
name = "shared_preload_libraries"
value = "pg_stat_statements,pgaudit"
apply_method = "pending-reboot"
}
parameter {
name = "pgaudit.log"
value = "ddl,role" # объектный аудит таблиц ПДн — через pgaudit.role
}
parameter {
name = "pgaudit.role"
value = "rds_pgaudit"
}
}
resource "aws_rds_global_cluster" "core" {
provider = aws.primary
global_cluster_identifier = "prod-core"
engine = "aurora-postgresql"
engine_version = "16.6" # проверить актуальную минорную версию, поддерживаемую Global DB
database_name = "core"
storage_encrypted = true
deletion_protection = true
}
resource "aws_rds_cluster" "primary" {
provider = aws.primary
cluster_identifier = "prod-core-euc1"
global_cluster_identifier = aws_rds_global_cluster.core.id
engine = aws_rds_global_cluster.core.engine
engine_version = aws_rds_global_cluster.core.engine_version
master_username = "core_admin"
master_password = data.aws_secretsmanager_secret_version.db_master.secret_string
# Ротация — через Secrets Manager. Проверьте поддержку manage_master_user_password
# для Global Database в актуальной версии RDS; если поддерживается — используйте её.
db_subnet_group_name = var.db_subnet_group_name
vpc_security_group_ids = [aws_security_group.aurora.id]
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.core.name
storage_encrypted = true
kms_key_id = aws_kms_key.core_data.arn
backup_retention_period = 28 # < 30 дней: бэкапы с удалёнными ПДн истекают естественно (GDPR)
preferred_backup_window = "01:00-02:00"
preferred_maintenance_window = "sun:02:30-sun:03:30"
copy_tags_to_snapshot = true
iam_database_authentication_enabled = true
enabled_cloudwatch_logs_exports = ["postgresql"]
deletion_protection = true
skip_final_snapshot = false
final_snapshot_identifier = "prod-core-euc1-final"
}
resource "aws_rds_cluster_instance" "primary" {
provider = aws.primary
count = 2 # writer + reader (цель failover) в разных AZ
identifier = "prod-core-euc1-${count.index}"
cluster_identifier = aws_rds_cluster.primary.id
instance_class = "db.r7g.xlarge"
engine = aws_rds_cluster.primary.engine
engine_version = aws_rds_cluster.primary.engine_version
availability_zone = element(["eu-central-1a", "eu-central-1b"], count.index)
promotion_tier = count.index
monitoring_interval = 30
monitoring_role_arn = aws_iam_role.rds_monitoring.arn
auto_minor_version_upgrade = false # обновления — осознанно, через stage
}
# Автомасштабирование readers на пики (Чёрная пятница)
resource "aws_appautoscaling_target" "aurora_readers" {
provider = aws.primary
service_namespace = "rds"
scalable_dimension = "rds:cluster:ReadReplicaCount"
resource_id = "cluster:${aws_rds_cluster.primary.cluster_identifier}"
min_capacity = 1
max_capacity = 3
}
resource "aws_appautoscaling_policy" "aurora_readers_cpu" {
provider = aws.primary
name = "aurora-readers-cpu"
service_namespace = aws_appautoscaling_target.aurora_readers.service_namespace
scalable_dimension = aws_appautoscaling_target.aurora_readers.scalable_dimension
resource_id = aws_appautoscaling_target.aurora_readers.resource_id
policy_type = "TargetTrackingScaling"
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "RDSReaderAverageCPUUtilization"
}
target_value = 60
scale_in_cooldown = 600
scale_out_cooldown = 120
}
}
# DR: secondary cluster в eu-west-1
resource "aws_rds_cluster" "dr" {
provider = aws.dr
cluster_identifier = "prod-core-euw1"
global_cluster_identifier = aws_rds_global_cluster.core.id
engine = aws_rds_global_cluster.core.engine
engine_version = aws_rds_global_cluster.core.engine_version
db_subnet_group_name = var.dr_db_subnet_group_name
vpc_security_group_ids = [var.dr_aurora_sg_id]
storage_encrypted = true
kms_key_id = aws_kms_replica_key.core_data_dr.arn
backup_retention_period = 28
deletion_protection = true
skip_final_snapshot = false
final_snapshot_identifier = "prod-core-euw1-final"
depends_on = [aws_rds_cluster_instance.primary]
lifecycle {
ignore_changes = [replication_source_identifier] # рекомендация провайдера для secondary Global DB
}
}
resource "aws_rds_cluster_instance" "dr" {
provider = aws.dr
identifier = "prod-core-euw1-0"
cluster_identifier = aws_rds_cluster.dr.id
instance_class = "db.r7g.large" # при failover масштабируется до xlarge по runbook
engine = aws_rds_cluster.dr.engine
engine_version = aws_rds_cluster.dr.engine_version
}
5.5 ECS-сервис с нативным blue/green (modules/ecs-service/main.tf, фрагмент)
resource "aws_ecs_task_definition" "this" {
family = var.name
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
cpu = var.cpu # напр. 512
memory = var.memory # напр. 1024
execution_role_arn = aws_iam_role.execution.arn
task_role_arn = aws_iam_role.task.arn # least privilege, свой на каждый сервис
runtime_platform {
operating_system_family = "LINUX"
cpu_architecture = "ARM64" # Graviton: ~20% дешевле
}
container_definitions = jsonencode([{
name = var.name
image = "${var.ecr_repo_url}:${var.image_tag}" # immutable tag = git SHA
essential = true
readonlyRootFilesystem = true
user = "10001"
portMappings = [{ containerPort = var.port, protocol = "tcp" }]
secrets = [for k, arn in var.secrets : { name = k, valueFrom = arn }]
healthCheck = {
command = ["CMD", "/app/healthcheck"]
interval = 15, timeout = 5, retries = 3, startPeriod = 20
}
logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.this.name
awslogs-region = var.region
awslogs-stream-prefix = var.name
}
}
}])
}
resource "aws_cloudwatch_log_group" "this" {
name = "/ecs/${var.env}/${var.name}"
retention_in_days = 30 # прикладные логи без ПДн, 30 дней
kms_key_id = var.logs_kms_key_arn
}
resource "aws_ecs_service" "this" {
name = var.name
cluster = var.cluster_arn
task_definition = aws_ecs_task_definition.this.arn
desired_count = var.min_count
availability_zone_rebalancing = "ENABLED"
propagate_tags = "SERVICE"
capacity_provider_strategy {
capacity_provider = "FARGATE"
base = var.min_count
weight = 1
}
# для воркеров: дополнительная стратегия FARGATE_SPOT с weight > 0
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.task.id]
assign_public_ip = false
}
# Нативный blue/green в ECS (требует свежий AWS provider 6.x — проверьте минимальную версию)
deployment_configuration {
strategy = "BLUE_GREEN"
bake_time_in_minutes = 10
}
alarms {
alarm_names = [aws_cloudwatch_metric_alarm.error_rate.alarm_name,
aws_cloudwatch_metric_alarm.p99_latency.alarm_name]
enable = true
rollback = true # автоматический откат на blue при срабатывании
}
load_balancer {
target_group_arn = aws_lb_target_group.blue.arn
container_name = var.name
container_port = var.port
advanced_configuration {
alternate_target_group_arn = aws_lb_target_group.green.arn
production_listener_rule = aws_lb_listener_rule.this.arn
role_arn = var.ecs_infrastructure_role_arn
}
}
lifecycle {
ignore_changes = [desired_count] # управляет Application Auto Scaling
}
}
resource "aws_appautoscaling_target" "svc" {
service_namespace = "ecs"
scalable_dimension = "ecs:service:DesiredCount"
resource_id = "service/${var.cluster_name}/${aws_ecs_service.this.name}"
min_capacity = var.min_count # >= 3 для критичных сервисов (по 1 на AZ)
max_capacity = var.max_count
}
resource "aws_appautoscaling_policy" "rps" {
name = "${var.name}-rps"
policy_type = "TargetTrackingScaling"
service_namespace = aws_appautoscaling_target.svc.service_namespace
scalable_dimension = aws_appautoscaling_target.svc.scalable_dimension
resource_id = aws_appautoscaling_target.svc.resource_id
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ALBRequestCountPerTarget"
resource_label = "${var.alb_arn_suffix}/${aws_lb_target_group.blue.arn_suffix}"
}
target_value = var.target_rps_per_task # определяется нагрузочным тестом
scale_out_cooldown = 60
scale_in_cooldown = 300
}
}
5.6 SCP: только регионы ЕС (live/org/scp.tf, фрагмент)
resource "aws_organizations_policy" "eu_only" {
name = "deny-non-eu-regions"
type = "SERVICE_CONTROL_POLICY"
content = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "DenyOutsideAllowedRegions"
Effect = "Deny"
NotAction = [ # глобальные сервисы, работающие через us-east-1
"iam:*", "organizations:*", "sts:*", "support:*", "budgets:*", "ce:*",
"cloudfront:*", "route53:*", "route53domains:*", "wafv2:*", "shield:*",
"acm:*", "health:*", "sso:*", "identitystore:*", "account:*", "pricing:*"
]
Resource = "*"
Condition = {
StringNotEquals = { "aws:RequestedRegion" = ["eu-central-1", "eu-west-1"] }
ArnNotLike = { "aws:PrincipalARN" = ["arn:aws:iam::*:role/AWSControlTowerExecution"] }
}
}]
})
}
# Примечание: ACM-сертификат для CloudFront создаётся в us-east-1 — это не хранение ПДн.
# wafv2:* и acm:* сознательно в NotAction; для максимальной строгости ограничьте их
# дополнительным условием по ресурсам CloudFront.
6. Оценка затрат (ориентировочно, $/мес)
Допущения по расчёту:
- цены eu-central-1 on-demand на осень 2026 приблизительны, перед закупкой проверьте их в AWS Pricing Calculator;
- базовая нагрузка ~250 RPS, [ДОП-2] — 8 ТБ CDN egress;
- ~12 сервисов, в сумме около 40 vCPU и 80 ГБ на Fargate ARM в prod-euc1, включая резерв на 3 AZ;
- НДС не учтён.
| # | Компонент | Конфигурация | On-demand | С обязательствами |
|---|---|---|---|---|
| 1 | ECS Fargate (prod euc1) | ~40 vCPU / 80 ГБ ARM64 | 1 300 | 1 050 (Compute SP 1 год) |
| 2 | ALB | 1 ALB, ~10–15 LCU | 150 | 150 |
| 3 | NAT Gateway | 3 шт. + ~500 ГБ обработки | 150 | 150 |
| 4 | VPC Interface Endpoints | 7 × 3 AZ + трафик | 200 | 200 |
| 5 | Aurora primary | 2× r7g.xlarge, ~300 ГБ, I/O, бэкапы | 1 200 | 900 (RI 1 год) |
| 6 | Aurora DR + репликация | 1× r7g.large + replicated writes + storage | 350 | 300 |
| 7 | RDS Proxy | по vCPU writer'а | 100 | 100 |
| 8 | ElastiCache Valkey | 3× cache.r7g.large | 450 | 320 (RI) |
| 9 | OpenSearch | 3× r7g.large.search + 3 малых master + 600 ГБ gp3 | 700 | 520 (RI) |
| 10 | DynamoDB + Global Tables | on-demand, корзины/сессии/идемпотентность | 150 | 150 |
| 11 | SQS / SNS / EventBridge / Step Functions / Lambda | 100 | 100 | |
| 12 | S3 | 8 ТБ медиа (Intelligent-Tiering) + CRR-копия + бэкапы + логи | 450 | 450 |
| 13 | CloudFront | ~8 ТБ egress + ~500 млн HTTPS-запросов | 900 | 800* |
| 14 | AWS WAF | 2 web ACL, managed rules, ~500 млн запросов, Bot Control (common) | 400 | 400 |
| 15 | Route 53 | зоны, health checks | 30 | 30 |
| 16 | Наблюдаемость | CloudWatch Logs (~400 ГБ), метрики, alarms, трейсы, Synthetics | 600 | 600 |
| 17 | Безопасность | GuardDuty, Security Hub, Config, Inspector, Macie, CloudTrail data events | 450 | 450 |
| 18 | KMS + Secrets Manager | ~15 CMK, ~50 секретов | 60 | 60 |
| 19 | AWS Backup | cross-region copy, тесты restore | 150 | 150 |
| 20 | DR-регион (warm standby) | ECS минимум, ALB, NAT ×1, endpoints, Valkey ×1, OpenSearch 2 ноды | 650 | 550 |
| 21 | Stage | 3 AZ, малые инстансы, выключение ночью/в выходные, Spot | 1 000 | 900 |
| 22 | Dev | 1 AZ-NAT, Aurora 1 инстанс, расписание | 500 | 450 |
| 23 | Shared-services + log-archive | ECR (+репликация), S3 Object Lock, Firehose | 150 | 150 |
| 24 | Межзонный и межрегиональный трафик | 250 | 250 | |
| 25 | AWS Business Support [ДОП-9] | % от счёта, ступенчатая шкала (сверьте с текущими планами) | 900 | 820 |
| ИТОГО базовый месяц | ≈ 11 340 | ≈ 10 150 |
* Оцените flat-rate тарифы CloudFront (пакеты с включёнными WAF и трафиком). При вашем профиле они могут быть заметно дешевле связки «CloudFront + WAF по запросам». Проверьте актуальные условия.
Пиковые месяцы (ноябрь–декабрь):
- Fargate ×2.5 на ~2–3 недели: +$800–1 100;
- дополнительные Aurora readers: +$300–400;
- CloudFront и WAF ×1.8: +$700–900;
- логи: +$150.
Итого ≈ $12 800–13 500, в пределах лимита $15K.
Прогноз на 12 месяцев при росте трафика ×3. Без мер оптимизации база составит ≈ $14–16K/мес: растут compute, CDN, WAF и логи, а Aurora, OpenSearch и базовые компоненты растут сублинейно. Поэтому меры ниже — это необходимость для удержания бюджета, а не опция.
Приоритетные меры экономии (в порядке эффект/усилие):
- Оптимизация изображений (WebP/AVIF, адаптивные размеры) — −30–50% CDN egress, до −$400/мес при росте.
- Compute Savings Plan + RI на Aurora, Valkey и OpenSearch — покупать на ~70% от фактической базовой линии через 2–3 месяца после cutover. Экономия ≈ $1 200/мес.
- Бюджет логов: уровни логирования, сэмплинг трейсов (5–10%), класс CloudWatch Logs Infrequent Access для отладочных логов, retention 14–30 дней — −$200–300.
- Расписания и Spot для dev/stage — уже заложены.
- Кэширование публичного каталога на CloudFront через persisted queries снижает нагрузку на origin (Fargate, ALB, Aurora readers) в пике.
- Контроль VPC endpoints: удалить неиспользуемые и сравнить с объёмом трафика через NAT.
- Пересматривать rightsizing ежемесячно (Compute Optimizer).
Предсказуемость на 6 месяцев вперёд:
- AWS Budgets на каждый аккаунт и сервис с алертами на 80/100/120% и forecast-алертами;
- Cost Anomaly Detection;
- обязательные теги
Environment/Service/Owner(Tag Policies в Organizations); - CUR 2.0 → Athena → дашборд «стоимость на 1000 запросов» и «стоимость на заказ». Прогноз строится как
(прогноз RPS / заказов) × unit cost + фиксированная база. Такой метод точнее трендовой экстраполяции Cost Explorer при сезонности.
7. Риски и trade-off'ы
| # | Риск / trade-off | Влияние | Митигация |
|---|---|---|---|
| 1 | Разрыв компетенций: 6 инженеров, облачного опыта мало, DevOps на part-time, а целевой SLA 99.95% | Критическое | Нанять (или перевести на full-time) platform-инженера. Обучение: AWS Cloud Practitioner → Solutions Architect Associate для 2–3 человек. On-call ротация 4–5 человек. Рассмотреть AWS Partner на этап Landing Zone и первого DR-теста (~2–4 недели работ). |
| 2 | Переход монолит → микросервисы одновременно с переездом в облако | Высокое | Два отдельных шага: сначала «lift & improve» монолита в ECS, затем постепенное выделение сервисов. 5–7 сервисов, а не 20. Сохранять модульный монолит там, где нет потребности в независимом масштабировании. |
| 3 | Переезд до Чёрной пятницы 2026 | Критическое | Cutover не раньше января 2027. На Q4 — укрепление Hetzner (этап 0). |
| 4 | Warm standby вместо active-active | Ниже стоимость и сложность, но RTO 25–50 мин вместо секунд | Соответствует требованию RTO 1 ч. Active-active пересмотреть при SLA 99.99%. |
| 5 | Межрегиональный failover ручной, а не автоматический | +5–10 мин к RTO | Защищает от ложных срабатываний и split-brain. Runbook автоматизирован, решение принимает человек. |
| 6 | Fargate вместо EKS или EC2 | Unit cost compute на 15–30% выше, меньше контроля | Резко меньше операционной нагрузки. Пересмотреть при compute больше $4–5K/мес (ECS на EC2 + Graviton + SP). |
| 7 | Vendor lock-in (Aurora Global, DynamoDB, EventBridge) | Средний | Код работает с PostgreSQL-совместимым API. Интерфейсы очередей и хранилищ абстрагированы в коде. DynamoDB используется только для простых key-value сценариев. |
| 8 | Хранение бэкапов 28 дней ради GDPR | Нельзя восстановиться от логической порчи данных старше 28 дней | Детектирование порчи (инварианты, сверки) в пределах дней. Долгосрочные архивы только с crypto-shredding. Финансовые записи дублируются в бухгалтерской системе. |
| 9 | Кэш CloudFront и edge-локации вне ЕС | Юридическая неопределённость | Не кэшировать ПДн, no-store, фиксация в RoPA, заключение DPO. Альтернатива — регионный ALB для персональных эндпоинтов. |
| 10 | Нехватка ёмкости Fargate в DR при массовом региональном инциденте | Средний | Warm tasks, ранее решение о failover, при необходимости Fargate + EC2 capacity providers в DR. |
| 11 | Бюджет при росте ×3 | Высокий | Unit economics, обязательства, оптимизация медиа. Ежеквартальный пересмотр с CFO. |
| 12 | ПДн в логах из-за ошибки разработчика | Нарушение права на забвение | Redaction-логгер, тесты, Macie, короткий retention. Инцидент по процедуре GDPR breach. |
| 13 | Зависимость от Stripe и SES | Недоступность платежей за пределами нашего SLA | Graceful degradation (заказ в статусе «ожидает оплаты» с повтором), мониторинг status-страниц, SLA в договорах. |
8. Дорожная карта внедрения
| Этап | Сроки (ориентир) | Содержание | Критерий завершения |
|---|---|---|---|
| 0. Остановить кровотечение (параллельно, на Hetzner) | Сентябрь–ноябрь 2026 | • Сегодня же: WAL-G/pgBackRest → S3 eu-central-1 (непрерывный WAL-архив + ежедневный base backup) — это даёт PITR. Проверить восстановление.<br>• Второй сервер Hetzner со streaming-репликой PostgreSQL (hot standby).<br>• GitHub Actions: тесты в CI, деплой только из CI (Capistrano из пайплайна, не с ноутбуков).<br>• CloudFront перед статикой и изображениями (снимает нагрузку в пик).<br>• Sentry + Grafana Cloud/Prometheus + алерты; нагрузочный тест монолита на 1500 RPS.<br>• Code freeze с 20 ноября по 2 декабря. | Проверенный restore, RPO меньше 5 мин на Hetzner, CI для каждого PR, Чёрная пятница пройдена |
| 1. Фундамент AWS | Октябрь–декабрь 2026 (без касания прода) | Organizations + Control Tower, SCP, Identity Center, log-archive, security baseline. Terraform-репозиторий, state, модули network/security. GitHub OIDC. Обучение команды. Договоры и DPA, старт DPIA. | Security Hub score выше 90%, dev-аккаунт полностью в IaC |
| 2. Платформа и контейнеризация монолита | Декабрь 2026 – январь 2027 | Docker-образ Rails-монолита, ECS в dev/stage, Aurora PG 16 в stage, S3-медиа, Valkey, CI/CD с blue/green, наблюдаемость и SLO-алерты, runbooks. | Stage обслуживает полный e2e-набор, деплой без простоя проверен |
| 3. Cutover в AWS | Январь – февраль 2027 (низкий сезон) | Логическая репликация PG14 (Hetzner) → Aurora (через DMS или нативную logical replication по TLS/VPN), синхронизация медиа в S3, дублирование трафика и сравнение. Переключение DNS с коротким read-only окном (цель меньше 5 мин, единственный согласованный плановый простой). Hetzner остаётся горячим откатом на 2–4 недели. | Прод в eu-central-1, 3 AZ, 99.95% в течение 30 дней |
| 4. DR и соответствие | Февраль – апрель 2027 | Aurora Global + warm standby в eu-west-1, S3 CRR, ECR и Secrets replication, FIS-эксперименты, первое полноценное DR-учение с замером RTO/RPO. GDPR: erasure workflow, журнал доступа к ПДн, Macie. Покупка SP/RI по фактическим данным. | RTO меньше 60 мин и RPO меньше 15 мин подтверждены отчётом, erasure выполняется end-to-end |
| 5. Декомпозиция (strangler fig) | Март – сентябрь 2027 | Порядок выделения — от низкого риска к высокому: notifications → search/catalog (+OpenSearch) → cart (DynamoDB) → GraphQL gateway → users/PII vault → orders + payments (последними, с сагой и outbox). Каждый сервис — отдельный canary-релиз с feature flags. | Rails обслуживает меньше 20% трафика или выведен из эксплуатации |
| 6. Операционная зрелость | С сентября 2027, постоянно | Подготовка к сезону: нагрузочный тест на ×1.5 от прогноза, scheduled scaling, LCU reservation. Ежеквартальные DR-учения, ежегодный внешний аудит и пентест, ежемесячный FinOps-обзор, ревизия IAM раз в квартал. | Чёрная пятница 2027 пройдена в рамках SLA и лимита $15K |
Что прислать для уточнения расчётов:
- Реальный объём медиа и egress (из статистики Hetzner или nginx) — это главная неопределённость в бюджете.
- Требования к хранению финансовых документов по юрисдикции.
- Решение DPO по API через CloudFront.
- Статус переписывания на Go/Node.js.
С этими данными я пересчитаю стоимость и при необходимости скорректирую DR-модель, например перейду на headless secondary Aurora ради экономии ещё ~$250/мес ценой RTO.
Похожие промпты
Ревью и рефакторинг PowerShell-скрипта
Разбирает существующий скрипт PowerShell: что сломается на реальных данных, где ошибки глушатся вместо обработки и что переписать в первую очередь, а что оставить.
Скрипт PowerShell под задачу
Пишет скрипт PowerShell с обработкой ошибок, логированием и режимом пробного прогона — так, чтобы его можно было запустить на рабочей машине и не бояться последствий.
Диагностика проблем VPN-подключения
Методично диагностирует проблемы VPN: соединение не устанавливается, скорость падает, утекает DNS — по одному шагу, с командами под вашу ОС.
Помощник по настройке WireGuard и OpenVPN
Пошагово разворачивает собственный VPN-сервер на WireGuard или OpenVPN: готовые команды и конфиги, firewall, клиентские профили и проверка утечек.