Рубрики
Uncategorized

Как создать воспроизводимую инфраструктуру AWS с модулями террафора

На данный момент я провожу большую часть моей недели внутри экосистемы Amazon Web Services. Если бы у меня было… Теги от AWS, DEVOPS, архитектуры.

На данный момент я провожу большую часть моей недели внутри экосистемы Amazon Web Services. Если бы мне пришлось сделать предположение, что я бы сказал, что 85% дня создает, обновление или уничтожение инфраструктуры AWS.

Но я провожу менее 1% от моей недели внутри консоли AWS.

То есть я не прикасаюсь к инфраструктуре AWS через консоль. Вся инфраструктура, с которой я взаимодействую, находится в коде, Террафор HCl быть конкретным.

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

Для всех позитивов с инфраструктурой в качестве кода, особенно HCl, есть нисходящие и негативы.

  1. HCl — еще один язык, чтобы узнать. Как мы увидим через минуту, это не похоже на язык, в котором вы, вероятно, создаете ваше заявление в.
  2. Он ограничен в наборе функций, которые он предлагает.
  3. Модульность может быть сложно, если вы не знакомы с ним.

Точка (3) — это тот, который мы собираемся сосредоточиться здесь. С модулями террафора мы можем создавать пользовательские пакеты, которые многоразовые.

Работа с примера

Давайте возьмем основной пример, создавая пользователь IAM с необходимой политикой для доступа к реестру EURACK CONSTALER ASACION (ECR). Вот три ресурса, которые нам нужны в террафоре.

# IAM User + Policy + Key to access ECR
resource "aws_iam_user" "some-user" {
  name = "some-user"
}

resource "aws_iam_user_policy" "some-user" {
  name = "some-user"
  user = aws_iam_user.some-user.name
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect   = "Allow",
        Action   = ["ecr:GetAuthorizationToken"],
        Resource = "*"
      },
      {
        Effect = "Allow",
        Action = [
          "ecr:GetAuthorizationToken",
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:GetRepositoryPolicy",
          "ecr:DescribeRepositories",
          "ecr:ListImages",
          "ecr:DescribeImages",
          "ecr:BatchGetImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
          "ecr:PutImage"
        ],
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_access_key" "some-user" {
  user    = aws_iam_user.some-user.name
}

Чтобы заземлить себя в реальности, давайте поставим их в реальный проект террафора. Запустите следующие команды в терминале. ( Примечание: вам нужно Установить Terraporm и есть AWS CLI Установлено ).

$ mkdir terraform-example 
$ cd terraform-example
$ touch main.tf

Теперь давайте добавим следующий блок для main.tf Отказ

terraform {
  required_version = ">=0.12, <0.13"
}

provider "aws" {
  version = "~> 2.58"
  region  = "us-west-2"
}

Это требует, чтобы у нас есть террафом Версия больше или равна 0,12, но менее 0,13. Второй бит, где мы объявляем, что мы собираемся использовать AWS поставщик. Это провайдер, который позволит нам получить доступ к ресурсам AWS внутри нашей учетной записи.

Под провайдером давайте добавим в ресурсы IAM с ранее. Теперь мы должны иметь что-то вроде этого в main.tf Отказ

terraform {
  required_version = ">=0.12, <0.13"
}

provider "aws" {
  version = "~> 2.58"
  region  = "us-west-2"
}

# IAM User + Policy + Key to access ECR
resource "aws_iam_user" "some-user" {
  name = "some-user"
}

resource "aws_iam_user_policy" "some-user" {
  name = "some-user"
  user = aws_iam_user.some-user.name
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect   = "Allow",
        Action   = ["ecr:GetAuthorizationToken"],
        Resource = "*"
      },
      {
        Effect = "Allow",
        Action = [
          "ecr:GetAuthorizationToken",
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:GetRepositoryPolicy",
          "ecr:DescribeRepositories",
          "ecr:ListImages",
          "ecr:DescribeImages",
          "ecr:BatchGetImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
          "ecr:PutImage"
        ],
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_access_key" "some-user" {
  user = aws_iam_user.some-user.name
}

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

$ terraform init
$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_iam_access_key.some-user will be created
  + resource "aws_iam_access_key" "some-user" {
      + encrypted_secret     = (known after apply)
      + id                   = (known after apply)
      + key_fingerprint      = (known after apply)
      + secret               = (sensitive value)
      + ses_smtp_password    = (sensitive value)
      + ses_smtp_password_v4 = (sensitive value)
      + status               = (known after apply)
      + user                 = "some-user"
    }

  # aws_iam_user.some-user will be created
  + resource "aws_iam_user" "some-user" {
      + arn           = (known after apply)
      + force_destroy = false
      + id            = (known after apply)
      + name          = "some-user"
      + path          = "/"
      + unique_id     = (known after apply)
    }

  # aws_iam_user_policy.some-user will be created
  + resource "aws_iam_user_policy" "some-user" {
      + id     = (known after apply)
      + name   = "some-user"
      + policy = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = [
                          + "ecr:GetAuthorizationToken",
                        ]
                      + Effect   = "Allow"
                      + Resource = "*"
                    },
                  + {
                      + Action   = [
                          + "ecr:GetAuthorizationToken",
                          + "ecr:BatchCheckLayerAvailability",
                          + "ecr:GetDownloadUrlForLayer",
                          + "ecr:GetRepositoryPolicy",
                          + "ecr:DescribeRepositories",
                          + "ecr:ListImages",
                          + "ecr:DescribeImages",
                          + "ecr:BatchGetImage",
                          + "ecr:InitiateLayerUpload",
                          + "ecr:UploadLayerPart",
                          + "ecr:CompleteLayerUpload",
                          + "ecr:PutImage",
                        ]
                      + Effect   = "Allow"
                      + Resource = "*"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + user   = "some-user"
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 

Применить Шаг остановил нас, чтобы подтвердить, что это все ресурсы, которые мы хотим создавать. Идти вперед и введите Да в подсказке. Мы должны видеть следующее после применения.

aws_iam_user.some-user: Creating...
aws_iam_user.some-user: Creation complete after 1s [id=some-user]
aws_iam_user_policy.some-user: Creating...
aws_iam_access_key.some-user: Creating...
aws_iam_access_key.some-user: Creation complete after 0s [id=]
aws_iam_user_policy.some-user: Creation complete after 1s [id=some-user:some-user]

Удивительно, у нас сейчас есть IAM пользователь, Некоторые пользователь У этого есть политика, которая позволяет им получить доступ к ЭКР. Если бы нам когда-либо пришлось только создавать один пользователь, были установлены, здесь нечего делать здесь.

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

Используя модули

Мы могли бы иметь более одного пользователя IAM с одной и той же политикой, копируя и вставляем ресурсы. Так что, если у нас был второй пользователь, наше main.tf мог бы выглядеть так.

terraform {
  required_version = ">=0.12, <0.13"
}

provider "aws" {
  version = "~> 2.58"
  region  = "us-west-2"
}

# IAM User + Policy + Key to access ECR
resource "aws_iam_user" "some-user" {
  name = "some-user"
}

resource "aws_iam_user_policy" "some-user" {
  name = "some-user"
  user = aws_iam_user.some-user.name
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect   = "Allow",
        Action   = ["ecr:GetAuthorizationToken"],
        Resource = "*"
      },
      {
        Effect = "Allow",
        Action = [
          "ecr:GetAuthorizationToken",
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:GetRepositoryPolicy",
          "ecr:DescribeRepositories",
          "ecr:ListImages",
          "ecr:DescribeImages",
          "ecr:BatchGetImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
          "ecr:PutImage"
        ],
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_access_key" "some-user" {
  user = aws_iam_user.some-user.name
}

# Second user
resource "aws_iam_user" "another-user" {
  name = "another-user"
}

resource "aws_iam_user_policy" "another-user" {
  name = "another-user"
  user = aws_iam_user.another-user.name
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect   = "Allow",
        Action   = ["ecr:GetAuthorizationToken"],
        Resource = "*"
      },
      {
        Effect = "Allow",
        Action = [
          "ecr:GetAuthorizationToken",
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:GetRepositoryPolicy",
          "ecr:DescribeRepositories",
          "ecr:ListImages",
          "ecr:DescribeImages",
          "ecr:BatchGetImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
          "ecr:PutImage"
        ],
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_access_key" "another-user" {
  user = aws_iam_user.another-user.name
}

Мы можем посмотреть на Другой пользователь Ресурсы и видите, что мы просто скопировали и вставили в ресурсы. Это работает и в порядке в щепоте. Но представьте, что если вы должны были сделать это для 10 пользователей 😭

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

На самом деле, мы уже используем модуль в нашем примере. Мы используем root модуль. root Модуль всегда вход main.tf Определяется в нашем проекте.

Мы собираемся преобразовать три ресурса, IAM пользователя, политику IAM и ключ доступа IAM в модуль, который можно использовать повторно.

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

$ mkdir modules
$ cd modules
$ touch iam.tf

Сейчас внутри IAM.TF Добавим наши три ресурса с ранее.

# IAM User + Policy + Key to access ECR
resource "aws_iam_user" "some-user" {
  name = "some-user"
}

resource "aws_iam_user_policy" "some-user" {
  name = "some-user"
  user = aws_iam_user.some-user.name
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect   = "Allow",
        Action   = ["ecr:GetAuthorizationToken"],
        Resource = "*"
      },
      {
        Effect = "Allow",
        Action = [
          "ecr:GetAuthorizationToken",
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:GetRepositoryPolicy",
          "ecr:DescribeRepositories",
          "ecr:ListImages",
          "ecr:DescribeImages",
          "ecr:BatchGetImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
          "ecr:PutImage"
        ],
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_access_key" "some-user" {
  user = aws_iam_user.some-user.name
}

Прямо сейчас этот модуль IAM — не параметризованный. Давайте пойдем вперед и исправить это, добавив Имя пользователя Переменная в верхней части IAM.TF Отказ

# IAM User + Policy + Key to access ECR
variable "username" {
  type = string
}

resource "aws_iam_user" "some-user" {
  name = var.username
}

resource "aws_iam_user_policy" "some-user" {
  name = "some-user"
  user = aws_iam_user.some-user.name
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect   = "Allow",
        Action   = ["ecr:GetAuthorizationToken"],
        Resource = "*"
      },
      {
        Effect = "Allow",
        Action = [
          "ecr:GetAuthorizationToken",
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:GetRepositoryPolicy",
          "ecr:DescribeRepositories",
          "ecr:ListImages",
          "ecr:DescribeImages",
          "ecr:BatchGetImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
          "ecr:PutImage"
        ],
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_access_key" "some-user" {
  user = aws_iam_user.some-user.name
}

Теперь весь модуль IAM занимает Имя пользователя Переменная. Он использует это для создания пользователей IAM, политики IAM и ключа доступа для этого имени пользователя.

Модули повторного использования

Теперь, когда у нас есть модуль IAM, который занимает имя пользователя Мы можем вернуться и редактировать наши main.tf Отказ Мы больше не должны копировать и вставлять ресурсы, чтобы добавить нового пользователя. Вместо этого мы можем назвать модуль с имя пользователя Мы хотим создать.

Вот пример, где мы создаем три пользователей.

terraform {
  required_version = ">=0.12, <0.13"
}

provider "aws" {
  version = "~> 2.58"
  region  = "us-west-2"
}

module "user-1" {
  source   = "./modules"
  username = "some-user-2"
}

module "user-2" {
  source   = "./modules"
  username = "another-user"
}

module "user-3" {
  source   = "./modules"
  username = "yet-another-user"
}

Вместо того, чтобы копировать и вставлять ресурсы вокруг, мы используем модуль, который мы создали. Этот модуль имеет все ресурсы, которые необходимо создавать. Снаружи мы даем модуль имя пользователя Мы хотим иметь пользователя IAM.

Давайте сделаем План На этом и посмотреть, что происходит. Мы должны бежать Terraform init Опять же, потому что добавил новый модуль.

$ terraform init
$ terraform plan

Мы видим, что будут созданы девять ресурсов, что имеет смысл, потому что мы создаем три новых пользователей. Если мы посмотрим на план, мы видим, что ресурсы теперь исходят из модуля.

# module.user-3.aws_iam_access_key.some-user will be created
  + resource "aws_iam_access_key" "some-user" {
      + encrypted_secret     = (known after apply)
      + id                   = (known after apply)
      + key_fingerprint      = (known after apply)
      + secret               = (sensitive value)
      + ses_smtp_password    = (sensitive value)
      + ses_smtp_password_v4 = (sensitive value)
      + status               = (known after apply)
      + user                 = "yet-another-user"
    }

  # module.user-3.aws_iam_user.some-user will be created
  + resource "aws_iam_user" "some-user" {
      + arn           = (known after apply)
      + force_destroy = false
      + id            = (known after apply)
      + name          = "yet-another-user"
      + path          = "/"
      + unique_id     = (known after apply)
    }

  # module.user-3.aws_iam_user_policy.some-user will be created
  + resource "aws_iam_user_policy" "some-user" {
      + id     = (known after apply)
      + name   = "some-user"
      + policy = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = [
                          + "ecr:GetAuthorizationToken",
                        ]
                      + Effect   = "Allow"
                      + Resource = "*"
                    },
                  + {
                      + Action   = [
                          + "ecr:GetAuthorizationToken",
                          + "ecr:BatchCheckLayerAvailability",
                          + "ecr:GetDownloadUrlForLayer",
                          + "ecr:GetRepositoryPolicy",
                          + "ecr:DescribeRepositories",
                          + "ecr:ListImages",
                          + "ecr:DescribeImages",
                          + "ecr:BatchGetImage",
                          + "ecr:InitiateLayerUpload",
                          + "ecr:UploadLayerPart",
                          + "ecr:CompleteLayerUpload",
                          + "ecr:PutImage",
                        ]
                      + Effect   = "Allow"
                      + Resource = "*"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + user   = "yet-another-user"
    }

Теперь, если мы пойдем и Применить Это мы должны увидеть, что три новых пользователей создаются. (Примечание. Я использую флаг -Авто-одобрение Флаг, чтобы рассказать Terraform для автоматического одобрения применения, не подскаженное мне).

$ terraform apply -auto-approve
module.user-1.aws_iam_user_policy.some-user: Creation complete after 0s [id=some-user-2:some-user]
module.user-1.aws_iam_access_key.some-user: Creation complete after 0s [id=]

Apply complete! Resources: 9 added, 0 changed, 0 destroyed.

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

С этим у нас теперь есть модуль пользователя Terraform IAM, который мы можем повторно использовать для создания новых пользователей IAM. Но на самом деле даже лучше, чем это, мы также можем использовать это для обновления пользователей.

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

Вывод

Инфраструктура в качестве кода является мощным инструментом в облачной среде. Это позволяет вашей инфраструктуре жить рядом с вашим повседневным кодом. Он поощряет обмен знаниями и процессами запроса на потянув на изменения инфраструктуры. С подходящими инструментами, он позволяет обмениваться общими идеями инфраструктуры между командами.

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

В этом примере мы сосредоточились на чем-то прямом направлении, IAM пользователю. Но модули могут быть созданы для любого количества вещей. Возможно, вы хотите создать модуль, который представляет собой каждый кусок инфраструктуры для Ваше приложение Отказ Или, может быть, вы хотите, чтобы каждая команда использовала общий модуль VPC, который имеет безопасность на переднем крае. Независимо от случая, модули позволяют вам создавать многоразовые блоки ресурсов.

Хотите проверить мои другие проекты?

Я огромный поклонник сообщества Dev. Если у вас есть какие-либо вопросы или хотите пообщаться о разных идеях, связанных с рефакторингом, Обратитесь в Twitter или бросить комментарий ниже.

Вне ведения блога я создал Узнайте AWS, используя его курс Отказ В ходе, в курсе мы ориентируемся на изучение веб-сервисов Amazon, на самом деле используя его для проведения, безопасных и доставлять статические сайты. Это простая проблема, со многими решениями, но она идеально подходит для наращивания вашего понимания AWS. Недавно я добавил два новых бонусных глава к курсу, который сосредоточен на инфраструктуре как код и непрерывное развертывание.

Оригинал: «https://dev.to/kylegalbraith/how-to-create-reproducible-aws-infrastructure-with-terraform-modules-1h31»