open atlas
← Все проекты

infra · advanced · 9d

Трёхзвенное приложение на AWS через IaC

Подними настоящую трёхзвенную систему на AWS — балансировщик спереди, вычислительный слой посередине, управляемый Postgres за ним и S3 для объектов — целиком из кода, который можно прогнать заново. Суть не в том, чтобы один раз прокликать консоль; суть в том, чтобы описать всю топологию, её IAM и сетевые границы как Terraform (или CDK), который можно передать коллеге, снести и пересоздать байт в байт. Это тот проект, где «инфраструктура» перестаёт быть кучей консолей и становится артефактом, который можно ревьюить.

Почти любая система, которую ты будешь разворачивать как сеньор, — это та или иная версия этой формы: балансировщик, вычислительный слой, управляемая база и бакет, склеенные сетью, которую ты спроектировал, и IAM, который ты ограничил. Собрать это один раз из кода, а затем доказать, что можешь снести и пересоздать, — вот как «облачная инфраструктура» перестаёт быть консолью, которую боишься трогать, и становится тем, о чём ты рассуждаешь в diff. Сложны не ресурсы, а границы: какая подсеть, какая security-группа, какое право, какой эндпоинт приватный. Сделай их правильно — и можешь передать репозиторий кому угодно. Сделай неправильно — и ты построил ровно ту misconfiguration, что попадает в отчёт об утечке. Этот разрыв, между стеком, который работает, и стеком, который безопасно запускать, — и есть вся работа.

Результат

Репозиторий Terraform (или CDK), который из чистого аккаунта разворачивает VPC с публичными и приватными подсетями, Application Load Balancer, вычислительный слой (ECS/Fargate или ASG), инстанс RDS Postgres в приватных подсетях и бакет S3 — связанные через IAM с минимальными правами и с полезными выводами стека (DNS-имя ALB, эндпоинт БД), который можно применять и сносить по команде.

Этапы

0/6 · 0%
  1. 01Заложи сеть

    Всё остальное держится на сети, поэтому собери её первой и собери честно. Опиши VPC минимум с двумя зонами доступности, публичные подсети для балансировщика и приватные — для вычислений и базы. Добавь internet gateway для публичной стороны и путь через NAT (шлюз или инстанс), чтобы приватные нагрузки могли выходить наружу, оставаясь недоступными из интернета. Не поддавайся искушению свалить всё в публичные подсети «чтобы заработало» — разделение public/private это и есть вся история безопасности этого проекта, а правильно настроенные таблицы маршрутизации сейчас избавят тебя от загадочных connection-refused потом. Опиши всё кодом, чтобы топология была диаграммой, читаемой прямо в diff.

    Критерии готовности
    • terraform apply (или cdk deploy) создаёт VPC с публичными и приватными подсетями минимум в двух AZ, а также IGW и путь через NAT.
    • Хост в приватной подсети может выходить в интернет исходящими запросами, но недоступен входящими из интернета.
  2. 02Сделай стек повторно прогоняемым

    Инфраструктура, которую нельзя пересоздать, — это пассив, а не актив. Настрой удалённое состояние (бэкенд S3 с таблицей блокировок или управляемое состояние CDK), чтобы двое людей — или две машины — не затирали изменения друг друга. Раздели конфигурацию на модули или конструкты по слоям (сеть, вычисления, данные), чтобы радиус поражения от правки был очевиден. Затем докажи контракт: прогони apply, прогони destroy, прогони apply ещё раз и убедись, что приходишь в то же состояние. Этот цикл и есть разница между IaC как привычкой и IaC как скриншотом — когда destroy-затем-apply становится скучным, ты по-настоящему доверяешь коду.

    Критерии готовности
    • Состояние хранится удалённо с блокировкой; повторный apply без изменений показывает ноль diff'ов.
    • Полный destroy с последующим чистым apply пересобирает стек без ручных правок в консоли.
  3. 03Вычисления за балансировщиком

    Теперь помести работу в средний слой и открой её только через парадную дверь. Запусти приложение как сервис ECS/Fargate (или EC2 Auto Scaling group) в приватных подсетях, а в публичные подсети поставь Application Load Balancer, который терминирует входящий трафик и проверяет здоровье целей. Вычислительный слой должен принимать соединения только от security-группы ALB — не от всего мира, — чтобы балансировщик был единственной наблюдаемой точкой входа. Настрой target group и health-check, который реально отражает готовность, потому что ALB, пометивший наполовину поднявшуюся задачу здоровой, с радостью направит пользователей прямо в ошибки.

    Критерии готовности
    • Запрос к DNS-имени ALB возвращает ответ от вычислительной задачи, работающей в приватной подсети.
    • Security-группа вычислений отклоняет прямые соединения и принимает трафик только от ALB.
  4. 04Управляемая база и объектное хранилище

    Дай приложению настоящее состояние: инстанс RDS Postgres в приватных подсетях, никогда на публичном IP, доступный только из security-группы вычислений по порту базы. Держи учётные данные вне кода — забирай их из Secrets Manager или SSM Parameter Store, а не из захардкоженной строки в tfvars. Добавь бакет S3 для объектов с заблокированным публичным доступом и шифрованием, включённым по умолчанию. Урок в том, что «управляемый» не значит «безопасный по умолчанию»: инстанс RDS с публичным эндпоинтом или бакет S3 с выключенным block-public-access — это ровно то, как утечки данных попадают в новости. Считай безопасную конфигурацию частью результата, а не отдельным тикетом на потом.

    Критерии готовности
    • Вычислительный слой подключается к RDS Postgres по секрету из хранилища секретов; у БД нет публичного эндпоинта.
    • Бакет S3 блокирует публичный доступ и имеет включённое шифрование по умолчанию, что подтверждено в plan и в консоли.
  5. 05IAM с минимальными правами и выводы

    Роль с правами на всё — это запах туториала; продакшен живёт на самых узких правах, которые всё ещё работают. Дай вычислительной задаче execution-роль, ограниченную ровно тем, что ей нужно, — прочитать вот этот один секрет, класть объекты в вот этот один префикс бакета, писать логи в вот эту одну log-группу — и никаких wildcard. Затем выведи наружу швы, от которых зависит остальной мир, как выводы стека: DNS-имя ALB, эндпоинт RDS, имя бакета. Выводы — это публичный API твоего стека; всё, что нужно деплоеру или нижестоящему стеку, должно выходить через парадную дверь, а не выкапываться из консоли. Затягивай политики, пока слишком широкое действие не сломает что-то настоящее, — и ты почувствуешь, где проходят реальные границы.

    Критерии готовности
    • Роль вычислений даёт только конкретные права на секрет, бакет и логи, которые использует приложение, — без wildcard '*' в ресурсах или действиях.
    • terraform output (или выводы CDK) печатает DNS-имя ALB, эндпоинт RDS и имя бакета.
  6. 06Доведи до боевого: blue/green, стоимость или serverless

    Стек, который просто существует, — это ещё не стек, которым можно управлять. Выбери самый важный шов и закрой его. Вариант один: добавь blue/green-деплой, чтобы новая версия выходила в бой за ALB только после того, как её target group признана здоровой, с мгновенным откатом — никакого «задеплой и молись». Вариант два: напиши заметку о стоимости, которая оценивает постоянно работающие части (NAT gateway, RDS, часы ALB набегают быстро) и предлагает, где serverless-вариант — Lambda за API Gateway, Aurora Serverless или DynamoDB — срезал бы трату на простое, с честно названным компромиссом. В любом случае ты отвечаешь на вопрос, который любому сеньору задают после демо: «сколько это стоит держать включённым и как менять это без простоя?»

    Критерии готовности
    • Либо задокументированный blue/green (или canary) деплой, который переключает трафик только после прохождения health-check'ов, либо письменная разбивка стоимости с конкретной serverless-альтернативой и её компромиссом.
    • Выбранный путь воспроизводим из IaC-репозитория, а не разовая ручная правка в консоли.

Рубрика

Джуниор Миддл Сеньор
Дизайн VPC и подсетей VPC и подсети есть, но вычисления и база находятся в одном слое или в публичных подсетях. Таблица маршрутизации допускает входящие из интернета к базе. Дизайн работает, но разделение public/private, на котором держится вся история безопасности, отсутствует. Публичные подсети содержат только ALB (и NAT gateway); вычисления и RDS — в приватных подсетях без публичных IP. Хост в приватной подсети может выходить в интернет через NAT, но недоступен входящим трафиком. Security groups обеспечивают приём трафика вычислительным слоем только от SG ALB, а БД — только от SG вычислений. Ты рассуждаешь о радиусе поражения каждого слоя: при компрометации веб-слоя атакующий достигает compute SG, но не базы (правило compute→db — единственный путь). Ты определяешь режим отказа «слишком-широкого-пока» правила security group, добавленного при отладке и так и не удалённого — оно тихо расширяет радиус поражения. Ты предлагаешь правило tfsec или AWS Config, которое выявило бы такую регрессию на этапе plan.
Воспроизводимость IaC и управление состоянием Инфраструктура определена в Terraform или CDK, но состояние локальное. Второй `apply` на другой машине создаст дублирующие ресурсы или упадёт. Цикл destroy/apply не протестирован. Состояние удалённое (бэкенд S3 + таблица блокировок DynamoDB или управляемое состояние CDK). Полный destroy с последующим чистым apply воспроизводит идентичный стек. Выводы стека (DNS ALB, эндпоинт RDS, имя бакета) определены в IaC, чтобы потребители никогда не выкапывали их из консоли. Ты рассуждаешь о том, что означает «идентичный» между циклами apply: ресурсы с `create_before_destroy` заменяются без простоя; ресурсы без него вызывают кратковременный простой. Ты определяешь, какие ресурсы в этом стеке (RDS, сервис ECS) нуждаются в правилах жизненного цикла, а какие можно наивно заменять. Ты описываешь, как дрейф между состоянием консоли и IaC (ручная правка в консоли) проявится в следующем `terraform plan` и как его reconcile.
IAM с наименьшими привилегиями и управление секретами Роль задачи ECS имеет широкие права ('s3:*' или 'secretsmanager:*'). Учётные данные БД — в переменной окружения, захардкоженной в определении задачи, а не получаемой из хранилища секретов. Роль выполнения задачи даёт только конкретный ARN секрета, префикс бакета и log-группу, которые использует приложение — без wildcard в ресурсе или действии. Учётные данные БД получаются в рантайме из Secrets Manager или SSM. Бакет S3 блокирует публичный доступ и имеет шифрование по умолчанию. У RDS нет публичного эндпоинта. Ты рассуждаешь о том, что может сделать скомпрометированная задача ECS с её ролью: прочитать ровно один секрет, записать в ровно один префикс бакета, записать логи. Ты определяешь следующий шаг бокового перемещения для атакующего, укравшего credentials метаданных инстанса задачи: он может вызывать те же три API откуда угодно в интернете, а не только изнутри VPC — поэтому условия VPC endpoint в политиках IAM (aws:SourceVpc) закрывают этот пробел. Ты говоришь, реализует ли этот стек такое условие и почему.
Размещение в нескольких AZ и режим отказа Ресурсы существуют, но в одной AZ. Отказ AZ роняет весь стек. У RDS нет резерва Multi-AZ. Подсети охватывают только одну зону доступности. Подсети существуют как минимум в двух AZ. ECS или ASG распределяет задачи/инстансы по AZ. У RDS есть резерв Multi-AZ. Отказ AZ вызывает кратковременный failover (60-120 с для RDS), а не полный простой. Target group ALB автоматически маршрутизирует только к здоровым AZ. Ты рассуждаешь о стоимости multi-AZ: инстанс RDS с Multi-AZ стоит примерно вдвое дороже однозонного, второй NAT gateway в другой AZ удваивает расходы на NAT, а задачи ECS в двух AZ могут простаивать. Ты сравниваешь это со стоимостью простоя (нарушение SLA, потеря выручки, трудозатраты на восстановление) и указываешь, когда точка безубыточности делает multi-AZ оправданным, а когда однозонный деплой с быстрым восстановлением из снимка является приемлемым компромиссом для небольшого приложения.
Эталонный разбор (спойлер)

Разделение публичных и приватных подсетей — это структурный контроль радиуса поражения: ресурсы в приватных подсетях недостижимы напрямую из интернета, даже если их security groups настроены неправильно. Security group — второй слой защиты, а не первый. Перемещение базы в приватную подсеть без публичного эндпоинта устраняет целый класс экспозиции, который никакая настройка security group не может полностью закрыть.

Воспроизводимость IaC — это операционный актив: стек, который можно снести и пересоздать за 15 минут, — это стек, от которого можно восстановиться при мисконфигурации, протестировать для него blue/green замену или склонировать в второй регион. Стек, существующий только в состоянии консоли — это один неправильный клик от невосстановимости. Удалённое состояние с блокировкой предотвращает гонку двух операторов, применяющих конфликтующие изменения.

Кража credentials через метаданные инстанса — наиболее распространённый путь бокового перемещения в AWS: SSRF-уязвимость в задаче ECS может вызвать http://169.254.169.254/latest/meta-data/iam/security-credentials/ и получить временные credentials с полной ролью задачи. Ключи условий IAM вроде aws:SourceVpc или политики VPC endpoint ограничивают эти credentials вызовами, сделанными изнутри VPC, так что украденные credentials бесполезны с машины внешнего атакующего.

Стоимость multi-AZ против отказоустойчивости: NAT gateway тарифицируется per-AZ (второй NAT в другой AZ стоит ~32$/мес), Multi-AZ RDS удваивает стоимость инстанса, а простаивающие задачи ECS во второй AZ добавляют расходы на вычисления. Для большинства production-приложений точка безубыточности — это первый раз, когда единственная AZ падает в рабочие часы. Senior-формулировка: сначала определи требования RTO/RPO, затем выбери минимальную архитектуру, им удовлетворяющую — multi-AZ часто оправдан, но это должен быть осознанный выбор со стоимостью, записанной явно, а не дефолт.

Сделай по-сеньорски

  • Добавь CI-пайплайн, который прогоняет terraform plan на каждом pull request и публикует diff, чтобы изменения инфраструктуры ревьюились как код, а не применялись с ноутбука.
  • Сделай стек multi-AZ от края до края — RDS с резервом во второй зоне, вычисления, распределённые по AZ, — и задокументируй поведение при отказе, которого ты ждёшь, когда одна зона гаснет.
  • Прогони проверку политик (tfsec, Checkov или правила AWS Config) по стеку и исправь либо обоснуй каждую находку, превращая «выглядит безопасно» в «проходит автоматический аудит».

Навыки

modelling a VPC with public/private subnet tierswriting Terraform/CDK for ALB + compute + RDS + S3scoping least-privilege IAM roles and policiesmanaging remote Terraform state and outputsputting a database in a private subnet and reaching it safelytearing down and recreating an environment deterministically

Рекомендуемый стек

awsterraform (or aws-cdk)ecs/fargate or ec2 + asgrds postgress3application load balancer