GCP の Cloud Logging から BigQuery へのログエクスポートがうまくいかないときに確認すること

#tech
#gcp

Cloud Logging のログを長期保存や分析目的で BigQuery に転送したいケースがある。これは Log Router の Sink を設定することで簡単に実現できる。 しかし最近転送がうまく動かなくなりハマったので調査と対応手順をまとめる。

問題の切り分け

公式ドキュメントにもあるが、Sink がうまく動かない原因はおおまかに 3 パターンある。
Google Cloud Console でのログのエクスポート  |  Cloud Logging

  1. Sink に設定したログのフィルタが間違っている
  2. Sink を設定して以降に新規のログが Cloud Logging に流れてきていない
  3. Sink からデータ転送先への書き込みが失敗している

1. と 2. は初歩的な問題なのですぐ気付けるはず。3. に関しては色々な可能性がありそうだが、 https://console.cloud.google.com/logs/metricsexports/error_count 指標を見ればエラーが発生しているか確認できる。

自分が遭遇したのは Sink から宛先テーブルへの書き込み権限が無くなっていたというものだった。 Sink から BigQuery テーブルへ書き込む場合、テーブルのデータ編集者権限で Sink に紐づいた Service Account gcp-sa-logging.iam.gserviceaccount.com ドメインのキーが登録されている必要がある。

自分の場合、最初に Sink を設定して BigQuery にデータを転送し始めた後、諸事情で dataset を削除して作り直した際 Service Account の設定が漏れていたらしい。 この問題が起こった時の対応手順は以下の通り。

Sink の Service Account をテーブル編集権限に追加

そもそも Web の Cloud Console 上では、各 Sink の設定ページに Service Account という項目は存在しない。なのでこれを宛先に登録する必要があるということに気づきにくかった。

各 Sink の Service Account は gcloud コマンドから確認できる。
Command-line interface  |  Cloud Logging  |  Google Cloud

# Sink の一覧を確認する
gcloud logging sinks list
NAME              DESTINATION                                                  FILTER
log_export_sink   bigquery.googleapis.com/projects/my-app/datasets/log_export  resource.type="k8s_container"
                                                                               resource.labels.cluster_name="my-app-cluster"
...
# Sink 名を指定して詳細を表示
gcloud logging sinks describe log_export_sink 
bigqueryOptions:
  usePartitionedTables: true
  usesTimestampColumnPartitioning: true
...
updateTime: '2020-11-30T02:46:33.462601605Z'
writerIdentity: serviceAccount:*********@gcp-sa-logging.iam.gserviceaccount.com

確認した Service Account を宛先テーブルに登録し、無事ログがエクスポートできた。

Tweet