インスタンス起動時にラベルを付与し、知らぬ間に膨らむクラウドコストを防ぎましょう。

「名無し」インスタンスを見つけ出す
Google Cloud Compute Engineの利用状況を確認していると、名前のないインスタンスやディスク、さらに厄介なケースとして用途がはっきりしない名前のリソースが見つかることがあります。これらは完全な無駄遣いかもしれませんし、本番のworkloadsを支える重要な存在かもしれません。
稼働開始から数年が経過し、社内に詳細を把握している人も、接続用の認証情報を持つ人もいない、というケースも珍しくありません。
こうした事態を防ぐため、多くの企業ではラベルポリシーを設け、プロビジョニングするすべてのインスタンスにName/Owner/Projectなどのラベル付けを必須としています。
Google Cloud Compute Engineでは、ラベルの利用に追加コストはかかりません。
……とはいえ、人手でインスタンスを起動したり、起動用の自動化スクリプトを書いたりしている以上、付け忘れや誤りはどうしても発生します。
そこで、Google Cloud向けの自動ラベル付けソリューションを作成しました(AWS版はこちら)。インスタンスには created-by ラベルを、ディスクには created-by と instance のラベルを自動で付与します。
これにより、後から用途不明のインスタンスやディスクに出くわしても、誰がセットアップしたのかをすぐに突き止められます。
Google Cloudのラベルは使用できる文字に制限があります。そのため本スクリプトでは、ユーザーのメールアドレスのアットマーク(@)をアンダースコア(_)に、ドット(.)をハイフン(-)に置き換えます。
自動ラベル付けの仕組み

ラベル付けプロセスの全体像
ユーザーまたはサービスアカウントが新しいCompute Engineマシンを作成します。
- API呼び出しがStackDriverに記録され、StackDriverシンク(別名Operations Logging)を経由してイベントがCloud Pub/Subへ送信されます。
- Cloud Pub/Subがイベント情報を添えてCloud Functionを起動します。
- Cloud Functionがインスタンスとそのディスクにラベルを付与します。
インスタンスとディスクへの自動ラベル付けを実装する
関数を初めてデプロイする場合は、Cloud Build APIが有効になっているかご確認ください。
1. 最小権限の専用サービスアカウントを作成する
このステップは任意ですが、強く推奨します。
新しいCloud Functionを作成すると、デフォルトではApp Engineサービスアカウントが使われ、プロジェクト全体に対する Editor ロールが付与されます。
Editorロールを使うと、関数にプロジェクト全体のリソースを変更する権限が与えられてしまいます。セキュリティの観点からは、関数に与える権限は必要最小限に留めるのが望ましく、万が一不具合が起きても、影響範囲をインスタンスとディスクの情報取得およびラベル設定だけに限定できます。
# 関数に必要なGCP IAM権限:
compute.disks.get
compute.disks.setLabels
compute.instances.get
compute.instances.setLabels
カスタムロール付きのサービスアカウントの作成は、複数の画面をまたぐためやや手間がかかります。手早く済ませられるよう、以下にgcloudコマンドをまとめました。
# <project-id> をご自身のプロジェクトIDに置き換えてください。 gcloud iam roles create autolabel_instances --title=autolabel-instances --project <project-id> --description='cloud function service account to label instanes and disks upon creation' --permissions=compute.disks.get,compute.disks.setLabels,compute.instances.get,compute.instances.setLabels --stage=GAgcloud iam service-accounts create autolabel-instancesgcloud projects add-iam-policy-binding <project-id> --member serviceAccount:autolabel-instances@<project-id>.iam.gserviceaccount.com --role projects/<project-id>/roles/autolabel_instancesgcloud projects add-iam-policy-binding <project-id> --member serviceAccount:autolabel-instances@<project-id>.iam.gserviceaccount.com --role roles/logging.logWriter
新しいサービスアカウントのメールアドレスは autolabel-instances@
2. Cloud Functionsページを開き、CREATE FUNCTIONをクリックする

a) 関数名を入力し、トリガーをCloud Pub/Subに変更します。続いて下のボックスでCREATE A TOPICをクリックし、新しいトピックに名前を付けます。

b) サービスアカウントの作成をスキップした場合は、SAVEとNextをクリックします。作成済みの場合はVARIABLES, NETWORKING AND ADVANCED SETTINGSをクリックし、先ほど作成したサービスアカウントを選択してからSAVEとNEXTをクリックします。
c) 関数のランタイムをPython 3.7に変更します。

続いてSource codeをクリックし、ZIP Uploadに切り替えます。zipファイルはGitHubリポジトリからダウンロードできます(関数のソースコードも同梱しています)。最後にDEPLOYをクリックします。
3. StackDriver Loggingを開く
検索ボックス右端の矢印をクリックして詳細フィルタに切り替え、以下を貼り付けます。
resource.type="gce_instance"
jsonPayload.event_subtype="compute.instances.insert"
jsonPayload.event_type="GCE_API_CALL"
次にCREATE SINKをクリックし、シンクに名前を付けます。シンクサービスをPub/Subに変更し、シンクの宛先には前のステップで作成したPub/Subトピックを指定します。最後にCreate Sinkをクリックします。

4. インスタンスを起動して関数の動作を確認する
VM instancesページを開くと、新しいインスタンスに自動的にラベルが付与されているはずです。

VM instancesページ
Disksページを開くと、インスタンスのディスクにも自動的にラベルが付与されているはずです。

Disksページ
補足
本ソリューションがラベル付けの対象とするのは、Cloud Functionを導入した後に新規作成されたインスタンスのみです。
Google Cloudリソースを自動でラベル付けする総合ソリューションとして、DoiT Internationalが開発したIrisをオープンソースで公開しています。