Представьте, что вы хотите создать в облаке десяток ресурсов — хранилище, базу данных, сеть — и при этом ничего не кликать мышкой в консоли. Вы описываете желаемое в текстовом файле, отдаёте его AWS, и облако само всё разворачивает. Если завтра нужно то же самое во втором регионе — запускаете тот же файл. Это и есть инфраструктура как код, а AWS CloudFormation — родной для AWS инструмент, который этим занимается.

CloudFormation бесплатен сам по себе (платите только за созданные им ресурсы) и встроен в AWS — отдельно ставить ничего не нужно. Если вы только знакомитесь с самой идеей описывать инфраструктуру текстом, начните с обзорной статьи Инфраструктура как код, а базовые понятия облака — в основах AWS.

Что такое CloudFormation

CloudFormation — это сервис, который читает ваш шаблон (текстовый файл с описанием ресурсов) и приводит реальную инфраструктуру в соответствие с ним. Создать недостающее, изменить отличающееся, удалить лишнее — всё по тому, что написано в файле.

Главная идея — декларативность. Вы не пишете пошаговую инструкцию «сначала создай это, потом то». Вы описываете результат — какие ресурсы должны существовать, — а CloudFormation сам вычисляет порядок: видит, что база зависит от сети, и создаёт сеть первой. Это как список покупок против рецепта: вы говорите «что должно быть», а не «что делать по шагам».

Аналогия: шаблон — это чертёж дома, а CloudFormation — строительная бригада, которая по чертежу всё возводит. Один чертёж — сколько угодно одинаковых домов.

Из чего состоит шаблон

Шаблон пишется на YAML или JSON (YAML читается приятнее, поэтому новичкам советуют его). Файл разбит на именованные секции:

  • AWSTemplateFormatVersion — версия формата. Значение почти всегда одно: 2010-09-09. Необязательная, но её принято указывать.
  • Parameters — входные значения, которые подставляются при запуске. Например, имя окружения или тип сервера. Благодаря им один шаблон годится и для теста, и для рабочей среды.
  • Mappings — таблицы соответствий «ключ → значение». Классический пример — разные идентификаторы образов в разных регионах.
  • Resourcesединственная обязательная секция. Здесь перечислены сами ресурсы: хранилища, серверы, базы, сети.
  • Outputs — что вернуть наружу после развёртывания: адрес хранилища, идентификатор сети. Эти значения видны в консоли и могут передаваться другим стекам.

Минимальный рабочий шаблон с одним хранилищем S3:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  MyBucket:
    Type: AWS::S3::Bucket

Каждый ресурс описывается одинаково: вы даёте ему логическое имя (MyBucket — как вы зовёте его внутри шаблона), указываете Type (что это — AWS::S3::Bucket значит хранилище S3) и Properties (настройки конкретно этого ресурса). Имя типа всегда вида AWS::Сервис::Тип.

Тот же ресурс, но с настройками:

Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled

А вот шаблон побогаче — с параметром на входе и значением на выходе:

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  BucketName:
    Type: String
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref BucketName
Outputs:
  BucketArn:
    Value: !GetAtt MyBucket.Arn

Что такое стек

Стек (stack) — это группа ресурсов, развёрнутых из одного шаблона и управляемых как единое целое. Запустили шаблон — получили стек. Все ресурсы внутри создаются, обновляются и удаляются вместе.

Это ключевое удобство: удалили стек — и CloudFormation сам убрал всё, что в него входило, в правильном порядке. Никаких забытых хранилищ, за которые потом приходит счёт. Стек — это «корзина», из которой ресурсы не теряются.

Создать стек из локального шаблона через командную строку (AWS CLI работает одинаково на любой операционной системе):

aws cloudformation create-stack \
  --stack-name my-first-stack \
  --template-body file://template.yaml

Обновить — тот же стек, изменённый шаблон:

aws cloudformation update-stack \
  --stack-name my-first-stack \
  --template-body file://template.yaml

Удалить стек целиком вместе со всеми ресурсами:

aws cloudformation delete-stack --stack-name my-first-stack

Если в процессе что-то ломается, CloudFormation по умолчанию откатывает стек к прошлому рабочему состоянию — частично сломанной инфраструктуры не остаётся.

Change sets: посмотреть перед применением

Обновлять рабочую инфраструктуру вслепую страшно: одно неосторожное изменение может пересоздать базу данных. Чтобы этого избежать, есть change set (набор изменений) — предпросмотр того, что произойдёт, до фактического применения.

CloudFormation сравнивает текущее состояние стека с новым шаблоном и показывает список: что добавится, что изменится, а что — внимание — будет пересоздано (replacement). Пересоздание ресурса нередко означает потерю данных, поэтому такой просмотр спасает от дорогих ошибок.

Работа идёт в три шага. Сначала создаём набор изменений:

aws cloudformation create-change-set \
  --stack-name my-first-stack \
  --change-set-name my-changes \
  --template-body file://template.yaml

Затем смотрим, что внутри:

aws cloudformation describe-change-set \
  --stack-name my-first-stack \
  --change-set-name my-changes

И, если всё устраивает, применяем:

aws cloudformation execute-change-set \
  --stack-name my-first-stack \
  --change-set-name my-changes

Привычка «сначала change set, потом execute» — один из главных признаков аккуратной работы с CloudFormation на рабочих средах.

Полезные функции шаблона

Чтобы шаблон не был набором жёстко зашитых строк, в CloudFormation есть intrinsic functions (встроенные функции) — они подставляют значения на лету. В YAML у каждой есть короткая запись через !.

  • !Ref — подставить значение параметра или сам ресурс (например, имя созданного хранилища).
  • !GetAtt — взять атрибут ресурса, которого нет в Ref: например, !GetAtt MyBucket.Arn — полный идентификатор хранилища.
  • !Sub — собрать строку с подстановками: !Sub "${AWS::StackName}-bucket" вставит имя стека.
  • !Join — склеить список строк через разделитель: !Join ["-", [prod, bucket]] даст prod-bucket.

Когда инфраструктура растёт, один файл становится неудобным. Тут помогают четыре механизма:

  • Nested stacks (вложенные стеки) — шаблон ссылается на другой шаблон как на ресурс типа AWS::CloudFormation::Stack, указывая его адрес в TemplateURL. Так большой шаблон разбивается на переиспользуемые куски (отдельно сеть, отдельно база).
Resources:
  NetworkStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/my-templates/network.yaml
  • Cross-stack references (ссылки между стеками) — один стек публикует значение через Export в секции Outputs, другой забирает его функцией Fn::ImportValue. Удобно, когда сеть живёт в одном стеке, а серверы — в другом.
Outputs:
  VpcId:
    Value: !Ref MyVPC
    Export:
      Name: !Sub "${AWS::StackName}-VPCID"
  • StackSets (наборы стеков) — разворачивают один шаблон сразу во многих аккаунтах и регионах одной командой. Незаменимо в крупных организациях.
  • Drift detection (обнаружение расхождений) — встроенная проверка: кто-то поправил ресурс вручную в консоли, и реальность разошлась с шаблоном. CloudFormation покажет эти расхождения, чтобы вы вернули порядок.

Где это применяется

CloudFormation встречается почти везде, где инфраструктура AWS управляется кодом, а не кликами: развёртывание сетей (networking), серверов (compute), бессерверных функций (serverless), баз данных (managed data). Шаблон обычно лежит в репозитории рядом с приложением, а развёртывание происходит автоматически из конвейера сборки — change set создаётся и применяется как шаг выкладки, что хорошо ложится на стратегии релизов.

Типичные ошибки новичков:

  • Правка ресурсов руками в консоли. Стоит включить привычку менять только шаблон. Ручные изменения создают drift, и следующее обновление стека может их затереть.
  • Обновление рабочего стека без change set. Легко случайно пересоздать базу. Сначала create-change-set и describe-change-set, потом execute-change-set.
  • Один гигантский шаблон. Когда файл переваливает за пару сотен строк, его пора резать на nested stacks или связывать через cross-stack.
  • Удаление того, что нельзя терять. Для критичных ресурсов (база, хранилище с данными) задают политику сохранения, чтобы удаление стека их не снесло.

Что учить дальше. CloudFormation — это родной для AWS способ; параллельно стоит посмотреть на облачно-независимый Terraform и на AWS CDK, где инфраструктуру описывают обычным языком программирования (TypeScript, Python и другими), а CDK уже сам генерирует шаблон CloudFormation. Чтобы понять, как любой из этих инструментов хранит представление о развёрнутом, полезна статья про состояние и доставку. А если ваши ресурсы — это хранилища объектов, загляните в раздел про объектное хранилище.