Создавайте модули Terraform, которые ваша команда будет использовать повторно.

Nitric спонсировал этот пост.

Многие организации испытывают трудности с внедрением модуля Terraform, сталкиваясь с такими проблемами, как:

  • Фрагментация версий: Разные проекты/команды используют разные версии.
  • Критические изменения: Команды не могут выполнить обновление без риска возникновения ошибок во время или после развертывания.
  • Теневые модули: Команды пишут свои собственные, когда модули не соответствуют их потребностям.

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

От монолитного к модульному: 2 шаблона
Отправная точка: что есть у большинства команд

Большинство команд начинают с работающей инфраструктуры: корзины, некоторых разрешений управления идентификацией и доступом (IAM) и базовых настроек безопасности. Проблема не в том, что он сломан; просто всё перепутано в одном модуле:

# модули/s3-with-access/main.tf ресурс «aws_s3_bucket» «app_bucket» { Bucket = «mycompany-app-uploads» # жестко запрограммированное имя } ресурс «aws_iam_role» «app_role» { # Создание ролей внутри модуля хранения name = «app-s3-access-role» take_role_policy = jsonencode({ Version = Заявление «17.10.2012» = [{
Action = «sts:AssumeRole»
Effect = «Allow»
Principal = { Service = «lambda.amazonaws.com» } # Lambda only
}]
}) } ресурс «aws_iam_role_policy» «app_bucket_access» { role = aws_iam_role.app_role.id policy = jsonencode({ Version = «2012-10-17» Statement = [{
Effect = «Allow»
Action = [«s3:GetObject», «s3:PutObject»] # Необработанные действия IAM Resource = «${aws_s3_bucket.app_bucket.arn}/*» }]}) } 12345678910111213141516171819202122232425262728 # Modules/s3-with-access/main.tfresource «aws_s3_bucket» «app_bucket» { Bucket = «mycompany-app-uploads» # Жестко запрограммированное имя} ресурс «aws_iam_role» «app_role» { # Создание ролей внутри модуля хранения name = «app-s3-access-role» Предположим_роль_политика = jsonencode({ Версия = «2012-10-17» Statement = [{      Action = «sts:AssumeRole»      Effect = «Allow»      Principal = { Service = «lambda.amazonaws.com» }  # Lambda only    }] })} ресурс «aws_iam_role_policy» «app_bucket_access» { role = aws_iam_role.app_role.id policy = jsonencode({ Version = «2012-10-17» Statement = [{      Effect = «Allow»      Action = [«s3:GetObject», «s3:PutObject»] # Необработанные действия IAM Resource = «${aws_s3_bucket.app_bucket.arn}/*» }]})}

Этот модуль включает в себя корзину, роль IAM и политики, но что происходит, когда вам нужно:

  • Тот же контейнер для задачи Elastic Container Service (ECS) вместо Lambda? Вы не можете повторно использовать этот модуль, поскольку эта роль жестко запрограммирована для Lambda.
  • Несколько сервисов для доступа к одному сегменту? Вам нужно будет скопировать и изменить весь модуль для каждой службы.
  • Просто ведро без роли IAM? Они неразрывно связаны.

Вот почему команды получают несколько разные копии одного и того же — s3-module-lambda, s3-module-ecs, s3-module-ec2.

Схема 1: Разделение задач — 1 модуль, 1 цель

Первая проблема: модули пытаются сделать слишком много. Когда ваш модуль S3 также создает роли и политики IAM, повторное использование для разных сервисов становится невозможным.

Единая ответственность означает, что каждый модуль хорошо выполняет одну задачу. Давайте разделим наши проблемы с помощью модуля, который управляет только сегментами S3. Нет ролей IAM. Никакой политики. Просто ведра с разумными настройками по умолчанию.

Модуль S3 — просто управляет сегментами

# Modules/s3/main.tf locals { Bucket_name = «${var.environment}-${replace(lower(var.name), «_», «-«)}» } ресурс «aws_s3_bucket» «this» { Bucket = local.bucket_name tags = var.tags } ресурс «aws_s3_bucket_public_access_block» «this» { Bucket = aws_s3_bucket.this.id block_public_acls = true block_public_policy = true ignore_public_acls = truestrict_public_buckets = true } ресурс «aws_s3_bucket_versioning» «this» { count = var.enable_versioning ? 1:0 Bucket = aws_s3_bucket.this.id versioning_configuration {status = «Enabled» } } вывод «arn» { value = aws_s3_bucket.this.arn } вывод «id» { value = aws_s3_bucket.this.id } 12345678910111213141516171819202122232425262728293031323334 # модули/s3/main.tf locals { Bucket_name = «${var.environment}-${replace(lower(var.name), «_», «-«)}»} ресурс «aws_s3_bucket» «this» { Bucket = local.bucket_name tags = var.tags} ресурс «aws_s3_bucket_public_access_block» «this» { Bucket = aws_s3_bucket.this.id block_public_acls = true block_public_policy = true ignore_public_acls = truestrict_public_buckets = true} ресурс «aws_s3_bucket_versioning» «this» { count = var.enable_versioning ? 1:0 Bucket = aws_s3_bucket.this.id versioning_configuration {status = «Enabled» }} вывод «arn» {value = aws_s3_bucket.this.arn} вывод «id» {value = aws_s3_bucket.this.id}

На практике: Ваш модуль S3 будет более сложным, требующим шифрования, совместного использования ресурсов между источниками (CORS), политик жизненного цикла и многого другого. Храните IAM, сетевые и вычислительные ресурсы в отдельных модулях, чтобы их можно было повторно использовать в разных службах и командах.

Паттерн 2. Компонуемость — модули, которые работают вместе

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

Сначала создайте ресурсы инфраструктуры, используя отдельные модули:

# Создать хранилище с модулем S3 mod «uploads» { source = «./modules/s3» name = «uploads» Environment = «production» } Module «backups» { source = «./modules/s3» name = «backups» Environment = «production» } # Создать ресурс вычислительных ресурсов «aws_iam_role» «app_service» { name = «app-service» take_role_policy = jsonencode({ Version = Заявление «17.10.2012» = [{
Action = «sts:AssumeRole»
Effect = «Allow»
Principal = { Service = «ecs-tasks.amazonaws.com» }
}]
}) } 1234567891011213141516171819202122232425 # Создать хранилище с модулем S3module «uploads» { source = «./modules/s3» name = «uploads» Environment = «production»} Module «backups» { source = «./modules/s3» name = «backups» Environment = «production»} # Создать ресурс вычислительных ресурсов «aws_iam_role» «app_service» { name = «app-service» take_role_policy = jsonencode({ Version = «2012-10-17» Statement = [{      Action = «sts:AssumeRole»      Effect = «Allow»      Principal = { Service = «ecs-tasks.amazonaws.com» }    }] })}

Затем соедините их вместе с явными разрешениями:

# Предоставьте службе доступ к необходимым ей сегментам ресурса «aws_iam_role_policy» «app_access» { name = «app-bucket-access» role = aws_iam_role.app_service.name policy = jsonencode({ Version = «2012-10-17» Statement = [
{
Effect = «Allow»
Action = [«s3:GetObject», «s3:PutObject»]
Resource = «${module.uploads.arn}/*» }, { Effect = «Разрешить» Action = [«s3:PutObject»]
Resource = «${module.backups.arn}/*» } ]}) } 123456789101112131415161718192021 # Предоставьте службе доступ к необходимым ей сегментамresource «aws_iam_role_policy» «app_access» { name = «app-bucket-access» role = aws_iam_role.app_service.name policy = jsonencode({ Version = «2012-10-17» Statement = [      {        Effect = «Allow»        Action = [«s3:GetObject», «s3:PutObject»] Resource = «${module.uploads.arn}/*» }, { Effect = «Разрешить» Action = [«s3:PutObject»] Ресурс = «${module.backups.arn}/*» } ]})}

Потому что модули имеют предсказуемые интерфейсы:

  • Любой сервис может использовать любой сегмент.
  • Разрешения являются явными и проверяемыми.
  • Никаких скрытых зависимостей между модулями.
  • Каждую деталь можно протестировать независимо.

На практике: Ваши модули будут более крупными единицами — «стеком приложений» или «конвейером данных», а не отдельными ресурсами. Стандартизированные интерфейсы и выходные данные позволяют модулям работать вместе независимо от того, составляете ли вы сегменты и политики или целые виртуальные частные облака (VPC) и кластеры Amazon Elastic Kubernetes Service (EKS). Предсказуемые интерфейсы позволяют создавать композиции.

От шаблонов к платформе

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

Разрыв между хорошими модулями и хорошей платформой — это координация. Вам необходимо убедиться, что каждая команда получит выгоду от улучшений, не заставляя их менять свои рабочие процессы.

Мы создали новую платформу, которая делает это возможным. С Suga ваши модули Terraform станут визуальными строительными блоками. Каждая команда получает одни и те же безопасные настройки по умолчанию. Обновления платформы автоматически приносят пользу всем приложениям, а не только новым. Разработчики создают инфраструктуру путем перетаскивания, а ваши стандарты незаметно применяются.

Хорошие модули используются повторно. Отличные модули становятся платформами. Запросите ранний доступ сегодня.

Nitric — это облачная платформа, которая повышает производительность разработчиков и повышает уверенность в эксплуатации, объединяя серверный и инфраструктурный код для быстрого создания и доставки облачных приложений. Разработчики создают ваше приложение, платформа определяет подходящую инфраструктуру, а Nitric автоматизирует подготовку, которая подходит для обоих. Узнайте больше Последние новости от Nitric ТЕНДЕНЦИОННЫЕ ИСТОРИИ YOUTUBE.COM/THENEWSTACK Технологии развиваются быстро, не пропустите ни одной серии. Подпишитесь на наш канал YouTube, чтобы смотреть все наши подкасты, интервью, демонстрации и многое другое. ПОДПИСАТЬСЯ Группа, созданная в Sketch. Рак Сива, вице-президент по разработке Team Nitric, глубоко стремится улучшить качество жизни разработчиков программного обеспечения. Имея богатый 15-летний опыт работы в индустрии программного обеспечения, он начал свой инженерный путь, погрузившись в волнующие задачи… Читать далее от Рака Шивы

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *