Google Cloud SDKのススメ
はじめに
※本記事は、2022年05月10日に公開済みの記事を移行して再掲載したものです。
技術開発部の林田と申します。
前職ではWebシステムの開発をしており、去年よりバックエンドエンジニアとしてフェズのデータ基盤の開発・運用に携わっています。
この記事では、Google Cloud SDKのgcloud, bq, gsutilコマンドを実務のどんな場面で使ったかについて紹介しています。
背景
データ基盤チームでは機能の素早いデリバリーや変更差分を大きくしすぎないためにデプロイ・検証を毎週行なっています。
別の記事で紹介されているデータ基盤の各サービスのうちCloud RunやDataflowなど個別のアプリケーションについてはGitフローに則ってデリバリーが自動化されていますが、Cloud StorageやBigQueryなどと連携した動作やリリースごとの検証項目についてはGCP上で検証する必要がある状態です。
簡単にまとめると下記の通りです。
自動化済み
- リソースの権限管理
- APIの有効化
手動実行
- データセット・バケットの作成
- データのマイグレーション
- Cloud StorageやBigQueryなどと連携した動作確認
そこで、
- 検証で使用するデータの準備や本番環境のデータの移行など、BigQuery・ストレージオブジェクトの操作やCloud Functionsの呼び出しなどで似たような呼び出しを複数回行うことがある。
- ブラウザの遷移が単純に遅い
- チーム内で検証の自動化の話題が上がっている。
などの理由から、上記の手動で行っていることをCLIでの操作にすると手間が少なく効率が良いのではないかと思い試してみた次第です。
環境
今回の記事で紹介するコマンドは以下のバージョンで実行しています。
※バージョンによっては挙動が異なる可能性があります。
Python | 3.7.4 |
---|---|
Google Cloud SDK | 362.0.0 |
bq | 2.0.71 |
gsutil | 5.4 |
ローカル環境からCloud Runを呼び出す
バケットやBigQueryと連携した動作確認のため、GCP上のCloud Runをローカルから呼び出しています。本番環境ではComposer(Airflow)から呼び出されていますが、Cloud Runのみに変更がある場合には下記でCloud Runのみの動作検証を行なっています。
curl -X POST \
-H "Content-Type: application/json" \
-d '{"aaa": "bbb"}' \
${URI}/${ENDPOINT}
認証ありの設定の場合、gcloudコマンドでログインユーザとして取得したJWTを使用しています。
token="$(gcloud auth print-access-token)"
またCloud RunのURLについては、gcloudコマンドでアウトプットのフォーマットを指定して取得することで、コンソールから確認する必要もなくなります。
cloudrun_url="$(gcloud run services describe ${SERVICE} --region REGION --format 'value(status.url)')"
以下のようなコマンドで認証とURLの取得をしてCloud Runを実行しています。
token="$(gcloud auth print-access-token)"
cloudrun_url="$(gcloud run services describe SERVICE --region REGION --format 'value(status.url)')"
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
-d '{"aaa": "bbb"}' \
${cloudrun_url}/${ENDPOINT}
BigQueryのテーブル・ビューをPythonで構築する
BigQueryのテーブルやビューのスキーマをドキュメントに記載されているようにPythonのスクリプトで定義してバージョン管理しています。
構築する際には下記のようにサービスアカウントのキーを発行してローカルから実行していました。
export GOOGLE_APPLICATION_CREDENTIALS="KEY_PATH"
python create_table.py
この場合、スクリプトを実行するためのサービスアカウントの作成・キーの発行が必要かつ、意図しないユーザがサービスアカウントを悪用して情報漏洩や攻撃対象になるなどのリスクもあるため、サービスアカウントキーを使用せずにGoogle Cloud SDKのライブラリをユーザとして認証して実行するようにしました。
gcloud auth application-default login
上記でGoogle Cloud SDKの認証が完了してユーザに権限があれば、GOOGLE_APPLICATION_CREDENTIALS
の環境変数を設定することなくPythonのスクリプトを実行できます。
複数テーブルに対してSQLを実行する
検証・本番環境のBigQueryに保存されているデータに対してSQLを実行することがあり、bqコマンドを使用して複数テーブルに対するSQLなどをまとめて実行します。
特定のプロジェクトのデータセットのテーブルを取得します
bq ls PROJECT_ID:DATASET
bashとbqコマンドで取得した全テーブルに対してSQLを発行します
下記では例として単純なSELECT文ですが、実際のケースではバックアップやスキーマの作成などで使用しています。
dataset_id=${PROJECT_ID}:${DATASET}
for table in $(bq ls ${dataset_id} | awk '{print $1}' | tail +3)
do
echo "TableId: $table"
query = "SELECT * FROM ${dataset_id}.${table}"
bq query --location=${LOCATION} --use_legacy_sql=false ${query}
done
Pub/Subの複数のトピックにメッセージを発行する
Pub/Subのトピックをトリガーに起動するサービスが複数あり、それぞれに対してGUIからメッセージを発行していましたが、メッセージの発行についてもCLIから実行可能なようでしたのでそちらで実行するようにしました。
数が多くなければ画面からでも構わないですが、10個以上となると数十分かかってしまっていました。
ドキュメントの通り下記でメッセージを発行することができます。
gcloud pubsub topics publish mytopic --message="Hello World!"
下記のように複数のトピックにまとめてメッセージを発行します。
set -f
topics=(
"topic1"
"topic2"
...
)
for t in "${topics[@]}"; do
echo "topic: $t"
gcloud pubsub topics publish $t \
--message="{'aaa' 'bbb'}" \
--project=PROJECT_ID
done
また、実行した際にはある程度トピックの名称が決まっていたので、トピック名についてもgcloudコマンドで取得して渡すようにしていました。
下記のコマンドでトピックを取得することができます。(ドキュメント)
gcloud pubsub topics list \
--filter="name.scope(topic):'my-topic'" \
--format="value(name)")
—filterパラメータを指定して特定の文字を含むトピック名を取得するようにしています。
--filter="name.scope(topic):'my-topic'"
アウトプットをトピック名のみ出力するようにします
--format="value(name)")
結果をメッセージを発行するコマンドに渡して実行します。
for t in $(gcloud pubsub topics list --filter="name.scope(topic):'my-topic'" --project=${PROJECT_ID} --format="value(name)"); do
echo "topic: $t"
gcloud pubsub topics publish $t \
--message="{}" \
--project=PROJECT_ID
done
--format, —project, —filterオプションについて
最後にところどころ使用している引数の使い方について簡単に紹介します。
—format(ドキュメント)
アウトプットのフォーマットの指定をします。
—format=”json”を指定して取得し、結果の特定のキーを—format=”value(key)”として指定することで特定の属性の値のみを取得していました、シェルコマンドのsedやawkを使用する手間が省けて便利です。
—project(ドキュメント)
こちらはドキュメントに記載の通り、対象リソースのプロジェクトや実行するAPIの有効化の確認をするプロジェクトの指定です。指定がない場合には実行時点の設定プロジェクトを想定します。
また、Pub/Subのトピックの指定などでトピック名をプロジェクト名を含めて指定する場合にはこちらのパラメータを指定しなくても認識されます。
—filter(ドキュメント)
リソースのリストを取得する際の条件を指定します。
キー・条件・値で指定します。条件についてはドキュメントの通りに指定することができます。
が、いざ自分で使用とするとキーの指定の方法が不明でした。
調べてみるとキーについてはlistコマンドに対して--format=flattened
オプションをつけることで値と一緒に確認できます。
gcloud run services describe ${SERVICE} \
--region REGION \
--project=${PROJECT_ID} \
--format=flattened
apiVersion: serving.knative.dev/v1
kind: Service
metadata.annotations.client.knative.dev/user-image: hoge
metadata.annotations.run.googleapis.com/client-name: gcloud
metadata.annotations.run.googleapis.com/client-version: 380.0.0
metadata.annotations.run.googleapis.com/ingress: all
metadata.annotations.run.googleapis.com/ingress-status: all
metadata.annotations.serving.knative.dev/creator: hoge
metadata.annotations.serving.knative.dev/lastModifier: hoge
metadata.creationTimestamp: 2021-11-08T06:29:46.332294Z
metadata.generation: 237
metadata.labels.cloud.googleapis.com/location: LOCATION
metadata.name: SERVICE
....
このキーと条件・値を指定することで特定のリソースだけをリストとして取得できます。
上記のCloud Runをサービス名の条件で取得する場合は下記のパラメータになります。
--filter="metadata.name=SERVICE_NAME"
まとめ
今回の記事ではGCPのリソースの操作をCLIで実行した例を紹介しました。
コンソールからの操作をCLIから実行することによって、繰り返し作業の時間が短くなるだけでなく、再現性が高まり同様の検証を再実行する際にも同一のコマンドを実行するだけで完了するようになり、作業時間を短縮することができました。
あくまで手段の一つという見方なので、一つの作業をわざわざCLIで実行しようという提案でもなく、そもそも検証の手順自体人がやる必要があるかどうかなども検討する必要がありますが、単純な作業をいかに効率化するかという観点からこういったことを試してみました。
また、データ基盤チームでは今回紹介したスクリプトなどを含めてデプロイ・検証を自動化していくことも検討中です。今後そのあたりの動向も記事にできればと思います。
フェズは、「情報と商品と売場を科学し、リテール産業の新たな常識をつくる。」をミッションに掲げ、リテールメディア事業・リテールDX事業を展開しています。 fez-inc.jp/recruit
Discussion