株式会社G-genのブログ - TECH PLAY

TECH PLAY

株式会社G-gen

株式会社G-gen の技術ブログ

全888件

G-gen の武井です。 当記事は gcloud と jq コマンドシリーズの第2弾として、Google Cloud (旧称 GCP) の IAM に関する情報の取得方法についてご紹介します。 組織 / フォルダ / プロジェクト 編の記事 組織の IAM Policy IAM ポリシーの表示 プリンシパルの抽出 jq コマンドの利用 重複値の除外 ( unique 構文 ) 特定のプリンシパルに紐づくロールの抽出 特定のロールに紐づくプリンシパルの抽出 フォルダの IAM Policy プロジェクトの IAM Policy 組織 / フォルダ / プロジェクト 編の記事 組織 / フォルダ / プロジェクト編 については以下の記事をご参照ください。 gcloud コマンドや jq コマンドの概要の他、コマンドの実行方法についても解説しています。 blog.g-gen.co.jp 組織の IAM Policy IAM ポリシーの表示 組織の IAM Policy 情報を取得するには、 gcloud organizations get-iam-policy コマンドを使用しますが、その中から特定の値を抽出する方法をいくつかご紹介します。 出力例は以下のとおりです。 $ gcloud organizations get - iam - policy $ { ORG_ID } -- format = json | \ jq - r '.bindings[]' { " members ": [ " group:tech@example001.co.jp " ] , " role ": " roles/accesscontextmanager.gcpAccessAdmin " } { " members ": [ " domain:example001.co.jp " ] , " role ": " roles/browser " } (〜中略〜) { " members ": [ " serviceAccount:service-org-1111111111@security-center-api.iam.gserviceaccount.com " ] , " role ": " roles/securitycenter.serviceAgent " } { " members ": [ " group:tech@example001.co.jp ", " serviceAccount:service-org-1111111111@security-center-api.iam.gserviceaccount.com " ] , " role ": " roles/serviceusage.serviceUsageAdmin " } プリンシパルの抽出 jq コマンドの利用 members というキーにプリンシパルが入っています。以下のように gcloud の出力結果をパイプで jq コマンドに渡すことで、プリンシパルだけを抽出できます。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '.bindings[] |.members[]' group:tech@example001.co.jp domain:example001.co.jp (〜中略〜) serviceAccount:service-org-1111111111@security-center-api.iam.gserviceaccount.com group:tech@example001.co.jp serviceAccount:service-org-1111111111@security-center-api.iam.gserviceaccount.com 重複値の除外 ( unique 構文 ) IAM Policy は members (プリンシパル) と role (権限) の組み合わせなので、プリンシパルに対して複数の権限が紐付いている場合は重複して表示されます。 このような場合、 unique 構文を使用すると重複値を除外できます。Linux コマンドで言う uniq コマンドや SQL で言う DISTINCT に相当します。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '[.bindings[].members[]] | unique | .[]' domain:example001.co.jp group:it-grp@example001.co.jp group:tech@example001.co.jp serviceAccount:sa-cloud-identity@pj002.iam.gserviceaccount.com serviceAccount:service-org-1111111111@security-center-api.iam.gserviceaccount.com serviceAccount:tf-exec@pj001.iam.gserviceaccount.com user:mike@example001.co.jp user:su@example001.co.jp 以下の例では、最後に sed コマンドに出力を渡し、プリンシパル種別 ( group: や user: など) の文字列を消しています。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '[.bindings[].members[]] | unique | .[]' | \ sed -e "s|.*:||" example001.co.jp it-grp@example001.co.jp tech@example001.co.jp sa-cloud-identity@pj002.iam.gserviceaccount.com service-org-1111111111@security-center-api.iam.gserviceaccount.com tf-exec@pj001.iam.gserviceaccount.com mike@example001.co.jp su@example001.co.jp 以下の例では、特定のプリンシパル種別 ( user: ) に絞って抽出しています。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '[.bindings[].members[]] | unique | .[] | select(startswith("user:"))' | \ sed -e "s|.*:||" mike@example001.co.jp su@example001.co.jp 特定のプリンシパルに紐づくロールの抽出 以下のように jq コマンドの select 構文を用いることで、特定のプリンシパルに与えられているロールだけを抽出することもできます。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '.bindings[] | select(.members[] == "group:it-grp@example001.co.jp") | .role' roles/cloudsupport.admin roles/orgpolicy.policyAdmin roles/resourcemanager.folderAdmin roles/resourcemanager.organizationAdmin roles/resourcemanager.projectCreator roles/securitycenter.admin 以下のように roles/ という文字列を除外することができます。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '.bindings[] | select(.members[] == "group:it-grp@example001.co.jp") | .role' | \ sed -e "s|roles/||" cloudsupport.admin orgpolicy.policyAdmin resourcemanager.folderAdmin resourcemanager.organizationAdmin resourcemanager.projectCreator securitycenter.admin 特定の文字列を含むプリンシパルを抽出することも可能です。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '.bindings[] | select(.members[] | test("it-grp")) .role' | \ sed -e "s|roles/||" cloudsupport.admin orgpolicy.policyAdmin resourcemanager.folderAdmin resourcemanager.organizationAdmin resourcemanager.projectCreator securitycenter.admin 特定のロールに紐づくプリンシパルの抽出 以下の例ではオーナー権限を持つプリンシパルを抽出します。 $ gcloud organizations get-iam-policy ${ORG_ID} --format=json | \ jq -r '.bindings[] | select(.role == "roles/owner") | .members[]' serviceAccount:sa-cloud-identity@pj002.iam.gserviceaccount.com user:su@example001.co.jp フォルダの IAM Policy フォルダの IAM Policy 情報を取得するには、 gcloud resource-manager folders get-iam-policy コマンドを使用します。 出力例は以下のとおりです。 $ gcloud resource - manager folders get - iam - policy $ { FLDR_ID } -- format = json | \ jq - r '.bindings[]' { " members ": [ " user:su@example001.co.jp " ] , " role ": " roles/resourcemanager.folderAdmin " } { " members ": [ " user:yutakei@example002.co.jp " ] , " role ": " roles/resourcemanager.folderCreator " } { " members ": [ " user:su@example001.co.jp ", " user:yutakei@example001.co.jp " ] , " role ": " roles/resourcemanager.folderEditor " } { " members ": [ " user:yutakei@example002.co.jp " ] , " role ": " roles/resourcemanager.folderViewer " } 先程と同じように、出力をパイプで jq や sed に渡すことで、様々な出力の加工が可能です。 プロジェクトの IAM Policy プロジェクトの IAM Policy 情報を取得するには、 gcloud projects get-iam-policy コマンドを使用します。 出力例は以下のとおりです。 $ gcloud projects get-iam-policy ${PRJ_ID} --format=json | \ jq -r '.bindings[]' { "members": [ "user:yutakei@example001.co.jp" ], "role": "roles/accesscontextmanager.policyAdmin" } { "members": [ "serviceAccount:service-999999999999@gcp-sa-servicemesh.iam.gserviceaccount.com" ], "role": "roles/anthosservicemesh.serviceAgent" } (〜中略〜) { "members": [ "serviceAccount:wada2@pj003.iam.gserviceaccount.com", "serviceAccount:wada@pj003.iam.gserviceaccount.com" ], "role": "roles/secretmanager.secretAccessor" } { "members": [ "serviceAccount:service-999999999999@service-networking.iam.gserviceaccount.com" ], "role": "roles/servicenetworking.serviceAgent" } やはり先程と同じように、出力をパイプで jq や sed に渡して出力を加工できます。 武井 祐介 (記事一覧) 2022年4月入社 / クラウドソリューション部 / 技術2課所属 趣味はゴルフにロードバイク。IaC や CI/CD 周りのサービスやプロダクトが興味分野です。 Google Cloud 認定全冠達成!(2023年6月)
当記事は みずほリサーチ&テクノロジーズ × G-gen エンジニアコラボレーション企画 で執筆されたものです。 みずほリサーチ&テクノロジーズ株式会社の高瀬です。 Google Cloud(旧GCP)上に HashiCorp 社の Vault Enterprise クラスタを構築したので流れをまとめました。 未経験の状態で構築しましたので、つまずきポイントも併記しています。 当ブログは G-gen × みずほRT によるコラボ記事です はじめに Vault (HashiCorp) とは 構築のおおまかな流れ Terraform Cloudの設定 Terraformモジュールの準備 クラスタの作成 prereqs_quickstart を実行 terraform-gcp-vault-ent-starterを実行 まとめ はじめに Vault (HashiCorp) とは Vault とは HashiCorp 社の製品で、プラットフォームフリーで、シークレットを一元管理することができる製品です。 例えばVaultでは一時的なユーザの発行も行え、有効期限を1週間にしたユーザーを作成すると1週間後に自動的にユーザが削除されます。自動でユーザが削除されるのはとても便利ですね。 詳細は こちら をご確認ください。 構築のおおまかな流れ 構築にはTerraform Cloud BusinessとCloud Shellを利用します。 今回構築するのは下図のVault Enterpriseの構成で、複数のアベイラビリティゾーンにクラスタを分割する可用性の高い構成です。 図は 公式マニュアル より引用 構築は以下の順に行います。 Terraform CloudとGoogle Cloudを連携 Vault Enterpriseクラスタを構築するためのTerraformモジュールを入手 Cloud ShellでTerraformを実行 後で触れるTerraformモジュールの実行にはVaultのライセンスファイルが必要なため、必要な際は こちら より HashiCorp社へお問い合わせ下さい。 Terraform Cloudの設定 まず Terraform Cloud と Google Cloud を連携させるための認証情報の登録を行います。 Google Cloudの資格情報が必要ですので Google CloudのIAMと管理>サービスアカウントからサービスアカウントを作成し、キーを控えておいてください。 今回は静的にGoogle Cloudの資格情報を設定していますが、Terraform CloudではOpenID Connectを利用し、動的にGoogle Cloudの資格情報を利用する事が可能です。セキュアにTerraformを扱うための必要な機能がビルドインされています。 Dynamic Credentials with the GCP Provider それではTerraform CloudとGoogle Cloudの連携を実施していきます。 はじめにTerraform Cloudの設定から行います。 Terraform Cloudの Projects & workspaces からワークスペースを作成し、CLI-drivenを選択してください。 次にSettings>Generalに移動し、Execution ModeをAgentに変更します。 ※Agentモードが利用できるのはBusinessプランのみとなります。他のモードでも実行できると思いますが、今回はAgentモードを利用していきます。 Terraform VersionはCloud ShellとのTerraformバージョンと同じものに変更します。その後、下までスクロールして保存してください。 TerraformのバージョンはCloud Shellから以下コマンドで確認可能です。 terraform --version 次にTerraform CloudにGoogle Cloudの認証情報を設定します。設定方法については以下URLがわかりやすいのでご参考ください。 How-to set up Google Cloud (GCP) credentials in Terraform Cloud 最後にCloud Shellからterraform loginコマンドを実行し、Terraform Cloudにログインします。設定方法については以下URLをご参考ください。 Log in to Terraform Cloud from the CLI Terraformモジュールの準備 Vault Enterpriseクラスタを構築するためのTerraformモジュール、 vault-ent-starter があるためダウンロードしていきます。 このモジュールを利用すると、 Vault with Integrated Storage Reference Architecture に沿った構成をGoogle Cloud上にプロビジョニングできます。 今回の構築にはvault-ent-starterを利用していきます。 vault-ent-starterモジュールをダウンロードします。Google CloudからCloud Shellを立ち上げてコマンドを実行してみてください。 ちなみに私はvault-testというフォルダを作成してその中で実行しています。 cd vault-test git clone https://github.com/hashicorp/terraform-gcp-vault-ent-starter コマンドを実行すると terraform-gcp-vault-ent-starter がダウンロードされます。中に examples/prereqs_quickstart と modules が入っていることを確認してください。 modulesを実行するためには先にVPCとTLS証明書を用意する必要があり、examplesにはVPCとTLS証明書を作成するためのモジュールが入っています。 今回はexampleを使ってVPC、TLS証明書を作成していきます。 本番利用の際はそれぞれ非機能要求にあったものをご準備ください。 gcp-vpc : Vault対応のVPCを作成するためのモジュールです。 gcp-tls : Load Balancerに設定するTLS証明書を作成するためのモジュールです。VaultクラスタはLoadBalancerで負荷分散されます。 vault-ent-starter : Enterprise Vaultクラスタを作成するためのモジュールです。実行にはVPCとTLS証明書の作成および、Vaultのライセンスファイルを用意しておく必要があります。 ダウンロードした terraform-gcp-vault-ent-starter フォルダ。 terraform-gcp-vault-ent-starter の直下から vault-test に examples を移動してください。検証時、examplesを移動せずに実行するとエラーが発生しました。 modulesはterraform-gcp-vault-ent-starter直下で実行するため移動不要です。 クラスタの作成 prereqs_quickstart を実行 prereqs_quickstartを実行し、VPCとTLSを作成します。 Terraform Cloudで実行するための設定がモジュールには記載されていませんので、main.tfとvariables.tfに設定を追加していきます。 examples/prereqs_quickstart/main.tf にTerraform Cloudの設定を追加してください。 terraform { cloud { organization = "Terraform Cloudのorganization名" workspaces { name = "Terraform Cloudのworkspaces名" } } } examples/prereqs_quickstart/variables.tf にデプロイ先であるGoogle CLoudのプロジェクトIDとリージョン名を追加します。 variable "network_name" { type = string default = "consul-test-network" description = "The name of the VPC network being created" } variable "project_id" { type = string description = "The GCP project ID in which to launch resources" # 追加 default = "Google CloudのプロジェクトID" } variable "region" { type = string description = "GCP region in which to launch resources" # 追加(今回は東京リージョンに構築していきます) default = "asia-northeast1" } Google CloudのプロジェクトIDが不明の場合はCloud Shellから以下コマンドで取得可能です。 gcloud projects list --format ' value(projectId) ' --filter name =プロジェクト名 Terraformで定義したvariables(変数)はdefault値が指定されていなかったり、コマンドラインで値が指定されていなかったりした場合、applyの際に対話式で設定値の入力を促されます。 Terraform Cloudでのapplyでは対話入力できなかったため、今回はdefault値を設定しました。(下記のエラーが発生しました) │ Error: No value for required variable │ │ on variables.tf line 7: │ 7: variable " project_id " { │ │ The root module input variable " project_id " is not set , and has no default │ value. Use a -var or -var-file command line argument to provide a value for │ this variable. ここまででTerraform Cloudで実行するための準備が完了しました。 Terraformでは実際にリソースを作成する前に、terraform planコマンドでどのようなリソースが作成されるか確認することができます。tfファイルの構造が正しいか確認するためにも使用できます。 まずはteraform planでエラーが発生しないことを確認します。planでエラーがなかった場合、terraform applyを実行しリソースを作成してください。 実行後、Outputsに作成されたVPCやTLS証明書の情報が出力されます。のちの手順で利用しますので控えておいてください。 cd examples/prereqs_quickstart/ terraform init terraform plan terraform apply Outputs: leader_tls_servername = " vault.server.com " ssl_certificate_name = " vault-xxxxxxx " subnetwork = " https://xxxxxxxx " tls_secret_id = " terraform_example_module_vault_tls_secret " terraform-gcp-vault-ent-starterを実行 prereqs_quickstart が無事に実行できたら、次は terraform-gcp-vault-ent-starter を実行し、Enterprise Vaultクラスタを作成します。 実行の前提条件としてVaultのライセンスファイルが必要です。 ライセンスファイルを terraform-gcp-vault-ent-starter の直下に配置してください。 入手したままではTerraform Cloudで実行するための設定が記載されていません。examples/prereqs_quickstart実行時と同じように、Terraform Cloudで実行するための設定をmain.tfとvariables.tfに追記していきます。 terraform-gcp-vault-ent-starter/main.tf に以下を追加してください。 terraform { cloud { organization = "Terraform Cloudのorganization名" workspaces { name = "Terraform Cloudのworkspaces名" } } } terraform-gcp-vault-ent-starter/variables.tf にdefaultを追加していきます。defaultにはexamples実行時のOutputsで出力された値を入力してください。 variable "leader_tls_servername" { type = string description = "One of the shared DNS SAN used to create the certs used for mTLS" # 追加 default = "vault.server.com" } variable "project_id" { type = string description = "GCP project in which to launch resources" # 追加 default = "Google CloudのプロジェクトID" } variable "resource_name_prefix" { type = string description = "Prefix for naming resources" # 追加(お好きなprefixを付けてください) default = "demo" } variable "ssl_certificate_name" { type = string description = "Name of the created managed SSL certificate. Required when create_load_balancer is true" # 追加 default = "vault-xxxxxxx" } variable "subnetwork" { type = string description = "The self link of the subnetwork in which to deploy resources" # 追加 default = "https://xxxxxxxx" } variable "tls_secret_id" { type = string description = "Secret id/name given to the Google Secret Manager secret" # 追加 default = "terraform_example_module_vault_tls_secret" } variable "vault_license_filepath" { type = string description = "Filepath to location of Vault license file" # 追加(ライセンスファイルをterraform-gcp-vault-ent-starter直下に配置した場合) default = "vault.hclic" } 修正が終わったらterraform-gcp-vault-ent-starterを実行し、Enterprise Vaultクラスタを作成します。planでエラーがないことを確認後、applyを実行して下さい。 cd ../../terraform-gcp-vault-ent-starter/ terraform init terraform plan terraform apply もしrequired field is not setエラーが発生した場合は、エラーが発生したmain.tfにパラメータを追加します。 │ Error: project: required field is not set │ │ with module.iam.google_service_account.main, │ on modules/iam/main.tf line 5 , in resource " google_service_account " " main " : │ 5: resource " google_service_account " " main " { │ 下記エラーですと modules/iam/main.tf の5行目、 google_service_account に project を追加します。検証時は設定がうまくいっていなかったのかprojectとregionのエラーが頻発したため都度追加していきました。 resource "google_service_account" "main" { account_id = "${var.resource_name_prefix}-vault-${random_id.vault.hex}" display_name = "Vault KMS and auto-join for auto-unseal" # 追加 project = プロジェクトID } 以下のように既存リソースが削除されるメッセージが出力された場合は、 prereqs_quickstart と terraform-gcp-vault-ent-starter で同じTerraform Cloudのワークスペースを参照している可能性があります。 新規でワークスペースを作成し、 terraform-gcp-vault-ent-starter/main.tf の workspaces の name を作成したワークスペース名に修正してください。 # module.secrets.google_compute_region_ssl_certificate.main will be destroyed # (because google_compute_region_ssl_certificate.main is not in configuration) - resource " google_compute_region_ssl_certificate " " main " { - certificate = ( sensitive value ) - certificate_id = xxxxxxxxxxxxxx - > null .... } Applyが表示され、VMインスタンスが立ち上がれば成功です! 立ち上げたインスタンスにSSHでログイン可能か確認してください。 まとめ はじめての構築のため不格好ではありますが、無事に実行することができました。Vaultを使うにあたってテンプレートがあるのは非常に便利だなと思います。 もし本記事がこれからVaultを使おうとしている方の助けになれましたら幸いです。 高瀬 優紀 みずほリサーチ&テクノロジーズ株式会社 先端技術研究部に所属。Google Cloudは触り始めて数か月。社内のAWS人材育成を主に担当している。
今回は Vertex AI Workbench を用いて JupyterLab の開発環境から BigQuery ML を実行し機械学習モデル(クラスタリング)を作成していきたいと思います。 概要 概要 今回使用するデータ K-means 法とは 準備 Vertex AI Workbench の作成 BigQuery データセットとテーブルの作成 JupyterLab 起動 実行 データの確認 ハイパーパラメータチューニング ハイパーパラメータチューニング機能の確認 モデルの作成 概要 概要 今回は、 Vertex AI Workbench を用いて JupyterLab の開発環境から BigQuery ML を使い K-means 法を用いたクラスタリングモデルを作成してみたいと思います。 Vertex AI Workbench とは、Vertex AI の機能の一つであり、 JupyterLab の開発環境が利用できます。 開発環境は マネージドノートブック と ユーザー管理のノートブック の 2 種類がありますが、今回はユーザー管理のノートブックを利用します。 Vertex AI Workbench を利用することで、BigQuery や Cloud Storage のデータへ容易にアクセスできたり、JupyterLab から BigQuery に対しクエリ発行も行うことができるため、データ移行の工数が削減でき開発スピードが上がります。 Vertex AI 全般について知りたい方は、以下の記事をご覧いただけますと幸いです。 blog.g-gen.co.jp また、以下の記事では BigQuery ML で 2 項ロジスティック回帰モデルの作成を行っております。 blog.g-gen.co.jp 以下の記事では BigQuery ML を詳細に解説していますので、ご参照ください。 blog.g-gen.co.jp 今回使用するデータ 今回は、筆者が塾の教師を務めている想定で、塾に通う生徒のクラス分けを行いたいと仮定します。 筆者の手元には、生徒の直近の テスト結果 (test_results.csv) があるとします。 A 列に生徒 ID が入り、B~F 列は各教科のテストの点数が入っています。 test_results.csv の中身 このデータをもとに、BigQuery ML の組み込みモデルの一つ、K-means モデルを用いていくつかのグループにクラスタリングを行ってみたいと思います。 K-means 法とは K-means 法とは互いに近いデータ同士を k 個のまとまりに分ける (クラスタリング) 手法を用いて、テスト結果データをもとに生徒をいくつかのクラスに分けたいと思います。 今回のように正解データ (教師データ) のない状態で、 学習データのみ をアルゴリズムに与え、データの特徴を求めることを 教師なし学習 といいます。 参考: k-means Clustering Algorithm 準備 Vertex AI Workbench の起動と BigQuery のテーブル作成は、 Cloud Shell 環境から gcloud コマンドを用いて行います。 Vertex AI Workbench の作成 以下のコマンドで Vertex AI Workbench の作成します。 # 環境変数の設定 export INSTANCE_NAME=<インスタンス名> # API の有効化 gcloud services enable notebooks.googleapis.com # Vertex AI Workbench の作成 gcloud notebooks instances create ${INSTANCE_NAME} \ --vm-image-project=deeplearning-platform-release \ --vm-image-family=caffe1-latest-cpu-experimental \ --machine-type=n1-standard-4 \ --location=asia-northeast1-a \ --machine-type=n1-standard-1 Vertex AI Workbench で作成するインスタンスについて、今回は Google が提供している Deep Learning VM Images から caffe1-latest-cpu-experimental イメージファミリーを選択しました。 その他利用可能な Deep Learning VM Images については以下をご覧ください。 参考: Listing all available versions BigQuery データセットとテーブルの作成 続いて、BigQuery の準備を行います。 はじめに、先程の成績データを CSV でローカルにダウンロードして、Cloud Shell にアップデートします。 その後、Cloud Shell 上に、schema.json というファイルを新規作成し、以下の json で定義したスキーマを記入します。 [ { " name ": " student_id ", " type ": " INTEGER ", " description ": " 生徒 ID " } , { " name ": " national_language ", " type ": " INTEGER ", " description ": " 国語の点数 " } , { " name ": " english ", " type ": " INTEGER ", " description ": " 英語の点数 " } , { " name ": " mathematics ", " type ": " INTEGER ", " description ": " 数学の点数 " } , { " name ": " science ", " type ": " INTEGER ", " description ": " 理科の点数 " } , { " name ": " sociology ", " type ": " INTEGER ", " description ": " 社会の点数 " } ] Cloud Shell 上のディレクトリが以下のように構成できれば必要なファイルの準備は揃っています。 . ├── test_results.csv └── schema.json 以下コマンドで BigQuery データセットとテーブルの作成を作成します。 # 環境変数の設定 export PROJECT_ID=<プロジェクトID> export DATASET_NAME=<データセット名> export TABLE_NAME=<テーブル名> # データセットの作成 bq mk --dataset --location=asia-northeast1 ${DATASET_NAME} # テーブルの作成 bq mk --table ${PROJECT_ID}:${DATASET_NAME}.${TABLE_NAME} schema.json # テーブルにデータをロード bq --location=asia-northeast1 load \ --source_format=CSV \ --skip_leading_rows=1 \ ${PROJECT_ID}:${DATASET_NAME}.${TABLE_NAME} test_results.csv JupyterLab 起動 それでは、JupyterLab を起動していきたいと思います。 Web コンソールから [Vertex AI ] > [ワークベンチ] > [ユーザー管理のノートブック] を選択し、先ほど作成した Vertex AI Workbench インスタンスの [Jupyterlab を開く] をクリックします。 以下の画面がでたら、Notebook の Python3 をクリックします。 JupyterLab画面① JupyterLab 画面② 実行 以降は、JupyterLab のノートブック内で以下のコマンドを実行して進めていきます。 データの確認 BigQuery に保存されたテーブルデータを確認します。 Vertex AI Workbench では、 %%bigquery (マジックコマンド)を用いることでノートブックファイル内から BigQuery に対しクエリを実行することができます。 %%bigquery SELECT * FROM `<プロジェクトID>.<データセット名>.<テーブル名>` ORDER BY student_id データの確認 ハイパーパラメータチューニング BigQuery ML で K-means クラスタリングモデルを作成する前に、何個 (k個) のクラスタに分けたいかユーザー側で決める必要があります。 今回は、BigQuery ML の ハイパーパラメータチューニング機能 を用いて k=2 or 3 or 4 の 3 つから適切な k を求めてみたいと思います。 %%bigquery CREATE OR REPLACE MODEL `<プロジェクトID>.<データセット名>.<モデル名>` OPTIONS ( MODEL_TYPE= ' KMEANS ' , KMEANS_INIT_METHOD= ' KMEANS++ ' , NUM_TRIALS= 3 , NUM_CLUSTERS=HPARAM_RANGE( 2 , 4 ), MAX_PARALLEL_TRIALS= 3 ) AS SELECT * EXCEPT(student_id) FROM `<プロジェクトID>.<データセット名>.<テーブル名>` CREATE OR REPLACE MODEL 構文を用いてモデルを構築していきます。 OPTIONS の中に各種パラメータを定義します。 model_type には [KMEANS] を選択します。 KMEANS_INIT_METHOD には [KMEANS++] を指定します。こちらは Centroid という重心となる点を最初にどのように決めるかを指定しています。 ハイパーパラメータチューニングでは、以下のオプションを追記します。 NUM_TRIALS で指定した数値分、探索してくれます。 NUM_CLUSTERS で [HPARAM_RANGE(min, max)] を指定することで min から max までの連続値でクラスタの数を調整してくれます。 MAX_PAEALLEL_TRAIALS で指定した数値分、並行で処理を行います。 参考: Hyperparameter tuning for CREATE MODEL statements ハイパーパラメータチューニング機能の確認 %%bigquery SELECT * FROM ML.TRIAL_INFO(MODEL `<プロジェクトID>.<データセット名>.<モデル名>`) ML.TRIAL_INFO 関数でハイパーパラメータチューニングの結果を確認します。 ハイパーパラメータチューニングの結果 num_clusters 列には各クラスタの数が入力されております。 hparam_tuning_evaluation_metrics 列には各クラスタ数でモデルを作成した際の評価指標である、 Davies–Bouldin 指標 が記載されています。この指標が小さいほど高品質なモデルとされています。 最後に、is_optimal 列では、今回のハイパーパラメータチューニングで最も適切なクラスタ数であるレコードに True が付きます。 ハイパーパラメータチューニングより、クラスタ数 3 の時 is_optimal が True となっていたので、今回はそのパラメータでモデルを作成してみたいと思います。 モデルの作成 以下のコマンドでモデルを作成します。 %%bigquery CREATE OR REPLACE MODEL `<プロジェクトID>.<データセット名>.<モデル名>` OPTIONS ( MODEL_TYPE= ' KMEANS ' , KMEANS_INIT_METHOD= ' KMEANS++ ' , NUM_CLUSTERS= 3 ) AS SELECT * EXCEPT(student_id) FROM `<プロジェクトID>.<データセット名>.<テーブル名>` モデルが作成できましたら、作成したモデルを使用し、先程のテスト結果データの 2 列目に centroid_id 列を追加し出力します。 この centroid_id がいわゆる各クラスタの ID のような位置づけとなります。今回ですと 3 つのクラスタに分けたので、centroid_id は 1~3 の値をとります。 %%bigquery SELECT student_id, CENTROID_ID AS centroid_id, national_language, english, mathematics, science, sociology FROM ML.PREDICT( MODEL `<プロジェクトID>.<データセット名>.<モデル名>`,( SELECT * FROM `<プロジェクトID>.<データセット名>.<テーブル名>` ) ) ORDER BY student_id モデルから推論を実行 また、centroid_id でグループ化し、各教科は平均点で集約させるクエリとその結果は以下となります。 %%bigquery SELECT CENTROID_ID AS centroid_id, ROUND ( AVG (national_language)) AS national_language, ROUND ( AVG (english)) AS english, ROUND ( AVG (mathematics)) AS mathematics, ROUND ( AVG (science)) AS science, ROUND ( AVG (sociology)) AS sociology FROM ML.PREDICT( MODEL `<プロジェクトID>.<データセット名>.<モデル名>`,( SELECT * FROM `<プロジェクトID>.<データセット名>.<テーブル名>` ) ) GROUP BY centroid_id ORDER BY centroid_id centroid_id に対する各教科の平均点 centroid_id によって分けられた 3 つのクラスタには、それぞれ以下のような特徴がありそうです。 centroid_id 特徴 1 全科目の点数にあまり差がない 2 比較的に数学と理科が高く、国語と英語が低い傾向にある 3 比較的に国語と英語が高く、数学と理科が低い傾向にある 上記より、[centroid_id = 1] のクラスには全科目の基礎硬めを、[centroid_id = 2] のクラスには比較的伸びしろが高い国語と英語、[centroid_id = 3] のクラスには数学と理科にそれぞれ重点をおいた授業を組むなど、 次回テストの点数 UP に向けた戦略 を練ることができるのかと思います。 このようなクラスタリング手法は、ビジネスにおいても自社の顧客分析や、競合他社との差別化戦略を考える際に使われたりと幅広く利用されています。 G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
当記事では、Google Cloud(旧称 GCP)の Compute Engine(以下 GCE)のインスタンス名の重複について、2 種類の内部 DNS タイプの観点から深堀していきます。 はじめに インスタンス名の重複 検証結果 サービスの概要 メタデータサーバー GCE と内部 DNS 内部 DNS 内部 DNS タイプ 設定方法 確認方法 検証 前提条件 例外 作成コマンド 作成順序 結果 まとめ はじめに インスタンス名の重複 コンソールや gcloud コマンドで GCE インスタンスを作成する際に、以下のようなエラーが出る場合があります。これはインスタンス名が既存のものと重複している場合に表示されます。 ERROR: (gcloud.compute.instances.create) Could not fetch resource: - The resource 'projects/demo-project/zones/asia-northeast1-a/instances/my-instance' already exists コンソールのインスタンス名重複エラー 実際にはゾーンが異なる場合、 gcloud コマンドでは同じインスタンス名でインスタンスを作成することができます。但し、作成の際に留意すべき点があります。そこで今回は、2 種類の内部 DNS タイプの観点からこのエラーを深堀していきます。 同一インスタンス名 検証結果 結論から書くと、以下のような結果になりました。 両者の内部 DNS タイプが ゾーン DNS の時は、異なるゾーンにインスタンスを作成することができる 一方の内部 DNS タイプが グローバル DNS のときは、グローバル DNS インスタンスを先に作成すれば、次に ゾーン DNS のインスタンスを作成することができる このことから、インスタンス名の名前空間はゾーンである (しかしインスタンスの作成順によってはバリデーションに引っかかる) ということがわかりました。 ここから、詳細な検証の過程を記載していきます。 サービスの概要 メタデータサーバー メタデータサーバーには、GCE インスタンスに関する様々な情報である メタデータ が保存されています。メタデータは key:value の形で保存されており、適用範囲の異なる以下の 2 種類があります。 プロジェクトメタデータ: プロジェクト内のすべて の VM に適用 インスタンスメタデータ: 単一 の VM にのみ適用 さらにその中で、 デフォルトのメタデータ とユーザーが定義する カスタムメタデータ があります。詳細は以下の記事の「メタデータ」の項目をご参照ください。 blog.g-gen.co.jp 後述の「検証」の項目では、インスタンスメタデータで内部 DNS タイプを指定します。 GCE と内部 DNS GCE インスタンスを作成すると、 インスタンスメタデータ の hostname にインスタンス名やプロジェクト ID、ゾーン名等が含まれる完全修飾ドメイン名(以下 FQDN)が保存されます。 この FQDN は後述する内部 DNS タイプによって異なります。また、GCE インスタンスの命名規則は ドキュメント に記載の通りです。 内部 DNS 内部 DNS は、 同じネットワーク内 の仮想マシン(以下 VM)が内部 DNS 名で相互にアクセスができるようにするサービスで、 Virtual Private Cloud(VPC) の機能の 1 つです。 .internal の DNS ゾーンに VM の内部 A レコードが作成されます。 内部 DNS タイプ 内部 DNS タイプには、以下の 2 種類があります。 ゾーン DNS グローバル DNS デフォルトの内部 DNS タイプがどちらになるかは、 プロジェクトで Compute Engine API を有効にしたタイミング によって決まります。タイプ別の FQDN やプロジェクトのデフォルトは以下の表の通りです。 VM は ゾーンリソース です。個々のゾーンへの DNS 登録で発生した障害を分離するためにゾーン DNS が推奨されています。 内部 DNS タイプ FQDN プロジェクトのデフォルトタイプ 備考 ゾーン DNS < VM 名>.<ゾーン名>.c.<プロジェクト ID>.internal 2018 年 9 月 6 日以降 に Compute Engine API を有効にした組織またはスタンドアロンプロジェクトのデフォルトタイプ VM 名は 各ゾーンで一意 。ゾーンが異なる場合、同じ VM 名をつけることができる。 グローバル DNS < VM 名>.c.<プロジェクト ID>.internal 2018 年 9 月 6 日より前 に Compute Engine API を有効にした組織またはスタンドアロンプロジェクトのデフォルトタイプ VM 名は プロジェクト全体で一意 。 参考: 内部 DNS 名のタイプ 設定方法 2023 年 3 月時点で Google Cloud の利用を開始し、GCE インスタンスを作成すると上述の通り、内部 DNS タイプはゾーン DNS になります。但し、カスタムメタデータキーとして、 VmDnsSetting を設定することで内部 DNS タイプを指定することができます。 gcloud コマンドで GCE インスタンスを作成する場合、以下のオプションを追加することで内部 DNS タイプを指定できます。 グローバル DNS : --metadata=VmDnsSetting=GlobalDefault ゾーン DNS : --metadata=VmDnsSetting=ZonalOnly コンソール上からもメタデータの設定はできます。しかし、後述の「例外」の項目にある通り コンソールからは ゾーンに関わらず既存の GCE インスタンスと同じ名前は使えません 。 参考: プロジェクトまたは VM の DNS 名を構成する / gcloud compute instances create 確認方法 Linux の場合、以下のコマンドで GCE インスタンスの FQDN を確認できます。デフォルトで VM のメタデータサーバー( 169.254.169.254 )が名前解決します。 curl "http://metadata.google.internal/computeMetadata/v1/instance/hostname" \ -H "Metadata-Flavor: Google" # 実行例 fujioka@my-instance:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/hostname" \ -H "Metadata-Flavor: Google" my-instance.c.demo-project.internal fujioka@my-instance:~$ fujioka@my-instance:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/hostname" \ -H "Metadata-Flavor: Google" my-instance.asia-northeast1-a.c.demo-project.internal fujioka@my-instance:~$ 参考: VM の内部 DNS 名を特定する 検証 内部 DNS タイプを明示的に指定し、同じインスタンス名で作成可能な組み合わせを検証していきます。 前提条件 CloudShell からコマンドを実行 作成するGCE インスタンスの OS は debian-11 インスタンス名は my-instance VPC やサブネットの構成は以下の通り 構成 例外 2023 年 3 月時点で、コンソール画面からはゾーンに関係なく、既存のインスタンス名と同じ名前の場合 名前 はすでに使用中です。 (英語表記: Name is already in use )のエラーが表示されます。そのため、検証は gcloud コマンドで GCE インスタンスを作成します。 コンソールのインスタンス名重複エラー 作成コマンド ゾーンごと、内部 DNS タイプごとに以下の 4 種類のコマンドで GCE インスタンスを作成します。 ################################### ゾーン:asia-northeast1-a ################################### # ① 内部 DNS タイプ:ゾーン DNS # 作成される FQDN:my-instance.asia-northeast1-a.c.demo-project.internal gcloud compute instances create my-instance \ --machine-type=e2-micro \ --image-project debian-cloud \ --image-family debian-11 \ --zone asia-northeast1-a \ --network=demo-vpc \ --subnet=demo-subnet \ --metadata=VmDnsSetting=ZonalOnly # ② 内部 DNS タイプ:グローバル DNS # 作成される FQDN:my-instance.c.demo-project.internal gcloud compute instances create my-instance \ --machine-type=e2-micro \ --image-project debian-cloud \ --image-family debian-11 \ --zone asia-northeast1-a \ --network=demo-vpc \ --subnet=demo-subnet \ --metadata=VmDnsSetting=GlobalDefault ################################### ゾーン:asia-northeast1-b ################################### # ③ 内部 DNS タイプ:ゾーン DNS # 作成される FQDN:my-instance.asia-northeast1-b.c.demo-project.internal gcloud compute instances create my-instance \ --machine-type=e2-micro \ --image-project debian-cloud \ --image-family debian-11 \ --zone asia-northeast1-b \ --network=demo-vpc \ --subnet=demo-subnet \ --metadata=VmDnsSetting=ZonalOnly # ④ 内部 DNS タイプ:グローバル DNS # 作成される FQDN:my-instance.c.demo-project.internal gcloud compute instances create my-instance \ --machine-type=e2-micro \ --image-project debian-cloud \ --image-family debian-11 \ --zone asia-northeast1-b \ --network=demo-vpc \ --subnet=demo-subnet \ --metadata=VmDnsSetting=GlobalDefault 作成順序 結果は 作成順序によって結果が異なる ため、図にします。赤枠の縦軸のインスタンスを 1 つ作成し、それに対し横軸のインスタンスを 1 つ作成し結果を確認していきます。それを全ての縦軸のインスタンスごとに確認していきます。 グローバル DNS の場合、 ドキュメント に以下の記載があることから、表には 2 つの FQDN( <VM 名>.<ゾーン名>.c.<プロジェクト ID>.internal / <VM 名>.c.<プロジェクト ID>.internal )を記載しています。 VM がグローバルとゾーンの両方の DNS 名を登録するように VmDnsSetting=GlobalDefault を設定しますが、デフォルトのドメイン名と検索パスのエントリにはグローバル名のみを使用します。 作成順序 結果 結果は以下の表の通りです。項番ごとに結果と理由を確認していきます。 結果 項番 結果 理由 (1) 不可 FQDN が同じのため (2) 不可 グローバル DNS の場合は、ゾーン DNS 名も登録され FQDN が同じのため (3) 不可 グローバル DNS の場合は、ゾーン DNS 名も登録され FQDN が同じのため (4) 不可 FQDN が同じのため (5) 可 FQDN が異なるため (6) 不可 ※後述 (7) 可 ※後述 (8) 不可 FQDN が同じのため 以上の結果から、(6), (7) は作成ゾーンが異なり、FQDN も異なることからどちらも「可」となるはずが、(6) は「不可」となっています。その理由は、 ドキュメント の以下の部分です。 推奨: VmDnsSetting=ZonalOnly を設定すると、VM の参照はゾーン DNS 名でのみ可能になります。VM は引き続き、ゾーンとグローバルの両方の検索パスを保持しますが、グローバル DNS 名は機能しなくなります。 グローバル DNS 名は機能しなくなるということは、(6) で先にゾーン DNS によって my-instance.asia-northeast1-b.c.demo-project.internal が作成された後、そのグローバル DNS 名である my-instance.c.demo-project.internal は機能しなくなります。つまり、ゾーン DNS を作成した後にグローバル DNS を作成しようとするとエラーとなります。そのため、(7) では「可」だった結果が (6) では「不可」となります。 それに対して、(7) のように先にグローバル DNS によって my-instance.c.demo-project.internal が作成されている場合は、その後にゾーン DNS 名の my-instance.asia-northeast1-a.c.demo-project.internal を作成することができます。 まとめ 以上の結果から、同一インスタンス名で作成が可能なパターンは以下の通りです。 両者の内部 DNS タイプが ゾーン DNS の時に異なるゾーンにインスタンスを作成する 一方の内部 DNS タイプが グローバル DNS のインスタンスを先に作成し、次に ゾーン DNS のインスタンスを作成する このことから、インスタンス名の名前空間はゾーンである (しかしインスタンスの作成順によってはバリデーションに引っかかる) ということがわかりました。 なお補足すると、あくまで推奨の内部 DNS タイプはゾーン DNS であり、現在はデフォルトの設定もゾーン DNS となっています。今回は検証のため、グローバル DNS も設定し確認しました。 G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
G-gen の佐々木です。当記事では Google Cloud ( 旧称 GCP ) の Google Kubernetes Engine ( GKE ) で作成した Ingress に対して、 Cloud Armor セキュリティポリシー を構成することで、ワークロードに対するアクセス元 IP アドレス制限を実装します。 前提知識 Google Kubernetes Engine とは Ingress とは Cloud Armor とは GKE クラスタの準備 GKE クラスタにサンプルアプリケーションをデプロイする Ingress を作成してアプリケーションを公開する Cloud Armor のセキュリティポリシーを作成する BackendConfig を作成する Service を更新して BackendConfig に紐づける 許可していない IP アドレスからアクセスしてみる GKE & Cloud Armor 前提知識 Google Kubernetes Engine とは Google Kubernetes Engine (以下、GKE ) は、Google Cloud のインフラストラクチャ上に構築された マネージドな Kubernetes クラスタ を利用することができるサービスです。 サービスの詳細は以下の記事で解説しています。 blog.g-gen.co.jp Ingress とは Ingress は Kubernetes の API リソースの 1 つで、Kubernetes クラスタ内のワークロードに対する L7 ロードバランシングを提供します。 Ingress は Service に関連付けることで、その背後にある Pod にデプロイされたアプリケーションを外部に公開することができます。 GKE では、組み込みのコントローラである GKE Ingress Controller によって、Kubernetes によって管理される HTTP(S) ロードバランサを GKE クラスタ外に作成することができます。 Ingressを用いたL7ロードバランサによるワークロードの外部公開 当記事では省略しますが、Ingress によって作成される HTTP(S) ロードバランサで HTTPS を使用する場合、Ingress と SSL 証明書を紐づける設定をする必要があります。 詳細な手順については以下の記事をご一読ください。 blog.g-gen.co.jp Cloud Armor とは Cloud Armor は Google 製のクラウド型 WAF であり、Cloud Armor の セキュリティポリシー を HTTP(S) ロードバランサのバックエンドに紐づけることで、バックエンドに対するアクセス元の制限をかけることができます。 Cloud Armor の詳細については、以下の記事で解説しています。 blog.g-gen.co.jp GKE クラスタの準備 当記事では Autopilot モードの限定公開クラスタを使用していきます。 クラスタの作成方法については 公式ドキュメント 、または Terraform を使用した以下の記事を参照してください。 blog.g-gen.co.jp GKE クラスタにサンプルアプリケーションをデプロイする Google Cloud が提供するサンプルのコンテナイメージを使用し、アプリケーションを GKE クラスタに登録します。 マニフェストファイルは以下のようになります。 # deployment.yaml apiVersion : apps/v1 kind : Deployment metadata : name : hello namespace : default spec : replicas : 3 selector : matchLabels : app : hello template : metadata : labels : app : hello spec : containers : - name : hello image : us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 ports : - containerPort : 8080 protocol : TCP 続いて、アプリケーションを公開するための Service を GKE クラスタに登録します。 Service のマニフェストファイルは後に編集するため、当記事ではファイル名を service.yaml と定めます。 # service.yaml apiVersion : v1 kind : Service metadata : name : hello namespace : default annotations : cloud.google.com/neg : '{"ingress": true}' spec : ports : - port : 8080 protocol : TCP targetPort : 8080 selector : app : hello type : NodePort それぞれのプロビジョニングが完了するまで待ちます。 $ kubectl get deployments hello NAME READY UP-TO-DATE AVAILABLE AGE hello 3 / 3 3 3 15m $ kubectl get services hello NAME TYPE CLUSTER-IP EXTERNAL-IP PORT ( S ) AGE hello NodePort 172 . 31 . 236 . 34 < none > 8080:32678/TCP 10m Ingress を作成してアプリケーションを公開する まずは Cloud Armor のセキュリティポリシーを構成せずに Ingress を作成してみます。 この Ingress によって作成される HTTP(S) ロードバランサはアクセス元の制限がされておらず、ロードバランサの IP アドレスを知っていれば誰でもアプリケーションにアクセスすることができてしまいます。 # ingress.yaml apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : hello-ingress namespace : default annotations : kubernetes.io/ingress.class : "gce" # 外部 HTTP(S) ロードバランサを指定 spec : defaultBackend : service : name : hello port : number : 8080 Ingress によって作成された HTTP(S) ロードバランサの外部 IP アドレスを確認し、ブラウザからアクセスしてみます。 $ kubectl get ingresses hello-ingress NAME CLASS HOSTS ADDRESS PORTS AGE hello-ingress < none > * 34 . 117 . 255 . 169 80 19m サンプルアプリケーションの画面 Cloud Armor のセキュリティポリシーを作成する アプリケーションに対するアクセス元 IP アドレスを制限するセキュリティポリシーを作成します。 ここで設定したセキュリティポリシーの名前は後で使用します。 セキュリティポリシーは Cloud Armor の機能ですが、 gcloud compute コマンドグループを使用して作成、編集を行うことができます。 当記事では hello-sec-policy という名前のセキュリティポリシーを作成します。 # セキュリティポリシーの作成 $ gcloud compute security-policies create hello-sec-policy ポリシーのデフォルトルール(優先度 2,147,483,647 )を更新し、すべてのアクセス元を拒否します。 # デフォルトルールの更新 $ gcloud compute security-policies rules update 2147483647 \ --security-policy hello-sec-policy \ --action " deny-403 " 特定の IP アドレス範囲からのアクセスを許可するルールを追加します。 ルールの優先度はデフォルトのルールより高ければよいので、ここでは優先度 1000 で設定します。 # 許可ルールの追加 $ gcloud compute security-policies rules create 1000 \ --security-policy hello-sec-policy \ --src-ip-ranges " <許可する IP アドレス範囲> " \ --action " allow " BackendConfig を作成する Ingress に対して Cloud Armor セキュリティポリシーを紐づけるため、GKE のカスタムリソースである BackendConfig リソースをクラスタに登録します。 BackendConfig リソースを使用することで、セキュリティポリシーだけではなく、Cloud CDN や Identity-Aware Proxy など、HTTP(S) ロードバランサで利用できる様々な機能を Kubernetes から有効化することができます。 BackendConfig のマニフェストファイルでは、先ほど作成したセキュリティポリシーの名前を使用します。 # backendconfig.yaml apiVersion : cloud.google.com/v1 kind : BackendConfig metadata : name : hello-backend-config spec : securityPolicy : name : hello-sec-policy # 作成したセキュリティポリシーの名前 Service を更新して BackendConfig に紐づける BackendConfig は、Ingress に対してではなく、HTTP(S) ロードバランサのバックエンドとなる Service に対して紐づけます。 バックエンドが使用するポートと BackendConfig を組み合わせた cloud.google.com/backend-config アノテーションを service.yaml に追記します。 annotations のキー 値 cloud.google.com/backend-config '{"ports": {"8080":"hello-backend-config"}}' # service.yaml apiVersion : v1 kind : Service metadata : name : hello namespace : default annotations : cloud.google.com/backend-config : '{"ports": {"8080":"hello-backend-config"}}' # 追記 cloud.google.com/neg : '{"ingress": true}' spec : ports : - port : 8080 protocol : TCP targetPort : 8080 selector : app : hello type : NodePort 許可していない IP アドレスからアクセスしてみる Ingress によって作成された HTTP(S) ロードバランサに Cloud Armor セキュリティポリシーが構成されたので、ポリシーで許可していない IP アドレス範囲からのアクセスが拒否されることを確認します。 ブラウザで、HTTP(S) ロードバランサの外部 IP アドレスに再度アクセスしてみます。 許可されていない IP アドレス範囲からのアクセスは拒否される 最後に、ポリシーで許可された IP アドレスからアクセスし、サンプルアプリケーションの画面が表示されることを確認します。 許可された IP アドレス範囲からのアクセス 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
こんにちは!G-genで営業をしている遠目塚です。当記事では、Google Cloud (旧称 GCP) のノーコードツールである Google AppSheet (以下AppSheet) を Google Sheets (以下Sheets) から簡単に作成する方法をご紹介します。 AppSheetの概要 AppSheetの始め方 アプリ化したい業務を考えてみよう こんな業務ありませんか? アプリをつくってみよう Sheetsに紙で入力している項目を洗い出してみよう 入力の簡素化についても考えてみる Sheetsの画面上から簡単にアプリ作成ができる! 設定を変更してみよう TYPEの変更 シート同士(テーブル)を連携させよう アプリ操作を確認する 便利な機能、「エミュレータ」 アプリで入力した項目が、反映されているか確認する AppSheetの概要 ノーコードでモバイルアプリケーションやウェブアプリケーションを構築することができるサービスです。 AppSheetの始め方 AppSheetの概要およびはじめ方については以下の記事で解説しています。 blog.g-gen.co.jp アプリ化したい業務を考えてみよう こんな業務ありませんか? 現場で紙で記録して、システムに再入力している 拠点からFAXで報告を受け、本社で基幹システムに再入力している 専用のシステムを構築するまでもないけれども、手間がかかっているので簡素化したい!そんな業務をアプリ化してみましょう。 アプリをつくってみよう Sheetsに紙で入力している項目を洗い出してみよう Sheetsをアプリのデータソースにすることができます。今回は「棚卸業務」を想像して項目を洗い出してみました。 シート名がアプリで利用するテーブル名になりますので、わかりやすいものに変更します。 入力の簡素化についても考えてみる 商品名を手入力してしまうと、間違いの元になるため今回は「商品名」のシートを別で作成してみました。 表計算ソフトのLUUKUPのようなイメージです。 Sheetsの画面上から簡単にアプリ作成ができる! 上部のメニュー一覧の「拡張機能」を選択すると「AppSheet」が表示されますので「アプリを作成」をクリックします。 アプリ作成中です AppSheetが表示され、アプリができました! 設定を変更してみよう 今回は、一部AppSheet上での設定変更についてご紹介します。詳細は今後ブログで発信していくので割愛させていただきます。 TYPEの変更 日付はカレンダー形式で入力出来たほうがよいので、「TYPE」を「Data型(日付)」に変更します シート同士(テーブル)を連携させよう 商品名の入力を簡素化するために、Sheets上に「商品名」のシートを準備していました。 まだテーブルとして追加されていないので、追加します。 画面左上の「+」ボタンをクリックします。 データソースの追加画面が表示されますので、画面下の「Add Table "商品名"」を選択します。 直感的でわかりやすいですね! 画面右下の「Add This Table」を選択します。 テーブルとして追加されました。 棚卸し業務テーブルの商品名の設定詳細を見てみましょう、先程までTYPEが「Text」だったのが「ref」に変わっています! NAME:商品名の左にある「edit」を選択してください。 SorceTableが自動的に「商品名」となっています。これでアプリで入力する際にあらかじめ準備された項目から商品名を選択できます。 アプリ操作を確認する 便利な機能、「エミュレータ」 画面右側の「エミュレータ」で、実際のアプリの操作を確認することができます。エミュレータの右下の、「Add」を選択します。 カレンダー入力ができます。 商品名もプルダウンで選ぶことができました! 必要事項を入力して「Save」を選択しましょう。 アプリで入力した項目が、反映されているか確認する データソースである Sheets を確認すると・・・? 入力項目が、反映されました! 今回は、Sheetsから簡単に棚卸しアプリを作成する方法を紹介しました。今後はもっと細かい機能やアプリ作成方法についても紹介していきます。 遠目塚美優希 (記事一覧) ビジネス推進部 G-genに飛び込んで、GoogleCloudの営業として日々奮闘中! 福岡でフルリモートワーク勤務、在宅なのに毎朝お手製弁当を作成中
当記事は みずほリサーチ&テクノロジーズ × G-gen エンジニアコラボレーション企画 で執筆されたものです。 当社では業務系システムを開発する機会が多く、定期的に実行する処理が多くあります。慣れ親しんだCron式でジョブの実行定義ができる Cloud Scheduler は利用機会も多く、優先的に仕様を調査することにしました。 G-gen の佐々木です。当記事では Google Cloud (旧称 GCP) のフルマネージドの cron ジョブスケジューラである Cloud Scheduler を解説します。 Cloud Scheduler とは ユースケース cron ジョブのターゲット cron ジョブスケジュールの設定 日時フィールド 特殊文字 設定例 ターゲットの認証 ジョブ失敗時の対処 ジョブ失敗の通知 失敗したジョブの再実行 使用上の注意点 サマータイムによる影響 べき等性を考慮する 料金 Cloud Scheduler とは Cloud Scheduler は サーバーレスなジョブスケジューラサービスです。 Google Cloud コンソールや gcloud コマンドを使用してジョブのスケジュールとターゲットを指定するだけで cron ジョブを簡単に作成することができ、一括で管理することができます。 ジョブ実行のためのインフラストラクチャのプロビジョニングや運用管理をする必要はありません。 ユースケース Cloud Scheduler は、cron ジョブを使用して Cloud Functions や Cloud Run などのコンピューティングプロダクトや、Pub/Sub のようなメッセージングのプロダクトにリクエストを送信することができます。 一般的なユースケースとしては、 cron ジョブを起点とした Cloud Functions によるバッチ処理 があります。 たとえば、Cloud Functions から他の Google Cloud プロダクトの API を使用することで、以下のような処理を定期実行タスクとして実装することができます。 Cloud SQL や Cloud Storage にあるデータを読み込んで変換し、BigQuery に書き込む ( ETL 処理 ) Compute Engine インスタンスのマシンイメージを取得する ( バックアップ ) Web サイトから収集したデータを Cloud Storage や BigQuery に出力する ( Web スクレイピング ) すべてのコンポーネントにサーバーレスのプロダクトを使用するため、インフラストラクチャの運用管理をすることなく定期バッチ処理を実装することができます。 Cloud Scheduler の一般的なユースケース cron ジョブのターゲット cron ジョブのターゲットには、以下のタイプが指定できます。 一般公開されている HTTP/S エンドポイント Cloud Pub/Sub トピック Google App Engine の HTTP/S アプリケーション Cloud Pub/Sub トピックを cron ジョブのターゲットとして利用することで、Pub/Sub サブスクライバーとなる Cloud Functions や Cloud Run にリクエストを送信することができ、定期実行タスクの柔軟性がかなり高まります。 なお、Cloud Functions や Cloud Run では HTTPS エンドポイントが提供されるため、Pub/Sub を間に挟むことなく使用することもできます。 しかし、Pub/Sub を使用することで、cron ジョブと実際の処理部分を疎結合にすることができ、同じ cron ジョブから複数のサブスクライバーにリクエストを送信するなど、処理の柔軟性が向上します。 また、Pub/Sub ターゲットを使用する場合のみ、ジョブを VPC Service Controls の境界に含めることができます。 cron ジョブスケジュールの設定 Cloud Scheduler では、cron ジョブを unix-cron 形式 で指定します。 日時フィールド cron 形式は、空白で区切られた 5 つの日時フィールドで構成されます。 cron 形式の 5 つの日時フィールド フィールド 有効な値 分 0~59 時間 0~23 日 1~31 月 1~12 ( JAN ~ DEC でも可 ) 曜日 0~6 ( SUN ~ SAT でも可。また日曜日は 7 でも可 ) 特殊文字 日時フィールドには先述した有効な値のほか、特殊文字を使用することができます。 特殊文字 説明 * (アスタリスク) 日時フィールドに設定できる すべての値 を表します。たとえば、曜日フィールドに * を設定した場合、 日曜日~土曜日までの全ての曜日 を意味します。 - (ハイフン) 範囲 を指定することができます。たとえば、月フィールドに 4-8 を設定した場合、 4 月から 8 月までの毎月 ( 8 月も含む ) を意味します。 /{数値} 範囲の指定とともに使用することで、指定した範囲内での 実行間隔 (ステップ) を指定することができます。たとえば、時間フィールドに 0-23/2 を設定した場合、ジョブは 0,2,4,6,8,10,12,14,16,18,20,22 時 に実行されます。 , (カンマ) 値の リスト を使用することができます。たとえば、日フィールドに 7,17,27 を設定した場合、 7 日、17 日、27 日 にジョブが実行されます。 設定例 設定したいスケジュール 値 毎週月曜日の午前 9 時 0 9 * * 1 毎平日の午前 0 時 30 分 30 0 * * 1-5 毎月 5, 15, 25 日の午後 6 時 0 18 5,15,25, * * 毎年 8 月 5 日 の午後 9 時 0 21 5 8 * ターゲットの認証 ターゲットに HTTP/S エンドポイントを使用し、認証が必要なターゲットを Cloud Scheduler から呼び出す場合、ジョブに対してサービスアカウントを設定します。 たとえば、認証が必要な Cloud Functions の HTTPS エンドポイントをターゲットとする場合、 Cloud Functions 起動元 ロール ( roles/cloudfunctions.invoker ) を紐付けたサービスアカウントをジョブに設定します。 Pub/Sub をターゲットとして使用する場合、Cloud Scheduler ジョブに対しては追加の権限を設定する必要はありません。 Pub/Sub 経由で Cloud Functions や Cloud Run などを使用する場合は、サブスクリプションに対してサービスアカウントを設定します。 ジョブ失敗時の対処 ジョブ失敗の通知 Cloud Scheduler ジョブの実行は、デフォルトで Cloud Logging に記録されます。 Cloud Logging に記録されたジョブのエラーログを ログベースの指標 として Cloud Monitoring で取得し、 アラートポリシー を設定することで、メールや Slack による通知や、Pub/Sub を使用した後続処理などを行うことができます。 失敗したジョブの再実行 Cloud Scheduler のジョブ実行が失敗した場合、 デフォルトでは再実行されません。 ジョブの再実行が必要な場合、最大実行回数 (1~5) や最大実行時間 (1s ~ 実質無制限)、再実行間隔などを指定し、 指数バックオフ による再実行を設定することができます ( 参考 )。 また、ジョブはコンソールや gcloud コマンドから手動で実行することも可能です。 使用上の注意点 サマータイムによる影響 ジョブの実行時間を設定する際、基準となるタイムゾーンを選択することができますが、 一部のタイムゾーンにおいて、夏時間の影響でジョブが予期せず実行される、もしくはジョブが実行されない可能性があります。 したがって、基本的には 夏時間のないタイムゾーン を選択します。 ドキュメントでは UTC を選択することが推奨されていますが、 JST もサマータイムの影響を受けないため、いずれかのタイムゾーンを選択するとよいでしょう。 べき等性を考慮する Cloud Scheduler では最低 1 回の実行 ( At-least Once ) を保証しており、そのため同じ cron ジョブが複数回実行されることが稀にあります。 したがって、cron ジョブを起点とする処理全体を べき等 に実装する必要があります。 ジョブの作成時に ヘッダー を設定し、ジョブ名や cron で設定した実行時刻をターゲットへのリクエストに含めることで、リクエストの重複削除に役立てることができます ( 参考 )。 料金 Cloud Scheduler の料金は、 ジョブの実行回数ではなく、ジョブの個数で決定されます。 1 日あたり $0.003 課金され、たとえばジョブを作成して 10 日後に削除した場合は $0.03 の課金となります。 無料枠はプロジェクト単位ではなく、請求先アカウント単位で集計される点に注意しましょう。 ジョブの料金 無料枠 ジョブあたり $0.10 / 月 請求先アカウントあたり 3 つのジョブ 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
今回は BigQuery に備わる機械学習機能である BigQuery ML で、2 項ロジスティック回帰を用いた分類モデルを作成してみました。 BigQuery ML とは サポートされているモデル 今回使用するデータ 準備 各種ファイルのアップロード データセットの作成 テーブルの作成 テーブルにデータをロード データの確認 モデルの作成 データの前処理を行います。 モデル構築 予測 評価 BigQuery ML とは BigQuery ML とは、BigQuery 上で機械学習モデルを作成、評価、実行ができるGoogle Cloud の機械学習プロダクトのひとつです。 通常、機械学習を行うには機械学習フレームワークに対する高度なプログラミングスキルと知識を必要としますが、BigQuery ML を用いれば SQL を用いて機械学習の一連の工程を実装できます。 BigQuery 自体はフルマネージドサービスであり、また BigQuery をデータウェアハウス (DWH) として使われている場合はデータをエクスポートする必要がないため機械学習モデルの開発効率を向上させることができます。 以下の記事では BigQuery ML を詳細に解説していますので、ご参照ください。 blog.g-gen.co.jp サポートされているモデル BigQuery ML では、2023年3月現在以下のモデルをサポートしています。 Linear regression Binary logistic regression Multiclass logistic regression K-means clustering Matrix Factorization Time series Boosted Tree Deep Neural Network Vertex AI AutoML Tables TensorFlow model importing Autoencoder 今回使用するデータ 今回使用するデータは、 kaggle で提供されている Loan Approval Prediction の Traning Dataset.csv を使用します。 このデータセットは、住宅ローン全般を取り扱っている会社がモデルとなっており、その会社でローンの審査を受ける個人の情報 (性別、婚姻状況、教育、扶養家族の数、収入、ローン金額、信用履歴など) と「実際にローンの審査が通ったのか否か」が記載されています。 今回は、BigQuery ML を用いて「各個人の情報と審査の結果を 教師データ として、ローンの審査が通るか通らないかを予測する分類モデル」を作成したいと思います。 準備 準備の工程は Cloud Shell 環境にて gcloud コマンドを用いて行います。 各種ファイルのアップロード 先程ダウンロードした Traning Dataset.csv データを、traning_dataset.csv にリネームし、 Cloud Shell にアップロードします。 また、schema.json というファイルを新規作成し、以下を記入します。 [ { " name ": " Loan_ID ", " type ": " STRING ", " mode ": " Required ", " description ": " Unique Loan ID " } , { " name ": " Gender ", " type ": " STRING ", " mode ": " Nullable ", " description ": " Male/ Female " } , { " name ": " Married ", " type ": " BOOLEAN ", " mode ": " Nullable ", " description ": " Applicant married (Y/N) " } , { " name ": " Dependents ", " type ": " STRING ", " mode ": " Nullable ", " description ": " Number of dependents " } , { " name ": " Education ", " type ": " STRING ", " mode ": " Nullable ", " description ": " Applicant Education (Graduate/ Under Graduate) " } , { " name ": " Self_Employed ", " type ": " BOOLEAN ", " mode ": " Nullable ", " description ": " Self-employed (Y/N) " } , { " name ": " ApplicantIncome ", " type ": " INTEGER ", " mode ": " Nullable ", " description ": " Applicant income " } , { " name ": " CoapplicantIncome ", " type ": " FLOAT ", " mode ": " Nullable ", " description ": " Coapplicant income " } , { " name ": " LoanAmount ", " type ": " INTEGER ", " mode ": " Nullable ", " description ": " Loan amount in thousands " } , { " name ": " Loan_Amount_Term ", " type ": " INTEGER ", " mode ": " Nullable ", " description ": " Term of the loan in months " } , { " name ": " Credit_History ", " type ": " INTEGER ", " mode ": " Nullable ", " description ": " Credit history meets guidelines " } , { " name ": " Property_Area ", " type ": " STRING ", " mode ": " Nullable ", " description ": " Urban/ Semi-Urban/ Rural " } , { " name ": " Loan_Status ", " type ": " BOOLEAN ", " mode ": " Nullable ", " description ": " (Target) Loan approved (Y/N) " } ] Cloud Shell 上のディレクトリが以下のように構成できれば必要なファイルの準備は揃っています。 root ├── training_dataset.csv └── schema.json データセットの作成 BigQuery のデータセットを作成します。 bq mk --dataset --location=asia-northeast1 <DATASET_NAME> DATASET_NAME:データセット名 テーブルの作成 BigQuery のテーブルを作成します。 bq mk --table <PROJECT_ID>:<DATASET_NAME>.<TABLE_NAME> schema.json PROJECT_ID:プロジェクト ID TABLE_NAME:テーブル名 テーブルにデータをロード 作成したテーブルにデータをロードします。 bq --location=asia-northeast1 load \ --source_format=CSV \ --skip_leading_rows=1 \ <PROJECT_ID>:<DATASET_NAME>.<TABLE_NAME> training_dataset.csv データの確認 BigQuery を開いてクエリエディタで以下 SQL を実行します。(614行/13列) SELECT * FROM `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>` クエリ結果 モデルの作成 データの前処理を行います。 ここからは BigQuery のコンソール画面 (クエリエディタ) から作業を行います。 まずはデータの前処理を行い、前処理を終えたデータをビューとして定義します。 CREATE OR REPLACE VIEW `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>` AS SELECT  * EXCEPT(Loan_ID), CASE WHEN MOD ( ABS (FARM_FINGERPRINT(Loan_ID)), 10 ) < 8 THEN ' training ' WHEN MOD ( ABS (FARM_FINGERPRINT(Loan_ID)), 10 ) >= 8 THEN ' prediction ' END AS dataframe FROM `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>` WHERE Gender is not null AND Married is not null AND Dependents is not null AND Education is not null AND Self_Employed is not null AND ApplicantIncome is not null AND CoapplicantIncome is not null AND LoanAmount is not null AND Loan_Amount_Term is not null AND Credit_History is not null AND Property_Area is not null AND Loan_Status is not null 「Loan_Status」列には、 True (審査が通った) と False (審査に落ちた) の 2 つの値が入っており、「Loan_Status」列と 関連性のある属性 を用いてモデルを構築します。 したがって、「Loan_ID」列は一意の値を持ち「Loan_Status」列とは関係がないため除外してます。 また、トレーニングデータと予測データを分けるために、「dataframe」列を作成しています。 最後に、各列に null が含まれる行を除外しています。 前処理を終えると 480行13列 のデータになります。 「dataframe」列を元に、トレーニングデータと予測データの割合は以下のようになっています。 No 種別 数量 全体 (480) に占める割合 [%] 1 training 360 75 % 2 prediction 120 25 % モデル構築 モデル構築を行います。 CREATE OR REPLACE MODEL `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>` OPTIONS ( model_type= ' LOGISTIC_REG ' , auto_class_weights= TRUE , data_split_method= ' NO_SPLIT ' , enable_global_explain= TRUE , input_label_cols=[ ' Loan_Status ' ]) AS SELECT * EXCEPT(dataframe) FROM `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>` WHERE dataframe = ' training ' CREATE OR REPLACE MODEL 構文を用いてモデルを構築していきます。 OPTIONS の中に各種パラメータを定義します。 model_type には [LOGISTIC_REG] (ロジスティック回帰モデル) を選択します。 デフォルトでは、ロジスティック回帰モデルの作成に使用されるトレーニング データは重み付けされていないため、 auto_class_weights を True に設定することでラベルに偏りが出てもバランスを取ってくれます。 data_split_method はトレーニングデータと評価データでデータを分けることができますが、今回は「dataframe」列を追加しデータ分割をしているため、明示的に不要としています。 enable_global_explain はモデルに対するグローバルな特徴の重要性を評価するために必要です。本検証の最後に使用するため True にしておきます。 input_label_cols はトレーニングデータのラベル列名となるため、今回は「 Loan_Status 」を記入します。 トレーニングが完了すると、モデルの結果を確認していきます。 トレーニング結果には、今回使ったモデルの詳細やトレーニングオプションについて確認することができます。 トレーニング結果 モデルの評価を確認する前に分類モデルの評価指標について軽く触れておきます。 分類モデルは主に以下の 4 つの評価指標を持ちます。 真陽数 (True Positive : TP ):正解が「◯」のものを、「◯」と予測した回数 真陰数 (True Nagative : TN ) :正解が「✕」のものを、「✕」と予測した回数 偽陽数 (False Pasitive : FP ):正解が「✕」のものを、「◯」と予測した回数 偽陰数 (False Nagative : FN ):正解が「◯」のものを、「✕」と予測した回数 上記の評価指標の組み合わせから以下のような指標が算出できます。 No 用語 概要 1 適合率 (Precision) 「◯」と予測したデータのうち、正しく分類できたデータの割合。式は TP / (TP+FP) 2 再現率 (Recall) または 真陽性率 (True Positive Tate) 正解が「◯」だったデータのうち、正しく「◯」と予測できた割合。式は TP / (TP + FN) 3 偽陽性率 (False Positive Rate) 正解が「✕」だったデータを、誤って「◯」と予測した割合。 式は FP / (FP + TN) 3 精度 (Accuracy) 全データ数のうち、正しく分類できたデータ数の割合。よく正解率ともいいます。式は (TP + TN) / (TP + TN + FP + FN) 4 F1 スコア (f1-score) 適合率と再現率の調和平均。式は 2×適合率×再現率 / (適合率 + 再現率) 5 ログ損失 (Log loss) モデル予測とターゲット値の間の交差エントロピー。 値が小さいほど高品質のモデル であることを示す。 6 ROC AUC 横軸に偽陽性率、縦軸に真陽性率を取った曲線の下の面積。0 ~ 1 の範囲を取り、 値が高いほど高品質 のモデルであることを示す。 今回のモデルの評価を確認してみます。 値が 0 に近ければ高品質とされる LogLoss が 0.4766 をとり、0 ~ 1 の範囲で値が高いほど高品質とされる ROC AUC は 0.8009 をとっております。 モデルの評価① モデルの評価② また、しきい値を変えることで適合率や再現率を調整することができます。 適合率は正解が「◯」を「✕」として分類してもよいが、正解が「✕」のものを確実に「✕」として分類したい場合に有用なので、今回のようなローンの審査において結果が False のものは極力 False と分類したいという要件があるなら重要な指標となるかと思います。 逆に再現率は正解が「✕」を「◯」と分類しても問題なく、かつ正解が「◯」は確実に「◯」として分類したい場合に有用なので、病気の診断などで再現率が重視されるケースが多いです。 このように、適合率と再現率は性質が異なるため、 ユースケースに合わせて調整 していく必要があります。 しかし、適合率と再現率はトレード・オフの関係であるため、適合率を極端に高めると再現率が極端に下がるのであまり良いモデルとは言えません。そこで、適合率と再現率の調和平均である F1 スコアも考慮しつつ 最適なしきい値 を決めていくことをおすすめします。 今回は特に要件がないため、しきい値を 0.5 として予測を行っていきたいと思います。 予測 以下の SQL を実行し予測を行います。 SELECT * FROM ML.PREDICT (MODEL `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>`, ( SELECT * EXCEPT(dataframe) FROM `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>` WHERE dataframe = ' prediction ' ), STRUCT( 0.5 as threshold) ) ML.PREDICT 関数 を用いて予測を行います。 STRUCT 型で threshold (しきい値) を 0.5 として設定しています。 元の列に加え、以下の 3 つの列が追加されます。 predicted_ label_column_name :ラベルの予測結果 predicted_ label_column_name _probs.label:ラベル (今回は True or False) predicted_ label_column_name _probs.prob:ラベルに対応する予測確率 結果は以下のようになりました。 予測結果 赤枠部分が今回の予測結果です。ローンの審査が通るか通らないかに対して、一番左の predicted_Loan_Status 列で、 True or False が表示されています。 このように過去の教師データをもとに、機械学習モデルで予測が簡単にできました。 評価 先程予測に用いたデータには正解のラベルもあるので、予測データに対して評価も行ってみます。 以下の SQL から評価を実行できます。 SELECT * FROM ML.EVALUATE (MODEL `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>`, ( SELECT * FROM `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>` WHERE dataframe = ' prediction ' ) STRUCT( 0.5 as threshold) ) ML.EVALUATE関数 で評価を行います。 評価結果 評価に用いる複雑な計算式が SQL 一発で出せるのは魅力的ですね。 正しく分類できたデータの割合を示す精度 (accuracy) が 81.7% でした。 他にも、適合率 (precision) や F1 スコア (f1_score) もともに 8 割を超えています。 最後に、特徴量の重要度スコアを見てみましょう。 SELECT *, ROUND (attribution * 100 / ( SELECT SUM (attribution) FROM ML.GLOBAL_EXPLAIN(MODEL `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>`) ), 1 ) AS percentage FROM ML.GLOBAL_EXPLAIN(MODEL `<PROJECT_ID>.<DATASET_NAME>.<TABLE_NAME>`) ML . GLOBAL_EXPLAIN関数 を用いて特徴量の重要度スコアを算出します。 特徴量の重要度スコアとは、各特徴量がどれほど影響を及ぼしているか数値化されています。 グローバル変数の説明 特に、以下の特徴量の影響が大きいようです。 Credit_History (Credit history meets guidelines) Property_Area (Urban/ Semi-Urban/ Rural) Married (Applicant married) いかがでしたでしょうか。BigQuery ML を使えば SQL を用いて、機械学習モデルの作成、予測、評価が簡単に実行できました。 G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
G-gen の荒井です。今回はコスト削減にも繋がる、Compute Engine VM の自動起動・停止のスケジューリングについて紹介します。 概要 VM の起動・停止のスケジューリング メリット スナップショットへの影響 シャットダウン時の動作 制限事項 設定方法 Compute Engine サービスエージェントへの権限付与 スケジュール作成 スケジュールの編集 スケジュールへ VM をアタッチ 新規 VM 作成時にスケジュールをアタッチ インスタンスのデタッチ スケジュールの削除 ログの確認 参考リンク 概要 VM の起動・停止のスケジューリング Google Cloud の VM インスタンス(Compute Engine)では、VM インスタンスの起動・終了をスケジューリングすることができます。 スケジュールは、Google Cloud コンソールや gcloud コマンドラインで設定できます。ソースコードを記述する必要はありません。 設定するには、起動時間や停止時間を指定して インスタンススケジュール を作成します。その後、作成したインスタンススケジュールに対象の VM を紐づけます。 参考 : VM インスタンスの起動と停止をスケジュールする メリット Google Cloud をはじめとするパブリッククラウドでは、リソースを使用しただけ課金が発生する従量課金方式となっていることがほとんどです。 Compute Engine も、VM を起動した時間に応じた従量課金であり、インスタンスを起動したままだと、常に課金が発生します。業務時間外には VM をシャットダウンしておくことで、コスト削減を図ることができます。 スナップショットへの影響 VM をシャットダウンさせておくと心配されるのがスナップショット(バックアップ)ですが、Google Cloud のスナップショットは VM がシャットダウンされていても、正しく取得されます。 むしろ、VM を停止した状態でスナップショットを取得すれば、ファイルシステムに読み書きがない状態でバックアップを取るので、VM が起動している状態でスナップショットを取るよりも、確実な整合性が担保されます。 シャットダウン時の動作 Compute Engine VM を停止すると、Google Cloud から VM インスタンスの OS に ACPI シャットダウン信号が送信され、OS がシャットダウンを開始します。そのため物理サーバーで言う「電源を引き抜く」イメージではなく、OS からシャットダウンをさせるイメージになります。 シャットダウン動作に関する詳細については、以下をご参照ください。 参考 : VM を停止する 制限事項 インスタンススケジュールには、OS 上のプロセス(サービス)を順番に終了させるような機能はありません スケジュールのオペレーションは最大15分程度遅延することがあります 指定時間に VM を起動させたい、または停止したい場合、指定時間の15分程度前にスケジューリング設定をする必要があります また起動、終了のオペレーションは最短でも15分以上の間隔を空けてスケジューリングします 1つの VM に対して紐付けることができるインスタンススケジュールは、1つだけです 反対に、1つのインスタンススケジュールには最大1,000個の VM を紐付けることができます インスタンススケジュールの作成時に、リージョンを指定します。スケジュールと同じリージョンの VM を対象にできます その他、詳細な制限事項については以下をご参照ください。 参考 : 制限事項 設定方法 Compute Engine サービスエージェントへの権限付与 VM の自動起動・終了は Google Cloud のシステム専用のアカウントである サービスエージェント の認証情報で実行されます。そのため、まずサービスエージェントに必要な権限を付与します。 サービス エージェントの詳細は、以下の記事を参照してください。 blog.g-gen.co.jp Compute Engine のサービスエージェントの詳細は、以下を参照してください。 参考 : Compute Engine サービス エージェント 付与する権限は以下のとおりです。 compute.instances.start : VM インスタンスの起動をスケジュールします。 compute.instances.stop : VM インスタンスの停止をスケジュールします。 上記を包括する権限であればどういったものでも構いません。今回は事前定義ロールとして用意されている Compute インスタンス管理者(v1)(roles/compute.instanceAdmin.v1) を付与します。 Cloud Console > IAM と管理 > IAM をクリック Google 提供のロール付与を含める を有効にする service-(PROJECT_NUMBER)@compute-system.iam.gserviceaccount.com の 編集 をクリック Compute インスタンス管理者(v1)(roles/compute.instanceAdmin.v1) の事前定義ロールを追加し 保存 をクリック Compute インスタンス管理者(v1) が付与されていることを確認 スケジュール作成 Compute Engine > VMインスタンス をクリック インスタンス スケジュール をクリック スケジュールを作成 をクリック 「新しいスケジュールの作成」ウインドウで、パラメータを入力し 送信 をクリック スケジュールが作成されていることを確認 スケジュールの編集 現在のところ、作成済みのスケジュールを編集することはできません。 スケジュールを変更したい際は、既存のインスタンススケジュールを削除してから、インスタンススケジュールを新規に作成します。 なお、インスタンススケジュールを削除する前に、そのスケジュールが持つ VM との紐づきをすべて削除する必要があります。また、1つの VM には複数のスケジュールを紐付けられませんので、一度既存のスケジュールと紐づきを削除してから、新しいスケジュールを作成することになります。 スケジュールへ VM をアタッチ 作成したスケジュールをクリック スケジュールにインスタンスを追加 をクリック スケジュールに追加したい インスタンス を選択し 追加 をクリック ※ 追加したいインスタンスが表示されていない場合、スケジュールとインスタンスのリージョン(ゾーン)が一致しているか確認をしてください。 指定インスタンスが追加されていることを確認 新規 VM 作成時にスケジュールをアタッチ 新規 VM 作成の際にスケジュールをアタッチしたい場合、gcloud コマンドを使用します。Google Cloud コンソールでは、2025年2月現在、新規 VM の作成時にスケジュールを紐付けることはできません。 gcloud compute instances create (INSTANCE_NAME) \ --resource-policies=(SCHEDULE_NAME) \ [--zone=(ZONE)] \ [--image (IMAGE) | --image-family (IMAGE_FAMILY)] \ [--image-project (IMAGE_PROJECT)] ※ ( ) 内のパラメータは任意で指定します。 参考 : 新しい VM インスタンスの作成時にインスタンス スケジュールを接続する 参考 : gcloud compute instances create インスタンスのデタッチ 作成したスケジュールをクリック デタッチしたいインスタンスを選択し スケジュールからインスタンスを削除 をクリック スケジュールの削除 作成したスケジュールをクリック 削除 をクリック 削除 をクリック スケジュールが削除されていることを確認 ログの確認 インスタンススケジュールによる VM の起動・停止のログは、Cloud Logging のログエクスプローラーで確認することができます。 Google Cloud コンソールでログエクスプローラ画面へ遷移して、以下のクエリを実行します。 最後の行の (PROJECT_NUMBER) の部分は、プロジェクト番号に置き換えてください。プロジェクト ID ではなく、数字で表されるプロジェクト番号であることに注意してください。プロジェクト番号は、Google Cloud コンソールの「IAM と管理 > 設定」で確認できます。 ( protoPayload.methodName= " v1.compute.instances.stop " OR protoPayload.methodName= " v1.compute.instances.start " ) AND protoPayload.authenticationInfo.principalEmail= " service-(PROJECT_NUMBER)@compute-system.iam.gserviceaccount.com " 参考リンク Compute Engine に関する詳細は、以下の記事を参照してください。 blog.g-gen.co.jp blog.g-gen.co.jp 荒井 雄基 (記事一覧) クラウドソリューション部 オンプレ環境のネットワーク・サーバーシステムを主戦場としていたが、クラウド領域にシフト。 Google Cloud 認定資格 7冠 現在は Google Workspace を中心に企業の DX 推進をサポート。 最近頑張っていることは、子どもがハマっている戦隊モノの踊りを踊れるようになること。
G-gen の佐々木です。当記事では Google Cloud ( 旧称 GCP ) の Google Kubernetes Engine ( GKE ) で Ingress を使用し、 Google マネージド SSL 証明書が構成された HTTPS ロードバランサ を Kubernetes のリソースとして作成していきます。 前提知識 Google Kubernetes Engine とは Ingress とは GKE クラスタの準備 GKE クラスタにサンプルアプリケーションをデプロイする 証明書を使用せずに Ingress を作成する Google マネージド SSL 証明書を使用して Ingress を作成する 静的外部 IP アドレスを払い出す A レコードを登録する ManagedCertificate リソースを作成する 証明書を使用するように Ingress を更新する Google マネージド SSL 証明書のステータスを確認する サンプルアプリケーションに HTTPS でアクセスできることを確認する 前提知識 Google Kubernetes Engine とは Google Kubernetes Engine (以下、GKE ) は、Google Cloud のインフラストラクチャ上に構築された マネージドな Kubernetes クラスタ を利用することができるサービスです。 サービスの詳細は以下の記事で解説しています。 blog.g-gen.co.jp Ingress とは Ingress は Kubernetes の API リソースの 1 つで、Kubernetes クラスタ内のワークロードに対する L7 ロードバランシングを提供します。 Ingress は Service に関連付けることで、その背後にある Pod にデプロイされたアプリケーションを外部に公開することができます。 GKE では、組み込みのコントローラである GKE Ingress Controller によって、Kubernetes によって管理される HTTP(S) ロードバランサを GKE クラスタ外に作成することができます。 Ingressを用いたL7ロードバランサによるワークロードの外部公開 GKE クラスタの準備 当記事では Autopilot モードの限定公開クラスタを使用していきます。 クラスタの作成方法については 公式ドキュメント 、または Terraform を使用した以下の記事を参照してください。 blog.g-gen.co.jp GKE クラスタにサンプルアプリケーションをデプロイする gcloud container clusters get-credentials コマンドを使用して GKE クラスタに接続した後、アプリケーションを GKE クラスタにデプロイします。 ここでは、Google Cloud が提供するサンプルのコンテナイメージを使用します。 また、Ingress に紐づける Service も同時にデプロイしていきます。 マニフェストファイルは以下のようになります。 # workload.yaml apiVersion : apps/v1 kind : Deployment metadata : name : hello namespace : default spec : replicas : 3 selector : matchLabels : app : hello template : metadata : labels : app : hello spec : containers : - name : hello image : us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 ports : - containerPort : 8080 protocol : TCP --- apiVersion : v1 kind : Service metadata : name : hello namespace : default annotations : cloud.google.com/neg : '{"ingress": true}' spec : ports : - port : 8080 protocol : TCP targetPort : 8080 selector : app : hello type : NodePort このマニフェストファイルにより、3 つの Pod を含む Deployment と、それらを公開するための Service ( NodePort ) が作成されます。 # デプロイ後 $ kubectl get deployments hello NAME READY UP-TO-DATE AVAILABLE AGE hello 3/3 3 3 3m45s $ kubectl get services hello NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello NodePort 172.31.113.220 <none> 8080:30989/TCP 4m24s 証明書を使用せずに Ingress を作成する まずは、最小限のマニフェストを使用して Ingress リソースを作成してみます。 ここで作成されるロードバランサは SSL 証明書が構成されておらず、HTTP トラフィック(ポート 80)を GKE クラスタ内のワークロードにルーティングします。 当記事では、Ingress リソースを作成するマニフェストファイルの名前を ingress.yaml とします。 # ingress.yaml apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : hello-ingress namespace : default annotations : kubernetes.io/ingress.class : "gce" # 外部 HTTP(S) ロードバランサを指定 spec : defaultBackend : service : name : hello port : number : 8080 # デプロイ後 $ kubectl get ingresses hello-ingress NAME CLASS HOSTS ADDRESS PORTS AGE hello-ingress <none> * 34.117.255.169 80 4m55s Ingress のデプロイが完了すると、Google Cloud コンソールで HTTP(S) ロードバランサが作成されていることを確認できます。 ここで作成されたロードバランサが使用できるプロトコルは HTTP のみ となっています。 Ingress から作成された HTTP(S) ロードバランサ ブラウザでロードバランサの IP アドレスにアクセスすると、サンプルアプリケーションのページが表示されます。 サンプルアプリケーションのページ Google マネージド SSL 証明書を使用して Ingress を作成する 静的外部 IP アドレスを払い出す 当記事では、 hello-app-address という名前で IP アドレスを払い出します。 この IP アドレスは、HTTP(S) ロードバランサに紐づけ、証明書に使用するドメインで解決できるようにします。 # 静的外部 IP アドレスの払い出し $ gcloud compute addresses create hello-app-address --global 払い出した IP アドレスは次の手順で使用するため、値を確認しておきます。 # 払い出した IP アドレスを確認する $ gcloud compute addresses describe hello-app-address --global address: 34.160.155.24 A レコードを登録する SSL 証明書に使用するドメインで、先ほど作成した IP アドレスを解決できるように DNS を構成します。 当記事では Cloud DNS に作成された DNS ゾーンに A レコードを作成していきます。 ここでは仮の値として、DNS ゾーンを hogehoge-zone 、ドメインを hogehoge.com とします。 # トランザクションの開始 $ gcloud dns record-sets transaction start --zone=hogehoge-zone Transaction started [transaction.yaml]. # Aレコードの登録 $ gcloud dns record-sets transaction add 34.160.155.24 \ --name=hogehoge.com \ --ttl=300 \ --type=A \ --zone=hogehoge-zone Record addition appended to transaction at [transaction.yaml]. # トランザクションの終了 $ gcloud dns record-sets transaction execute --zone=hogehoge-zone Executed transaction [transaction.yaml] for managed-zone [hogehoge-zone]. Created [https://dns.googleapis.com/dns/v1/projects/myproject/managedZones/hogehoge-zone/changes/32]. ID START_TIME STATUS 32 2023-02-21T14:38:43.813Z pending ManagedCertificate リソースを作成する ManagedCertificate カスタムリソースを使用して、Google マネージド SSL 証明書を Kubernetes リソースとして作成します。 マニフェストファイルには、先ほど DNS に登録したドメインを記述します。 # cert.yaml apiVersion : networking.gke.io/v1 kind : ManagedCertificate metadata : name : hello-managed-cert spec : domains : - hogehoge.com # デプロイ後 $ kubectl get managedcertificate.networking.gke.io hello-managed-cert NAME AGE STATUS hello-managed-cert 6m21s Provisioning 証明書を使用するように Ingress を更新する 作成した Google マネージド SSL 証明書を使用するように Ingress を更新します。 始めに作成した ingress.yaml の annotations に以下の 2 つを追記して GKE クラスタに再適用します。 annotations のキー 値 kubernetes.io/ingress.global-static-ip-name ロードバランサ用に払い出した静的外部 IP アドレスの名前 networking.gke.io/managed-certificates ManagedCertificate の名前 # ingress.yaml apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : hello-ingress namespace : default annotations : kubernetes.io/ingress.global-static-ip-name : hello-app-address # 追記 networking.gke.io/managed-certificates : hello-managed-cert # 追記 kubernetes.io/ingress.class : "gce" spec : defaultBackend : service : name : hello port : number : 8080 Ingress を更新すると、Ingress が使用する(ロードバランサで使用する) IP アドレスが、払い出した静的外部 IP アドレスに変更されます。 $ kubectl get ingresses hello-ingress NAME CLASS HOSTS ADDRESS PORTS AGE hello-ingress <none> * 34.160.155.24 80 19m Google Cloud コンソールから、HTTP(S) ロードバランサが HTTPS プロトコルを使用するように構成され直したことが確認できます。 HTTP(S) ロードバランサに HTTPS プロトコルが追加されている Google マネージド SSL 証明書のステータスを確認する Google マネージド SSL 証明書のステータスが Active になるまで待ちます。 ※ 証明書のステータス反映は Google Cloud コンソールのほうが早いようです。 # 証明書のステータス確認 $ kubectl get managedcertificate.networking.gke.io hello-managed-cert --watch NAME AGE STATUS hello-managed-cert 31m Active 証明書のステータスが ACTIVE になっていることを確認 サンプルアプリケーションに HTTPS でアクセスできることを確認する 証明書を構成したあと、DNS に設定したドメインに接続すると、サンプルアプリケーションに HTTPS でアクセスすることができます。 サンプルアプリケーションに HTTPS でアクセスできることを確認 佐々木 駿太 (記事一覧) G-gen 最北端、北海道在住のクラウドソリューション部エンジニア。 2022 年 6 月に G-gen にジョイン。Google Cloud All Certifications Engineer。 好きな Google Cloud プロダクトは Cloud Run。最近は Dataflow を勉強中。 Follow @sasashun0805
当記事では、Google Cloud(旧称 GCP)の Compute Engine(以下 GCE)において、Windows Server のオンデマンドライセンスを使用した場合のライセンス認証の設定編について紹介します。 はじめに 検証 構成図 前提条件 Terraform のコード リソースの確認 結果 パターン1 パターン2 パターン3 パターン4 おわりに はじめに 以下の記事で Windows Server のオンデマンドライセンスを使用した場合のライセンス認証についての概要や確認方法を紹介しました。 blog.g-gen.co.jp 上記を踏まえ、 外部 IP アドレスを持たない Windows Server VM でライセンス認証を行うには、 限定公開の Google アクセス (以下 Private Google Access)を有効にする必要があります。 そのため当記事では、 外部 IP アドレスの有無と Private Google Access の On/Off の観点 から4つのパターンの検証結果について記載します。 なお、以下の記事を理解しておくことで、後述の検証内容への理解が深まります。 Compute EngineのWindows Serverでライセンス認証エラー(0xC004F074) 限定公開の Google アクセスの仕組みと手順をきっちり解説 検証 構成図 構成は以下の通りです。通信経路については後述します。 構成図 * 参考: 限定公開の Google アクセス / IAP の TCP 転送の仕組み 前提条件 ここでは、以下を前提条件とし、Terraform を用い環境を構築します。 請求アカウントが紐付いたプロジェクトが作成済みである 本検証で必要な API が有効化されている 実行ユーザーに適切な権限が付与されている Private Google Access では デフォルトのドメイン名を利用 する Terraform はCloudShell で実行する Terraform のコード 実行する Terraform のコードは以下のとおりです。 variable "project" の ${PROJECT_ID} を自身のプロジェクト ID に置き換えた上で実行します。 /* 変数定義 https://developer.hashicorp.com/terraform/language/values/variables */ variable "project" { type = string default = "$ { PROJECT_ID } " // プロジェクト ID } variable "region" { type = string default = "asia-northeast1" } variable "zone" { type = string default = "asia-northeast1-a" } variable "subnet-cidr-a" { type = string default = "10.0.10.0/24" } variable "subnet-cidr-b" { type = string default = "10.0.20.0/24" } variable "instance_os" { type = string default = "windows-cloud/windows-2022" } variable "instance_type" { type = string default = "n2-standard-2" } /* プロバイダー定義 https://developer.hashicorp.com/terraform/language/providers/configuration */ provider "google" { project = var.project region = var.region zone = var.zone } /* terraform 設定 https://developer.hashicorp.com/terraform/language/settings */ terraform { required_version = "~> 1.2" required_providers { google = ">= 4.32.0" } } /* vpc 作成 https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_network */ resource "google_compute_network" "vpc" { name = "vpc" auto_create_subnetworks = "false" routing_mode = "GLOBAL" } /* subnet 作成 https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_subnetwork */ resource "google_compute_subnetwork" "subnet_a" { // Private Google Access: ON name = "subnet-a" ip_cidr_range = var.subnet-cidr-a network = google_compute_network.vpc.name private_ip_google_access = true } resource "google_compute_subnetwork" "subnet_b" { // Private Google Access: OFF name = "subnet-b" ip_cidr_range = var.subnet-cidr-b network = google_compute_network.vpc.name } /* firewall 作成 https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_firewall */ resource "google_compute_firewall" "allow_iap" { // IAP 用 name = "allow-ingress-from-iap" network = google_compute_network.vpc.name direction = "INGRESS" allow { protocol = "tcp" ports = [ "3389" ] } source_ranges = [ "35.235.240.0/20" ] } /* サービスアカウント作成 https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account */ resource "google_service_account" "service_account_for_vm" { account_id = "service-account-for-vm" display_name = "VM 用サービスアカウント" } /* サービスアカウント権限付与 https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam */ resource "google_project_iam_member" "service_account_for_vm_role" { project = var.project role = "roles/compute.admin" member = "serviceAccount:$ { google_service_account.service_account_for_vm.email } " } /* vm 作成 x4 https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance */ resource "google_compute_instance" "vm_a_1" { // パターン1 name = "vm-a-1" machine_type = var.instance_type service_account { email = google_service_account.service_account_for_vm.email scopes = [ "cloud-platform" ] } boot_disk { initialize_params { image = var.instance_os } } network_interface { network = google_compute_network.vpc.name subnetwork = google_compute_subnetwork.subnet_a.name network_ip = "10.0.10.2" access_config {} } allow_stopping_for_update = true } resource "google_compute_instance" "vm_a_2" { // パターン2 name = "vm-a-2" machine_type = var.instance_type service_account { email = google_service_account.service_account_for_vm.email scopes = [ "cloud-platform" ] } boot_disk { initialize_params { image = var.instance_os } } network_interface { network = google_compute_network.vpc.name subnetwork = google_compute_subnetwork.subnet_a.name network_ip = "10.0.10.3" } allow_stopping_for_update = true } resource "google_compute_instance" "vm_b_1" { // パターン3 name = "vm-b-1" machine_type = var.instance_type service_account { email = google_service_account.service_account_for_vm.email scopes = [ "cloud-platform" ] } boot_disk { initialize_params { image = var.instance_os } } network_interface { network = google_compute_network.vpc.name subnetwork = google_compute_subnetwork.subnet_b.name network_ip = "10.0.20.2" access_config {} } allow_stopping_for_update = true } resource "google_compute_instance" "vm_b_2" { // パターン4 name = "vm-b-2" machine_type = var.instance_type service_account { email = google_service_account.service_account_for_vm.email scopes = [ "cloud-platform" ] } boot_disk { initialize_params { image = var.instance_os } } network_interface { network = google_compute_network.vpc.name subnetwork = google_compute_subnetwork.subnet_b.name network_ip = "10.0.20.3" } allow_stopping_for_update = true } 参考: TerraformをGoogle Cloudで使ってみた リソースの確認 terraform apply によって作成されたリソースを一部確認します。 リソース(VPC) リソース(GCE) 結果 結果は以下の通りです。Private Google Access が On の場合は、外部 IP アドレスの有無に関わらずライセンス認証が可能です。対して、Private Google Access が Off の場合は、外部 IP アドレスがないとライセンス認証はできません。 パターン名 詳細 ライセンス認証の結果 パターン1 Private Google Access:On 外部 IP:有 可 パターン2 Private Google Access:On 外部 IP:無 可 パターン3 Private Google Access:Off 外部 IP:有 可 パターン4 Private Google Access:Off 外部 IP:無 不可 通信経路としては以下のようになっています。 通信経路図 これ以降はパターンごとに実際の画面と、Windows Server VM から KMS サーバー(35.190.247.13)への通信を Google Cloud の 接続テスト で結果を確認していきます。各 VM へは Identity-Aware Proxy の TCP 転送 を利用して RDP します。 参考: 接続テストを作成して実行する / RDP 接続のトンネリング パターン1 問題なくライセンス認証されています。 結果①(パターン1) 接続テストも問題ありません。 結果②(パターン1) パターン2 問題なくライセンス認証されています。 結果①(パターン2) 接続テストも問題ありません。 結果②(パターン2) パターン3 問題なくライセンス認証されています。 結果①(パターン3) 接続テストも問題ありません。 結果②(パターン3) パターン4 Not activated となっており、ライセンス認証ができていません。 結果①(パターン4) 接続テストの結果、以下のようなエラーが出ています。 パケットはドロップされている可能性があります 内部 IP アドレスのみを持つインスタンスが Google API とサービスにアクセスしようとしています。限定公開の Google アクセスが有効になっていません。 結果②(パターン4) おわりに 以上で、外部 IP アドレスを持っていない Windows Server VM の場合でも、Private Google Access を On にすることでライセンス認証ができることが確認できました。 G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
当記事は みずほリサーチ&テクノロジーズ × G-gen エンジニアコラボレーション企画 で執筆されたものです。 G-gen の片岩です。Google Cloud の Cloud Spanner について徹底解説します。Cloud Spanner は強整合性を持ちながらグローバルな負荷分散が可能なサービスです。高い可用性、データの完全性が求められる金融分野での活用が見込まれるデータベースです。 Cloud Spanner の概要 Cloud Spanner とは 強整合性と結果整合性 水平スケーリング インターフェイス SQL API クライアント ユースケース Cloud Spanner が適したケース 代表的な事例 類似サービスの使い分け Cloud SQL AlloyDB Cloud Spanner 料金 インスタンスと構成 インスタンス リージョン構成、マルチリージョン構成 コンピューティング容量 読み取り方式 バックアップ バックアップと復元 インポート/エクスポート ポイントインタイムリカバリ 運用 データ処理の仕組み シャーディング インターリーブ 強整合性とスケーラビリティの両立 3 種類のレプリカ 書き込み(commit)の仕組み 読み取りの仕組み 強力な読み取り (最新データを読み取る必要がある場合) ステイル読み取り リージョン構成 / マルチリージョン構成それぞれにおけるレプリカの内訳 データブースト Cloud Spanner の概要 Cloud Spanner とは Cloud Spanner は 強整合性 を保証する RDB(リレーショナルデータベース)の特徴と グローバルに水平スケーリング できる NoSQL データベースの特徴を併せ持つデータベースです。そしてダウンタイムが最小限であり運用負荷の少ない フルマネージド のデータベースでもあります。 Cloud Spanner は強整合性 (RDB の強み) と、スケーラビリティ (NoSQL の強み) のいいとこどりのアーキテクチャを兼ね備えており、他クラウドにも類似サービスのない、ユニークなデータストアサービスです。 参考 : Cloud Spanner 強整合性と結果整合性 強整合性 とは、読み取り処理で必ず最新の書き込み情報を読み取れる性質です。例えばECサイトでは必ず最新の在庫状況を取得できなければ、在庫がないにもかかわらずお客さまから商品の注文を受け付けてしまいます。勘定、決済などを取り扱う場合にも強整合性が必要なことは想像に難くないと思います。 対照的に、最新情報の読み込みを保証しない性質が 結果整合性 です。NoSQL データベースは、スケーラビリティとパフォーマンスが高い(後述)反面、結果整合性を持ちます。例えば自分の投稿にお気に入りをした人の数など、結果整合性で十分なデータでは NoSQL データベースの特性を十二分に活用できます。 水平スケーリング NoSQL データベースの内部ではデータを分割して保存するため、簡単に水平スケーリングすることができます。 一方、RDB ではデータベースを分割しないため水平スケーリングは難しく、垂直スケーリングしか取れないため、性能上限に抵触しやすいです。 Cloud Spanner は強整合性という RDB の特徴を持ちながら、NoSQL の特徴である水平スケーリングも実現する、ユニークなデータベースサービスです。 インターフェイス SQL Cloud Spanner のデータは SQL で操作することができます。SQL の方言として GoogleSQL と PostgreSQL のいずれかから選択することができます。選択はデータベース作成時に行います。 GoogleSQL と PostgreSQL は完全互換ではありませんが、ほとんど同様に利用できます。開発チームが PostgreSQL に慣れていたり、あるいはクライアントとして psql などの PostgreSQL エコシステムのツールを利用したい場合は PostgreSQL を選択することが望ましいです。 参考 : PostgreSQL Interface 参考 : Dialect parity between GoogleSQL and PostgreSQL API SQL の他にも、各プログラミング言語用のクライアントライブラリを使ったり、Rest API / gRPC を使ったデータの読み書きを行うことができます。 参考 : トランザクションについて 参考 : トランザクション外部の読み取り 参考 : ミューテーションを使用してデータを挿入、更新、削除する クライアント Spanner では以下のようなユーザーインターフェイスを通じて SQL を実行したり、 ミューテーション (API コールによるデータの更新)を実行したりすることができます。 Google Cloud コンソール (Spanner Studio) 各言語用の Spanner クライアントライブラリ (Cloud SDK) REST API RPC API PostgreSQL クライアント (PostgreSQL Interface モードの場合) psql などのコマンドラインで Spanner に接続する場合、 PGAdapter というプロキシソフトウェアを経由して接続します。PGAdapter は JVM の動作するスタンドアロンプロセスあるいは Docker イメージとして提供され、クライアントのローカル環境やサイドカーコンテナとして起動されます。psql 等のクライアントからこの PGAdapter に対して接続すると、PGAdapter は IAM 認証を経て、インターネット経由(gRPC プロトコル)で Spanner インスタンスに接続します。 ユースケース Cloud Spanner が適したケース 以下のいずれかにあてはまる場合に Cloud Spanner が有力な選択肢となります。 強整合性とスケーラビリティがどちらも必要な場合 ダウンタイムを極力減らしたい場合 データベースの運用負荷を軽減したい場合 代表的な事例 Cloud Spanner を利用した、代表的な公開事例をご紹介します (Google Cloud 社の Web サイト)。 みんなの銀行 の勘定系システムで利用されています。東阪両現用を実現するデータストアとして Cloud Spanner を活用しています。 ポケモンGo で利用されています。1 秒あたり 100 万件近いトランザクションを処理することも可能です。 メルペイ で利用されています。信頼性の高い決済処理を数百万のユーザーに 24 時間 365 日 提供しています。 類似サービスの使い分け Google Cloud が提供する RDB のサービスには Cloud Spanner のほかに Cloud SQL と AlloyDB があります。 Cloud SQL Cloud SQL は MySQL、PostgreSQL、SQLServer を扱える RDB です。利用規模が小〜中規模な場合、また非常に大きなスループットを要しない場合は、コスト面で優位な Cloud SQL で十分と言えます。 blog.g-gen.co.jp AlloyDB AlloyDB は 99.99% の可用性(1年間における停止時間の合計が約53分以内)を保証する、パフォーマンスに優れたデータベースで、AWS の Amazon Aurora に相当するサービスです。 PostgreSQL 完全互換のため利用可能なライブラリが充実しています。利用規模が中〜大規模で、高パフォーマンスが要求され、PostgreSQL の豊富なライブラリを利用したい場合は AlloyDB が望ましいと言えます。 blog.g-gen.co.jp Cloud Spanner Cloud Spanner ではマルチリージョン構成の場合に 99.999 % の可用性(1年間における停止時間の合計が約5分以内)を保証します。 スケーラビリティにも優れているため、グローバルにサービスを展開したい場合や、サービスをほぼ無停止で展開したい場合に Cloud Spanner の利用を検討します。 料金 Cloud Spanner は割り当てたコンピューティング容量と使用しているストレージ量に対して課金されます。 例として 100 処理ユニット、ストレージ使用量を 100GB で 1 ヶ月間フル稼働すると、約 16,795 円 / 月です(2023年2月時点、東京リージョン、135円/ドル)。 同一のコンピューティング容量であっても、シングルリージョンとマルチリージョン、さらにアメリカとアジアとヨーロッパをまたいだマルチリージョンで単価が異なります。 最新の利用料金は以下の公式ページでご確認ください。また、公式の見積もりツールで料金が試算できます。 参考 : Cloud Spanner の料金 参考 : Google Cloud Pricing Calculator また、Cloud Spanner には 確約利用割引 の仕組みがあります。1 年間または 3 年間の利用を確約することで最大 40% の割引を受けることができます。詳細は以下のドキュメントをご参照ください。 参考 : Spanner CUD の料金 インスタンスと構成 インスタンス Cloud Spanner は インスタンス の単位で管理します。 Cloud Spanner におけるインスタンスは、データベースの基盤となる仮想サーバー群のことです。インスタンスごとに構成(リージョン構成またはマルチリージョン構成)とコンピューティング容量を選択します。 リージョン構成、マルチリージョン構成 リージョン構成 では、指定したリージョン内の複数のゾーンにクラスタが展開されます。マルチリージョン構成に比べて、コストパフォーマンスに優れています。 マルチリージョン構成 では、指定した複数のリージョンにまたがってクラスタが構成されます。リージョン構成に比べて、可用性や、複数の国や地域からアクセスされる際のレイテンシに優れています。 リージョン障害への対応が必要な場合や、東阪両現用のように複数のリージョンにまたがって高いパフォーマンスが要求される場合はマルチリージョン構成を選択します。 また、SLA にも違いがあります。リージョン構成では99.99%、マルチリージョン構成では99.999%の可用性 SLA が設定されています。 参考 : Cloud Spanner Service Level Agreement (SLA) 各構成においては、選択する地域によって、どのリージョンにレプリカ(サーバー)が配置されるかが決まります。詳細は後述の「リージョン構成 / マルチリージョン構成それぞれにおけるレプリカの内訳」の項をご参照ください。 なおインスタンス構成は、運用開始後でもダウンタイム無く変更できるため、最初はリージョン構成から開始し、利用規模が大きくなってからマルチリージョン構成に変更することも可能です。 参考 : インスタンスを移動する コンピューティング容量 インスタンスのコンピューティング容量は、 処理ユニット (処理単位、processing units)の割り当てで決定します。処理ユニットの値によって、データのスループットや秒間クエリ数、ストレージの上限が決まります。 また、テーブル数の上限も処理ユニットによって決定されます。10ユニット毎に1テーブルの上限があります。 処理ユニットの下限値は 100 で、100 処理ユニット単位でコンピューティング容量を指定できます。また 1,000 処理ユニットを 1 ノードと呼び、1,000 処理ユニット以上を指定したい場合はノード単位でコンピューティング容量を指定することになります。 参考 : コンピューティング容量、ノード、処理単位 読み取り方式 Cloud Spanner では 強力な読み取り と ステイル読み取り 、そして トランザクション という3種類の読み取り方法があります。 デフォルトの読み取り方式は強力な読み取りです。強力な読み取りでは強整合性を持った読み取りが可能な反面、読み取りの都度最新のデータであるかチェックするため、内部通信が発生しレイテンシが大きくなります。 必ずしも強整合成が必要のない読み取りの場合はステイル読み取りを使用します。stale は新鮮ではない、というニュアンスの言葉です。 ステイル読み取りではレプリカ自身が持つ最新のデータであるかのチェックをスキップするため、より高速な読み取りが可能となります。 参考 : トランザクション外部の読み取り 最後に、トランザクションは、ロックに依存する書き込みと読み込みを同時に行う場合や、複数の読み取りで一貫性を持たせたい場合に用います。以下のドキュメントを参照してください。 参考 : トランザクションの概要 バックアップ Cloud Spanner のバックアップでは、 バックアップと復元 機能、もしくは インポート/エクスポート 機能が使用できます。 バックアップと復元 バックアップと復元(back up and restore)機能では、インスタンスと同じ地理的ロケーションにバックアップを保管することができます。 また、バックアップはトランザクションの処理には直接関係しないため、インスタンスのパフォーマンスには影響しません。 バックアップ機能は手軽に利用できる反面、以下のような制約があります。 バックアップの保存期間は最長 1 年間 インスタンス内のリソースになるため、同じ構成のインスタンスを作成する場合を除いてデータの持ち出し不可 基本的にはバックアップと復元 機能の利用を検討し、上記の制約が許容できない場合はインポート/エクスポートを使用します。 参考 : バックアップの概要 インポート/エクスポート インポート/エクスポートでは、Cloud Storage の CSV ファイルや Avro ファイルの読み取り/書き込みが可能です。 バックアップはファイルとして出力されるので上記の形式に対応した外部のデータベースにデータを持ち出したり、ファイル自身のライフサイクルを管理して1年以上保管することができます。 「バックアップと復元」機能と「インポートとエクスポート」機能の比較については、以下のドキュメントもご参照ください。 参考 : Spanner のインポートとエクスポートの概要 ポイントインタイムリカバリ マスタデータを誤って削除した場合など、一部データのみ復元したい場合には、 ポイントインタイム リカバリ (PITR)を利用できます。 最長7日間の任意の時刻のスキーマとデータを復元することができます。 参考 : ポイントインタイム リカバリ(PITR)の概要 運用 従来のデータベースであれば、データ量が膨大になり 1 つのデータベースに収まりきらなくなると、以下のように複数のデータベースにデータを分割するといった作業が発生しました。 ユーザー ID が a 〜 m から始まる場合はデータベース 1 を利用 ユーザー ID が n 〜 z から始まる場合はデータベース 2 を利用 Cloud Spanner では全自動でデータの分割処理が実施されるため、上記のような作業は発生しません。必要に応じて以下の作業を行うだけとなります。 CPU 使用率をモニタリングする ノードの追加や削除を実施する バックアップ / リストアを実施する このように運用負荷が少ないことも Cloud Spanner の強みです。 データ処理の仕組み ここからは Cloud Spanner の内部的な仕組みをご紹介します。まずは大量のデータを高速に処理する仕組みです。 シャーディング Cloud Spanner では PK のレンジに沿ってデータがいくつかに分割 (シャーディング) されてストレージに保存されます。この分割されたデータをスプリットと呼びます。 各ノードは、それぞれ割り当てられたスプリットの読み込み処理や書き込み処理を担当します。ノードを増やすと 1 ノードあたりのデータ量が減り、それだけ負荷分散できることになります。 3 ノード構成の場合の内部構成 各データが均等にアクセスされる場合は、各スプリットのサイズも概ね均等になります。 各データへのアクセス頻度が均等な場合のスプリット 各データが均等にアクセスされない場合、たとえば上記の図で y や z から始まるデータのアクセス量が多い場合は、各ノードの負荷が均等になるように、以下のように自動的にリシャーディングされます。 y や z から始まるデータのアクセス量が多い場合のスプリット 一時的なリシャーディングは問題ありませんが、継続的なリシャーディングが発生するとデータベースに無駄な負荷がかかってしまいます。たとえば上記の図で z から開始するデータだけが増え続けてしまうと、ノード 3 のみに負荷が集中することになり、継続的なリシャーディングが発生してしまいます。 特定のノードに負荷が集中して継続的なリシャーディングが発生しないよう、データベースのスキーマ設計時はご留意ください。 インターリーブ 詳細は後述しますが、単一リージョン構成の場合はデータが 3 つのゾーンに 3 重に冗長化されています。以下は 2 つのテーブル①とテーブル②が 3 つのゾーンで冗長化されるイメージです。 テーブル①とテーブル②が 3 つのゾーンで冗長化される それら 3 のゾーンのうち読み書きを実行するリーダーがスプリットごとに選ばれます。特段の指定をしない場合は、テーブル①とテーブル②はそれぞれ独立してスプリットに分割されます。 スプリットごとにリーダーが選ばれる たとえば上の図の PK が b からはじまるデータに対してテーブル①とテーブル②に更新処理を実行すると、更新処理はリーダーを通して実行されるため、テーブル①ではゾーン a で処理し、テーブル②ではゾーン b で処理するといった事象が発生します。 このようにJOIN したいテーブルのノードが異なると、ノード間の通信が必要になり、オーバーヘッドが発生してしまいます。 このオーバーヘッドを回避するために、関連するテーブルのデータを物理的に連続した同じ位置に配置することができる仕組みをインターリーブと呼びます。インターリーブを使用することにより、JOIN 時に異なるノード間の通信が発生することを抑えることができます。 インターリーブにより PK の先頭列が同じデータを同じスプリットに含められる 強整合性とスケーラビリティの両立 次にグローバルに強整合性を担保できるユニークな仕組みを見ていきましょう。 3 種類のレプリカ Cloud Spanner のインスタンスは、読み書きレプリカ、読み取り専用レプリカ、ウィットネス レプリカの 3 種類のレプリカから構成されます。 読み書きレプリカ は読み書きすることができます。唯一書き込みが処理できます。 読み取り専用レプリカ も読んで字のごとく読み取りのみすることができます。 ウィットネス レプリカ は読み取りしないで、書き込みの commit を決める投票(後述)のみ参加するレプリカです。 読み書きレプリカは複数存在し、そのうちの 1 つが リーダーレプリカ となります。 詳細は後述しますが、リーダーレプリカは書き込み処理において中心的な役割を果たします。 レプリカの種類 リーダー可否 書き込み 読み込み 投票 読み書き ◯ ◯ ◯ ◯ 読み取り専用 x x ◯ x ウィットネス x x x ◯ 書き込み(commit)の仕組み Cloud Spannerは commit の仕組みに特徴があります。 すべての書き込みリクエストがリーダーレプリカに送信されます。 リーダーレプリカは書き込みリクエストがあったことをログに記録します。 リーダーレプリカは読み書きレプリカとウィットネスレプリカに書き込みリクエストを転送します。 書き込みリクエストを受け取ったレプリカは書き込みを実行後、リーダーレプリカに投票を返却します。 投票が過半数のレプリカから返却されるとリーダーレプリカはcommit 完了とみなします。 リーダーレプリカがcommitを完了とみなした後も、書き込みリクエストを受け取ったレプリカは書き込みを継続し完了します。 画像は 公式ブログ から引用 分散データベースで利用される 2 フェーズコミットでは投票可能なレプリカの すべて が書き込みの commit に同意した時点で、書き込みが commit されます。 対して Cloud Spanner では投票可能なレプリカの 過半数 が書き込みの commit に同意した時点で、書き込みが commit される点が特徴です。 なお、リーダーレプリカは 10 秒間隔で読み取り専用レプリカを更新します。ステイル読み取りでは何秒前のデータを読み取るかが指定できますが、15 秒とすることが推奨されています。これは前述の 10 秒間隔の更新を想定したものです。 参考 : Cloud Spanner のマルチリージョン構成について理解する 読み取りの仕組み 強力な読み取り (最新データを読み取る必要がある場合) レプリカは自身が持つデータが最新であるか判断するために、以下の処理を行います。 レプリカは読み取りリクエストを受信します。 レプリカはリーダーに読み取りリクエストを送信します。 リーダーは、対象行の最新トランザクションのタイムスタンプを応答します。 レプリカは自身が持つデータが最新であるか判断します。 行が最新の場合、レプリカは結果を返すことができます。 最新でない場合は、リーダーからの更新情報を受け取ってから応答します。 画像は 公式ブログ から引用 なお、読み書きトランザクションに含まれる読み取りはこの流れではありません。書き込みが必要なトランザクションでは直接リーダーレプリカがトランザクションを処理するためです。 ステイル読み取り 前述のステイル読み取りではリーダーレプリカに最新のデータかどうか問い合わせる処理をスキップすることで、強整合性を犠牲にレイテンシーを低減することができます。 たとえば 最新時刻から見て 15 秒前のデータで問題なければ、15 秒前のデータをリクエストします。レプリカはリーダーに最新情報を問い合わせる必要なく低レイテンシでデータを返すことができます。 画像は 公式ブログ から引用 リージョン構成 / マルチリージョン構成それぞれにおけるレプリカの内訳 リージョン構成の場合は以下の構成になります。 1 つのリージョンの 3 つの異なるゾーンそれぞれに読み書きレプリカ マルチリージョン構成、たとえば asia1(東京 / 大阪 / ソウル)の場合は以下の構成になります。 東京に 2 個の 読み書きレプリカ 大阪に 2 個の 読み書きレプリカ ソウルに 1 個のウィットネスレプリカ 大陸間をまたぐマルチリージョン構成、たとえば nam-eur-asia1(北アメリカ / ヨーロッパ / アジア)の場合は以下の構成になります。 アイオワに 2 個の 読み書きレプリカ オクラホマに 2 個の 読み書きレプリカ ベルギーに 2 個の読み取り専用レプリカ 台湾に 2 個の読み取り専用レプリカ サウスカロライナに 1 個のウィットネスレプリカ データブースト Cloud Spanner の データブースト (Data Boost)機能は、読み取り専用のコンピュートリソースを既存クラスタとは別で割り当てることで、分析用途などの読み取りワークロードを分離することができる仕組みです。 この機能を用いることで、通常のアプリケーションが使っている Spanner のリソースに影響を与えることなく、分析用のクエリを発行することなどが可能です。この機能を有効化すると、必要に応じて読み取り専用のコンピュートリソースが臨時で割り当てられ、Spanner のストレージにアクセスできます。 利用例として「BigQuery から Cloud Spanner への連携クエリ(Federated query)のために利用する」「レポート作成やデータエクスポートのための定期ジョブに利用する」などが挙げられます。 当機能を利用すると、一時的に割り当てられた処理ユニットに対して料金が発生することにご注意ください。 参考 : データブーストの概要 片岩 裕貴 (記事一覧) クラウドソリューション部 クラウドディベロッパー課 2022年5月にG-genにジョインした和歌山県在住のエンジニア。興味分野はAI/ML。2024年にGoogle Cloud認定資格全冠達成。最近は子供と鈴鹿サーキットや名古屋のレゴランドに行ってきました。
クラウドサービスの普及に伴い、オンプレミスからクラウドへの移行を検討する企業が増加しています。しかし、いざクラウド移行を進めるとなると考慮する点も多いものです。クラウド移行にはメリット・デメリットがあり、すべての企業にとって最善の選択肢とは限りません。この記事では、クラウド移行のメリット・デメリットを解説します。具体的な移行手順も紹介しているので、ぜひ参考にしてください。 クラウドとオンプレミス クラウドとは オンプレミスとは クラウドとオンプレミスの違い クラウド移行のメリット スモールスタートできる スピーディに導入できる 導入コストを抑えられる 運用負荷を軽減できる エンジニア採用に有利に働く クラウド移行のデメリット 既存システムとの互換性 レイテンシ スキルセットの違い クラウド移行の判断ポイント クラウドがおすすめな企業の特徴 オンプレミスがおすすめな企業の特徴 クラウド移行の具体的な手順 (1) 既存資産の可視化 (2) 移行計画の作成 (3) 設計・構築・移行 (移行後) 運用・保守 クラウド移行の失敗事例 クラウド移行で重視すべきポイント 運用体制 クラウド利用料を考慮する ネットワーク要件 まとめ クラウドとオンプレミス クラウドとは クラウドとは、クラウド事業者が提供する環境やサービスを、ネットワーク経由で利用するシステム利用形態のことです。 自社でサーバを用意する必要がない点が特徴で、IT分野で急速に普及しつつあります。たとえば、現在主流のメールサービスの多くは、メールサーバを社内に構築する必要がありません。サービスの Web サイトからアカウントを発行するだけで、メールを利用できます。これもクラウドサービスの1つです。 大別すると IaaS、PaaS、SaaS の3種類に分けることが可能です。当記事では特に、企業のITインフラのクラウド化に用いられる IaaS (Infrastructure as a Service) に着目してご紹介します。 オンプレミスとは オンプレミスとは、自社で物理的なサーバを保有するシステム利用形態のことです。 自社でサーバやネットワーク、ソフトウェアを構築し、管理・運用も社内で行います。クラウドサービスが普及する前は、こうした自社運用システムが一般的でした。 クラウドとオンプレミスの違い クラウドとオンプレミスの特徴をまとめると、以下の通りです。 クラウド オンプレミス コスト ・初期費用がかからない ・従量課金制が主流で、必要なときに、必要な分のコストを支払えばよい ・サーバ機器などの初期費用がかかる ・拡張が必要となる度、新たなコストが発生する 導入スピード ・スピーディに利用できる ・サーバ機器などの選定から、導入まで1か月程度かかる セキュリティ ・高い ・自社で構築する必要あり カスタマイズ性 ・サービスによる ・高い 障害対応 ・クラウド事業者が対応するため、業務負担が軽減される ・自社が復旧作業にあたる バックアップ ・サービスによるが、機能として用意されていることが多い ・自社で構築する必要あり クラウド移行のメリット ここからは、クラウド移行のメリットについて詳しく解説します。なお、ここでいうクラウド移行とは、自社のサーバ資産を IaaS へ移行することを指します。 スモールスタートできる クラウドサービスはオンプレミスと比べて拡張性が高く、ストレージやCPU、メモリなどのリソースを柔軟に増やすことができます。自社の利用状況に応じた、迅速な性能拡張が可能です。 新規事業など、成否や成長速度の予測をしづらいビジネスの IT 基盤にはクラウドが最適です。クラウドにより基盤をスモールスタートさせ、ビジネスの成長と共に拡大していけばよいのです。 スピーディに導入できる 自社でイチからサーバを構築する場合や、システムを開発する場合と比べて、導入までのスピード感が速い点もメリットです。利用登録後すぐにサーバを構築できるため、スピーディな導入を実現できるでしょう。 またシステムの利用ボリュームや頻度の変化に応じて、柔軟にサーバ台数やスペックの変更がスピーディに可能なため、コストが最適化されます。 導入コストを抑えられる 自社でサーバを保有する必要がないため、サーバ機器の購入・設置にかかる初期設備投資が不要です。 また、多くのクラウドサービスは利用量に応じて料金が発生する従量課金制を採用しています。必要なときに、必要な分だけの費用を支払えばよいため、コストの無駄がありません。 運用負荷を軽減できる サーバの運用・管理はクラウド事業者が行うため、自社の人員が最低限で済みます。メンテナンスや障害対応もクラウド事業者に任せられるので、運用負荷を軽減できます。 エンジニア採用に有利に働く 募集要項に「クラウドを利用している=社内でクラウドを扱える」ことを記載しておくと、技術的に好奇心旺盛なエンジニアが募集してくる可能性が高まります。その結果、優秀なエンジニアを確保しやすくなり、自社のIT活用力を強化できるでしょう。 クラウド移行のデメリット クラウド移行にはさまざまなメリットがある一方、いくつかのデメリットも存在します。 既存システムとの互換性 既存システム (パッケージ) によっては、パブリッククラウドサービスをサポートしておらず、クラウド上に移行すると製品サポートが受けられなかったり、他の既存システムとの連携や移行がうまくいかない場合もあります。 引き続き同じパッケージやソフトウェアを利用する場合には、互換性をしっかり確認しておくことが大切です。 レイテンシ クラウドサービスはネットワーク経由でクラウド事業者のコンピュートリソースを利用することが最大の特徴です。地理的に・ネットワーク的に離れている場所にあるリソースを利用するので、ミリセカンドのレベルのパフォーマンス要件が求められるシステムでは、レイテンシが問題になることがあります。 とはいえこれが問題になるのはレスポンスが重要となるような IoT、制御系システムやアクションゲームのサーバなどであり、通常の社内システムや Web サービスではこのようなレイテンシが問題となることは稀です。 スキルセットの違い クラウドサービスは日進月歩であり、管理・運用を行うエンジニアにも日々、スキルのアップデートが求められます。 クラウドでは物理レイヤの保守・運用が一切不要になる代わりに、より上位レイヤ (アプリケーションやデータに近いレイヤ) の知見が求められます。これまでの社内のインフラエンジニアやアプリケーションエンジニアには、新しいスキルセットが求められることになりますので、それが戸惑いを呼んだり、新しいエンジニア育成や採用の戦略が必要になるかもしれません。 クラウド移行の判断ポイント クラウドがおすすめな企業、オンプレミスがおすすめな企業の特徴をそれぞれ記載します。オンプレミスを続行するのか、クラウド移行するのか、自社にとって最善の選択肢を選ぶための判断材料として活用してください。 クラウドがおすすめな企業の特徴 課題 メリット 運用・保守に人員を割く余裕がない ・サーバの運用・管理はクラウド事業者に任せられる ・業務負担の軽減や、人件費の削減につながる 内製でデジタル化、DX化を進めたい ・アジリティが高く、スモールスタートがしやすい ・新たなビジネスを素早く、小さくはじめて試すということができる スタートアップ企業・新規事業 同上 オンプレミスがおすすめな企業の特徴 課題 メリット ミリセカンドレベルのレイテンシが問題である ・制御系 ・ゲームサーバ ・その他レスポンス要件がシビアなシステム 互換性に問題がある ・既存システムをそのまま移行したいがパッケージシステム等がクラウドに対応していない クラウド移行の具体的な手順 ここからは、クラウド移行の具体的な手順を説明します。ここでは特に自社のサーバ資産を AWS、Azure、Google Cloud 等の IaaS に移行する場合の、計画から運用開始までをイメージして解説します。 (1) 既存資産の可視化 自社サーバ資産がインベントリ化されていない場合、これを機にリストアップします。全物理サーバのスペック、用途、OSとそのバージョン、含まれている仮想サーバ台数、インストール済みソフトウェアやそのバージョンを精査します。 またそれらサーバの監視の有無、方法なども整理します。 (2) 移行計画の作成 既存資産の可視化に基づいて、クラウド (IaaS) への移行計画を策定します。 まずは、移行対象サーバの分類を行います。サーバを「そのまま IaaS へ移行する」「PaaS や SaaS に置き換える」「廃棄する」などの選択肢があります。必ずしも全てのサーバを移行する必要はなく、これを機に不要なサーバ資産の棚卸しを行うことが重要です。 また、サーバ移行の優先順位を付け、それに基づいたスケジュール策定も行います。 移行に当たってクラウドパートナー (インテグレーター) の支援を仰ぐ場合は、各ベンダへの見積もり依頼や役割分担の確認、自社体制の確立を行います。 (3) 設計・構築・移行 クラウド環境の仮想ネットワーク、仮想サーバ、セキュリティ設定に関する設計と構築を行います。 適切な設計を行うことで、クラウドサービスをセキュアに、かつコスト効率良く利用できます。クラウドサービスでは物理的な構築に一切時間がかからず、サーバをボタン一つで起動できるという利便性がありますが、インフラ設計はオンプレミスと変わらず重要です。 構築が完了して移行の準備ができたら、データ移行を行います。データ移行の方法は複雑で多岐にわたり、適切な計画が必要です。 以下は、データ移行とカットオーバー (リリース) の計画の一例です。 既存システムの利用を停止 (データベースへの書込が停止) データベースからダンプを出力 ダンプファイルをクラウド上の新データベースに転送 クラウド上の新データベースでデータを取込 新アプリケーション・新データベースの動作確認 ユーザ側の向き先をクラウド上の新アプリケーションに変更 (DNS 変更等) 新アプリケーションの打鍵確認 上記のようにファイルを用いた伝統的な移行方法とは別に、各クラウドベンダが提供するオンライン移行ツールを用いて、最小限のダウンタイムでデータを移行することも検討できます。 (移行後) 運用・保守 移行手順ではありませんが、必ずついて回るものとして、運用・保守のフェイズも意識することが必要です。IaaS では物理機器の運用・保守は不要ですが、OS、ミドルウェア、アプリケーションの運用・保守は引き続き必要になります。 運用コストを最適化するために、IaaS だけでなく、PaaS や SaaS との適切な組み合わせが望ましいと言えます。 クラウドベンダーのパートナーによっては、クラウド環境の運用・保守をサービスとして提供している場合があります。 クラウド移行の失敗事例 クラウド移行には失敗事例もつきものです。失敗してもすぐリカバーできるのがクラウドの魅力でもありますが、いくつか先例をご紹介します。 例 事象 利用料金が想定よりも大きくなった ・利用サービスの適切な選定や、設定値の適切な設計が無かったため、運用をしていく中で想定よりも速いペースで利用料金が増大した(例: ストレージ料金) 運用コストが想定よりも大きくなった ・運用メンバーのスキルアップが思うように進まず、クラウド環境の運用に想定より大きな工数が発生 ・セキュリティリスクとその対処が適切にできず (判断できず) オンプレミスの運用をクラウドでもそのまま続けていることで工数が削減できない ライセンスやサポート料金の発生 ・クラウドサービスの利用にあたり、必要なライセンスやサポートを見落としてしまうケース クラウド移行で重視すべきポイント 最後に、クラウド移行で重視すべきポイントをまとめます。 運用体制 前述の通り、IaaS では物理機器の運用・保守は不要ですが、OS、ミドルウェア、アプリケーションの運用・保守は引き続き必要です。 高い優先度で運用体制を検討する必要があります。クラウドの最も大きい特徴である「アジリティ (敏捷性)」を活かすために、自社での運用内製化を検討することが重視されます。 クラウド利用料を考慮する 利用しようとしているクラウドサービスを正しく理解し、実際にかかるクラウド利用料を計算します。 クラウドへの移行は、金銭的なコストだけを考慮するとオンプレミスよりも高価になる場合も多いです。前述の運用コストと合わせて、総合的に判断する必要があります。運用にかかる人的コストも含めた総合的なコストを指して Total Cost of Ownership (TCO) という語を用いることもあります。 ネットワーク要件 社内システムをクラウド (IaaS) に配置する場合、インターネット経由でのアクセスとするか、あるいは Internet VPN / 専用線の確保をするか、選択することになります。 接続方法と想定される通信量に合わせて、十分なインターネット回線や専用線の帯域を確保する必要もあります。 まとめ クラウド移行やオンプレミス続行か、自社にとって最適な選択を見定めるためには、クラウドサービスのメリット・デメリットや考慮点をしっかりと把握することが大切です。 自社の利益につながるようなシステムの構築を目指しましょう。 クラウド移行を検討中なら、ぜひG-genにご相談ください。お客様のGoogle Cloud環境に対する運用代行・伴走支援を行い、豊富な実績にもとづく技術サポートを安価な利用環境とセットでご提供します。 お問い合わせはこちら G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、2021年よりクラウドの導入から最適化までを支援しているGoogle Cloud専業のクラウドインテグレーターです。
当記事は みずほリサーチ&テクノロジーズ × G-gen エンジニアコラボレーション企画 で執筆されたものです。 みずほリサーチ&テクノロジーズ株式会社の浅香です。 G-gen さんとのコラボ企画のもと、弊社エンジニアによる Google Cloud の記事を執筆する機会を頂戴しました。 他の方々が先行して Google Cloud に関する各種記事を投稿していますので、本記事では少し趣向を変えてみて Google Cloud と関わりが深い Terraform について、その中でも特に Terraform Cloud Business をご紹介させていただきます。 当ブログは G-gen × みずほRT によるコラボ記事です Terraformについて Terraform とは Terraform の特徴 Terraform の種類 Terraform Cloud Business とは Terraform OSS の利用イメージ Terraform OSS を利用している場合の課題 Terraform Cloud Business の利用イメージと課題への対応 人的なRV依頼 / 実施 への解決アプローチ コード / シークレットの管理(バージョン管理や自動化) への解決アプローチ 操作ログや監査、変更の通知など への解決アプローチ CLI による操作/管理 への解決アプローチ ステートファイルの管理 への解決アプローチ Terraform外の変更管理 への解決アプローチ Terraform Cloud Business と プロビジョニング先の通信 まとめ Terraformについて Terraform とは Terraform とは、 IaC ( Infrastructure as Code ) ツールの一種です。 HashiCorp 社によって開発され、オープンソースソフトウェアとして開発され続けています。 Terraform の特徴 Terraform は、各種パブリッククラウド / SaaS 製品に対応しています。 どのプラットフォームであっても統一された構文で IaC 化を実現することが可能で、各プラットフォームごとの IaC ツール / サービスを使うための学習コストを削減することができます。 ご参考までに、メジャーなパブリッククラウドでは、それぞれの IaC ツール / サービスが提供されていますが、このいずれのパブリッククラウドも Terraform は対応しています。 プラットフォーム IaC ツール / サービス AWS AWS CloudFormation 、 AWS Cloud Development Kit (AWS CDK) など Microsoft Azure Azure Resource Manager (ARM) など Google Cloud Cloud Development Manager Terraform の種類 Terraform は大きく分けて 3 種類あります。 Terraform OSS 名前の通り、 OSS として提供されている形態です。 Terraform Enterprise 商用版の Terraform で、自ホストにインストールして利用する形態です。 Terraform Cloud 名前から想像できるかもしれませんが、 Cloud として提供されている形態です。 HashiCorp 社 が運用する Terraform のマネージドサービスです。 Terraform Cloud Business とは 上述した Terraform Cloud の中にもいくつかのプランがあります。 プランごとに料金はもちろん、利用できる機能やサポートが異なります。(詳細は リンク先 をご参照ださい。) Terraform Cloud Business はその中の 1 つのプランです。 後述していますが、様々な機能が利用可能となっています。 本記事では、この Terraform Cloud Business について、Terraform OSS との比較を交えてご紹介していきます。 Terraform OSS の利用イメージ まずは Terraform OSS をそのまま利用した場合の利用イメージを共有したいと思います。 Terrafrom OSS の利用フロー 担当者Aさんが、Terraform のコードを書いて、必要な変数やシークレットを用意して、Plan を実行し確認して… 次に承認を得るために、コードと Plan 結果を添えて、管理者に承認依頼をして… 管理者さんは、メールをもとに内容を確認しますが、機械的ではなく人間の目によるチェックを実施し… 問題があれば差戻をし、問題なければ添付ファイルもとに Apply を CLI で実行し… 比較のためにもあえて、シンプルな利用イメージとしてますが、IaC としてコード化しているにも関わらず、実行に至るまでのプロセスは手動となっており、その分ヒューマンエラーの可能性も大きくなってしまいます。 また、今回は登場人物は 2 人だけ、かつ、やりとりするコードも少数のイメージになっていますが、実際はこれが複数かつ並列に走っていくことになり、より複雑になっていきます。 Terraform OSS を利用している場合の課題 Terraform OSS を利用している場合の課題 上述のフローをもとにした際に生じる課題を挙げてみます。 人的なRV依頼 / 実施 メールを介したレビュー依頼や、人の目によるチェックなどは、どうしてもヒューマンエラーが生じてしまいます。 コード / シークレットの管理(バージョン管理や自動化) バージョン管理をしないと事故のもとになります。ただ一方で、シークレットは平文管理は望ましくないです。 操作ログや監査、変更の通知など 有事に備える意味でも、いつ、誰が、何をしたのかは把握が必要です。 CLI による操作/管理 CLI でも操作は可能ですが、視覚的には見づらくなってしまいます。GUI で直観的に情報に辿りつける方が優しいです。 ステートファイルの管理 Terraform を使う以上、ステートファイル ( tfstate ) の管理は必須です。不用意に変更できないように管理する必要があります。 Terraform外の変更管理 急ぎの対応などは、リソースを直接修正してしまいがちですが、そうすると Terraform との差分が出てきてしまいます。 忘れることなくて追い付きの Terraform 修正を抜け漏れなく対応できればいいですが… Terraform Cloud Business の利用イメージと課題への対応 上述の課題を踏まえて、Terraform Cloud Business を利用した場合に置き換えてみます。 文章での説明の前に、課題の解決案を示したイメージを先に載せてみます。 Terrafrom Cloud の利用フロー 構成については、先程の OSS 利用時はコンピューターにしていた箇所を VCS ( Version Control System ) に置き換えていますが、OSS で生じていた課題に対して、それぞれ解決策となるTerraform Cloud Businessの機能を示しています。 Terraform Cloud Businessの機能の紹介を兼ねて、先程の課題への解決アプローチを説明していきます。 人的なRV依頼 / 実施 への解決アプローチ 画像は Run Tasks Integration より引用 Plan と Apply の間に、レビューにあたる各種設定を組み込むことが可能になります。 画像の中にも載っていますが、具体的には Cost Estimation 、 Sentinel Policy ( Policy as Code ) 、 Run Tasks を設定することができ、それぞれで各種レビューの役割を果たすことができます。 Cost Estimation 主にIaaSを中心に、Applyを実行して作成されるリソースの月額コストの予想見積を出すことが可能になります。 数が多い、サイズが大きいリソースの作成を意図せず組み込んでしまった際に、実行前に検知することができます。 Sentinel Policy ( Policy as Code ) 標準的なセキュリティや社内ルールなどを Policy という形で定義 ( Policy as Code ) することで、それらに準拠しているかを機械的にチェックすることが可能になります。 そのチェック結果に応じて、後続のオペレーションをどうするか(実行中止や警告出力した上で続行など)を設定することもできます。 Policy as Code を実現する手段として、 Hashicorp 社が提供している Sentinel というツールや、Open Policy Agent (OPA) などを適用することができます。 Sentinel であれば、Cost Estimation のあとに実行されるため、コスト次第では実行させないなどの制御も可能です。 Run Tasks サードパーティーツールとの連携に加え、自前のツールによるチェックを組み込むことが可能になります。 上記の機能で補完できない部分を自作して使う方法などが考えられます。 コード / シークレットの管理(バージョン管理や自動化) への解決アプローチ 各種 VCS と連携することで、VCS 側のイベントを契機に Terraform を実行することが可能になります。 Pull Request を契機に Plan の自動実行、merge を契機に Apply を自動実行などができます。 コードの作成 -> Pull Request -> ( Plan ) -> レビュー -> merge -> ( Apply ) を一連で行うことができ、コードの変更履歴やレビュー指摘などを VCS 側に記録できます。後述しますが、Terraform での実行履歴を GUI を介して確認することも可能です。 なお、連携できるVCSは リンク先 をご確認ください。 また、必要なクレデンシャル情報や環境変数などの Variable を Terraform Cloud 内に保存することができ、コードとして管理する必要がなくなります。誤ってクレデンシャル情報を VCS に平文で格納してしまうなどの事故を防止します。 なお、保存された情報は Terraform Cloud 内で暗号化されるため、セキュリティも確保されています。 暗号化対象や暗号化方法は リンク先 をご確認ください。 操作ログや監査、変更の通知など への解決アプローチ 各種APIを用いて、ログや監査証跡を取得することが可能になります。 Audit Trails API を用いると、監査証跡として、いつ・誰が・何をしたかなどの情報を取得することができます。 監査証跡は Splunk と統合することもでき、定期的に Splunk に取り込まれ、可視化できます。 また、Terraform の各種イベントを契機にして、通知を発信することもできます。 Email / Slack / Microsoft Teams などは設定のみで通知可能となっていますし、Webhook にも対応しているため、それら以外の柔軟な対応も可能です。 CLI による操作/管理 への解決アプローチ Web UI が提供されており、各種設定や情報の参照が視覚的にわかりやすくなります。 ワークスペースごとの Plan や Apply などの Terraform の実行履歴なども一覧で見ることができます。 例えば、実行状態の確認をしたい場合を考えると、CLI だとコマンドを確認する必要がありますが、GUI であればクリックしてアクセスするのみになります。 Terraform の CLI に慣れている人であれば、大きな違いはないかもしれませんが、慣れていない人や初学者にとっては、技術的にも心理的にもハードルが大きく下がります。 画像は Change Infrastructure より引用 また、ユーザー認証を SSO を利用して行うことができます。対応している連携先は、MS Azure AD / Okta / SAML があり、既存で利用しているものがあればそれを流用し ID 管理やガバナンスを実現できます。 それに加え、Teams 管理機能を用いて権限管理(認可)を設定できます。ユーザーは Team に所属する必要があり、その Team 単位に実行権限やアクセスできるワークスペースの設定などができ、適切なアクセス管理を実現できます。 ステートファイルの管理 への解決アプローチ 文字通りになりますが、ステートファイル ( tfstate ) の管理をマネージド化し、 Terraform Cloud 上での管理にできます。 これによりローカル環境に保存していた場合の共有管理や排他制御の必要性がなくなります。 (必要性自体は変わっていませんが、その部分の管理を利用者側でする必要がなくなります) ステートファイルには、コードによっては DB の管理パスワードなど機密情報が含まれる場合があり、暗号化やアクセス制御も重要になります。 Terraform Cloud上での管理にすれば、暗号化の実施やアクセス制限、監査証跡から追跡することが可能になり、より厳格な管理が可能になります。 Terraform外の変更管理 への解決アプローチ ドリフト検出機能 ( Drift Detection ) を利用することで、Terraform 外からの変更を監視 / 検出することが可能になります。 利用者側でスケジュール定義はできませんが、24時間ごとに実行され継続的なドリフト検出ができ、ドリフト検出をした際には、上述の通知機能により通知することも可能です。 実際にドリフトを検出をした場合には、そのドリフトへの対応が必要になりますが、以下の 2 つの選択肢があります。 ドリフト検出の変更結果を受け入れる 変更内容(実リソースの内容)を正として、ステートファイルを更新します。 Refresh State にて実行することでステートファイルを、実リソースに合わせることができます。 ただし、実際のコード ( tfファイル ) までは修正されないため、そこは手動で修正する必要があります。 ドリフト検出の変更結果を受け入れない 実際のコード ( tfファイル ) を正とします。 既存のコードを用いて改めてApplyすることで、実リソースが更新され、あるべき姿の状態になります。 Terraform Cloud Business と プロビジョニング先の通信 上述の通り Terraform Cloud Business を用いると、Terraform OSS で抱えていた課題を解決してくことができます。 一方で、Terraform を Cloud 環境に移行することにより、Terraform OSS にはなかった通信経路も必要になります。 Plan や Apply 、ドリフト検出等により、Terraform Cloud からプロビジョニング先に対してアクセスが発生します。 その際のアクセスイメージは以下の通りです。 デフォルトのアクセスイメージ プロビジョニング先から見ると、Terraform Cloud 側の IP アドレスから各種APIを実行されていることになります。 プロビジョニング先の設定によりソース IP アドレス制限などをしている場合は、Terraform Cloud 側の IP アドレスを許可しておく必要があります。 なお、Terraform Cloud 側の IP アドレスは可変となっておりますが、 IP Range API を通して取得することができます。 頻繁な更新があるわけではないとドキュメントにも記載はありますが、変更される可能性はあるため考慮する必要があります。 しかし、環境によってはこれらの要件が受け入れがたい場合もあると思います。 その場合は、Terraform Cloud Business で利用可能な Terraform Cloud Agent という選択肢があります。 その際のアクセスイメージは以下の通りです。 Terraform Cloud Agentのアクセスイメージ Terraform Cloud Agent を利用すると、Terraform Cloud からのインバウンドアクセスはなくなり、アウトバウンド通信のみにすることができます。 プロビジョニング先から見ると、Terraform Cloud Agent の配置先が各種APIの実行元となります。 図のように、プロビジョニング先 = Terraform Cloud Agent の配置先とすれば、内部から API を発行していることになります。 これにより IP 制限がかけられている環境であっても、必要最低限の対応で利用することが可能になります。 ただし、Terraform Cloud Agent は VCS とは直接通信することはできません。 VCS 連携する場合は、VCS に対してTerraform Cloud 側の IP アドレスからのアクセスを許可しておく必要があります。 特に、VCS をプロビジョニング先やオンプレなどに構築している場合は、VCS に限り Terraform Cloud からのインバウンドアクセスの許可が必須となるのでご注意ください。 VCS 連携時のアクセスイメージ まとめ 改めてにはなりますが、本記事では Terraform Cloud Business についてご紹介させて頂きました。 今回紹介できた内容は一部に過ぎず、その他にも多種多様な機能が提供されていますし、続々とアップデートされています。 直近で発表のあった以下のアップデートなども、個人的には管理面やセキュリティ面で大きなアップデートだと思っています。 Terraform Cloud Adds Dynamic Provider Credentials for Vault and Official Cloud Providers Terraform Cloud Adds ‘Projects’ to Organize Workspaces at Scale これらのアップデートがいち早く享受できることも Cloud 利用の大きなメリットの 1 つですね。今後も注目して行きたいと思います。 最後までご覧いただきありがとうございました。本記事がどなたかの一助となれれば幸いです。 浅香 樹 みずほリサーチ&テクノロジーズ 先端技術研究部に所属。2019年から、CCoEとしてAWSの社内利活用の推進に従事。 Google Cloudは2022年より利用開始し、それを機にTerraformにも取り組んでいます。
当記事と2回に分けて Google Cloud(旧称 GCP)の Compute Engine(以下 GCE)において、Windows Server のオンデマンドライセンスを使用した場合のライセンス認証の概要と設定について紹介します。当記事は「概要」についてです。 はじめに サービスの概要 GCE とは OS イメージ Windows Server VM における Microsoft ライセンス 認証方法 ライセンスの更新と有効期限 確認方法 サーバーマネージャー 設定 コマンドプロンプト PowerShell ログから見る Windows Server VM から KMS サーバーへの通信 前提 ファイアウォールルールロギング VPC フローログ KMS サーバーへアクセスできない時に認証強制をした際の挙動 はじめに GCE で Windows Server VM を使う際は、Microsoft ライセンスの認証をする必要があります。ライセンス認証がされていない場合、以下の記事のようなエラーが出力されます。 blog.g-gen.co.jp 当記事では、上記の記事を踏まえライセンス認証の概要や確認方法について紹介します。今後の「設定編」では、 外部 IP アドレスを持たない Windows Server VM でライセンス認証を行う方法 について紹介します。 サービスの概要 GCE とは GCE は、 Google Cloud が提供する仮想サーバーのサービスです。 GCE について詳しく知りたい方は以下の記事をご参照ください。 blog.g-gen.co.jp blog.g-gen.co.jp OS イメージ GCE では、Debian 系や Red Hat 系の Linux ディストリビューションから Windows Server 等の OS イメージが提供されています。 イメージには無料で使えるものと、プレミアムイメージとして使用料が発生するものがあります。 当記事で扱う Windows Server はプレミアムイメージであり、プレミアムイメージの場合、 Spot VM (および プリエンプティブル VM )によってイメージのコストが削減はされません。また、 無料トライアルは適用されません 。 参考: オペレーティング システムの詳細 / ディスクとイメージの料金 Windows Server VM における Microsoft ライセンス 認証方法 前述の通り、Windows Server VM を使う際は、Microsoft ライセンスの認証をする必要があります。 ライセンスオプションの詳細は ドキュメント に記載の通りで、当記事ではその中から Google から Windows Server のオンデマンド ライセンスを購入した場合 のライセンス認証について紹介します。 Microsoft ライセンス認証は、Windows Server VM が Windows Key Management Service(KMS)サーバーと通信することでライセンス認証および更新することができます。 Google Cloud の KMS サーバーの情報は以下の通りです。 項目 値 エンドポイント名 kms.windows.googlecloud.com IP アドレス 35.190.247.13/32 ポート 1688 プロトコル TCP 参考: Windows Server インスタンスの作成 / ライセンスについて ライセンスの更新と有効期限 Windows Server VM は、KMS サーバーにアクセスをして、 7日ごとにライセンスを更新 (下部キャプチャの 更新間隔 項目)します。ライセンスの有効期限は、180日です。Windows Server VM(Windows Server 2022 Datacenter) を作成直後にライセンスの認証状況を確認すると以下のようになっています(表示言語は 日本語 に変更)。 認証状況(GCE) 以下、一部抜粋します。 項目( 英語表記の場合) 値(英語表記の場合) ライセンスの状態 (License Status) ライセンスされています (Licensed) ボリュームライセンス認証の有効期限 (Volume activation expiration) 180日 (180 day(s)) 登録 KMS コンピューター名 (Registered KMS machine name) kms.windows.googlecloud.com:1688 KMS コンピューターの IP アドレス (KMS machine IP address) 35.190.247.13 ライセンス認証の間隔 (Activation interval) 120 分 (120 minutes) 更新間隔 (Renewal Interval) 10080 分 (10080 minutes) 以上の有効期限や更新間隔等の結果は、Microsoft の ドキュメント に記載の通りです。 例として AWS EC2 の Windows Server VM(Windows Server 2022 Base)の場合のライセンス認証状況は以下の通りです(表示言語は 日本語 に変更)。 GCE で確認した、登録 KMS コンピューター名 と KMS コンピューターの IP アドレス が異なることが確認できます。 認証状況(EC2) 参考: Windows Serverを完全日本語化してみた 確認方法 Windows Server VM のライセンスの認証状況の確認方法を4種類紹介します。 全てライセンス認証されている状態の表記 です。 サーバーマネージャー サーバーマネージャーで プロダクト ID から確認できます。 サーバーマネージャーで確認 設定 スタートメニューで 設定 > 更新とセキュリティ > ライセンス認証 から確認できます。 設定から確認 コマンドプロンプト コマンドプロンプトで slmgr /dlv を実行すると Windows Script Host が起動し、 ライセンスの状態 から確認できます。 コマンドプロンプトで確認 PowerShell PowerShell で Get-CimInstance -ClassName SoftwareLicensingProduct | where {$_.PartialProductKey} | select LicenseStatus を実行することで確認できます。 PowerShell で確認 (実行例) PS C:\Users\fujioka> Get-CimInstance -ClassName SoftwareLicensingProduct | where {$_.PartialProductKey} | select LicenseStatus LicenseStatus ------------- 1 PS C:\Users\fujioka> LicenseStatus の説明は ドキュメント をご参照ください。 ログから見る Windows Server VM から KMS サーバーへの通信 前提 1. KMS サーバー(35.190.247.13/32)へ 1688/tcp の下り通信を明示的に許可、 ファイアウォールルールロギング を有効化したファイアウォールルール(ルール名: allow-kms-egress )を作成 (※ 以降一部 xxxxx として伏せ字) fujioka @ cloudshell :~ ( xxxxx )$ gcloud compute firewall - rules list -- filter =" name = 'kms' " -- format = json [ { " allowed ": [ { " IPProtocol ": " tcp ", " ports ": [ " 1688 " ] } ] , " creationTimestamp ": " 2023-02-25T23:17:58.678-08:00 ", " description ": "", " destinationRanges ": [ " 35.190.247.13/32 " ] , " direction ": " EGRESS ", " disabled ": false , " id ": " xxxxx ", " kind ": " compute#firewall ", " logConfig ": { " enable ": true , " metadata ": " INCLUDE_ALL_METADATA " } , " name ": " allow-kms-egress ", " network ": " https://www.googleapis.com/compute/v1/projects/xxxxx/global/networks/default ", " priority ": 1000 , " selfLink ": " https://www.googleapis.com/compute/v1/projects/xxxxx/global/firewalls/allow-kms-egress " } ] fujioka @ cloudshell :~ ( xxxxx )$ 参考: gcloud compute firewall-rules list 2. 対象サブネットで VPC フローログ を有効化 logConfig が "enable": true になっています。サンプリングレートは 1.0(100%)としていますが、取得できるログは平均で 3% 程度のためご注意ください。 fujioka @ cloudshell :~ ( xxxxx )$ gcloud compute networks subnets list -- filter =" name = 'default' " -- format = json | jq - r '.[] | select(.region == "https://www.googleapis.com/compute/v1/projects/${PROJECT_ID}/regions/asia-northeast1")' { " creationTimestamp ": " 2022-09-06T02:45:41.176-07:00 ", " enableFlowLogs ": true , " fingerprint ": " xxxxx ", " gatewayAddress ": " 10.146.0.1 ", " id ": " xxxxx ", " ipCidrRange ": " 10.146.0.0/20 ", " kind ": " compute#subnetwork ", " logConfig ": { " aggregationInterval ": " INTERVAL_5_SEC ", " enable ": true , " flowSampling ": 1 , " metadata ": " INCLUDE_ALL_METADATA " } , " name ": " default ", " network ": " https://www.googleapis.com/compute/v1/projects/xxxxx/global/networks/default ", " privateIpGoogleAccess ": true , " privateIpv6GoogleAccess ": " DISABLE_GOOGLE_ACCESS ", " purpose ": " PRIVATE ", " region ": " https://www.googleapis.com/compute/v1/projects/xxxxx/regions/asia-northeast1 ", " selfLink ": " https://www.googleapis.com/compute/v1/projects/xxxxx/regions/asia-northeast1/subnetworks/default ", " stackType ": " IPV4_ONLY " } fujioka @ cloudshell :~ ( xxxxx )$ 参考: gcloud compute networks subnets list / ログのサンプリングと処理 3. Windows Server VM の情報 項目 値 VM 名 windows-server 内部 IP アドレス 10.146.15.210 外部 IP アドレス 34.146.103.xx VPC default(デフォルトで作成されている VPC) 次の項で Cloud Logging の出力結果を記載します。 ファイアウォールルールロギング KMS サーバー(35.190.247.13)へアクセスしていることがわかります。 { " insertId ": " xxxxx ", " jsonPayload ": { " disposition ": " ALLOWED ", " connection ": { " dest_port ": 1688 , " src_port ": 49696 , " protocol ": 6 , " dest_ip ": " 35.190.247.13 ", " src_ip ": " 10.146.15.210 " } , " rule_details ": { " reference ": " network:default/firewall:allow-kms-egress ", " destination_range ": [ " 35.190.247.13/32 " ] , " action ": " ALLOW ", " ip_port_info ": [ { " ip_protocol ": " TCP ", " port_range ": [ " 1688 " ] } ] , " direction ": " EGRESS ", " priority ": 1000 } , " remote_location ": { " continent ": " America ", " country ": " usa " } , " instance ": { " project_id ": " xxxxx ", " region ": " asia-northeast1 ", " vm_name ": " windows-server ", " zone ": " asia-northeast1-b " } , " vpc ": { " subnetwork_name ": " default ", " project_id ": " xxxxx ", " vpc_name ": " default " } } , " resource ": { " type ": " gce_subnetwork ", " labels ": { " project_id ": " xxxxx ", " subnetwork_name ": " default ", " location ": " asia-northeast1-b ", " subnetwork_id ": " xxxxx " } } , " timestamp ": " 2023-02-26T10:47:49.672982838Z ", " logName ": " projects/xxxxx/logs/compute.googleapis.com%2Ffirewall ", " receiveTimestamp ": " 2023-02-26T10:47:55.869479250Z " } VPC フローログ 同様に、KMS サーバー(35.190.247.13)へアクセスしていることがわかります。 { " insertId ": " xxxxx ", " jsonPayload ": { " start_time ": " 2023-02-26T10:47:49.687694347Z ", " end_time ": " 2023-02-26T10:47:50.430404649Z ", " src_instance ": { " region ": " asia-northeast1 ", " project_id ": " xxxxx ", " zone ": " asia-northeast1-b ", " vm_name ": " windows-server " } , " connection ": { " src_ip ": " 10.146.15.210 ", " dest_ip ": " 35.190.247.13 ", " protocol ": 6 , " dest_port ": 1688 , " src_port ": 49696 } , " dest_location ": { " continent ": " America ", " asn ": 15169 , " country ": " usa " } , " packets_sent ": " 8 ", " reporter ": " SRC ", " src_vpc ": { " vpc_name ": " default ", " subnetwork_name ": " default ", " project_id ": " xxxxx " } , " bytes_sent ": " 0 " } , " resource ": { " type ": " gce_subnetwork ", " labels ": { " location ": " asia-northeast1-b ", " project_id ": " xxxxx ", " subnetwork_id ": " xxxxx ", " subnetwork_name ": " default " } } , " timestamp ": " 2023-02-26T10:48:03.213215298Z ", " logName ": " projects/xxxxx/logs/compute.googleapis.com%2Fvpc_flows ", " receiveTimestamp ": " 2023-02-26T10:48:03.213215298Z " } KMS サーバーへアクセスできない時に認証強制をした際の挙動 一時的に KMS サーバーへ下り 1688/tcp を拒否(deny)するファイアウォールールを作成し、ライセンス認証を強制した際の挙動を確認します。以下のようなエラーが出力された場合は、KMS サーバーへアクセスができていないため、ファイアウォールルールやルートを確認してください。 TcpTestSucceeded : False となる。 # (事前確認)PowerShell で疎通確認 PS C:\Users\fujioka> Test-NetConnection 35.190.247.13 -Port 1688 WARNING: TCP connect to (35.190.247.13 : 1688) failed ComputerName : 35.190.247.13 RemoteAddress : 35.190.247.13 RemotePort : 1688 InterfaceAlias : Ethernet SourceAddress : 10.146.15.210 PingSucceeded : True PingReplyDetails (RTT) : 1 ms TcpTestSucceeded : False Error: 0x80070005 Access denied: the requested action requires elevated privileges となる。 # KMS のサーバー IP アドレスを設定 PS C:\Users\fujioka> cscript \windows\system32\slmgr.vbs /skms 35.190.247.13:1688 Microsoft (R) Windows Script Host Version 5.812 Copyright (C) Microsoft Corporation. All rights reserved. Error: 0x80070005 Access denied: the requested action requires elevated privileges PS C:\Users\fujioka> Error: 0xC004F074 The Software Licensing Service reported that the computer could not be activated. No Key Management Service (KMS) could be contacted. Please see the Application Event Log for additional information. となる。 # ライセンス認証を強制 PS C:\Users\fujioka> cscript \windows\system32\slmgr.vbs /ato Microsoft (R) Windows Script Host Version 5.812 Copyright (C) Microsoft Corporation. All rights reserved. Activating Windows(R), ServerDatacenter edition (ef6cfc9f-8c5d-44ac-9aad-de6a2ea0ae03) ... Error: 0xC004F074 The Software Licensing Service reported that the computer could not be activated. No Key Management Service (KMS) could be contacted. Please see the Application Event Log for additional information. PS C:\Users\fujioka> 参考: ライセンスについて G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
当記事では、 Google Cloud(旧称 GCP)のノーコードツールである Google AppSheet(以下 AppSheet)の概要からはじめ方について紹介します。 概要 AppSheet とは データソース 4つのプラン AppSheet と Google Workspace 注意点 ユースケース はじめ方 概要 AppSheet とは AppSheet は、プログラミングの知識のない人や開発経験のない人でもマウス操作のみで簡単にアプリケーションを開発できるノーコードツールのサービスです。IT 部門ではなく、実際の業務を遂行する現場の社員がアプリケーションを作る、という「市民開発」を掲げてサービスが開始されました。 2020年に Google が AppSheet 社を買収し、Google のサービスに加わりました。従来使われていた Google のノーコードツールのサービスである App Maker は 2021年1月にサービスが終了 し、現在は AppSheet が使われています。 開発したアプリは、ブラウザやスマートフォン、タブレットで使うことができます。以下のようなステップでアプリを開発します。 開発の流れ また、 AppSheet Automation 機能を使うことで、アプリ内の一連のフローの中でメールや SMS 配信、データ変更等のイベントをトリガーに Google Apps Script を実行することもでき、業務改善により役立ちます。 以下のようにテンプレートも用意されているため、ゼロから自分たちで作る必要はありません。 www.appsheet.com データソース データソースには、Google のサービスである Google Sheets や BigQuery はもちろん、Microsoft Excel(Office 365 および SharePoint)や Amazon DynamoDB、Salesforce など多様なデータソースを選択することができます。 対応しているデータソースの詳細は以下のドキュメントをご参照ください。 support.google.com 4つのプラン AppSheet には以下の4つのプランがあります。プランによって使える機能が異なります。例として Apigee や BigQuery のコネクタを使うためには Enterprise Standard 以上のプランが必要です。また、アプリケーションのパフォーマンスのためのリソースの割り当てもプランによって異なるため、用途に合わせて選択してください。 Starter Core Enterprise Standard Enterprise Plus 各プランの料金の詳細は以下のドキュメントをご参照ください。 about.appsheet.com なお、アプリを公開する場合は利用機能に応じたプランに登録する必要がありますが、そこまでの アプリの開発とテストは無料 です。加入プランを問わず、全ての機能を無料で開発、テストすることができます。また、教育機関および非営利団体には割引があります。 参考: How to choose a subscription plan / AppSheet for non-profits AppSheet と Google Workspace Google Workspace (旧称 G Suite)の Enterprise Plus と Education Plus のプランには、前述の Core プランのライセンスが含まれています。そのため追加料金なしで、Core プランの機能を使うことができます。Enterprise Standard 以上の機能を使う場合には追加でライセンスを購入する必要があります。 参考: Google Workspace の各エディションの比較 注意点 2023年2月時点で、AppSheet は日本語に対応していません。そのため、公式ドキュメントや操作画面は英語表記です。 ユースケース AppSheet を使うことで、業務の効率化やデータの見える化を実現できるため、例えば以下のような場面で活用できます。 在庫管理 / 棚卸し 顧客情報管理 日報 予約管理 また、前述の AppSheet Automation を使うことで承認フローの自動化等も可能です。 はじめ方 URL にアクセスします。以降の UI は変わる場合があります。 Get started をクリックします。 始め方-2 サインインするアカウントを選択します。Google の他にも Microsoft や Apple アカウントも使用できます。今回は Google をクリックします。 始め方-3 対象の Google アカウントをクリックします。 始め方-4 AppSheet が Google アカウントへアクセスすることを許可します。 許可 をクリックします。 始め方-5 サインイン完了です。ここからアプリを作成することができます。 始め方-6 プランを確認します。My account > Billing から現在のプランを確認できます。 始め方-7 今回は、AppSheet の概要について紹介しました。今後、実際にアプリを作る方法についても紹介していきます。 G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
当記事は みずほリサーチ&テクノロジーズ × G-gen エンジニアコラボレーション企画 で執筆されたものです。 当記事では、Cloud Functions を用いて Google Workspace もしくは Cloud Identity (以下、Google Workspace 等) で管理している Google アカウント / グループの棚卸し を日次で行う方法を紹介します。 なお、Google Cloud 側の設定は Terraform を使用します。 概要 背景 今回やること 準備 フォルダ階層 Python ソースコード main.py requirements.txt 説明 Terraform コード main.tf 実行 Terraform 実行 Google Workspace 管理コンソールでの設定 カスタムロールの作成 ロールの付与 確認 概要 背景 Google Cloud を利用する際、企業の監査要件等で Google アカウント (ID) / グループの管理・棚卸しを定期的に行わければいけない時はないでしょうか? 同じパブリッククラウドの AWS では、 ID は IAM User 、グループは IAM Group と呼ばれ AWS アカウント (テナント) の中で管理されているため、AWS のインベントリサービスである AWS Config を用いることで、ID / グループ のスナップショットも AWS Config ひとつで取得できます。 しかし、Google Cloud の場合、Google アカウント / グループは Google Cloud からは分離 されており、Google Workspace 等で管理されております。 したがって、Google Cloud のインベントリサービスである Cloud Asset Inventory を用いても、Google Cloud の組織配下のリソースやポリシーのメタデータは取得できるものの、 組織の Google アカウント / グループは取得できません 。 Google Cloud の ID や IAM についての概念を、AWS との違いと合わせて詳しく知りたい方は以下の記事をご参照下さい。 blog.g-gen.co.jp 今回やること 今回は、Cloud Functions を用いて Directory API を実行し、Google Workspace 等で管理されている Google アカウント / グループの棚卸しを日次で行う方法をご紹介します。 構成図 準備 フォルダ階層 フォルダ階層は以下の通りです。 cloud_identity_inventory ├── terraform │ └── main.tf └── python_source_code ├── main.py └── requirements.txt cloud_identity_inventory というフォルダ配下に、 Terraform を実行する terraform フォルダと、Cloud Functions で使うソースファイルを格納している python_source_code フォルダを作ります。 Cloud Functions を Terraform からデプロイする際、関数のソースコードの場所を Cloud Storage もしくは Cloud Source Repository から指定でき、今回は Cloud Storage から取得するように構成しています。 Terraform を実行すると、以下の流れで処理が進みます。 python_source_code 配下のファイルを圧縮した ZIP ファイルを main.tf と同階層に作成 ソースコード格納用 Cloud Storage バケットを作成し 1. で作成した ZIP ファイルを格納 2 でバケットに格納されたソースコードを指定して Cloud Functions をデプロイ Python ソースコード Python ソースコードは以下の通りです。 main.py import os from datetime import datetime, timedelta import pandas as pd import functions_framework from googleapiclient.discovery import build from google.cloud import storage CUSTOMER_ID = os.environ[ "CUSTOMER_ID" ] UPLOAD_BUKET_NAME = os.environ[ "UPLOAD_BUKET_NAME" ] # storage クライアントのインスタンス化 storage_client = storage.Client() def gcs_upload (kind, file_name, df): # 本日の日付を取得し、["YYYY", "MM", "DD"] のリストで格納 now = (datetime.utcnow() + timedelta(hours= 9 )).strftime( "%Y-%m-%d" ) now_li = now.split( "-" ) # file_name を作成 kind = kind file_name = f "{kind}/{now_li[0]}/{now_li[1]}/{now_li[2]}/{file_name}.csv" # csv に変換し GCS にアップロード content_type = "text/csv" bucket = storage_client.get_bucket(UPLOAD_BUKET_NAME) blob = bucket.blob(file_name) blob.upload_from_string( df.to_csv(index= False , header= True , sep= "," ), content_type=content_type ) @ functions_framework.cloud_event def main (cloud_event): # service オブジェクトの作成 service = build( "admin" , "directory_v1" ) # ユーザー一覧を取得 users_list_result = service.users().list(customer=CUSTOMER_ID).execute() users = users_list_result.get( "users" , []) # ユーザー数が 0 のときは処理を終了 if len (users) == 0 : return "User does not exist." users_df = pd.DataFrame.from_records(users) gcs_upload(kind= "users_list" , file_name= "users_list" , df=users_df) # グループ一覧を取得 groups_list_result = service.groups().list(customer=CUSTOMER_ID).execute() groups = groups_list_result.get( "groups" , []) # グループ数が 0 のときは処理を終了 if len (groups) == 0 : return "Group does not exist." groups_df = pd.DataFrame.from_records(groups) gcs_upload(kind= "groups_list" , file_name= "groups_list" , df=groups_df) # グループ配下のメンバーを取得 for i in range ( len (groups_df)): groupKey = groups_df.at[i, "id" ] groupName = groups_df.at[i, "name" ] members_list_result = service.members().list(groupKey=groupKey).execute() members = members_list_result.get( "members" , []) members_df = pd.DataFrame.from_records(members) gcs_upload(kind= "members_list" , file_name=groupName, df=members_df) return "ok" requirements.txt DateTime==5.0 pandas==1.5.2 functions-framework==3.3.0 google-api-python-client==2.72.0 google-auth==2.16.0 google-cloud-storage==2.7.0 説明 今回、Python クライアントライブラリを用いて以下の 3 つの Directory API を実行しています。 No Method 名 説明 1 users.list 削除されたユーザーまたはドメイン内のすべてのユーザーのリストを取得します。 2 groups.list ドメインまたはユーザーのすべてのグループのリストを取得します。 3 members.list グループ内のすべてのメンバーのリストを取得します。 groups.list のレスポンスからはグループの一覧は取得できますが、グループに所属しているユーザー情報が取得できないため、groups.list で取得したグループ数だけ members.list の処理を回すようにしています。 そうすることで、グループに所属しているメンバー一覧も取得できます。 データの形成については、後々分析しやすいようデータは csv 形式に変換して Cloud Storage へアップロードしています。 また、生データをそのままの形式で蓄積しつつ、分析しやすいようにデータ形成も行いたい場合は以下のアーキテクチャも検討できます。 今回はサンプルのため実装しておりませんが、 Directory API を実行する時の注意点として、1 回のリクエストで大量のレスポンスデータを取得することが保証されていない点です。 本番運用では、 nextPageToken/pageToken を考慮し、大量のレスポンスデータは複数回に分けて取得する必要があります。 Terraform コード main.tf # ローカル変数の定義 locals { project_id = “<プロジェクト ID>” customer_id = “<顧客 ID>” } # terraform / providers の設定 terraform { required_providers { google = { source = "hashicorp/google" version = ">= 4.0.0" } } required_version = ">= 1.3.0" backend "gcs" { bucket = "<state 管理バケット名>" prefix = "<任意の prefix>" } } ## プロジェクトの作成 resource "google_project" "poc" { name = local.project_id project_id = local.project_id folder_id = "<folder_id>" billing_account = "<billing_account>" } ## API 有効化 module "audit_project_services" { source = "terraform-google-modules/project-factory/google//modules/project_services" version = " 14.1.0 " project_id = google_project.poc.project_id enable_apis = true activate_apis = [ "run.googleapis.com" , "cloudfunctions.googleapis.com" , "eventarc.googleapis.com" , "cloudscheduler.googleapis.com" , "admin.googleapis.com" , "artifactregistry.googleapis.com" , "pubsub.googleapis.com" , "cloudbuild.googleapis.com" , "storage.googleapis.com" , ] disable_services_on_destroy = false } ## ソースコード格納用バケットの作成 # バケットの作成 resource "google_storage_bucket" "source" { project = local.project_id location = "ASIA-NORTHEAST1" name = "ggen-matayuuu-admin-sdk-api-gcf-source-002" force_destroy = true } # Cloud Functions で使うソースコードを ZIP 化 data "archive_file" "source_code" { type = "zip" source_dir = "../python_source_code" output_path = "./source_code.zip" } # ZIP 化したソースコードをバケットに追加 resource "google_storage_bucket_object" "source_code" { name = "code/function-run-1.${data.archive_file.source_code.output_md5}.zip" bucket = google_storage_bucket.source.name source = data.archive_file.source_code.output_path } ## API で取得したデータ格納用バケットの作成 # バケットの作成 resource "google_storage_bucket" "cloud_identity_inventory" { project = local.project_id location = "ASIA-NORTHEAST1" name = "ggen-cloud-identity-inventory" force_destroy = true } ## Cloud Functions と Eventarc に付与するサービスアカウントを作成 # サービスアカウント作成 resource "google_service_account" "sa_gcf" { project = local.project_id account_id = "sa-gcf" display_name = "Cloud Functions & Eventarc 用サービスアカウント" } # cloud function 実行権限を付与 resource "google_project_iam_member" "invoke_gcf" { project = local.project_id role = "roles/run.invoker" member = "serviceAccount:${google_service_account.sa_gcf.email}" } # データ格納用バケットのストレージ管理者権限を付与 resource "google_storage_bucket_iam_member" "member" { bucket = google_storage_bucket.cloud_identity_inventory.name role = "roles/storage.admin" member = "serviceAccount:${google_service_account.sa_gcf.email}" } ## Cloud Functions の作成 # pub/subトピックの作成 resource "google_pubsub_topic" "topic" { project = local.project_id name = "cloud-scheduler" } # cloud schedulerの作成 resource "google_cloud_scheduler_job" "job" { project = local.project_id region = "asia-northeast1" name = "invoke-gcf" schedule = "0 10 * * *" pubsub_target { topic_name = google_pubsub_topic.topic.id data = base64encode("run") } } # cloud functionsの作成 resource "google_cloudfunctions2_function" "execute_admin_sdk_api" { project = local.project_id location = "asia-northeast1" name = "execute-admin-sdk-api" build_config { runtime = "python310" entry_point = "main" source { storage_source { bucket = google_storage_bucket.source.name object = google_storage_bucket_object.source_code.name } } } service_config { max_instance_count = 3 min_instance_count = 1 available_memory = "256M" timeout_seconds = 60 ingress_settings = "ALLOW_ALL" all_traffic_on_latest_revision = true service_account_email = google_service_account.sa_gcf.email environment_variables = { CUSTOMER_ID = local.customer_id UPLOAD_BUKET_NAME = google_storage_bucket.cloud_identity_inventory.name } } event_trigger { trigger_region = "asia-northeast1" event_type = "google.cloud.pubsub.topic.v1.messagePublished" retry_policy = "RETRY_POLICY_DO_NOT_RETRY" pubsub_topic = google_pubsub_topic.topic.id service_account_email = google_service_account.sa_gcf.email } } 当記事では Terraform の概要等について触れないため、コマンドや tfstate ファイル等については以下の記事をご参照ください。 blog.g-gen.co.jp blog.g-gen.co.jp 実行 Terraform 実行 main.tf ファイルのある階層に移動した後、 terraform init で初期化し、 terraform plan でドライランを行い問題がなければ、 terraform apply で実環境に適用します。 Apply complete! Resources: 20 added, 0 changed, 0 destroyed. と表示されれば成功です。 matayuuu@penguin:~/cloud_identity_inventory/terraform$ terraform apply data.archive_file.source_code: Reading... 〜省略〜 Plan: 20 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes 〜省略〜 Apply complete! Resources: 20 added, 0 changed, 0 destroyed. Google Workspace 管理コンソールでの設定 今回使用する Directory API は、 Google Workspace 等の ユーザー読み取り権限 と グループ読み取り権限 が必要です。 したがって、必要最小限の権限を持ったカスタムロールを作成し、Cloud Functions のサービスアカウントに付与します。 カスタムロールの作成 Google Workspace ( Cloud Identity ) 管理コンソール > [ アカウント ] > [ 管理者ロール ] > [ 新しいロールを作成 ] をクリック 任意の[ 名前 ]と[ 説明 ]を入力し、[ 続行 ]をクリック [ ユーザー / 読み取り ]と[ グループ / 読み取り ]を選択し、[ 続行 ]をクリック [ ロールを作成 ] をクリック ロールの付与 Google Workspace ( Cloud Identity ) 管理コンソール > [ アカウント ] > [ 管理者ロール ] > [ 先程作成したカスタムロール ] をクリック [ ロールを割り当て ] をクリック [ サービスアカウントへの割り当て ]をクリック [ <Cloud Functions のサービスアカウント> ]を入力し、[ 追加 ]を選択 [ ロールを割り当て ]をクリック ここまでで設定は完了です。 確認 日次で Cloud Scheduler が実行されるのですが、強制的に即時実行させてみます。 Google Cloud コンソール > [ Cloud Scheduler ] > [ 操作 ] の「︙」をクリック [ ジョブを強制実行する ] をクリック すると Cloud Scheduler から Pub / Sub を経由し Cloud Functions が実行されます。 Cloud Storage バケットを確認すると、 3 つのフォルダ ができてました。 また、それぞれのフォルダ配下には、 年 / 月 / 日 / csv ファイル が存在しました。 このように、組織で管理する Google アカウント / グループ の棚卸しを自動化することができます。 G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
G-gen の佐々木です。当記事では Google Cloud ( 旧称 GCP ) の代表的サービスである Google Kubernetes Engine ( GKE ) の限定公開クラスタを、 Terraform を使用して作成していきます。 前提知識 Google Kubernetes Engine とは Terraform とは なぜ 検証用の GKE クラスタを Terraform で作成するのか 構成図 Terraform のディレクトリ構成 Terraform 詳細 environments/test/main.tf environments/test/variables.tf および modules/variables.tf environments/test/terraform.tfvars modules/vpc.tf modules/gke.tf modules/bastion.tf modules/nat.tf modules/outputs.tf Terraform の実行 前提知識 Google Kubernetes Engine とは Google Kubernetes Engine (以下、GKE ) は、Google Cloud のインフラストラクチャ上に構築された マネージドな Kubernetes クラスタ を利用することができるサービスです。 サービスの詳細は以下の記事で解説しています。 blog.g-gen.co.jp Terraform とは Terraform は Infrastructure as Code (IaC) を実現するオープンソースのツールです。 Terraform の概要は以下の記事で解説しています。 blog.g-gen.co.jp なぜ 検証用の GKE クラスタを Terraform で作成するのか GKE クラスタを作成する際、設定できるパラメータの項目数は非常に多く、検証のたびに 同じ構成でクラスタを作成するのは非常に煩雑な作業 になります。 クラスタのパラメータ以外にも、クラスタを配置する VPC とサブネットの作成が必要となり、限定公開クラスタを使用したい場合は、以下のリソースも追加で必要となる場合があります。 コントロールプレーンにプライベート IP で接続するための 踏み台 VM クラスタからインターネットにアクセスするための Cloud NAT このように GKE クラスタ以外のリソースが増えてくると、環境の構築手順が煩雑になり、またクラスタが不要になった際に、 リソースの削除漏れ が起こりやすくなります。 リソースの管理に Terraform を使用することによって、コマンド 1 つで すべてのリソースを一括で作成/削除する ことができます。 また、GKE では、Standard モードのクラスタであれば、ノードとして起動される Commpute Engine インスタンスの料金が常に発生します。 そして Standard モード、Autopilot モードのどちらであっても、 クラスタ管理手数料 として $74.40 / 月 の料金が発生します (最初の 1 クラスタのみ条件を満たせば無料枠あり)。 簡単な検証目的の利用であれば、料金節約のためにこまめにクラスタを削除することが望ましいでしょう。 構成図 当記事では、限定公開の GKE クラスタを Autopilot モードで作成していきます。 GKE ノードが配置される VPC に踏み台 VM を作成し、踏み台から Kubernetes の管理操作を行えるようにします。 また、クラスタからインターネットにアクセスできるように、Cloud NAT を作成します。 構成図 Terraform のディレクトリ構成 ファイルを environments/ ディレクトリと modules/ ディレクトリに分けています。 root/ ├ environments/ │ └ test/ │   ├ main.tf │   ├ terraform.tfvars │   └ variables.tf └ modules/ ├ bastion.tf ├ gke.tf ├ nat.tf ├ outputs.tf ├ variables.tf └ vpc.tf 各 Google Cloud リソースを定義するモジュールを modules/ ディレクトリに集約し、 environments/ ディレクトリ配下にある test/main.tf から各モジュールを呼び出します。 同一構成の環境を異なる設定値で作成したい場合は、 environments/ 配下の test/ ディレクトリを複製し、 terraform.tfvars に記述されている設定値を書き換えます。 Terraform 詳細 environments/test/main.tf terraform.tfvars から変数を受け取り、 modules/ 配下にあるモジュールを呼び出して各リソースを作成します。 リソースの作成後、 modules/outputs.tf から受け取った出力を元に、作成した GKE クラスタに接続するためのコマンドをターミナルに出力します。 terraform { required_providers { google = { source = "hashicorp/google" version = ">= 4.0.0" } } required_version = ">= 1.3.0" backend "gcs" { # tfstate ファイルの保存先となる GCS バケット bucket = "tfstate" prefix = "gke-test" } } provider "google" {} module "modules" { source = "../../modules" # 変数を modules に渡す common = var.common vpc = var.vpc gke = var.gke bastion = var.bastion } # 全リソース作成後、GKE クラスタの接続コマンドを出力 output "command_to_connect_cluster" { value = "\n$ gcloud container clusters get-credentials $ { module.modules.cluster_name } --region $ { module.modules.cluster_location } --project $ { module.modules.cluster_project } \n" } environments/test/variables.tf および modules/variables.tf 変数を宣言するファイルで、変数の受け渡しのために environments/ 側と modules/ 側で同一のファイルを配置します。 変数をオブジェクト型で設定することで、リソースの種類ごとにパラメータをグループ分けすることができ、どのリソースに関するパラメータなのかが明瞭になります。 variable "common" { type = object ( { prefix = string # 固有のプレフィクス (任意の文字列) env = string # 環境名 ( dev、prod など) project = string # プロジェクト region = string # リージョン zone = string # ゾーン } ) description = "リソース共通の設定値" } variable "vpc" { type = object ( { subnet_cidr = string # サブネットの CIDR 範囲 ( GKE ノード、踏み台ホストが使用する IP 範囲) } ) description = "VPC の設定値" } variable "gke" { type = object ( { cluster_cidr = string # GKE Pod が使用する IP 範囲 service_cidr = string # GKE Service が使用する IP 範囲 master_cidr = string # コントロールプレーンが使用する IP 範囲 } ) description = "GKE の設定値" } variable "bastion" { type = object ( { machine_type = string # 踏み台 VM のマシンタイプ ssh_sourcerange = string # 踏み台 VM に SSH アクセスできるソース IP 範囲 } ) description = "踏み台 VM の設定値" } environments/test/terraform.tfvars variables.tf で宣言した変数にパラメータを代入します。 同一の構成で別のクラスタを作成したい場合は、 test/ ディレクトリを複製し、このファイルのパラメータを修正するだけで実現できるようにします。 common = { prefix = "ggen" env = "test" project = "myproject" region = "asia-northeast1" zone = "asia-northeast1-b" } vpc = { subnet_cidr = "192.168.100.0/24" } gke = { cluster_cidr = "172.16.0.0/16" service_cidr = "172.31.0.0/16" master_cidr = "192.168.200.0/28" } bastion = { machine_type = "e2-small" ssh_sourcerange = "35.235.240.0/20" # IAP の IP 範囲 } modules/vpc.tf GKE クラスタを配置する VPC リソースを作成します。 # GKE クラスタを作成する VPC resource "google_compute_network" "vpc_network" { project = var.common.project name = "vpc-$ { var.common.prefix } -$ { var.common.env } " auto_create_subnetworks = false } # GKE クラスタを作成するサブネット resource "google_compute_subnetwork" "subnet_asia_ne1" { project = var.common.project name = "subnet-$ { var.common.prefix } -$ { var.common.env } " ip_cidr_range = var.vpc.subnet_cidr region = var.common.region network = google_compute_network.vpc_network.id private_ip_google_access = true } modules/gke.tf 限定公開の GKE クラスタを Autopilot モードで作成します。 resource "google_container_cluster" "primary" { project = var.common.project name = "cluster-$ { var.common.prefix } -$ { var.common.env } -autopilot" enable_autopilot = true # Autopilot モードでクラスタを作成 location = var.common.region network = google_compute_network.vpc_network.id subnetwork = google_compute_subnetwork.subnet_asia_ne1.id ip_allocation_policy { cluster_ipv4_cidr_block = var.gke.cluster_cidr services_ipv4_cidr_block = var.gke.service_cidr } # 限定公開クラスタの設定 private_cluster_config { enable_private_nodes = true enable_private_endpoint = true master_ipv4_cidr_block = var.gke.master_cidr } master_authorized_networks_config { # コントロールプレーンへのアクセスを許可する IP 範囲 cidr_blocks { cidr_block = var.vpc.subnet_cidr # ノードと踏み台が作られるサブネットからのアクセスを許可 } } } modules/bastion.tf コントロールプレーンに接続する踏み台 VM を作成します。 起動スクリプトを使用して、Kubernetes の管理操作に必要なコマンドと GKE のプラグインをインストールしています。 # 踏み台 VM が使用するサービスアカウント resource "google_service_account" "bastion" { project = var.common.project account_id = "sa-$ { var.common.prefix } -$ { var.common.env } " display_name = "Service Account for bastion-$ { var.common.prefix } -$ { var.common.env } " } # サービスアカウントにロールを付与 resource "google_project_iam_member" "bastion" { project = var.common.project role = "roles/container.developer" # Kubernetes Engine デベロッパー ロール member = "serviceAccount:$ { google_service_account.bastion.email } " } # 踏み台 VM resource "google_compute_instance" "bastion" { project = var.common.project name = "bastion-$ { var.common.prefix } -$ { var.common.env } " machine_type = var.bastion.machine_type zone = var.common.zone tags = [ "ssh" ] # ネットワークタグ boot_disk { initialize_params { image = "debian-cloud/debian-11" # OS イメージ } } network_interface { subnetwork_project = var.common.project network = google_compute_network.vpc_network.name # VPC subnetwork = google_compute_subnetwork.subnet_asia_ne1.name # サブネット access_config {} # パブリック IP を付与 } metadata = { enable-oslogin = "true" # OS Login を有効化 } # 起動スクリプトで kubectl と GKE のプラグインをインストール metadata_startup_script = <<EOF #!/bin/bash sudo apt update sudo apt install kubectl sudo apt install google-cloud-sdk-gke-gcloud-auth-plugin EOF service_account { email = google_service_account.bastion.email scopes = [ "cloud-platform" ] } } resource "google_compute_firewall" "ssh" { project = var.common.project name = "vpc-$ { var.common.prefix } -$ { var.common.env } -ssh-allow" network = google_compute_network.vpc_network.name allow { protocol = "tcp" ports = [ "22" ] } source_ranges = [ var.bastion.ssh_sourcerange ] target_tags = [ "ssh" ] } modules/nat.tf クラスタからインターネットアクセスするための Cloud NAT を作成します。 Cloud NAT を使用するためには Cloud Router が必要になるため、このモジュールで一緒に作成します、 # Cloud Router resource "google_compute_router" "router" { project = var.common.project name = "router-$ { var.common.prefix } -$ { var.common.env } " region = var.common.region network = google_compute_network.vpc_network.id } # Cloud NAT resource "google_compute_router_nat" "nat" { project = var.common.project name = "nat-$ { var.common.prefix } -$ { var.common.env } " router = google_compute_router.router.name region = google_compute_router.router.region nat_ip_allocate_option = "AUTO_ONLY" source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" log_config { enable = true filter = "ERRORS_ONLY" } } modules/outputs.tf GKE クラスタの接続コマンドを出力するために必要なリソース情報を main.tf に返します。 output "cluster_name" { value = google_container_cluster.primary.name } output "cluster_location" { value = google_container_cluster.primary.location } output "cluster_project" { value = google_container_cluster.primary.project } Terraform の実行 terraform apply コマンドは environments/test/ ディレクトリで実行します。 実行が完了すると、ターミナルに以下のような文字列が出力されます。 Apply complete! Resources: 9 added, 0 changed, 0 destroyed. Outputs: command_to_connect_cluster = <<EOT $ gcloud container clusters get-credentials cluster-ggen-test-autopilot --region asia-northeast1 --project myproject EOT ここで出力された gcloud container clusters get-credentials コマンドを踏み台 VM で実行することで、作成した GKE クラスタに接続することができます。 佐々木 駿太 (記事一覧) G-gen 最北端、北海道在住のクラウドソリューション部エンジニア。 2022 年 6 月に G-gen にジョイン。Google Cloud All Certifications Engineer。 好きな Google Cloud プロダクトは Cloud Run。最近は Dataflow を勉強中。 Follow @sasashun0805
こんにちは!G-genの片岡です。本記事では Cloud Monitoring で利用可能な、機械学習を使った Forecast condition (予測条件) を実際に検証してみました。 はじめに Cloud Monitoring 振り返り Forecast condition とは 検証内容 VM のセットアップ アラート設定 設定する内容 条件設定 動作検証 ダミーファイルを定期生成 アラート確認 VM 確認 Incident metrics 確認 はじめに Cloud Monitoring 振り返り Cloud Monitoring では、アラートポリシーを用いて、アラートを通知する条件と手法を定義することができます。 例えば GCE の運用において、VMの負荷や稼働状況を収集し、指定した条件に応じてメールやSlack 通知を行うことで、事象に素早く気付くことが可能となります。 Cloud Monitoring の概要及び基本機能については、以下の記事で解説しています。 blog.g-gen.co.jp Forecast condition とは Forecast condition (予測条件) は、 ディスク容量 、 メモリ使用率 、 Google Cloud クォータ などの指標(メトリクス)の値が、指定したウインドウ内にしきい値を超えると予測される場合に、アラートを発報できる機能です。 参考: アラート ポリシーの種類  |  Cloud Monitoring  |  Google Cloud なお、本機能は 2023 年 2 月現在 Preview 中です。Preview 段階のサービスは本番環境での利用は推奨されませんのでご注意ください。以下の記事で Preview 版について触れています。 blog.g-gen.co.jp 検証内容 今回は Google Compute Engine (以下GCE) の VM の、永続ディスクの使用済み容量の増加傾向を学習させて、アラート通知をしてみます。 VM のセットアップ 検証用 VMは、 Debian GNU/Linux 11 (bullseye) とします。 Cloud Monitoring はデフォルトで標準的な指標(Google Cloud の指標)を取得することができますが、今回取得したい ディスク使用率 は、「Ops エージェント」を VM にインストールしないと取得できない指標です。 Ops エージェントの概要とセットアップ方法については、以下の記事で触れています。 blog.g-gen.co.jp アラート設定 設定する内容 今回は Forecast condition(予測条件)を利用し、メトリックの予測値に関するアラートを設定していきます。 Forecast condition を作成することで、予測ウィンドウ(予測期間)内において、しきい値に違反することが予測されたときに通知を受け取ることができます。 ディスク容量 、 メモリ使用率 、 Google Cloud クォータ などに利用可能ですが、予測を始めるために、予測ウィンドウの 2倍 の初期学習時間が必要です。 予測ウィンドウは、1時間 〜 7日で指定可能ですが、例えば予測ウィンドウを 1 時間とした場合、2 時間の初期学習時間が必要です。初期学習のあとも、最大で予測ウインドウの 6倍の時間の直近データが学習されていきます。 条件設定 こちら の手順を参考に、ディスク使用率が予測ウィンドウ内にしきい値を超える と予測された場合に、通知を行うポリシーを作成します。 アラート条件を指標から選択します。 VM Instance > Disk > Disk utilization を選択します。 Monitoring の対象とするデバイスのフィルタ設定を行います。 条件タイプとして Forecast を選択、予測期間(予測ウィンドウ)は 1時間 、しきい値は 90% より上 とします。 通知チャンネル と アラートポリシー名 を設定し、ポリシーを作成します。 動作検証 ダミーファイルを定期生成 VM上でディスク使用率を増加させるために、500MBのダミーファイルを、10分に1個作成するスクリプトを実行し、アラート状況を確認します。 # 500MB のダミーファイルを10分毎に作成(21:00から起動するようセット) $ while true; do dd if=/dev/zero of=`date "+%Y_%m%d_%H%M"`.dummy bs=1M count=500; sleep 600; done 今回は予測ウィンドウを1時間に設定しているため、ポリシー設定完了後から2時間の初期学習時間を経て、しきい値を超える1時間前にアラートが発報されるだろう という仮説を立て、その時を待ちます。 アラート確認 結果として期待通り、しきい値超過のタイミングが予測され、その約1時間前にアラートが発報されました。 VM 確認 VMのダミーファイルは以下の通り作成され、ファイル作成開始から約4時間経過後の 2023_0212_1601.dummy が作成された後にアラートが発報されていました。 # ダミーファイル 作成状況の確認 ls -lh |grep 500M -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 12:00 2023_0212_1200.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 12:10 2023_0212_1210.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 12:20 2023_0212_1220.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 12:30 2023_0212_1230.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 12:40 2023_0212_1240.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 12:50 2023_0212_1250.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 13:00 2023_0212_1300.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 13:10 2023_0212_1310.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 13:20 2023_0212_1320.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 13:30 2023_0212_1330.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 13:40 2023_0212_1340.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 13:50 2023_0212_1350.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 14:00 2023_0212_1400.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 14:10 2023_0212_1410.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 14:20 2023_0212_1420.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 14:30 2023_0212_1430.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 14:40 2023_0212_1440.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 14:50 2023_0212_1450.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 15:00 2023_0212_1500.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 15:11 2023_0212_1510.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 15:21 2023_0212_1521.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 15:31 2023_0212_1531.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 15:41 2023_0212_1541.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 15:51 2023_0212_1551.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 16:01 2023_0212_1601.dummy ★ -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 16:11 2023_0212_1611.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 16:21 2023_0212_1621.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 16:31 2023_0212_1631.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 16:41 2023_0212_1641.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 16:51 2023_0212_1651.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 17:01 2023_0212_1701.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 17:11 2023_0212_1711.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 17:21 2023_0212_1721.dummy -rw-rw-r--. 1 yoshinari yoshinari 500M Feb 12 17:31 2023_0212_1731.dummy Incident metrics 確認 事前学習したディスク増加傾向を元に、このまま推移すると1時間以内(予測ウィンドウ)にしきい値を超えるということが予測され、アラートを通知することができました。 機械学習により未来が予測されることで、先回りした対応が可能になるなど、多くのメリットを享受できそうです。 様々な分野で機械学習が取り入れられており、今後もますます目が離せないですね! 片岡 義就 (記事一覧) クラウドソリューション部 2022年7月 G-genにジョイン。 前職ではAWSをはじめインフラ全般の設計構築、販促企画に従事。お客様にとって最適なクラウドジャーニーを伴走支援すべく、スキルUPに奔走中。
本記事では、データポータル(英名 Data Studio、旧称 Looker Studio)で BigQuery データソースを使う際のコスト最適化について説明します。 はじめに データポータルとは 料金体系 料金削減の基本方針 レポートごとの BigQuery コストを調べる レポート側の基本方針 BigQuery 側の方針 データポータルのキャッシュ機能 レポートのキャッシュ 抽出されたデータソース BigQuery のキャッシュ機能 クエリ結果のキャッシュ マテリアライズドビュー BI Engine キャッシュ以外の手法 BigQuery Editions パーティショニングとクラスタリング 事前集計とカラム設計 データポータルから BigQuery のパーティションは有効なのか API 上限設定 その他の参考記事 はじめに データポータルとは データポータル (英名 Data Studio、旧称 Looker Studio)とは、Google Cloud が提供するデータ可視化ツールであり、様々なデータソースに接続し、簡単にダッシュボードを作ることができます。 もともとデータポータル(Data Studio)と呼ばれていたものが Looker Studio と呼ばれるようになり、再度、データポータルに名称が戻りました。この名称の変遷の経緯と、なぜ「データポータル」と「Data Studio」の2つの名称があるのかは、以下の記事を参照してください。 参考 : GoogleのBIツール、Lookerとデータポータルを比較してみた - G-gen Tech Blog - 名称の変遷 料金体系 データポータルは無料版と Pro 版の二種類があります。データポータル Pro は、無料版にガバナンス機能が追加されたものであり、ユーザー単位でのサブスクリプションとして申込可能です。 データポータル Pro の詳細な解説は、以下の記事をご参照ください。 blog.g-gen.co.jp データポータルの無償版は、料金は発生しません。ただしデータソースとして BigQuery を利用している場合、ダッシュボード(レポート)が読み込まれた際にクエリが実行され、BigQuery からのデータ読み出し料金が発生します。 当記事では、BigQuery をデータソースとするデータポータルのレポートで、コストを削減する手法について紹介します。 料金削減の基本方針 レポートごとの BigQuery コストを調べる まずは、どのレポートでコストが多く発生しているかを把握することが重要です。 データポータルの特定のレポートで、どのくらいの BigQuery コストがかかっているかは、以下の記事の方法で調べることができます。 blog.g-gen.co.jp レポート側の基本方針 データポータルのレポート側では、以下の基本方針に従って、コスト削減を図ります。 データの更新頻度を減らす こと レポートの編集者権限を持っている人はデータを手動で更新できるが、閲覧者権限の人は手動更新ができない 閲覧者権限の人は、データソースに設定した更新頻度でデータが自動更新されるのを待つことになるが、これを許容してコスト削減を図る データが更新されるまでは、同じクエリに対してはレポートのキャッシュが適用されるため、BigQuery にクエリが発行されない 参考 : データの更新頻度を管理する 抽出されたデータソース を使用すること 一定のデータ容量制限までは、データの一部を事前抽出しておける。表示の高速化とクエリの節約に使用できる 参考 : パフォーマンス向上のためにデータを抽出する BigQuery 側の方針 BigQuery 側では、以下の基本方針に従って、コスト削減を図ります。 BI Engine を使用して BigQuery データソースを高速化する 参考 : BI Engine とは パーティショニング や クラスタリング を設定する 参考 : BigQueryのパーティションとクラスタリングについての解説 BigQuery Editions を導入して Baseline や Max 値を設定する 参考 : BigQuery Editionsを徹底解説 事前集計した マートテーブル を作成する マテリアライズドビュー を使用する 参考 : マテリアライズド ビューの概要 BigQuery のキャッシュを利用する 同じ Google アカウントから発行された同じクエリには、キャッシュが適用される データポータルのキャッシュ機能 レポートのキャッシュ データポータルのキャッシュは、レポートによって生成されたクエリとその結果を保持します。本記事では「 レポートのキャッシュ 」と表現しますが、ドキュメントでは「一時的にメモリに保存する」と表現されています。 データポータルでは、レポートのページを読み込んだときや、フィルタを変更したり、プルダウンから項目を選択したりした際に、データソースへのクエリ(SQL)が生成されます。このときに生成されたクエリが 以前に実行されたことのあるクエリと完全に同一 であり、かつデータソースに設定された 「データの更新頻度」の時間内 であれば、キャッシュにヒットする可能性があります。 データポータルのデータソースには データ更新頻度 の設定項目があり、この時間を超えた場合は、クエリが過去のものと同一でもデータソースへクエリが再発行され、キャッシュがリフレッシュされます。 また、キャッシュはデータソースへの認証情報ごとに保持されるため、 オーナーの認証情報によって認証するようデータソースを設定する と、最もキャッシュ効率が良くなります。ただし、データソースへの認証情報に何を設定するかは、コスト面だけでなく、データへのアクセス権限の要件をよく検討したうえで決定してください。 キャッシュが最後に更新された日時は、 レポートの左下に表示 されています。レポートを読み込んだり、フィルタを変更した際に、左下の「最終更新日」が変更された場合、キャッシュヒットせずに、データソースへクエリが発行されたことがわかります。 なお BigQuery コネクタの場合、更新頻度は「分単位: 1~50 分」「時間単位: 1~12 時間」から選択可能です。 参考 : データの更新頻度を管理する 抽出されたデータソース レポートのキャッシュとは別に、 抽出されたデータソース というデータのスナップショットを保持する機能があります。 データソースを選択して、特定のフィールドを指定すると、そのフィールドだけを含む「抽出済みデータソース」を作成することができます。 抽出されたデータソースは、100 MB を上限として、データをデータポータルに保持しておくことができます。データを自動的に更新したい場合は、自動更新を有効化し、更新頻度を設定します。 参考 : パフォーマンス向上のためにデータを抽出する BigQuery のキャッシュ機能 クエリ結果のキャッシュ BigQuery の クエリ結果のキャッシュ は、デフォルトで提供される機能です。過去に実行されたクエリと同一のクエリが同じ Google アカウントから実行された場合、キャッシュが使用されます。 なお、BigQuery Editions のうち Enterprise または Enterprise Plus エディションを使っている場合、別の Google アカウントのキャッシュも利用できます。 参考 : キャッシュに保存されているクエリ結果を使用する 参考 : BigQueryを徹底解説!(基本編) - クエリ結果のキャッシュ マテリアライズドビュー マテリアライズドビュー は、データの実体を保持するビューです。マテリアライズドビューを SQL で定義すると、定期的にデータが更新され、また古くなったデータをクエリするとその部分だけが自動的に更新されるため、常に最新の情報を取得できます。 通常のビューとは異なりいくつかの制約がありますが、要件に応じて導入を検討してください。 参考 : マテリアライズド ビューの概要 BI Engine BI Engine は、BI ツールのために BigQuery のデータをキャッシュしておくためのメモリです。パーティショニングやクラスタリングと組み合わせることで、特に効果を発揮します。 参考 : BI Engine とは 参考 : BI Engine の容量を予約する 参考 : 最適化される SQL 関数と演算子 BI Engine には、以下のような特徴があります。 BI Engine に保存されたデータから結果を取得するクエリを実行する場合、データの読み取りが課金されない BigQuery Editions で購入したスロット数に応じて無料の BI Engine 容量が付帯する 例として100スロットを購入すると、5 GiB の BI Engine 容量が無料で付帯する 参考 : BI Engine の料金 BI Engine に有効なクエリ演算子が決まっており、このリスト以外のクエリでは効果が薄れる 参考 : 最適化される SQL 関数と演算子 BI Engine は結合が多いクエリだと効果が弱くなる 参考 : 結合を最小化する 優先テーブル設定により、BI Engine が適用されるテーブルを限定できる 参考 : 優先テーブル キャッシュ以外の手法 BigQuery Editions BigQuery Editions を使うと、Autoscaler の効果により、デフォルト設定であるオンデマンドよりも料金が安くなる可能性があります。 必要に応じてスロットの1年または3年コミットメントを購入すると、さらに安価に利用可能になります。 blog.g-gen.co.jp パーティショニングとクラスタリング パーティション分割テーブルやクラスタリングを利用することで BigQuery テーブルに対するフルスキャンが回避され、コスト削減に繋がります。 blog.g-gen.co.jp 事前集計とカラム設計 動的集計が必要なケース(例 : 日付の期間指定によるユニークカウント(distinct)。小計の合計が総計にならない)以外は、raw データを扱うのではなく、なるべく事前集計をします。 日付やフィルタ項目のパターン分、あらかじめ集計しておくことが有用です。以下は、その例です。 SELECT date_, title, contributor_ip, COUNT (title) AS revision_count FROM `jkamiya.Looker Studio_test.wikipedia`, UNNEST ([date_, " 9999-12-31 " ]) AS date_, UNNEST ([title, " ALL " ]) AS title, UNNEST ([contributor_ip, " ALL " ]) AS contributor_ip GROUP BY date_, title, contributor_ip ORDER BY revision_count desc 「9999-12-31」は全期間、「ALL」は全項目での集計という意味です。 BigQuery での GROUP BY CUBE の実装方法 データポータルのフィルタ項目を「UNNEST」と対応させ、BigQuery のパーティショニングやクラスタリングのカラムとして設定します。 パーティションは1つ、クラスタリングは4つまで設定可能で、併用もできます。クラスタリングカラムは裏側でデータをソートし整理しておくことでスキャン量を減らすことができます。 設定順が重要なため、フィルタ項目でよく使うものから設定すると良いでしょう。 データポータルから BigQuery のパーティションは有効なのか データポータルから BigQuery のパーティションは、有効に働きます。データポータルから BigQuery にアクセスする際には、以下のようにデータポータル側で自動生成された SQL が BigQuery にクエリされます。 データポータルで自動生成された BigQuery の SQL 一見、日付パーティションである「date_」カラムで絞り込む前に「 jkamiya.Looker Studio_test.wikipedia t0」テーブルにアクセスしているため、フルスキャンをしているのではと心配になります。 しかし、BigQuery はこういった書き方でもパーティションによるスキャンが効果を発揮します。 試しに、パーティションフィルタを有効化した上で、対象箇所をコメントアウトすると、以下のようにエラーが出ます。 パーティション未指定エラー コメントアウトを戻すと、以下のように「924.62MB」となり、エラーも起きず、対象パーティションで絞り込まれていることがわかります。 日付パーティションによるスキャン パーティションは GROUP BY したものに対して WHERE をかけても有効です。 GROUP BY したあとでもパーティションは有効 API 上限設定 オンデマンドモードで BigQuery を利用している場合、BigQuery API に上限を設定することで、ある一定以上は課金されないようにフタをすることが可能です。以下の記事を参考にしてください。 blog.g-gen.co.jp その他の参考記事 blog.g-gen.co.jp blog.g-gen.co.jp G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。