В этой статье поговорим о нюансах использования Terraform от HashiCorp, в частности о том, как использовать Terraform при управлении несколькими аккаунтами Amazon Web Services (так делают все чаще — из-за размера организации или предпочтений команды DevOps). По сути, AWS сами намекают клиентам, что неплохо было бы использовать несколько аккаунтов, и недавно даже выпустили для этого несколько сервисов.


Зачем нужно несколько аккаунтов AWS?


Причин много. Например — дополнительная безопасность. Такая стратегия помогает разделить ресурсы по темам, чтобы, допустим, выделить по аккаунту для каждого разработчика, окружения или отдела.


Управлять безопасностью в этом случае определенно проще, чем когда у вас есть один гигантский аккаунт AWS с запутанной структурой разрешений IAM. По умолчанию отдельные аккаунты AWS не имеют доступа к ресурсам друг друга.


На практике крупные организации из-за своих размеров уже используют несколько аккаунтов AWS, но эти аккаунты никак не связаны. Это серьезно усложняет жизнь отделам закупок — на каждый аккаунт AWS нужен отдельный счет, причем организация может группировать счета в соответствии со своими внутренними правилами или нормативными требованиями. Чтобы упростить работу, можно использовать AWS Organizations для управления иерархией аккаунтов и объединения счетов по группам. Недавно AWS представили AWS Control Tower для подготовки новых аккаунтов с предустановленным набором ресурсов и централизованным управлением всеми аккаунтами.


Новый тренд


В целом, организации все чаще используют несколько аккаунтов AWS, наверное, потому, что владельцы дают всем пользователям в своем аккаунте права админа, так что они могут просматривать любые ресурсы и делать что угодно.


Нужно много времени, чтобы настроить разрешения IAM вместо дефолтного админского доступа для этих пользователей. Причем нет гарантий, что принцип наименьших привилегий будет соблюдаться. С другой стороны, по умолчанию у администратора одного аккаунта AWS нет доступа к другому аккаунту, даже в той же организации. Это безопасно, но нужно поработать над разрешениями IAM, чтобы пользователь из одного аккаунта при необходимости имел доступ к ресурсам в другого. Команда DevOps в таких случаях, скорее всего, будет применять принцип наименьших привилегий.


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


Инфраструктура как код с несколькими аккаунтами


Управление ресурсами в разных аккаунтах


Допустим, один стейт Terraform может управлять ресурсами в разных аккаунтах. Обычно для этого требуется объявить несколько блоков провайдеров, по одному на аккаунт.


По умолчанию блок провайдера AWS работает в аккаунте, данные которого использовались для подключения к AWS API. Например, если вы используете идентификатор ключа доступа/секретный ключ доступа определенного пользователя AWS, Terraform будет ссылаться на аккаунт этого пользователя. Код Terraform:


provider “aws” {

region = “us-east-1”

}

Чтобы создавать ресурсы в разных аккаунтах, используйте параметр assume_role блока провайдера, чтобы назначить роль в другом аккаунте и получить доступ к нему:


provider “aws” {
  region = “us-east-1”
  assume_role {
    role_arn = “arn:aws:iam::123456789012:role/iac”
  }
}

Очевидно, что для этого нужно будет назначить разрешения IAM для этой роли и пользователя, выполняющего команды Terraform. Инструкции по выполнению этой задачи в AWS см. здесь.


Промежуточная роль для доступа к третьему аккаунту


Второй вариант использования продолжает первый: назначенная роль может иметь разрешения на создание, обновление и удаление ресурсов в третьем аккаунте AWS. Для этого нужно настроить разрешения IAM в финальном аккаунте AWS, чтобы промежуточный аккаунт мог создавать, обновлять и удалять ресурсы в нём. Схематично это выглядит так:



Рис. 1. Схема промежуточной роли для доступа к финальному аккаунту AWS


Это довольно сложный сценарий, в котором придется приложить немало усилий для контроля и отладки разрешений IAM. В определенной ситуации это допустимо, но на особые преимущества с точки зрения безопасности не рассчитывайте. Вместо атаки на аккаунт 333333333333 хакеры попытаются получить доступ к 222222222222, чтобы уже оттуда добраться до 333333333333. Если аккаунт 222222222222 используется для контроля ресурсов не только в 333333333333, но и в других аккаунтах, безопасность пострадает еще больше.


Другие продвинутые стратегии Terraform


Несколько стейтов


Если ресурсов относительно много, можно разделить скрипты Terraform на несколько стейтов — особенно при использовании continuous deployment (CD). Управление всеми ресурсами в одном стейте имеет недостатки:


  • Каждый раз, когда мы вносим даже незначительные изменения, мы боимся, что Terraform затронет базовые ресурсы, которые трогать не надо.
  • Ошибочные изменения в базовых ресурсах, примененные вслепую в рамках continuous deployment, могут иметь плачевные последствия.
  • Разрешения IAM, которые нужны для выполнения скрипта Terraform, будут затрагивать самые разные задачи. Их будет больше, чем требуется для CD.
  • На применение изменений нужно очень много времени, потому что Terraform будет собирать стейт всех ресурсов, которыми управляет стейт, даже если в большинстве из них ничего не поменялось.
  • Если при деплойменте произойдет сбой, последствия могут быть обширными.

Обычно базовые ресурсы редко меняются. Речь идет о VPC, подсетях, Transit Gateways, VPN, базах данных RDS и балансировщиках нагрузки. Эти ресурсы принадлежат базовому стейту, который почти не меняется, а если и меняется, то руками человека.


Некоторые ресурсы, наоборот, меняются постоянно. Это инстансы EC2, автоскейлинг группы, сервисы в ECS и EKS. Обычно такие ресурсы деплоятся (или обновляются) через пайплайны CD и помещаются в другой стейт, отдельно от базовых ресурсов. Этот отдельный набор скриптов Terraform будет управлять лишь небольшой, быстро меняющейся группой ресурсов, и вам потребуется гораздо меньше разрешений. Такое разделение стейтов Terraform идеально подойдет для автоматизированных деплоев.


Интересный пример такой конфигурации — кластер Kubernetes, управляемый базовым стеком, где деплоями Kubernetes управляет стек CD.


Модули


Terraform упрощает разбивку кода IaC на модули. Просто поместите код в другой каталог и используйте директиву module:


provider “aws” {

region = “us-east-1”

}

module “mymodule” {

source = “./modules/my_module”

variable1 = “value1”

variable2 = “value2”

}

У Terraform есть репозиторий со множеством модулей, написанных сообществом Terraform для всеобщего использования. Прежде чем использовать этот репозиторий, убедитесь, что нужные модули соответствуют политикам безопасности вашей организации.


Модули Terraform позволяют соблюдать принцип DRY (Don’t Repeat Yourself — не повторяйся). Но все равно остается шаблонный код (определения в бэкенде и вызовы к самим модулям), который нельзя поместить в модуль.


Окружения


Для рабочей нагрузки часто существует несколько окружений — стейджинг, продакшн, тестовая среда и т. д. Эти окружения должны быть максимально похожи друг на друга, чтобы деплой, прекрасно работающий в стейджинге, показал себя не хуже в продакшене (без оправданий в стиле: «Не знаю, у меня все работало»).


Terraform предлагает воркспейсы, но прежде чем применить изменения, мы должны переключиться с одного на другой (например, с продакшена на стейджинг). Если делать это вручную, высок риск, что однажды кто-нибудь забудет сменить воркспейс и задеплоит код не в то окружение. Очевидно, что последствия могут быть катастрофическими.


Есть и другое решение — составить разные наборы скриптов для разных окружений, но это громоздко, и будет много повторяющих друг друга фрагментов даже при использовании модулей. Это одна из причин создания Terragrunt (подробнее об этом один из основателей рассказывает здесь).


Заключение


Большие (и не очень) организации часто используют несколько аккаунтов AWS, и, если постараться, вполне можно наладить Terraform в такой системе. По сути, Terraform специально разработан как мультиоблачный инструмент и поддерживает множество провайдеров, которые могут использоваться в определенном наборе скриптов.


С помощью советов в этой статье можно создать аккуратный код Terraform в соответствии с принципами DRY.