Динамодб отлично! Он может использоваться для таблиц маршрутизации и метаданных, использоваться для блокировки файлов штата террафора, отслеживать состояния приложений и многое другое! Этот пост будет предлагать решение для заполнения нескольких элементов (строк) данных в таблице «Динамодби» при времени создания, полностью в террафоре.
Проблема, которую я хочу решить, чтобы решить здесь, заключается в том, чтобы полностью предоставить таблицу поиска на динамодб, полностью от террафора, не включающая дополнительные шаги, которые террафом не может вызывать, без тонны дополнительной работы, и что-то может быть легко воспроизводимым и масштабируемым.
Код доступен здесь для тех, кто просто хочет добраться до решения, находится в Github внизу поста. Я использую версию 0.12.24, но ничего 0,12+ должен работать без проблем. Кроме того, пользователь/роль AWS для запуска этой конфигурации также должен быть в состоянии использовать dynamodb: CreateTable
и dynamodb: BatchwriteItem
Отказ
Требования:
- Это должно быть в состоянии быть вызванным Форма террафора
- Он должен быть в состоянии совершить в управлении версиями
- Он должен работать над любого количества предметов для dynamodb
- В идеале не должно быть никаких других зависимостей
Требуется знания:
- 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»