Защита истории отчётов при обновлениях

AWSBeginner
Практиковаться сейчас

Введение

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

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

Связь с сертификацией

Сертификация Задача экзамена Практика
Cloud Practitioner (CLF-C02) Задача 3.1 Использование воспроизводимых определений инфраструктуры и эксплуатационных запросов к ресурсам.
Developer – Associate (DVA-C02) Задача 3.3, навык 3.3.4 Базовая практика развёртывания определения инфраструктуры.
DevOps Engineer – Professional (DOP-C02) Задача 2.1 Базовая практика управления ресурсами через определение IaC.
Solutions Architect – Associate (SAA-C03) Задача 1.3 Базовая практика сохранения и чтения исторических данных S3 перед осознанной очисткой.

Обзор фактических ресурсов этой лабораторной работы и границ их сохранения.

Публикация первой версии

На этом шаге вы настроите управление версиями бакета с помощью Terraform перед публикацией первого отчёта.

Версии объектов S3 — это сохранённые копии данных, каждая со своим идентификатором версии. Они отличаются от ревизий HCL в Git и от файла фиксации провайдера Terraform. Terraform может настроить управление версиями; затем S3 сохраняет версии объектов при обновлении данных. Сам по себе план без изменений не доказывает, что исторические данные доступны для чтения.

Перейдите в подготовленный корневой каталог и запишите определение хранилища:

cd /home/labex/project/report-history
cat > main.tf <<'EOF'
variable "report" { type = string }

resource "aws_s3_bucket" "reports" {
  bucket = "terraform-history-reports"
}

resource "aws_s3_bucket_versioning" "reports" {
  bucket = aws_s3_bucket.reports.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_object" "report" {
  bucket       = aws_s3_bucket.reports.id
  key          = "reports/current.csv"
  content      = var.report
  content_type = "text/csv"
  depends_on   = [aws_s3_bucket_versioning.reports]
}
EOF

Теперь есть три ресурса: бакет, его настройки управления версиями и объект. Объект уже зависит от бакета через ссылку на его идентификатор. Явный depends_on добавляет порядок, который нельзя вывести из этой ссылки: управление версиями должно быть включено до первой загрузки.

Запишите входное значение первого отчёта и выполните инициализацию:

cat > release1.tfvars <<'EOF'
report = "orders,12\n"
EOF
terraform init
terraform validate
terraform plan -var-file=release1.tfvars

Ожидайте три добавления. Примените изменения и введите yes:

terraform apply -var-file=release1.tfvars

Запросите фактическую настройку и первую версию:

aws s3api \
  get-bucket-versioning \
  --bucket terraform-history-reports
aws s3api \
  list-object-versions \
  --bucket terraform-history-reports \
  --query 'Versions[].{Key:Key,VersionId:VersionId,Current:IsLatest}'

Статус — Enabled. У отчёта есть идентификатор версии, отличный от null, и Current: true. AWS View показывает текущий доступный для чтения объект; для изучения истории используйте запрос версий. AWS View после развёртывания: фактическое хранилище под вашим управлением отображается рядом с сохранённым эталонным отчётом.

Обновление отчёта и чтение его истории

На этом шаге вы опубликуете другие байты, явно прочитаете старую версию и докажете, что чтение истории оставляет текущий отчёт без изменений.

Создайте второй файл входных значений. Сохранение обоих файлов позволяет легко сравнить задуманные версии данных; сами файлы не являются сохранённой историей.

cat > release2.tfvars <<'EOF'
report = "orders,25\n"
EOF
terraform plan -var-file=release2.tfvars -out=update.tfplan
terraform show update.tfplan

Ожидайте одно обновление объекта без замены бакета. -out сохраняет артефакт плана, включающий выбранные входные значения. Примените этот проверенный артефакт; команда не запрашивает подтверждение, потому что вы уже выбрали сохранённый план:

terraform apply update.tfplan

Снова выведите список фактических версий:

aws s3api \
  list-object-versions \
  --bucket terraform-history-reports \
  --query 'Versions[].{Key:Key,VersionId:VersionId,Current:IsLatest}'

У старой и текущей записей разные идентификаторы версий. Выберите идентификатор старого отчёта и выведите его. Запрос фильтрует по ключу отчёта и IsLatest == false; [0] выбирает первую подходящую старую запись в истории из двух версий этой лабораторной работы.

OLD_VERSION=$(aws s3api \
  list-object-versions \
  --bucket terraform-history-reports \
  --query 'Versions[?Key==`reports/current.csv` && IsLatest==`false`].VersionId | [0]' \
  --output text)
echo "$OLD_VERSION"
CURRENT_VERSION=$(aws s3api \
  head-object \
  --bucket terraform-history-reports \
  --key reports/current.csv \
  --query VersionId \
  --output text)
echo "$CURRENT_VERSION"

Загрузите старую версию по идентификатору, затем загрузите текущую версию без указания идентификатора версии:

aws s3api \
  get-object \
  --bucket terraform-history-reports \
  --key reports/current.csv \
  --version-id "$OLD_VERSION" \
  old-report.csv
cat old-report.csv
aws s3api \
  get-object \
  --bucket terraform-history-reports \
  --key reports/current.csv \
  current-report.csv
cat current-report.csv

Ожидайте orders,12 в старом файле и orders,25 в текущем файле. GET с указанием версии читает существующую версию; он не копирует её поверх текущего объекта. Ещё раз запросите текущий идентификатор и сравните его с выведенным CURRENT_VERSION:

aws s3api \
  head-object \
  --bucket terraform-history-reports \
  --key reports/current.csv \
  --query VersionId \
  --output text

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

Осознанное удаление собственной истории

На этом шаге вы составите список и удалите все версии в своём одноразовом бакете отчётов перед удалением его ресурсов конфигурации Terraform.

Удаление инфраструктуры и решение отказаться от истории отчётов — разные действия. Непустой бакет с управлением версиями обычно нельзя удалить. Удаление текущего объекта без идентификатора версии может создать маркер удаления, который скрывает текущий объект, тогда как старые версии сохраняются. Здесь вы явно удалите версии из составленного списка по идентификаторам после подтверждения их сохранности на предыдущем шаге.

Создайте запрос удаления на основе списка версий, полученного от сервиса. В этой лабораторной работе есть только небольшой набор версий отчёта и нет существующих маркеров удаления; каждая перечисленная версия принадлежит вашему бакету. --query преобразует каждую запись в поля Key/VersionId, которые принимает delete-objects.

aws s3api \
  list-object-versions \
  --bucket terraform-history-reports \
  --query '{Objects: Versions[].{Key:Key,VersionId:VersionId}}' \
  > owned-versions.json
cat owned-versions.json

Убедитесь, что файл содержит только версии из terraform-history-reports. Затем удалите именно эти версии. file:// указывает AWS CLI прочитать JSON-запрос из локального файла.

aws s3api \
  delete-objects \
  --bucket terraform-history-reports \
  --delete file://owned-versions.json
aws s3api \
  list-object-versions \
  --bucket terraform-history-reports

В успешно полученном списке нет записей Versions или DeleteMarkers. Теперь удалите ресурсы этой корневой конфигурации и введите yes:

terraform destroy -var-file=release2.tfvars

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

terraform state list
aws s3api \
  list-buckets \
  --query 'Buckets[].Name'
aws s3api \
  head-object \
  --bucket team-reference-reports \
  --key keep.txt \
  --query ContentLength

Список ресурсов в состоянии пуст, и остаётся только эталонный бакет команды. Не используйте эту процедуру удаления данных для хранилища, историю которого необходимо сохранить.

Резюме

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