terraformで設定するCloud Storage bucket アクセスログ/ストレージログ

terraformおじさん再びです。

前回の記事ではterraformでhttp(s)負荷分散を作ってみましたが、今回はCloud Storageのアクセスログ/ストレージログ出力設定をゆるく行っていきます。

  1. GCPを触ったことがある
  2. terraformを触ったことがある
  3. Cloud Storage Bucketのlogging設定を手動で行っている

といった方にとって有用な情報となれば幸いです。

作ってみる

それでは、下記ドキュメントを参考に設定を行っていきましょう。

https://cloud.google.com/storage/docs/access-logs?hl=ja

ログ配信の設定

1. ログを保存するバケットを作成

まずはログを保存するバケットを作成します。
頻繁には参照されないため、ストレージクラスはNearlineを設定します。

command
gsutil mb gs://example-logs-bucket
terraform
resource "google_storage_bucket" "example-logs-bucket" {
  name          = "example-logs-bucket"
  location      = "us-central1"
  storage_class = "NEARLINE"
}

はい。

2. Cloud Storage にバケットへの WRITE 権限を付与するため、権限を設定します。

それでは、terraformとgoogleのdocumentをもとに設定していきます。

gcs document

Cloud Storage では、ログを新しいオブジェクトとして作成して保存するために、WRITE 権限が必要です。Cloud Storage にバケットへの WRITE アクセスを許可するために、次のコマンドを使って cloud-storage-analytics@google.com グループに書き込みアクセスを許可します。

command
gsutil acl ch -g cloud-storage-analytics@google.com:W gs://example-logs-bucket
terraform document

https://www.terraform.io/docs/providers/google/r/storage_bucket_acl.html

role_entity - (Optional) List of role/entity pairs in the form ROLE:entity. See GCS Bucket ACL documentation for more details. Must be set if predefined_acl is not.

ここでは ROLE:entity の形式で role_entity を設定します。

gcs access control document

https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls

Property name Value Description Notes
entity string The entity holding the permission, in one of the following forms:

group-email
writable
role string The access permission for the entity.
Acceptable values are:

“WRITER”
writable

cloud-storage-analytics@google.com グループに書 き込みアクセスを許可とあるので、access control documentにある表の項目を元に、entityをgroup-cloud-storage-analytics@google.comに、roleをWRITERにそれぞれ指定します。

terraform
  role_entity = [
    "WRITER:group-cloud-storage-analytics@google.com",
  ]

続いてデフォルト オブジェクト ACLを設定します。

document

ログ オブジェクトには、ログバケットのデフォルト オブジェクト ACL が適用されます。ログバケットのデフォルト オブジェクト ACL を設定するには gsutil を使用します。たとえば、デフォルト オブジェクト ACL を project-private に設定するには、次のコマンドを使用します。

command
gsutil defacl set project-private gs://example-logs-bucket

terraformではJSON APIのprojectPrivateでもなく、XML API/gsutilのproject-privateでもなくprojectprivateを設定します。
若干もやもやします

  default_acl = "projectprivate"

以上2点をもとにACLのconfigを書いてみます

# acl
resource "google_storage_bucket_acl" "example-logs-bucket" {
  bucket = "${google_storage_bucket.example-logs-bucket.name}"

  role_entity = [
    "WRITER:group-cloud-storage-analytics@google.com",
  ]

  default_acl = "projectprivate"

  lifecycle {
    ignore_changes = [
      "role_entity",
    ]
  }
}

一点ポイントとなるのはbucket作成時にdefaultで作成されるACL誤って消さないよう、lifecycle ignore_changesでrole_entityの更新を除外している点です。
副作用としてrole_entityを追加したい際には追加したentityが反映されなくなります。lifecycle ignore_changesから"role_entity"をコメントアウトしたうえでterraform planを実行し、不足しているrole_entityをconfigに追加する形が漏れがなく設定できるかと思います。

3.バケットのロギングを有効にします。

command
gsutil logging set on -b gs://example-logs-bucket [-o log_object_prefix ] gs://example-bucket

logginglog_bucketlog_object_prefixにそれぞれ記載します。
log_object_prefixが未記載の場合は、ロギングを行うbucket名(この場合はexample-bucket)がデフォルトで入ります。
複数のbucketからログを保存する場合は、下のサンプルのように階層を分けた方が見分けをつけやすくなるでしょう。

terraform
# bucket
resource "google_storage_bucket" "example-bucket" {
  name          = "example-bucket"
  location      = "us-central1"
  storage_class = "REGIONAL"

  logging {
    log_bucket        = "example-logs-bucket"
    log_object_prefix = "example-bucket/example-bucket"
  }
}

ロギング状態を調べる

設定されたロギング状態は、以下のように確認できます。

gsutil logging get gs://example-bucket

ログのダウンロード

バケットに対するアクセスは1時間毎に出力されます。
即時は出力されませんので注意してください。

使用状況ログは、モニタリング対象バケットで報告すべき活動がある場合に、1 時間ごとに生成されます。使用状況ログは、通常は時間の終わりから 15 分後に作成されます。

おまけ

ログファイルのlifecycleを設定する

保存されてから時間が経過したログファイル(オブジェクト)は、他のデータストアに保存されたり、統計情報として成形されるなどし、それほど頻度高く参照されないケースは多いかと思います。
GCSでは参照頻度の低いオブジェクト向けに安価なストレージクラスが用意されていますので、一定期間より古いオブジェクトに対しストレージクラスを変更する設定を追加します。

下記の例では、ストレージクラスがNEARLINEのオブジェクトに対し、14日以上経過した場合はストレージクラスをCOLDLINEに変更します。 オブジェクトはバージョニングされてないため、対象を is_live = true としています。

  lifecycle_rule {
    action {
      type          = "SetStorageClass"
      storage_class = "COLDLINE"
    }

    condition {
      age = "14"

      matches_storage_class = [
        "NEARLINE",
      ]

      is_live = true
    }
  }

おわりに

以上、GCSのLogging設定をドキュメントと照らし合わせながら行ってみました。
terraformを使ったGCS運用の助けになれば幸いです。