サーバーアプリケーションを開発していると、現在動いている環境がクラウドか、ローカルかで処理を分けたい場合がある。
自分はよくGCP (Google Cloud Platform) を利用しているが、今動いているのがGCP上なのか判定したい場面が何度かあった。 クラウドの場合のみ手動で環境変数を設定しても良いのだが、できれば自動的に判定してほしい。
そこで探してみたところ、GCPが提供するリポジトリに GCP Resource detection library というモジュールを見つけた。
ここにある Detector.CloudPlatform を呼び出せばGCPのどのプラットフォーム上で動作しているかかんたんに取得できる。
// CloudPlatform returns the platform on which this program is running func (d *Detector) CloudPlatform() Platform { switch { case d.onGKE(): return GKE case d.onCloudRun(): return CloudRun case d.onCloudFunctions(): return CloudFunctions case d.onAppEngineStandard(): return AppEngineStandard case d.onAppEngine(): return AppEngineFlex case d.onGCE(): return GCE } return UnknownPlatform }
実装の詳細を見ていると、環境変数またはCompute Metadata経由で現在の環境を取得しているらしい。なるほど!
// GCEの場合 // See the available GCE instance metadata: // https://cloud.google.com/compute/docs/metadata/default-metadata-values#vm_instance_metadata const machineTypeMetadataAttr = "instance/machine-type" func (d *Detector) onGCE() bool { _, err := d.metadata.Get(machineTypeMetadataAttr) return err == nil } // GKEの場合 const ( // If the kubernetes.default.svc service exists in the cluster, // then the KUBERNETES_SERVICE_HOST env var will be populated. // Use this as an indication that we are running on kubernetes. k8sServiceHostEnv = "KUBERNETES_SERVICE_HOST" ) func (d *Detector) onGKE() bool { _, found := d.os.LookupEnv(k8sServiceHostEnv) return found }
Compute Metadataは内部的にHTTP Requestだし、環境変数は環境変数なので実装で見ている変数の名前さえ抑えておけば、 Go以外の言語でも同じようなDetectorを容易に作れそうである。