gcloud にカレントプロジェクトを設定しない派

gcloud CLI にカレントプロジェクトをなるべく持たせないようにして暮らしている。

gcloud はデフォルトでカレントプロジェクトのリソースを操作する。操作するプロジェクトが 1 つなら良いけど、仕事でも遊びでもいくつもの GCP プロジェクトを扱っているので、うっかり異なるプロジェクトのリソースを操作してしまったり、意図しないプロジェクトに費用が計上されてしまうのが嫌だから。

カレントプロジェクトは設定しないようにして、gcloud を使う時は都度 --project=PROJECT_ID で渡すようにしている。

# カレントプロジェクトを確認するには以下のコマンドなど
$ gcloud config get-value project
$ gcloud config list

# カレントプロジェクトの設定を消す
$ gcloud config unset project

ローカルの ADC の quota project

忘れられがちだけど、ローカルの Application Default Credentials にもカレントプロジェクトに相当する "quota project" がある。

ADC についてはこちら
blog.pokutuna.com

ADC の quota project は、gcloud auth application-default login した時点のカレントプロジェクトが設定される。

~/.config/gcloud/application_default_credentials.json を見ると分かるし、ログイン時のメッセージにも出てくる。

Credentials saved to file: [/Users/pokutuna/.config/gcloud/application_default_credentials.json]

These credentials will be used by any library that requests Application Default Credentials (ADC).

Quota project "pokutuna-playground" was added to ADC which can be used by Google client libraries for billing and quota. Note that some services may still bill the project owning the resource.

普段からカレントプロジェクトを設定しないようにしていると気にしなくて良いが、unset したり切り替えたりしていると gcloud のカレントプロジェクトと ADC の quota project が異なる状態になるのがややこしい。

なのでこれも設定しないようにしている。

カレントプロジェクトを ADC に伝播させたくない場合は ADC ログイン時に --disable-quota-project オプションを使う。

$ gcloud auth application-default login --disable-quota-project

ADC に quota project を設定しない場合、以下のような警告を見ることになるけど、アプリケーションコードからプロジェクト ID を与えればよいので気にしない。

WARNING:
Cannot find a quota project to add to ADC. You might receive a "quota exceeded" or "API not enabled" error. Run $ gcloud auth application-default set-quota-project to add a quota project.

ADC にプロジェクト ID を持たせない暮らし

ADC に quota project を設定しない場合、アプリケーションコード中にプロジェクトIDが登場することになるけど、意図しないプロジェクトを操作してしまう危険を避けることを優先している。

認証情報はメンドイので ADC に解決してほしいが、プロジェクト ID まで暗黙に解決したいことはほぼないし、複数のプロジェクトで同じコードを実行する場合でも、設定や環境変数などでアプリケーションに伝えればいいという考え。

GCP 上の実行環境でも、実行環境とプロジェクト ID が異なってないなら問題はない。

Node

Google Cloud の各種プロダクトに用意されたクライアントライブラリはコンストラクタに渡せばいい。

// Imports the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');

const client = new BigQuery({ projectId: "<PROJECT_ID>" });

Spreadsheet など、Google Cloud 感ないものは GoogleAuth に渡す。Spreadsheet や Calendar なども API を有効にしたり使用量を管理するために Google Cloud プロジェクトが必要。

googleapis/google-api-nodejs-client

import { google } from "googleapis";

const auth = new google.auth.GoogleAuth({
  projectId: "<PROJECT_ID>",
  scopes: [
    "https://www.googleapis.com/auth/cloud-platform",
    "https://www.googleapis.com/auth/spreadsheets.readonly",
  ],
});

const sheets = google.sheets({ version: "v4", auth });

Node の場合、明に指定しない場合は google-auth-library がプロジェクト ID を解決しようとする。その過程で GCLOUD_PROJECTGOOGLE_CLOUD_PROJECT 環境変数を参照したり、gcloud のカレントプロジェクトを参照したりする(歴史的経緯だろうけど、この挙動が嫌だなあ)。

Go

Go でも Google Cloud 系のクライアントライブラリでは素直に渡せばいい。

googleapis/google-cloud-go

import (
        "context"

        "cloud.google.com/go/bigquery"
)

func main() {
        ctx := context.Background()
        client, err := bigquery.NewClient(ctx, "<PROJECT_ID>")

        ...
}

Google Cloud 感のないものは google.golang.org/api を使うことになるが、こちらは option.WithQuotaProject() を使う。google.golang.org/api 以下でほぼすべての GoogleAPI を叩けるので、Cloud API もこちらの方法で叩ける。

googleapis/google-api-go-client

import (
    "context"

    "google.golang.org/api/option"
    "google.golang.org/api/sheets/v4"
)

func main() {
    ctx := context.Background()
    client, err := sheets.NewService(ctx, option.WithQuotaProject("<PROJECT_ID>"))

  ...
}

まとめ

  • いろんなプロジェクトを触る場合は gcloud にカレントプロジェクトを設定しないのをおすすめしている
  • ローカルの ADC も quota project があり、ログイン時のカレントプロジェクトが引き継がれる、これも設定しないのがいい
  • アプリケーションコードでプロジェクト ID を明に指定すればいい

blog.pokutuna.com