Рубрики
Uncategorized

Массовая динамическая вещь Загрузить с террафором

Простой метод использования BatchwiteItem для создания таблицы Dynamodb с террафом, затем загрузки данных через Local-Exec. Помечено террафом, AWS, Dynamodb, Devops.

Динамодб отлично! Он может использоваться для таблиц маршрутизации и метаданных, использоваться для блокировки файлов штата террафора, отслеживать состояния приложений и многое другое! Этот пост будет предлагать решение для заполнения нескольких элементов (строк) данных в таблице «Динамодби» при времени создания, полностью в террафоре.

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

Код доступен здесь для тех, кто просто хочет добраться до решения, находится в Github внизу поста. Я использую версию 0.12.24, но ничего 0,12+ должен работать без проблем. Кроме того, пользователь/роль AWS для запуска этой конфигурации также должен быть в состоянии использовать dynamodb: CreateTable и dynamodb: BatchwriteItem Отказ

Требования:

  1. Это должно быть в состоянии быть вызванным Форма террафора
  2. Он должен быть в состоянии совершить в управлении версиями
  3. Он должен работать над любого количества предметов для dynamodb
  4. В идеале не должно быть никаких других зависимостей

Требуется знания:

  • Dynamodb — предметы
  • Террафор — Основы ресурсов и даваний

Предоставление пустой таблицы dynamodb в террафоре довольно просто, пример конфигурации террафора ниже:

resource "aws_dynamodb_table" "basic-dynamodb-table" {
  name           = "GameScores"
  billing_mode   = "PROVISIONED"
  read_capacity  = 20
  write_capacity = 20
  hash_key       = "UserId"

  attribute {
    name = "UserId"
    type = "S"
  }


  tags = {
    Name        = "dynamodb-table-1"
    Environment = "production"
  }
}

Источник

Эта декларация ресурсов приведет к пустой таблице, которая должна иметь данные, загруженные позже. Hashicorp предлагает решение для управления элементами Dynamodb, как показано ниже:

resource "aws_dynamodb_table_item" "example" {
  table_name = "${aws_dynamodb_table.example.name}"
  hash_key   = "${aws_dynamodb_table.example.hash_key}"

  item = <

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

Note: This resource is not meant to be used for managing large amounts of data in your table, it is not designed to scale. You should perform regular backups of all data in the table, see AWS docs for more.

Это явно не оптимальное решение, так что можно сделать? Давайте посмотрим, что может предложить AWS, поскольку dynamodb — это продукт AWS. Сканирование через документацию открывает два возможных метода, Путитем и BatchwriteItem Отказ

Dynamodb предлагает несколько методов записи данных в таблицы, Путитем и BatchwriteItem Отказ Некоторые ключевые детали каждого из них ниже:

Путицем

  • Используется для загрузки одного элемента
  • Можно определить, существует ли поле перед загрузкой

Путитем выглядит как то, что dynamodb_table_item Ресурс использует в предыдущем разделе. Пример ниже:

aws dynamodb put-item \
    --table-name MusicCollection \
    --item '{"Artist": {"S": "Obscure Indie Band"}}' \
    --condition-expression "attribute_not_exists(Artist)"

Источник

Это добавит товар выше на таблицу музыки, на условиях, когда художник еще не существует. Можно удалось использовать петлю и определить некоторые стандартные стандартные для хранения нескольких элементов, итерации по поводу каждого элемента и добавить его в таблицу; Но это кажется много работы. Давайте проверим альтернативы.

BatchwriteItem.

  • Может загрузить много предметов в таблицу сразу
  • Будет просто перезаписать все предметы, которые имеют соответствующие основные ключи

Источник

Пример ниже:

aws dynamodb batch-write-item \
    --request-items file://request-items.json

Вот фрагмент request-items.json.

{
    "MusicCollection": [
        {
            "PutRequest": {
                "Item": {
                    "Artist": {"S": "No One You Know"},
                    "SongTitle": {"S": "Call Me Today"},
                    "AlbumTitle": {"S": "Somewhat Famous"}
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "Artist": {"S": "Acme Band"},
                    "SongTitle": {"S": "Happy Day"},
                    "AlbumTitle": {"S": "Songs About Life"}
                }
            }
        },
        ...

(Обратите внимание, таблица для загрузки элементов объявлена в самом JSON).

Пример JSON может быть любое количество элементов, его можно управлять в системе управления версией, и документация дает следующее предупреждение об обновлении элементов:

BatchWriteItem cannot update items. To update items, use the UpdateItem action.

Это не проблема для этого случая, так как все данные будут жить внутри одного файла JSON в управлении версиями.

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

Теперь, как мы можем вызвать это исключительно из террафора?

Provisioner в террафоре позволяет выполнять файл на либо локальную машину, работающую на террафоре для машинного террафора, только что предоставленной. Provisersers могут настроить инфраструктуру, как правило, виртуальные машины, либо на локальном узле (то, что работает Terrapormorm), либо удаленный аппарат (созданный террафом). В этом случае мы будем использовать Local-Exec , что позволит запустить файл на машине, на котором работает Terraporm. Для получения дополнительной информации проверить Документы на давателях.

Пример Local-Exec с EC2 в этом случае ниже:

resource "aws_instance" "web" {
  # ...

  provisioner "local-exec" {
    command = "echo The server's IP address is ${self.private_ip}"
  }
}

Пример выше для EC2; Тем не менее, Local-Exec Может работать для любого AWS Resource, включая Dynamodb!

Хорошо, так что теперь у нас есть следующее:

  • Конфигурация террафора для создания таблицы Dynamodb
  • Способ загрузки нескольких предметов на указанную таблицу
  • Решение для выполнения нагрузки данных из террафора

Единственное, что осталось сейчас — поставить все вместе!

Я предоставим очень простую таблицу DynamOdb, с 1 единицей чтения и пишущейся емкости, без шифрования, без потоков, а без аутокалирования. В пределах ресурса Dynamodb я вызываю Local-Exec Provisioner, чтобы загнать скрипт оболочки на том же машине, который работает Terraporm (который также установлен AWSCLI), это будет работать BatchwriteItem Для таблицы я только что создал и загрузите все данные образца.

Вот конфигурация террафора:

provider "aws" {
  region  = "us-east-2"
}

resource "aws_dynamodb_table" "basic-dynamodb-table" {
  name           = "ExternallyManagedTable"
  billing_mode   = "PROVISIONED"
  read_capacity  = 1
  write_capacity = 1
  hash_key       = "UserId"

  attribute {
    name = "UserId"
    type = "S"
  }

  provisioner "local-exec" {
    command = "bash populate_db.sh"
  }
}

Я проинструктировал террафору использовать AWS Поставщик построить Dynamodb Ресурс, затем используйте Local-Exec Provisioner, чтобы вызвать скрипт оболочки ниже:

#!/usr/bin/env bash

aws dynamodb batch-write-item --request-items file://items.json
{% endhighlight %}

The shell script references the following JSON:

{% highlight json %}
{
    "ExternallyManagedTable": [
        {
            "PutRequest": {
                "Item": {
                    "UserId": {
                        "S": "A"
                    },
                    "Title": {
                        "S": "Principal Engineer"
                    }
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "UserId": {
                        "S": "E"
                    },
                    "Title": {
                        "S": "Senior Engineer"
                    }
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "UserId": {
                        "S": "I"
                    },
                    "Title": {
                        "S": "Mid Level Engineer"
                    }
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "UserId": {
                        "S": "O"
                    },
                    "Title": {
                        "S": "Lead Engineer"
                    }
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "UserId": {
                        "S": "U"
                    },
                    "Title": {
                        "S": "Associate Engineer"
                    }
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "UserId": {
                        "S": "Y"
                    },
                    "Title": {
                        "S": "Half-Present Intern"
                    }
                }
            }
        }
    ]
}

Это построит наш стол, который является простым поиском метаданных на столе для инженерной группы без головы, состоящей из гласных!

Для начала, давайте инициализируем конфигурацию террафора:

terraform init

Initializing the backend...

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 2.59"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

На этапе плана:

terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

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_dynamodb_table.basic-dynamodb-table will be created
  + resource "aws_dynamodb_table" "basic-dynamodb-table" {
      + arn              = (known after apply)
      + billing_mode     = "PROVISIONED"
      + hash_key         = "UserId"
      + id               = (known after apply)
      + name             = "ExternallyManagedTable"
      + read_capacity    = 1
      + stream_arn       = (known after apply)
      + stream_label     = (known after apply)
      + stream_view_type = (known after apply)
      + write_capacity   = 1

      + attribute {
          + name = "UserId"
          + type = "S"
        }

      + point_in_time_recovery {
          + enabled = (known after apply)
        }

      + server_side_encryption {
          + enabled     = (known after apply)
          + kms_key_arn = (known after apply)
        }
    }

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

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Наконец, время применить нашу конфигурацию и создать таблицу!

terraform apply -auto-approve
aws_dynamodb_table.basic-dynamodb-table: Creating...
aws_dynamodb_table.basic-dynamodb-table: Provisioning with 'local-exec'...
aws_dynamodb_table.basic-dynamodb-table (local-exec): Executing: ["/bin/sh" "-c" "bash populate_db.sh"]
aws_dynamodb_table.basic-dynamodb-table (local-exec): {
aws_dynamodb_table.basic-dynamodb-table (local-exec):     "UnprocessedItems": {}
aws_dynamodb_table.basic-dynamodb-table (local-exec): }
aws_dynamodb_table.basic-dynamodb-table: Creation complete after 7s [id=ExternallyManagedTable]

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

Если вы перейдете к консоли или сканируете таблицу, вы увидите, что все данные присутствуют!

aws dynamodb scan --table-name ExternallyManagedTable

Результатом должно быть что-то вроде ниже:

{
    "Items": [
        {
            "Title": {
                "S": "Mid Level Engineer"
            },
            "UserId": {
                "S": "I"
            }
        },
        {
            "Title": {
                "S": "Principal Engineer"
            },
            "UserId": {
                "S": "A"
...

Для тех новых для Dynamodb, S Является ли DataType, строка в этом случае.

Если у вас есть какие-либо вопросы, комментарии, проблемы или запросы относительно того, какие Облака/DEVOPS/Automation/Monitoring/Sre Timics вы бы охватить дальше (я разрабатываю главный список будущих постов и объявлю его позже); Спасибо снова за чтение и, надеюсь, это помогает улучшить рабочие процессы Terraform/Dynamodb!

Github repo.

Оригинал: «https://dev.to/jacob_hudson/bulk-dynamodb-item-upload-with-terraform-1inp»