更新中もレポートの履歴を保護する

AWSBeginner
オンラインで実践に進む

はじめに

新しいレポートを公開しても、チームが以前のデータを読めなくなってはいけません。バージョニングを設定し、2 つのレポートを公開して、過去のバージョンの読み取りと現在のバージョンの読み取りを区別した後、この使い捨てのストアを意図的に削除します。

前の実験で学んだ変数、オブジェクト参照、独立したルートの知識を活用します。この新しい環境に用意されているのは、ツール、プロバイダーのアクセス設定、管理対象ではない参照用レポートだけです。

認定試験との関連

認定資格 試験のタスク 演習内容
Cloud Practitioner (CLF-C02) Task 3.1 再現可能なインフラストラクチャ定義と、運用時のリソース照会を使用します。
Developer – Associate (DVA-C02) Task 3.3, Skill 3.3.4 インフラストラクチャ定義をデプロイする基礎演習です。
DevOps Engineer – Professional (DOP-C02) Task 2.1 IaC 定義を通じてリソースを管理する基礎演習です。
Solutions Architect – Associate (SAA-C03) Task 1.3 過去の S3 データを保持して読み取り、その後で意図的に削除する基礎演習です。

この実験で実際に扱うリソースと、保持する対象の境界を示す概念図。

最初のバージョンを公開する

このステップでは、最初のレポートを公開する前に、Terraform でバケットのバージョニング設定を管理します。

S3 のオブジェクトバージョンは、保持されたデータのコピーで、それぞれにバージョン ID があります。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

これで、バケット、バージョニング設定、オブジェクトの 3 つのリソースがあります。オブジェクトは ID 参照を通じて、すでにバケットに依存しています。明示的な depends_on は、その参照からは推測できない順序を追加します。つまり、最初のアップロードより前にバージョニングを有効にする必要があります。

最初のレポートの入力を書き込み、初期化します。

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

追加は 3 つのはずです。適用し、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 ではないバージョン ID があり、Current: true と表示されます。AWS View は現在読み取り可能なオブジェクトを表示します。履歴の確認にはバージョンのクエリを使ってください。 デプロイ後の AWS View:作成したストレージが、保持された参照用レポートの隣に表示されています。

レポートを更新して履歴を読む

このステップでは、異なるバイト列を公開し、古いバージョンを明示的に読み取って、履歴の読み取りが現在のレポートを変更しないことを確かめます。

2 つ目の入力ファイルを作成します。両方のファイルを保持すると、意図したデータバージョンを比較しやすくなります。ただし、ファイル自体が保存済みの履歴というわけではありません。

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

バケットの置き換えなしで、オブジェクトの更新が 1 つ提案されるはずです。-out は、選択した入力値を含むプラン成果物を保存します。確認済みの成果物を適用します。保存済みプランをすでに選択しているため、このコマンドは確認を求めません。

terraform apply update.tfplan

実際のバージョンを再び一覧表示します。

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

古いエントリーと現在のエントリーでは、バージョン ID が異なります。古いレポートの ID を選択して表示します。クエリはレポートのキーと IsLatest == false で絞り込み、[0] が、この実験の 2 バージョンの履歴の中で最初に一致した古いエントリーを選択します。

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"

ID を指定して古いバージョンをダウンロードし、次にバージョン ID を指定せずに現在のバージョンをダウンロードします。

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 は既存のバージョンを読み取るもので、現在のオブジェクトに上書きコピーするものではありません。現在の ID をもう一度照会し、表示済みの CURRENT_VERSION と比較します。

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

ID は変更されていません。バージョンを削除する前に、このステップのチェックを完了してください。チェックは古いバージョンと現在のバージョンの実際のバイト列を読み取り、両方を保持します。オブジェクトキー、バージョン、削除マーカーの違いについては、S3 のバージョニングを参照してください。

自分が所有する履歴を意図的に削除する

このステップでは、Terraform 設定のリソースを削除する前に、使い捨てのレポート用バケットにあるすべてのバージョンを一覧で確認し、削除します。

インフラストラクチャの削除と、レポート履歴を破棄する判断は別の操作です。空でないバージョン管理されたバケットは、通常は削除できません。バージョン ID を指定せずに現在のオブジェクトを削除すると、削除マーカーが作成され、古いバージョンを残したまま現在のオブジェクトが見えなくなる場合があります。ここでは、前のステップで保持を確認した後で、一覧で確認したバージョンを ID によって明示的に削除します。

サービスから取得したバージョン一覧を基に、削除リクエストを作成します。この実験には少数のレポートバージョンだけがあり、既存の削除マーカーはありません。一覧にあるすべてのバージョンは、自分のバケットに属します。--query は、各エントリーを delete-objects が受け取る Key/VersionId フィールドに整形します。

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:// は、ローカルファイルから JSON リクエストを読み取るよう AWS CLI に指示します。

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

状態の一覧は空になり、チームの参照用バケットだけが残ります。履歴を保持しなければならないストアでは、このデータ破棄の手順を使わないでください。

まとめ

設定の変更とデータのバージョンを区別し、アップロード前にバージョニングを有効にして、現在のバージョンを上書きせずに異なる旧版と現行版のレポートのバイト列を読み取りました。その後、自分が所有するバージョンだけを明示的に一覧で確認して破棄しました。