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

TECH PLAY

株式会社G-gen

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

全888件

G-gen の溝口です。この記事では Gemini Notebook in Pro を使い、架空の会社に存在する社内データを用いたAIアシスタントの作成方法と機能の解説をします。 はじめに Gemini Notebook とは Gemini Notebook Enterprise とは Gemini アプリとの違い 事前準備 検証方法 ケース1 : 会社説明を作成させる ケース2 : 取り扱い製品について質問する ケース3 : 人事制度について質問する Studio 機能を使う Discover、音声概要、マインドマップ はじめに Gemini Notebook とは Gemini Notebook は、Google が提供する AI リサーチアシスタントです。ユーザーがアップロードしたドキュメントに基づいて、情報の要約、質問応答、ノート作成などを支援します。Google アカウントがあれば Web ブラウザから利用でき、料金は発生しません。無償で簡単に独自の生成 AI アシスタントを用意できるのが強みです。 Gemini Notebook in Pro とは、Gemini Notebook の有料プランです。無償プランとの主な違いとして、ノートブック数やソース数、1日のクエリ数、音声生成数などの上限が挙げられます。また、高度な機能や優先的なサポートも提供されます。Gemini Notebook in Pro は、Gemini Notebook のヘビーユーザーや、ビジネスでの利用に適しています。 Gemini Notebook Gemini Notebook in Pro 料金 無料 有料もしくは、GoogleWorkspace の対象プランに組み込み ノートブック数 100 500 ノートブックあたりのソース数 50 300 1日のチャットクエリ数 50 500 高度な機能 なし ・ 回答スタイルのカスタマイズ ・ 利用状況分析 など 1日のチャットクエリ数 50 500 1日の音声概要生成数 3 20 当記事では、多数のユーザーが Gemini Notebook を利用するビジネスシーンを想定して、無償版の Gemini Notebook ではなく、Google Workspace に組み込みの Gemini Notebook in Pro を使用して紹介します。 参考 : NotebookLM ヘルプ 参考 : Gemini Notebook をアップグレードする なお、Gemini Notebook in Pro は、2026年7月までは「NotebookLM in Pro」、2025年5月までは「NotebookLM Plus」と呼ばれていました。現在の正式名称は Gemini Notebook in Pro です。 Gemini Notebook in Pro Gemini Notebook Enterprise とは Google Cloud と統合され、より企業向けの企業が強化された Gemini Notebook Enterprise も存在します。Gemini Notebook Enterprise は Google Cloud と統合されており、より高度なセキュリティや統制を敷くことができます。 Gemini Notebook Enterprise で作成されたノートブックは、無償版 Gemini Notebook や Google Workspace の Gemini Notebook in Pro に対して共有することはできません。 Gemini Notebook の各エディションの違いについての詳細は、以下の記事を参照してください。 blog.g-gen.co.jp Gemini アプリとの違い Google は、Gemini Notebook のほかにも、 Gemini アプリ という対話型 AI ツールを提供しています。Gemini Notebook と Gemini アプリの違いについては、以下の記事も参照してください。 blog.g-gen.co.jp 事前準備 まずは、Gemini Notebook in Pro が組み込まれているエディション(Business Standard/Plus や Enterprise Standard/Plus 等)の Google Workspace アカウントにログインした状態で、Gemini Notebook のページ( https://notebook.google.com/ )へアクセスします。 画面右上に「PRO」の表記があれば、お使いのエディションは Gemini Notebook in Pro です。 PRO の表記 画面中央の「+ 新規作成」ボタンを押下して、新しいノートブックを作成します。ノートブック画面が開いたら、画面左部分の「+ ソースを追加」ボタンを押下して、データソースを追加できます。 ソースを追加 データソースとして、以下のようなものが利用できます。 PC 上のファイルの直接アップロード Google ドライブ内にあるGoogle ドキュメント、Google スライド ウェブサイトリンクや Youtube リンク クリップボード内のテキスト ファイルのアップロードの際は、フォルダの一括アップロードはできませんが、ファイルを複数選択することができます。 ソースをアップロード Gemini Notebook in Pro には、回答のスタイルや、長さをカスタマイズする機能もあり、生成 AI からの回答をユーザーのニーズに合わせて調整できます。これは、無償版には備わっていない機能です。 カスタマイズ画面 作成されたノートブックは同じ Google Workspace 組織に所属する他のユーザに共有することができます。これにより、同じ組織の中で、カスタマイズした AI アシスタントを共同利用することができます。Google Workspace アカウントで Gemini Notebook in Pro を使っている場合、無償版(個人アカウント)の Gemini Notebook ユーザーや、他の Google Workspace 組織のユーザーには、ノートブックを共有することはできません。 共有画面 検証方法 実際の運用されているデータに近いものをサンプルとして用意しました。本記事に登場する会社情報、値及び作成された文章はすべて生成 AI で生成した架空のものです。 サンプル商事株式会社の概要 サンプル商事株式会社は、大阪に本社を置く石油化学製品を扱う総合商社です。創業50年の歴史を持ち、国内外に多くの取引先を持つ、業界屈指の企業です。 今回は一般的な企業が所有する「就業規定」や「給与規定」などの10以上の規定の他に、主に取り扱う化学製品の Wikipedia と、Youtube に掲載のある化学製品を紹介しているページを参照元にします。 アップロード後のソース画面 ケース1 : 会社説明を作成させる プロンプト 新人研修用にわかりやすく会社概要説明をお願いします サンプル商事株式会社の新人研修向け会社概要説明: サンプル商事株式会社は、 社員の能力を最大限に引き出し、会社の発展に貢献することを目的 としています。 事業の基本方針 能力主義 経営理念や事業戦略に合う人材を能力に基づいて採用します。 能力開発 社員の能力開発を支援し、会社の成長に貢献できる人材を育成します。 人事評価 社員の能力、業績、貢献度を公正に評価する人事評価制度を設けています。評価結果は、昇進、昇格、異動、賞与、給与に反映されます。 組織活性化 社員の能力開発、キャリア形成、組織活性化のため、異動を命じることがあります。 給与 従業員の給与は、基本給、諸手当、賞与で構成されます。 会計処理 公正妥当と認められる企業会計の基準に従い、会計期間は毎年4月1日から翌年3月31日までです。 顧客関係 顧客との良好な関係を構築し、顧客満足度向上を目指します。 情報管理 情報の適切な保護と利用を図ります。 これらの情報から、サンプル商事株式会社は、 社員の成長と公正な評価を重視し、効率的で活性化された組織運営を目指している と考えられます。 与えられたデータソースから企業概要を簡潔にまとめてくれました。 ケース2 : 取り扱い製品について質問する プロンプト キシレンの有害性はトルエンとどう違いますか? キシレンとトルエンの有害性の違いについて、ソースから得られる情報は以下の通りです。 キシレンの有害性: トルエンと比較して、 皮膚腐食性、眼刺激性、生殖毒性、全身毒性が高い 。 毒劇物取締法 の劇物に該当する。 トルエンの有害性: 毒劇物取締法 の劇物に該当する。 シンナー中毒の原因となる。中枢神経系に影響を与える。 これらの情報から、キシレンはトルエンよりも 皮膚や目への刺激性、生殖機能への毒性、全身への毒性が強い と考えられます。 取扱製品の比較と注意点を出力してくれました。 ケース3 : 人事制度について質問する プロンプト 人事評価で重視するポイントはどこですか? 人事評価で重視するポイントは、サンプル商事株式会社の人事規定によると、社員の 能力、業績、貢献度 です。 人事評価制度に関する詳細は以下の通りです 目的 : 社員の能力を最大限に引き出し、会社の発展に寄与すること 評価制度 : 社員の能力、業績、貢献度を公正に評価するための人事評価制度を設ける 評価方法 : 目標管理制度、360度評価、その他適切な方法 評価結果の活用 : 昇進、昇格、異動、賞与、給与などに反映 サンプル商事株式会社では、 能力主義 を基本とし、社員の 能力開発 を支援し、会社の 成長 に貢献できる人材を育成することを重視しています。人事評価は、社員の 昇進・昇格 、 異動 、 賞与 、 給与 などに反映され、社員の モチベーション向上 や キャリア形成 に繋がるように設計されています。 各規定から抜粋し記述してくれました。 Studio 機能を使う Gemini Notebook の Studio 機能は、アップロードされたソース文書から、さまざまなコンテンツを生成するための機能です。 Studio 機能を利用することで、アップロードされた文書や音声ファイルから、以下のようなコンテンツを生成することができます。この機能により、大量の情報を効率的に把握することができます。 音声概要の生成(2人の登場人物がコンテンツについて概要を語りあう音声を AI が生成。2025年2月現在、英語のみ対応) よくある質問 学習ガイド タイムライン(計画を時系列で整理) ブリーフィングドキュメント Studio 機能 サンプル商事では、Studio 機能を利用することで、石油化学物質、プラスチックの歴史、化学に関する FAQ、用語集などの解説ドキュメントやブリーフィング用のドキュメントを作成してくれました。 作成されたドキュメント一覧 作成されたブリーフィングメモ 作成されたドキュメントは、Gemini Notebook のソースとして利用することができます。 Discover、音声概要、マインドマップ Gemini Notebook には、さらに「Discover(ソースの発見)」「音声概要」「マインドマップ」などの応用機能があります。これらの機能については以下の記事で紹介していますので、併せてご参照ください。 blog.g-gen.co.jp blog.g-gen.co.jp 溝口 直 (記事一覧) ビジネス推進部 営業2課 2023年10月よりG-gen にジョイン。 HRサービスを展開するベンチャー企業から、Google専業の営業へ。関西在住でGoogle Cloudをメインに活動中。育児と仕事のバランスを常に模索中・・
G-gen の杉村です。2025年2月のイチオシ Google Cloud(旧称 GCP)アップデートをまとめてご紹介します。記載は全て、記事公開当時のものですのでご留意ください。 はじめに 生成 AI アプリ保護のフルマネージドサービス Model Armor が公開 Google スプレッドシートの性能が改善 OneDrive から Google ドライブへのデータ移行ツールが一般公開 Gemini 2.0 Flash が GA。2.0 Flash Lite や 2.0 Pro も利用可能に Gemini Notebook(Plus)が Google Workspace がコアサービスに Gemini Code Assist で50ライセンスが1ヶ月間無料 IAP でWorkforce Identity Federation を使った認証が可能に BigQuery データセットが Marketplace で購入/販売可能に Spanner で Managed autoscaler が GA Google チャットに投票機能が登場 Looker Studio のテーブルで閲覧時に複数列の並べ替えができるように VPC Service Controls で「違反ダッシュボード」が Preview 公開 Sensitive Data Protection(旧 DLP)で日本の法人番号が検知可能に Cloud Run service で手動スケーリングが Preview 公開 Compute Engine で A4X VM が Preview 公開 Data Loss Prevention が Gmail で一般公開(GA) Cloud Run API での関数(functions)のデプロイが Preview -> GA Gemini Deep Research が Google Workspace で使用可能に Cloud SQL で最終バックアップが取得可能に(GA) Cloud DNS でパブリック IP ヘルスチェックが GA VPC Service Controls violation analyzer(違反アナライザー)が登場 Gemini in Looker で複数の生成 AI 機能が Preview 公開 Gemini 2.0 Flash-Lite が 一般公開 無償版の個人向け Gemini Code Assist が Public Preview 公開 Cloud SQL for PostgreSQLでプライマリとレプリカの同時アップグレード Vertex AI Agent Builder の answer メソッドで Personalize answers Vertex AI Agent Builder の search メソッドで関連度スコアが取得可能に はじめに 当記事では、毎月の Google Cloud(旧称 GCP)や Google Workspace(旧称 GSuite)のアップデートのうち、特に重要なものをまとめます。 また当記事は、Google Cloud に関するある程度の知識を前提に記載されています。前提知識を得るには、ぜひ以下の記事もご参照ください。 blog.g-gen.co.jp リンク先の公式ガイドは、英語版で表示しないと最新情報が反映されていない場合がありますためご注意ください。 生成 AI アプリ保護のフルマネージドサービス Model Armor が公開 Model Armor overview (2025-02-03) 生成 AI アプリ保護のフルマネージドサービス Model Armor が公開。 不快なコンテンツやプロンプトインジェクション、データ漏洩等を検知・緩和。トークン数に応じた課金だが、無料枠あり。Security Command Center Premium が必要(プロジェクトレベルの有効化で OK)。 Google スプレッドシートの性能が改善 Additional improvements to everyday actions in Google Sheets (2025-02-03) Google スプレッドシートの性能が改善。 データの表示速度やスプシ間のデータのペースト時の速度、フィルタ条件指定時の表示速度などが性能向上する。昨年にも、関数やピボットテーブルなどの速度向上のアップデートがあったが、引き続いてのアップデートとなる。 OneDrive から Google ドライブへのデータ移行ツールが一般公開 Now generally available: Easily migrate files from Microsoft OneDrive to Google Drive (2025-02-04) OneDrive から Google ドライブへのデータ移行ツールが Google から一般公開。 最大100ユーザーのデータ移行が同時に実施可能。Google Workspace の特権管理者が使用できる。 以下の記事も参照。 blog.g-gen.co.jp Gemini 2.0 Flash が GA。2.0 Flash Lite や 2.0 Pro も利用可能に Gemini 2.0 is now available to everyone (2025-02-05) Vertex AI や Google AI Studio で新しいモデルが利用可能に。 Gemini 2.0 Flash (プレビュー → 一般公開) Gemini 2.0 Flash Lite([NEW] プレビュー) Gemini 2.0 Pro([NEW] 試験運用版) Gemini Notebook(Plus)が Google Workspace がコアサービスに NotebookLM and NotebookLM Plus now available as a Google Workspace core service with enterprise-grade data protection (2025-02-05) Gemini Notebook と Gemini Notebook in Plus(旧称 NotebookLM Plus )が Google Workspace がコアサービスとして利用可能に。 エンタープライグレードのデータ保護により企業データは Google に利用されない。2025-02-05から順次リリース。 Gemini Code Assist で50ライセンスが1ヶ月間無料 Gemini Code Assist release notes - January 30, 2025 (2025-01-30) Gemini Code Assist で、初めて契約する場合に限り、50ライセンスが1ヶ月間無料。 デフォルトだと自動更新なので注意。設定で自動更新をオフにできる。 以下の記事も参照。 blog.g-gen.co.jp IAP でWorkforce Identity Federation を使った認証が可能に Configure IAP with Workforce Identity Federation (2025-02-07) Identity-Aware Proxy(IAP)でWorkforce Identity Federation を使った認証が可能に(GA)。 Okta や Entra ID、ADFS など外部 IdP から SAML や OIDC を使って、Google Cloud でホストしたアプリに認証する仕組みを簡単に実装できる。 BigQuery データセットが Marketplace で購入/販売可能に BigQuery datasets now available on Google Cloud Marketplace (2025-02-08) BigQuery データセットが Google Cloud Marketplace で購入/販売可能になった。 データは Analytics Hub を通して公開され、データを複製することなく共有できる。データの購入や販売を、Google Cloud の仕組みを通して適切に行うことができるようになった。企業が保有データをマネタイズするためのプラットフォームができあがったといえる。 Spanner で Managed autoscaler が GA Managed autoscaler (2025-02-11) Spanner で Managed autoscaler 機能が GA。 有効化すると負荷の増減に応じて自動的にスケールアップ/ダウン。CPU負荷やストレージ使用率に応じて反応。ストレージは自動的に再シャーディング。リードレプリカだけのスケールアウトも可能。 以下の記事も参照。 blog.g-gen.co.jp Google チャットに投票機能が登場 Create and vote on polls directly in Google Chat (2025-02-11) Google チャットに投票機能が登場。簡単にチャット参加者から意見を募ることができる。 Looker Studio のテーブルで閲覧時に複数列の並べ替えができるように Sort your data (2025-02-13) Looker Studio のテーブルで、レポート閲覧時に Shift キーを押しながら列をクリックすることで複数列で並べ替えができるように。 これまでは表の編集時にのみ、「サブの並べ替え」で2列まで設定できた。 VPC Service Controls で「違反ダッシュボード」が Preview 公開 Set up and view the violation dashboard (2025-02-14) VPC Service Controls で「違反ダッシュボード」が Preview 公開。 境界への違反が一覧表示できるダッシュボード。以下のブログ記事を参照。 blog.g-gen.co.jp Sensitive Data Protection(旧 DLP)で日本の法人番号が検知可能に InfoType detector reference (2025-02-14) Sensitive Data Protection(旧 Data Loss Prevention、DLP)で日本の法人番号が検知できるように。 InfoType として JAPAN_CORPORATE_NUMBER が追加された。Sensitive Data Protection とは、BigQuery や Cloud Storage 等から機密情報を検知、保護できるサービス。 Cloud Run service で手動スケーリングが Preview 公開 Manual scaling (2025-02-18) Cloud Run service で手動スケーリングが Preview 公開。 コンテナインスタンス数を手動で指定可能。Cloud Scheduler で Cloud Run API を叩くことでスケジュールに基づいたスケーリングもノーコードで実現。 以下の記事も参照。 blog.g-gen.co.jp Compute Engine で A4X VM が Preview 公開 Introducing A4X VMs powered by NVIDIA GB200 — now in preview (2025-02-20) Compute Engine で A4X VM が Preview 公開。 72 個の NVIDIA Blackwell GPU と 36 個の Arm ベースの NVIDIA Grace CPU を搭載した NVIDIA GB200 NVL72 がベース。chain-of-thought やマルチモーダルモデルなどの推論に利用。 Data Loss Prevention が Gmail で一般公開(GA) Workspace data loss protection (DLP) for Gmail is now generally available (2025-02-18) Data Loss Prevention(DLP、データ流出防止)が Gmail で一般公開(GA)。 従来から Google ドライブ、Google チャットで利用可能。本文、添付ファイル、ヘッダー、件名などから機密情報を検知してブロックまたは通知。 Cloud Run API での関数(functions)のデプロイが Preview -> GA Cloud Run functions (formerly known as Cloud Functions) release notes - February 19, 2025 (2025-02-19) Cloud Run API 経由での関数(functions)のデプロイが Preview -> GA。 ただし引き続き Cloud Functions v2 API も使用可能。今後、Cloud Run API のほうに寄せられていく可能性がある。 Google Cloud コンソールでも、Cloud Run functions の独自画面が消えて、Cloud Run に統合された(第1世代 function が存在しないプロジェクトのみの可能性あり)。 Gemini Deep Research が Google Workspace で使用可能に Gemini Deep Research and experimental models now available to Google Workspace users in Gemini Advanced (2025-02-20) Gemini Deep Research が Google Workspace で使用可能に。 Business Standard 以上のエディションで利用可能。Gemini ウェブアプリから実行できる。2025-02-20から順次リリース。 Gemini Deep Research では、AI がインターネットから情報収集してレポートを作成。業界調査、顧客調査、教育・研究などに活用できる。 Cloud SQL で最終バックアップが取得可能に(GA) Final backups (2025-02-20) Cloud SQL で最終バックアップが取得可能に(GA)。 Cloud SQL のインスタンス削除時に、最終バックアップが取得可能になった。保持期間は1日〜最長365日。 インスタンスを削除すると自動バックアップも手動バックアップもすべて削除されるので、従来までは Cloud Storage へのダンプファイルのエクスポートが必要だった。 Cloud SQL のバックアップについては以下の記事を参照。 blog.g-gen.co.jp Cloud DNS でパブリック IP ヘルスチェックが GA Introducing Cloud DNS public IP health checks, for more resilient multicloud deployments (2025-02-22) Cloud DNS でパブリック IP ヘルスチェックが GA。 パブリック IP を最も地理的に近いリージョンからヘルスチェックして、正常でない場合は別の IP アドレスに名前解決する。マルチリージョン、あるいはマルチクラウドのフェイルオーバーに使える。 VPC Service Controls violation analyzer(違反アナライザー)が登場 Diagnose an access denial event using the VPC Service Controls violation analyzer (2025-02-24) VPC Service Controlsでviolation analyzer(違反アナライザー)が登場。 境界違反ログに一意のIDであるトラブルシューティングトークン(vpcServiceControlsUniqueId)が記録され、そのIDから辿ると何が原因で拒否されたかを確認できる画面が見られる。 VPC Service Controls 違反アナライザー Gemini in Looker で複数の生成 AI 機能が Preview 公開 Looker release notes - February 24, 2025 (2025-02-24) Gemini in Looker で以下の2つの生成 AI 機能が登場(Public Preview)。 自然言語による LookML の生成 自然言語によるカスタムフォーマット生成 Looker バージョン 25.2 以降で対応。上記に加えて、対話式に分析を行える Conversational Analytics も Preview。 Gemini 2.0 Flash-Lite が 一般公開 Gemini 2.0 (2025-02-25) Gemini 2.0 Flash-Lite が Preview から一般公開に。2.0 Flash より軽量で料金が安い。料金面やスピード面で 1.5 Flash ユーザーにとってのアップグレードパスとされている。 1M のマルチモーダルインプット 8k のテキストアウトプット Gemini 系モデルの現在のリリース状況は、以下のとおり。 Gemini 2.0 Pro : Experimental(試験運用版) Gemini 2.0 Flash : GA(一般公開) Gemini 2.0 Flash Thinking : Experimental(試験運用版) Gemini 2.0 Flash-Lite : GA(一般公開) 無償版の個人向け Gemini Code Assist が Public Preview 公開 Get coding help from Gemini Code Assist — now for free (2025-02-26) 無償版の個人向け Gemini Code Assist が Public Preview 公開。 Gemini 2.0 によるコード生成、補完、修正。VSCode などの IDE で利用可能。無償版は1か月あたり最大180,000件のコード補完。 また、GitHub レポジトリのコードレビュー・修正提案も無料で利用できる。 Cloud SQL for PostgreSQLでプライマリとレプリカの同時アップグレード Include replicas in the major version upgrade (2025-02-26) Cloud SQL for PostgreSQL で、メジャーバージョンのアップグレード時に、レプリカもアップグレードできるようになった。 現状では、gcloud と REST での操作のみ。コンソールからは不可。まずプライマリインスタンスがアップグレードされ、次にレプリカインスタンスがアップグレードされる。 Vertex AI Agent Builder の answer メソッドで Personalize answers Personalize answers (2025-02-26) Vertex AI Agent Builder(Vertex AI Search)の answer メソッドで Personalize answers が利用可能に(GA)。 リクエスト時に endUserMetadata オブジェクトを渡すことで回答がパーソナライズされる。 Vertex AI Agent Builder の search メソッドで関連度スコアが取得可能に Get document-relevance score with search results (2025-02-28) Vertex AI Agent Builder(Vertex AI Search)で検索結果から関連度スコアが取得可能に(GA)。 0〜1.0の間でクエリと検索結果ドキュメントの関連度を返す。search メソッドのリクエスト時に "returnRelevanceScore": true に設定することで取得できる。 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-genの菊池です。当記事では、Looker の 対称集計機能 について解説します。 対称集計とは 対称集計が必要になる状況 対称集計の仕組み 対称集計の使い方 必要な設定 一意の主キー(primary_key) 正しい結合関係(relationship) 対称集計とは 対称集計 は、Looker の標準機能です。Looker では、複数のテーブルを結合して利用する場合があります。結合するテーブル間の関係が「1対多」の場合、集計関数(カウント、合計、平均など)で値を求めると、一部の値が二重にカウントされる可能性があります。集計結果が誤った値にならないように、本来はテーブルを結合する段階で考慮が必要です。 しかし Looker では、ユーザーが明示的に対処しなくても、対称集計機能を用いることでデータの二重カウントを気にせずにテーブルを結合して集計できます。 参考 : 対称集計について  |  Looker  |  Google Cloud 対称集計が必要になる状況 ここでは、対称集計が必要な状況と、対象集計がない場合に発生する問題について説明します。 顧客テーブル( customers )と注文テーブル( orders )の2つのテーブルがあるとします。それぞれのテーブルは、以下の列を持っています。 顧客テーブル( customers ) 顧客番号( customer_id ) 名前( name ) 訪問回数( visits ) 注文テーブル( orders ) 注文番号( order_id ) 金額( amount ) 顧客番号( customer_id ) 1人の顧客が複数の注文をする可能性があるため、顧客テーブルと注文テーブルの関係は「1対多」です。 各テーブルで SQL を使い COUNT や SUM 演算を行うと、以下のようになります。 顧客テーブルの COUNT(*) で顧客数は 3、sum(visits) で訪問回数の合計は 8 注文テーブルの COUNT(*) で注文数は 4、sum(amount) で金額の合計は 250 顧客ごとの注文数を知るために、2つのテーブルを結合します。2つのテーブルに共通する顧客番号で紐づけて結合するのが一般的です。 1対多のテーブルを結合すると、行数が少ないテーブルの行が重複します。 例では、顧客テーブルのAmeliaは2回注文しているため、結合後のテーブルでは2行になります。 ここで、結合後のテーブルで、最初に求めたカウントと合計を計算します。 COUNT(*)=4で注文数と一致するが、顧客数とは一致しない sum(amount)=250は金額の合計と一致するが、sum(visits)=10は訪問回数の合計とは一致しない 注文テーブルの集計は結合後のテーブルでも一致しますが、顧客テーブルの集計は一致しません。 このように、1対多のテーブルを結合すると、 行数が少ないテーブルの数値が重複カウントされ、誤った集計値になり ます。 Lookerの対称集計はこのような1対多のテーブル結合による重複カウントを防ぐことができます。 対称集計の仕組み Looker では、顧客テーブル( customers )や注文テーブル( orders )を view ファイルとして保持します。また、顧客ごとの金額を算出するには、 model ファイルでテーブルの結合を定義します。 Looker では、 Explore で表示したいフィールドを選ぶと、表やグラフで結果を可視化できます。この時、Looker はバックグラウンドで SQL クエリを生成し、データベースに送信してデータを取得します。 訪問回数と金額のフィールドを表示する際、対称集計機能がないと、各列を 単純に合計する SQL が生成されます。この SQL では、前述した重複集計の問題が発生します。 しかし、Looker には標準で対称集計機能があるため、SQL クエリは以下のように自動で修正されます。 結合後のテーブルで訪問回数( visits )の合計を正確に集計するための対称集計の計算方法を説明します。 Looker は、MD5 ハッシュ関数で主キーごとに一意の数値を生成し、割り当てます。顧客名が Amelia の2つの行には、同じ big_unique_number が割り当てられます。 そして、正確な訪問回数を計算するために、以下の計算式を使用します。 SUM ( DISTINCT visits + big_unique_number ) - SUM ( DISTINCT big_unique_number ) 通常の SUM(DISTINCT) 関数だけで計算する場合、visits の値だけで同じ顧客のレコードかどうかを判断してしまいます。訪問回数が2回になっている3つのレコードを同じ顧客のレコードとみなした結果、訪問回数の合計は「6回」となり、誤った値になります。 ハッシュを付与する理由は、visits の値だけでは同じ顧客のレコードを特定できないためです。主キーである顧客ID( customer_id )ごとに一意のハッシュ値を割り当てることで、訪問回数が同じ2回のレコードでも、Amelia と Charles のレコードを区別できます。 顧客ID( customer_id )ごとの訪問回数+ハッシュ値の合計を算出し、そこからハッシュ値の合計を引くことで、正確な訪問回数の合計を計算します。 対称集計の使い方 必要な設定 これらの計算は Looker が自動で実行するため、ユーザーが理解したり、意識する必要はありません。 Lookerの対称集計機能は標準で有効であり、ユーザーが明示的に有効にする必要はありません。ただし、対称集計を正しく動作させるには、view ファイルと model ファイルの Explore で、以下の2つの項目を正しく定義する必要があります。 一意の主キー( primary_key ) 正しい結合関係( relationship ) 一意の主キー(primary_key) レコードを一意に識別できる列が主キーです。 主キーは、図のように primary_key で指定します。対称集計を有効にするには、結合するすべてのテーブルに主キーを設定する必要があります。 主キーが一意なキーとして機能しているか確認するには、テーブルのカウントと主キーのカウントが一致するかを確認します。一致しない場合は、各行を一意に識別できる列を探します。ない場合は、複数の列で一意に識別できるもの(複合主キー)を探します。 ただし、 primary_key: yes パラメータを設定できるのは view 内で1つのディメンションのみですので、複合主キーを利用する場合は、必要な列を連結して新しいディメンションを作成します。 正しい結合関係(relationship) テーブルを結合する際は、テーブル間の正しい関係を定義する必要があります。 結合関係は、図のように model ファイル内で relationship の値を設定します。 relationship には、左右のテーブルという概念があります。 join パラメータの前にあるビュー(画像では order )を左側、 join パラメータの右にあるビュー(画像では customers )を右側とします。 テーブル間の関係は、 relationship で以下の4つの値のいずれかを指定して定義します。 値 関係 one_to_one 1対1の関係。2つのテーブルが1対1に紐づく。 one_to_many 1対多の関係。左のテーブルの1行が右のテーブルの複数行に紐づく。 many_to_one 多対1の関係。左のテーブルの複数行が右のテーブルの1行に紐づく。 many_to_many 多対多の関係。左のテーブルの複数行が右のテーブルの複数行に紐づく。 テーブル間の関係が上記の4つのうちどれに該当するかを確認するには、データ同士の関係を文章で考えてみます。 1人の顧客は1つの注文にのみ関連付けられる 1人の顧客は複数の注文に関連付けられる 複数の顧客は1つの注文にのみ関連付けられる 複数の顧客は複数の注文に関連付けられる 今回のテーブルで実際にあり得る関係は 2. であるため、顧客と注文の関係は one_to_many です。 菊池 健太 (記事一覧) クラウドソリューション部データアナリティクス課。2024年7月より、G-genに入社。群馬出身のエンジニア。前職でLookerの使用経験はあるが、GCPは未経験なので現在勉強中。
G-gen の佐々木です。当記事では、Google Cloud で新規プロジェクトを作成する際の注意点として、プロジェクト ID 重複に関する仕様について解説します。 プロジェクトの識別情報について 新規プロジェクト作成時に ID が重複していた場合の動作 コンソールからプロジェクトを作成する場合 コンソール以外からプロジェクトを作成する場合 ID の重複を事前に知ることはできない プロジェクト ID 重複エラーを想定した実装 プロジェクトの識別情報について Google Cloud のプロジェクトを識別するための情報としては、 プロジェクト名 、 プロジェクト ID 、 プロジェクト番号 の3種類があります。このうち、Google Cloud の全利用者のどのプロジェクトと重複してはいけない( グローバルに一意 となる)ものはプロジェクト ID とプロジェクト番号の2つです。 識別情報 一意性 説明 プロジェクト ID グローバルに一意 プロジェクト作成時にユーザー側で指定できる。 プログラムからの操作時に対象プロジェクト指定に 使用されることが多い プロジェクト番号 グローバルに一意 プロジェクト作成時に自動で払い出され、ユーザー側 では指定できない。デフォルトのサービスアカウント などリソース ID の一部として使用されることがある プロジェクト名 なし 表示名(display name)と呼ばれることもある。 同じ組織、フォルダ内でも重複可能 参考: プロジェクトの作成と管理 新規プロジェクト作成時に ID が重複していた場合の動作 コンソールからプロジェクトを作成する場合 Google Cloud コンソールで新規プロジェクトを作成する場合、プロジェクト名を入力すると、プロジェクト ID が自動で決定されます。このとき「編集」を押下することでユーザー側で変更することもできます。 入力されたプロジェクト名がそのままプロジェクト ID として使用できない、つまりグローバルに一意になっていない場合は、 {プロジェクト名}-{ランダムの数字} という形式で、グローバルに一意の ID が提案されます。 プロジェクトIDが重複している場合、グローバルに一意のIDが提案される コンソール以外からプロジェクトを作成する場合 gcloud コマンドや REST API、クライアントライブラリなど、コンソール以外の方法でプロジェクトを作成する場合、任意のプロジェクト ID を指定して作成リクエストを送信しますが、 プロジェクト ID が重複している場合はエラーとなります 。 コンソールからプロジェクトを作成する場合のように、指定した ID が使用できない場合に、自動で一意の ID を使用してくれるような仕組みはありません。 たとえば、 gcloud projects create コマンドでプロジェクトを作成する際、プロジェクト ID に重複がある場合は以下のようなエラーが返ります。 $ gcloud projects create myproject ERROR: ( gcloud.projects.create ) Project creation failed. The project ID you specified is already in use by another project. Please try an alternative ID. ID の重複を事前に知ることはできない コンソール以外からプロジェクトを作成する場合、たとえばスクリプトを用いて自動でプロジェクトを作成したい場合などでは、「まず ID が現在使われていないか検索し、使われていなければその ID でプロジェクトを作成」すればよいと考えるかもしれませんが、これは上手くいきません。 プロジェクトに関する操作を行うことができる Resource Manager API のうち、特定のプロジェクトの検索に使用できるメソッドは projects.get と projects.search の2種類があります。それぞれ gcloud コマンドの gcloud projects describe と gcloud alpha projects search と対応しています。 gcloud projects describe コマンドで使用されていないプロジェクト ID を検索した場合、以下のようなエラーが返ってきます。 $ gcloud projects describe { 使用されてないプロジェクトID } ERROR: ( gcloud.projects.describe ) [ example@g-gen.co.jp ] does not have permission to access projects instance [ { 使用されてないプロジェクトID } ] ( or it may not exist ) : The caller does not have permission. This command is authenticated as example@g-gen.co.jp which is the active account specified by the [ core/account ] property エラーメッセージに does not have permission to access projects instance [{使用されてないプロジェクトID}] (or it may not exist) とあるように、「指定した ID のプロジェクトに対するアクセス権がない」ため失敗したのか、「指定した ID のプロジェクトが存在しない」ため失敗したのか判別できなくなっています。REST API を直接叩いた場合は、どちらのケースでもステータスコード 403 が返ります。 次に、 gcloud alpha projects search コマンドを使用する場合の例です。 $ gcloud alpha projects search --query =" projectId={使用されてないプロジェクトID} " (空のレスポンス) search コマンドは「コマンドを実行したユーザーがアクセスできる範囲内で検索する」仕様になっており、「アクセス権のないプロジェクトの ID を検索した場合」と「存在しないプロジェクト ID を検索した場合」のどちらも空のレスポンスが返ってきます。REST API を直接叩いた場合、どちらのケースでもステータスコード 200 が返るようになっています。 このように、あるプロジェクト ID が現在使用されているか調べようとしても、API の仕様により「その ID を持つプロジェクトが存在していてアクセス権がない」ケースと「その ID を持つプロジェクトが存在しない」ケースの識別ができません。 プロジェクト ID 重複エラーを想定した実装 スクリプトを用いてプロジェクトを払い出す仕組みを開発する場合は、ID 重複時のエラーを想定した実装にする必要があります。 たとえば以下の Python コードでは、実行時にプロジェクト ID を入力し、ID 重複によりプロジェクトの作成が失敗すると、別の ID を入力するように要求しています。 from google.cloud import resourcemanager_v3 from google.api_core.exceptions import AlreadyExists import sys, time def create_project (project_id: str ) -> bool : """ 引数の ID を元にプロジェクトを作成する Args: project_id (str): プロジェクト ID Returns: bool: プロジェクト作成の成否 """ client = resourcemanager_v3.ProjectsClient() request = resourcemanager_v3.CreateProjectRequest( project=resourcemanager_v3.Project( project_id=project_id, display_name=project_id, ) ) try : operation = client.create_project(request=request) print ( "Create project requested." ) while not operation.done(): print ( "Waiting for project creation..." ) time.sleep( 5 ) print ( "Create Project succeeded." ) return True # プロジェクト ID 重複時の例外処理 except AlreadyExists: print (f "Project ID {project_id} is already exists." ) return False except Exception as e: raise Exception (e) if __name__ == "__main__" : id = input ( "Enter new project ID: " ) try : while not create_project( id ): # プロジェクト作成が成功するまで別の ID の入力を要求する id = input ( "Enter another project ID: " ) except Exception as e: print (f "Create project failed. {e}" ) sys.exit( 1 ) print (f "Project {id} created." ) sys.exit( 0 ) このほかには、ID にランダムなサフィックスを追加して再実行したり、再実行をせずにエラー通知を行ったりといった実装が考えられます。 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
G-gen の三浦です。当記事では、Google Workspace の Data Loss Prevention(以下、DLP)を使用して、Gmail の機密情報が外部に漏洩するのを防ぐ方法を紹介します。 概要 Data Loss Prevention(DLP)とは 前提条件 制約 検証内容 動作確認 DLP のルール設定(警告) 動作確認(警告) DLP のルール設定(検疫) 動作確認(検疫) 動作確認(OCR) 概要 Data Loss Prevention(DLP)とは Data Loss Prevention (DLP、データ損失防止)とは、組織内の重要情報を保護し、情報流出を防ぐための技術です。クレジットカード番号やマイナンバーなどの個人情報を自動的に検出し、保護します。 Google Workspace(以下、GWS)の DLP は、Gmail に加え、Google Chat や Google ドライブにも対応しています。 社外秘の情報や顧客データなどの機密情報が、意図せず共有されたり、流出するのを防ぐルールを設定できます。 参考 : DLP で機密情報を保護する Google ドライブでの検証結果は、以下の記事で解説しています。 blog.g-gen.co.jp 前提条件 Gmail の DLP は、以下の特定の Google Workspace エディションでのみ利用可能です。 Frontline Standard Enterprise Standard / Plus Education Fundamentals / Standard / Plus Teaching and Learning Upgrade 詳細は以下の公式ドキュメントをご参照ください。 参考 : メールと添付ファイルのデータ漏洩を防止する 制約 当機能には以下のような制限があります。 Gmail はスキャンの対象ですが、Google グループは対象外です(グループの代理としてメールを送信した場合、ルールは適用されません)。 1 MB までの添付ファイルがスキャン対象で、1 MB を超える場合、先頭の 1MB のみスキャンされます。10 MB を超える場合はスキャンされません。 添付ファイルが Google ドライブにある場合、Google ドライブ側の DLP ルールが適用されます。 詳細は以下の公式ドキュメントを確認してください。 参考 : 既知の制限事項 参考 : Gmail コンテンツの DLP に関する制限 検証内容 検証手順は次のとおりです。最初に「警告」設定で動作を確認し、次に「管理者による検疫」に変更して、より強力な制御を確認します。 項番 作業 詳細 1 DLP のルール設定(警告) 「関係者外秘」または「confidential」という文字を含むメールの送信時に警告を表示する DLP ルールを設定します。 2 動作確認(警告) 条件を満たすメールを送信し、警告が表示されることを確認します。 3 DLP のルール設定(検疫) ルールを「メールを検疫する」に変更します。 4 動作確認(検疫) 対象のメールが検疫対象であることを確認し、管理者側で拒否します。 5 動作確認(OCR) OCR(光学式文字認識)スキャンを有効にし、条件を満たす画像ファイルを添付し、検疫されることを確認します。 参考 : メール検疫を設定する 動作確認 DLP のルール設定(警告) GWS の管理コンソール(URL : https://admin.google.com )にログインします。 参考 : 管理コンソールにログインする [セキュリティ] > [アクセスとデータ管理] > [データの保護] に移動し、[ルールを管理] を選択します。 ルールを管理を選択 [ルールを追加] > [新しいルール] を選択します。 新しいルールを選択 以下を設定し、[続行] を選択します。 名前:任意の DLP ルール名 範囲:DLP ルールの適用範囲を選択( 組織全体 か 特定の組織部門 、 Google グループ から選択) DLPルール作成1 以下を設定し、[続行] を選択します。 Gmail : メッセージを送信しました DLPルール作成2 [条件を追加] から以下のとおりに設定し、[続行] を選択します。 スキャンするコンテンツの種類: すべてのコンテンツ スキャン対象: 関係社外秘 か confidential という テキスト文字列を含む 場合 DLPルール作成3 以下のとおりに設定し、[続行] を選択します。 操作 操作: ユーザーへの警告 適用対象: 外部(組織外) と 内部(組織内) 宛ての全送信メール アラート 重大度: 高 アラートセンターに送信する: 有効化 し、管理者のメールアドレスを指定 DLPルール作成4 DLPルール作成5 設定内容を確認し、[作成] を選択します。 DLPルール作成6 動作確認(警告) 以下のメールを作成し、[送信する] を選択します。 テストメールの送信 警告が表示されることを確認し、[このまま送信] を選択します。送信者側で、メールが受信できていることを確認します。 警告の表示とメール送信 管理者宛てに、DLP ルールに該当する操作の通知メールが届くことを確認します。 アラート通知の確認 [セキュリティ] > [アラートセンター] へ移動し、アラートが通知されていることを確認します。 アラートセンターの確認 アラートを選択すると、詳細情報が確認できます。 アラートの詳細確認 参考 : ドライブの DLP ダッシュボードでインシデント、アラート、監査イベントを表示する 参考 : アラートの詳細を表示する DLP のルール設定(検疫) [アプリ] > [Google Workspace] > [Gmail の設定] > [検疫の管理] へ移動し、[検疫を追加] を選択します。 検疫の追加 以下を設定し、[保存] を選択します。 名前:任意の検疫設定名 送信拒否の結果: デフォルトの拒否メッセージを送信する メールが検疫されたときに定期的に通知する: 有効化 検疫の設定 [セキュリティ] > [アクセスとデータ管理] > [データの保護] > [ルールを管理] > 作成したルールを選択し、[ルールを編集] を選択します。 ルールを編集を選択 操作 まで移動し、以下のとおりに設定し、ルールを保存します。 操作: メールを検疫する 検疫の条件: 前手順で作成した検疫設定 を選択 アクションの変更(検疫) 動作確認(検疫) 先ほどと同じメールを作成して送信し、[このまま送信] を選択します。送信者側のメール受信トレイを確認し、メールが受信されてないことを確認します。 警告の表示とメール送信 管理者宛てに、メールが検疫されたことを通知するメールが届くことを確認します。 メール検疫のアラート通知確認 [アプリ] > [Google Workspace] > [Gmail の設定] > [検疫の管理] > [管理者検疫に移動] を選択し、送信したメールが存在することを確認します。 検疫されたメールの確認 メールを選択し、 許可(送信) または 拒否(送信不可) を選択します。今回は 拒否 を選択します。 拒否を選択 送信者側にメール送信が失敗したことを示すメールが届くことを確認します。 メール送信失敗通知確認 動作確認(OCR) [セキュリティ] > [アクセスとデータ管理] > [データの保護] へ移動し、[光学式文字認識(OCR)] の Gmail 設定を有効化して [保存] します。 GmailのOCRスキャンの有効化 ※ OCR スキャンを有効にした場合、スキャンの処理により画像や PDF が添付されたメールの処理に遅延が発生する可能性があります。 以下の画像ファイルを添付してメールを送信します。 添付ファイル テストメール [アプリ] > [Google Workspace] > [Gmail の設定] > [検疫の管理] > [管理者検疫に移動] を選択し、送信したメールが存在することを確認します。 検疫されたメールの確認 今回は [許可] を選択します。 許可を選択 送信者側で対象のメールを受信していることを確認します。 メールの受信確認 三浦 健斗 (記事一覧) クラウドソリューション部 2023年10月よりG-genにジョイン。元オンプレ中心のネットワークエンジニア。ネットワーク・セキュリティ・唐揚げ・辛いものが好き。
G-gen の杉村です。VPC Service Controls の 違反ダッシュボード (violation dashboard)機能を解説します。当機能は、VPC Service Controls の境界のアクセス制御に対する違反を一覧表示したり、傾向を把握するためのダッシュボード機能です。 概要 違反ダッシュボードとは ユースケース ダッシュボードの閲覧方法 ダッシュボードの内容 スクリーンショット 表示内容 ダッシュボードのフィルタ ダッシュボードの有効化 有効化画面 作成されるリソース ログルーター ログバケット 閲覧権限 概要 違反ダッシュボードとは VPC Service Controls の 違反ダッシュボード (violation dashboard)とは、VPC Service Controls の境界のアクセス制御に対する違反を一覧表示したり、傾向を把握するためのダッシュボードです。 なお、当記事で紹介する機能やスクリーンショット等は、いずれも2025年2月当時の Preview 段階中のものです。当機能は、2025年7月に一般公開(GA)されました。 参考 : Set up and view the violation dashboard VPC Service Controls とは、接続元 IP アドレスやアカウント情報に基づいて、境界(Perimeter)と呼ばれる論理的境界によって Google Cloud のデータを保護するための機能です。 VPC Service Controls の詳細は以下の記事を参照してください。 blog.g-gen.co.jp ユースケース VPC Service Controls の違反の傾向を掴むことで、プロジェクトへの不正アクセスの試みの増減を把握したり、本来は正しいとみなされるべきアクセスがどのくらい拒否されているかなど、傾向を掴むことができます。 また、本来は許可されるべきアクセスが拒否されてしまっているとき、該当の違反をダッシュボードで確認し、 トラブルシューティングトークン を取得することもできます。トラブルシューティングトークンは、境界への違反に対して発行される一意の ID です。トラブルシューティングトークンがわかれば、VPC Service Controls の 違反アナライザー (violation analyzer)により、そのアクセスが拒否された理由を詳細に確認することができます。 ダッシュボード上ではトラブルシューティングトークンが違反アナライザー画面へのリンクとなっており、すぐに違反の原因を確認することができます。 参考 : Diagnose an access denial event using the VPC Service Controls violation analyzer ダッシュボードの閲覧方法 Google Cloud コンソールのセキュリティ > VPC Service Controls 画面の左上部分に表示される「違反ダッシュボード」のリンクから、ダッシュボード画面に遷移できます。 違反ダッシュボードへの遷移(スクリーンショットはプレビュー中のもの) ダッシュボードの内容 スクリーンショット ダッシュボードは以下のように表示されます。 違反ダッシュボード(スクリーンショットはプレビュー中のもの) 表示内容 閲覧可能な情報は、以下のとおりです。 違反 指定期間内で発生した、境界に対する違反が表示されます。表示される内容は以下のとおりです。 トラブルシューティングトークン(違反の ID) プリンシパル(Google アカウント等) 接続元 IP アドレス アクセスポリシー 境界 ID リソース(境界が保護するプロジェクトまたは VPC ネットワーク) 接続先 API 名 メソッド名 モード(適用済みまたはドライラン) 前述のとおり、トラブルシューティングトークンをクリックすることで、違反アナライザー画面へ遷移し、違反とみなされた原因を確認することができます。 プリンシパル別の上位の違反 指定期間内の違反数が上位のプリンシパルやその回数が表示されます。 プリンシパル IP 別の上位の違反 指定期間内の違反数が上位の接続元 IP アドレスが表示されます。 サービス別の上位の違反 指定期間内の違反数が上位の接続先 Google Cloud API 名が表示されます。 メソッド別の上位の違反 指定期間内の違反数が上位の API メソッドが表示されます。 リソース別の上位の違反 指定期間内の違反数が上位の接続先リソース(境界が保護するプロジェクトまたは VPC ネットワーク)が表示されます。 サービス境界別の上位の違反 指定期間内の違反数が上位の境界 ID が表示されます。 ダッシュボードのフィルタ ダッシュボードの表示期間を、1時間、6時間、12時間、1日、2日、4日、7日、14日、30日、カスタムから選択できます。 ダッシュボードで表示する違反は、期間以外にも、以下の項目でフィルタできます。 アクセスポリシー リソース(境界が保護するプロジェクトまたは VPC ネットワーク) トラブルシューティングトークン(違反の ID) プリンシパル モード(適用済みまたはドライラン) トラフィックの方向(内向きまたは外向き) 接続先 API 名 メソッド ダッシュボードの有効化 有効化画面 違反ダッシュボードを閲覧する前に、ダッシュボードを有効化する必要があります。ダッシュボードでは 有効化した後の違反情報が閲覧可能 であり、 有効化する以前の情報は閲覧できません 。 初めてダッシュボード画面に遷移しようとすると、有効化の設定画面が表示されます。 ダッシュボードの有効化(スクリーンショットはプレビュー中のもの) 作成されるリソース 違反ダッシュボードは、Cloud Logging に記録される Cloud Audit Logs の ポリシー拒否監査ログ をもとに情報を表示しています。 Cloud Audit Logs のポリシー拒否監査ログについては、以下の記事をご参照ください。 参考 : Cloud Audit Logsを解説。Google Cloudの証跡管理 - 4 つの監査ログ ダッシュボードを有効化すると、 組織のルート に ログルーター (シンク)が作成されます。また有効化時に、ログルーターがポリシー拒否監査ログをルーティングする先の プロジェクトとログバケット を指定します。ログバケットは、この画面から新規作成することもできます。 なおログルーターとは、Cloud Logging がログを任意の保存先にルーティングするための設定です。 Cloud Logging のログルーターの詳細は以下の記事をご参照ください。 参考 : Cloud Loggingの概念と仕組みをしっかり解説 - ログルーティングとログの保存 ログルーター ダッシュボードを有効化すると、組織のルート(最上位階層)に reserved_vpc_sc_dashboard_log_router という名称のログルーターが作成されます。 このログルーターは、以下のようなフィルタによってポリシー拒否監査ログを抽出し、ログバケットにルーティングします。 resource . type = " audited_resource " protoPayload.metadata.@ type = " type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata " ログバケット 有効化時に指定したプロジェクトの、既存のログバケットまたは新規作成したログバケットに、ログがルーティングされます。 違反ダッシュボードはこのログバケットに保存されたログに基づいて情報を表示するため、 このログバケットに設定された保持期間が、ダッシュボードの情報の情報保持期間 となります。 閲覧権限 ダッシュボードを閲覧するには、閲覧者の Google アカウントが、ログバケットの存在するプロジェクトに対して以下のロールを持っている必要があります。 ログ表示アクセス者( roles/logging.viewAccessor ) VPC Service Controls Troubleshooter Viewer( roles/accesscontextmanager.vpcScTroubleshooterViewer ) 詳細は、以下の公式ドキュメントに記載されています。 参考 : Required roles 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-gen の佐々木です。当記事では、Cloud Run の手動スケーリング機能について解説します。 Cloud Run とは 手動スケーリングの仕様 手動スケーリングとは サービスとリビジョンの設定 トラフィック分割への影響 サービスの無効化 手動スケーリングの使用 手動スケーリング設定時の料金 リクエストベースの課金の場合 インスタンスベースの課金の場合 スケジュールベースの自動スケーリング Cloud Scheduler の利用 自動スケーリングにおけるスケールのスケジューリング Cloud Run とは Cloud Run は Google Cloud のマネージドなコンテナ実行環境でアプリケーションを実行することができる、サーバレス コンテナコンピューティング サービスです。 Cloud Run には Cloud Run services と Cloud Run jobs、そして Cloud Functions から統合された Cloud Run functions の3種類がありますが、当記事における Cloud Run は Cloud Run services を指すものとします。 blog.g-gen.co.jp 手動スケーリングの仕様 手動スケーリングとは Cloud Run の 手動スケーリング 機能は、Cloud Run services のコンテナインスタンス数を手動で指定できる機能です。 デフォルトでは、Cloud Run services のコンテナインスタンスは自動でスケーリングを行います。受信トラフィック数と CPU 使用率に基づき、事前に指定された最小(最大)インスタンス数をスケーリングの下限(上限)として、自動的にスケーリングが行われます。一方、手動スケーリング設定を行うと、コンテナインスタンス数を任意の値に設定できます。 手動スケーリングでは新たなリビジョンをデプロイすることなく、起動するインスタンスを任意の数に固定することができます。この設定操作を Cloud Scheduler などで自動化することで、「特定の時間帯のみインスタンス数を10に固定し、それ以外の時間は3に固定する」といった自動化を実現できます。 参考: Manual scaling サービスとリビジョンの設定 手動スケーリングはサービスの設定であり、手動スケーリングを設定する場合はリビジョンのインスタンス数の設定は無視されます。リビジョンレベルとサービスレベルのインスタンス数の設定については以下の記事も参照してください。 参考: Cloud Runの最小インスタンス数をスケジュールベースで自動スケーリングする - サービスレベルの最小インスタンス数の設定 トラフィック分割への影響 手動スケーリングを使用している Cloud Run サービスでリビジョン間のトラフィック分割を設定している場合、以下のルールが適用されます。 各リビジョンに対してトラフィック分割の割合に比例したインスタンス数が割り当てられる。 トラフィック分割対象のリビジョンの数 > インスタンス数 の場合、インスタンスが存在しないリビジョンができる。そのリビジョンにトラフィックが送信された場合はエラーが返る。 リビジョンレベルの最小(最大)インスタンス数の設定は無視される。 サービスの無効化 手動スケーリングでインスタンス数を 0 に設定することで、サービスを無効にすることができます。 無効化したサービスに送信されたリクエストは、 Service unavailable または Service disabled エラーで失敗します。 手動スケーリングの使用 手動スケーリングは、サービスの作成時や更新時に設定することができます。 サービス作成時に手動スケーリングを設定する(コンソール) 既存のサービスで手動スケーリングを設定する(コンソール) gcloud コマンドの場合、 gcloud run service deploy コマンドや gcloud run service update コマンドで --scaling フラグを利用することで設定できます。以下はサービス更新時に手動スケーリングを設定するコマンドです。 # 手動スケーリングへの切り替え gcloud run services update < サービス名 > \ --scaling =< インスタンス数 > 手動スケーリングを設定すると、自動スケーリングにおけるリビジョンレベル/サービスレベルのインスタンス数の設定は無効になります。 手動スケーリング設定時の料金 リクエストベースの課金の場合 通常、リクエストベースの課金(旧称:「リクエスト処理中にのみ CPU を割り当てる」設定)では、リクエスト数に応じた料金と、リクエストの処理時間に応じた CPU、メモリの利用料金が発生します。 それに加えて、手動スケーリング設定時は、最小インスタンス数を1以上にしている場合と同様に インスタンスのアイドル時間 に対してもCPU、メモリの利用料金が発生します。 リクエストベースの課金で手動スケーリングを使用する場合 インスタンスベースの課金の場合 インスタンスベースの課金(旧称:「CPU を常に割り当てる」設定)の場合、Cloud Run の料金はリクエスト数に関係なく、インスタンスが起動している時間(アクティブ、アイドル状態問わず)に応じて CPU とメモリの料金が発生します。 したがって、手動スケーリングでインスタンスベースの課金を適用する場合は、インスタンスの起動数だけ CPU とメモリの料金が常に発生することになります。 参考 : Cloud Run pricing スケジュールベースの自動スケーリング Cloud Scheduler の利用 手動スケーリングと Cloud Scheduler を併用することで、任意の時刻にインスタンス数をスケーリングすることが可能です。 Cloud Scheduler で HTTP エンドポイントをターゲットとしたジョブを作成し、Cloud Run API へリクエストすることで、ノーコードでサービスをスケーリングすることができます。 gcloud scheduler jobs create http hello-start-instances \ --location = REGION \ --schedule =" 0 9 * * MON-FRI " \ --time-zone = America/Los_Angeles \ --uri = https://run.googleapis.com/v2/projects/PROJECT_ID/ locations/REGION/services/hello? update_mask =launchStage,scaling.manualInstanceCount \ --headers = Content-Type = application/json,X-HTTP-Method-Override = PATCH \ --http-method = PUT \ --message-body =' {"launchStage":"BETA","scaling":{"manualInstanceCount":10}} ' \ --oauth-service-account-email = PROJECT_NUMBER-compute@developer.gserviceaccount.com 参考 : Schedule-based scaling example 自動スケーリングにおけるスケールのスケジューリング なお前述の方法で、手動スケーリング設定でスケジュールに基づいてスケーリングした場合は、インスタンス数を特定の数に固定することしかできないため、設定した以上のインスタンス数が予期せず必要になったときなどに柔軟なスケールアウトを行うことができません。 以下の記事では、サービスレベルの最小インスタンス数をスケジュールベースで変更することで、最大インスタンス数の設定が有効な状態(自動スケーリングの設定)で、任意の数以上のインスタンスを維持する方法を解説しています。 blog.g-gen.co.jp 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
G-genの杉村です。Gemini Enterprise Agent Platform(旧称 Vertex API)経由での Gemini API を定額で利用できる Provisioned Throughput を解説します。 概要 Provisioned Throughput とは サポートされるモデル 購入すべきユースケース 購入方法と料金 GSU(Generative AI Scale Unit) 購入期間 購入方法と料金 Single Zone Provisioned Throughput 使用方法 自動適用 超過したスループットの扱い 明示的に従量課金を指定 スループットのモニタリング 考慮事項 ファインチューンされたモデル その他の考慮事項 概要 Provisioned Throughput とは Provisioned Throughput (プロビジョニングされたスループット)とは、Gemini Enterprise Agent Platform(旧称 Vertex API、略称 Agent Platform )経由の Gemini や Claude などの生成 AI モデルの API 利用について、固定金額で利用できる月額サブスクリプションサービスです。 これらの生成 AI モデルは本来、インプットとアウトプットのボリュームに応じた従量課金で使用するものです。しかし、事前にモデルとロケーション(リージョン)を指定して Provisioned Throughput を購入すると、月額利用料金で API を利用できるほか、優先的にリソースが割り当てられるため、多くのユーザーが API を利用しているときでもリソース枯渇による RESOURCE_EXHAUSTED (ステータスコード 429)エラーを回避することができます。 参考 : Provisioned Throughput overview サポートされるモデル Provisioned Throughput が利用できるモデルには、以下のようなものがあります(一部抜粋)。 Gemini 3.8 Flash、3.7 Flash、3.6 Flash、3.5 Flash Gemini 3.5 Flash-Lite Gemini Omni 1.1 Flash Gemini 3.1 Flash-Lite Image(Nano Banana 2 Lite) Gemini 3 Pro Image(Nano Banana Pro) Gemini 2.5 Pro、Gemini 2.5 Flash Anthropic Claude Fable 5.1、Opus 5、Sonnet 5 最新の対象モデルの一覧は、以下の公式ドキュメントを参照してください。 参考 : Supported models 購入すべきユースケース Provisioned Throughput を購入すべきユースケースは、以下のとおりです。 重要なワークロードであり、高いスループットが継続的に求められる 生成 AI 本番環境アプリケーションのため一貫性のあるパフォーマンスが必要 AI のトークン数のスループットが高い 月額固定料金で API 利用料金を支払いたい また Provisioned Throughput が効果的に働く事象として、エラーコード429が挙げられます。従量課金モードで Gemini モデル等を利用していると、しばしば エラーコード429 Resource exhausted, please try again later. (status : RESOURCE_EXHAUSTED )が返却され、リクエストが失敗することがあります。これは Google 側でリソースが枯渇かけており、利用制限がかけられたことを意味しています。 エクスポネンシャルバックオフ(指数バックオフ)を実装してリクエストをリトライする方法もありますが、Provisioned Throughput を購入することによって優先的にリソースが割り当てられ、このようなエラーを回避することができます。 参考 : Error code 429 エラーコード429 ( RESOURCE_EXHAUSTED )についての詳細は、以下の記事も参照してください。 blog.g-gen.co.jp 購入方法と料金 GSU(Generative AI Scale Unit) Provisioned Throughput は、 GSU (Generative AI Scale Unit)という単位で購入します。1 GSU は、例えば Gemini 3.6 Flash の場合、675 トークン/秒です。 GSU が持つ秒あたりの文字数について、例えば Gemini 3.6 Pro の場合、1トークンのインプットは1トークンとしてカウントされますが、1トークンのアウトプットは5トークンとしてカウントされます。この消費トークン数を バーンダウン率 (Burndown rates)といいます。画像や音声、動画などについても、それぞれ独自のバーンダウン率が設定されています。 1 GSU あたりのスループット(文字/秒)やバーンダウン率はモデルによって異なります。バーンダウン率は、Google Cloud コンソールの Provisioned Throughput 購入画面で確認できます。 参考 : Calculate Provisioned Throughput requirements 参考 : Purchase Provisioned Throughput 購入期間 Provisioned Throughput は1週間、1ヶ月、3ヶ月、1年の期間で購入できます。自動更新を有効にすることで、更新作業を省略することができます。一度購入すると、コミットした期間は注文をキャンセルすることはできません。 購入時にはモデルを指定する必要があり、生成 AI では頻繁に新しいモデルが登場することを考慮すると、1年単位の購入には慎重になるべきと考えられます。ただし公式ドキュメントでは、同じリージョン内でかつ同じ事業者から提供されているモデルであれば、バージョンの切り替えができることも示されています。 参考 : Purchase Provisioned Throughput 購入方法と料金 購入は Google Cloud コンソールの「Agent Platform > モデル > プロビジョンド スループット」画面( https://console.cloud.google.com/agent-platform/provisioned-throughput/orders )から購入することができます。 購入画面上で、モデル、リージョン、GSU 数、期間を入力すると、料金見積もりが表示されます。 購入に必要な権限などの詳細は、公式ドキュメントをご参照ください。 参考 : Purchase Provisioned Throughput Single Zone Provisioned Throughput Provisioned Throughput には、標準の Provisioned Throughput と、Single Zone Provisioned Throughput の2種類があります。 参考 : Single Zone Provisioned Throughput Gemini 3.5 Flash 等、一部のモデルでは、global ロケーションではなく特定リージョンのエンドポイントで使用したい場合に、従量課金が使用できず、Single Zone Provisioned Throughput の購入が必須となる場合があります。 参考 : Gemini 3.5 Flash 標準と Single Zone の Provisioned Throughput は価格は同じである一方、Single Zone には以下のような制限があります。 Monthly Latency Target Attainment Percentage SLO が適用されない 参考 : Gemini Online Inference API on Gemini Enterprise Agent Platform Service Level Agreement (SLA) ファインチューニングされたモデルには適用できない Google Cloud コンソールでの購入はできず、Google Cloud の営業担当者への連絡が必要 使用方法 自動適用 Provisioned Throughput を購入すると、自動的に利用が開始されます。プログラムのソースコードを変更する必要はありません。 参考 : Use Provisioned Throughput 超過したスループットの扱い Provisioned Throughput で購入したスループットを超過して API を利用すると、デフォルトでは従量課金が適用されます。 しかし、超過した場合に従量課金を利用せずエラーコード429を返却するようにすることもできます。REST API へのリクエスト時に、HTTP ヘッダーに X-Vertex-AI-LLM-Request-Type: dedicated を付与します。 この場合、購入した Provisioned Throughput を超過した場合に、エラーコード429レスポンスが返ります。メッセージは Too many requests. Exceeded the Provisioned Throughput. になります。 参考 : Use Provisioned Throughput - Use only Provisioned Throughput 明示的に従量課金を指定 上記とは逆に、開発環境アプリケーションからの利用であることなどを理由に、Provisioned Throughput をバイパスして従量課金モードでのみを使用するように明示的にリクエストすることもできます。REST API へのリクエスト時に、HTTP ヘッダーに X-Vertex-AI-LLM-Request-Type: shared を付与します。 参考 : Use Provisioned Throughput - Use only pay-as-you-go スループットのモニタリング Provisioned Throughput の使用状況をモニタリングするには、Cloud Monitoring が利用できます。 aiplatform.googleapis.com/PublisherModel というリソースタイプで、指標が記録されます。 インプット、アウトプットの文字数や消費されたスループット量などが記録されるため、Provisioned Throughput が過不足なく利用されているかが確認できます、。 参考 : Use Provisioned Throughput - Monitor Provisioned Throughput 考慮事項 ファインチューンされたモデル ファインチューニングされたモデルにも、Provisioned Throughput を適用できます。 参考 : Supported models - Supervised fine-tuned model support その他の考慮事項 その他の考慮事項としては、以下が挙げられます。 未使用のスループットは翌月に繰り越せない 契約期間の途中で解約はできない デフォルトでは Provisioned Throughput 超過分は従量課金される(前述のとおり) その他の考慮事項については以下の公式ドキュメントを注意深くご参照ください。 参考 : Purchase Provisioned Throughput - What to consider before purchasing 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-gen の佐々木です。当記事では Spanner の組み込みのオートスケーリング機能である Managed autoscaler を紹介します。 前提知識 Spanner とは インスタンス、ノード、処理ユニット オープンソースのオートスケーリングツール Managed autoscaler とは スケーリングのトリガー リードレプリカのオートスケーリング 費用 制限事項 オートスケーリングの設定方法 検証 サンプルコード(Go) 環境変数の設定 Spanner インスタンスの作成 データの準備 データベースとテーブルの作成 データの挿入 挿入したデータの確認 Managed autoscaler の設定 オートスケーリングの動作確認 後処理 前提知識 Spanner とは Spanner は、強整合性を保証する RDB(リレーショナルデータベース)の特徴と、グローバルに水平スケーリングできる NoSQL データベースの特徴を併せ持つ、フルマネージドな RDB サービスです。 参考 : Spanner Spanner の詳細については、以下の記事も参照してください。 blog.g-gen.co.jp インスタンス、ノード、処理ユニット Spanner は インスタンス という単位で管理され、インスタンスに割り当てられたコンピューティングリソースがインスタンス内のデータベースに割り当てられます。インスタンスには ノード 、もしくは 処理ユニット (processing units)という単位でコンピューティングリソースを割り当て、1,000処理ユニットが1ノードに相当します。このリソースの量によってストレージの上限も決められており、コンピューティングリソースもしくはストレージのどちらかに合わせてインスタンスのスケーリングを行う必要があります。 Spanner におけるノードと処理ユニットの追加・削除(スケールアウト・スケールイン)は 無停止 で行われるのが特徴であり、データベース接続を切断することなく、需要に応じた柔軟な水平スケーリングを実現できます。 オープンソースのオートスケーリングツール 当記事で紹介する Managed autoscaler が一般提供(GA)になる以前は、オープンソースのオートスケーラーを使用して Spanner にオートスケーリングを設定することができました。 オートスケーラーツールは Cloud Scheduler、Pub/Sub、Cloud Run functions、Firestore といった Google Cloud のサービスによって構成されており、Cloud Monitoring API でインスタンスの負荷状況を確認し、Spanner インスタンスのスケーリングをトリガーします。 当記事ではオープンソースのオートスケーラーツールに関する解説は行いません。組み込み機能である Managed autoscaler が一般提供になったことから、基本的にはそちらを使用してスケーリングを設定することになるでしょう。 参考: Autoscaler tool overview 参考: cloudspannerecosystem/autoscaler(GitHub) Managed autoscaler とは Managed autoscaler は Spanner に組み込みのオートスケーリング機能です。負荷に応じてインスタンスのサイズ(ノード数または処理ユニット数)が自動的に調整されます。 参考: Autoscaling overview 参考: Managed autoscaler Spanner には3種類の エディション が存在し、エディションによって提供される機能と料金が異なります。Managed autoscaler は Enterprise と Enterprise Plus エディションで利用できる機能です。Standard エディションでは利用できません。 参考 : Spanner editions overview スケーリングのトリガー Managed autoscaler は、以下の要素に基づいてインスタンスのスケーリングを行います。 スケーリング基準 説明 高優先度 CPU 使用率ターゲット (High priority CPU utilization target) スケーリングをトリガーする CPU 使用率(10%~90% で設定)。 インスタンスの CPU 使用率がターゲット値を超えるとスケールアウトがトリガーされる。 CPU 使用率がターゲット値より大幅に低い場合にスケールインがトリガーされる。 ストレージ使用率ターゲット (Storage utilization target) スケーリングをトリガーするストレージ使用率(10~99% で設定)。 下限(Minimum limit) スケールインの下限(最小1ノードまたは1,000処理ユニット)。 Managed Autoscaler を設定すると、インスタンスのデフォルトのサイズがこの値になる。 上限(Maximum limit) スケールアウトの上限。 下限の10倍を超える値に設定することはできない(下限が3ノードであれば30ノードまで設定可能) Spanner は高優先度 CPU 使用率ターゲットとストレージ使用率ターゲットの値に基づき、それぞれで推奨容量を算出します。算出された推奨容量のうち、高いほうが自動で選択されてスケーリングが行われます。 たとえば、ストレージ使用率ターゲットにより10ノード、高優先度 CPU 使用率ターゲットにより12ノード必要であると算出された場合、Managed autoscaler はインスタンスを12ノードにスケーリングします。 スケーリングが起こると、ノード間でストレージの最適化が行われ、単一のノードが過負荷にならないようにトラフィックが均等に分散されます。 参考 : How managed autoscaler works リードレプリカのオートスケーリング Managed autoscaler では、 非対称読み取り専用オートスケーリング (Asymmetric read-only autoscaling)と呼ばれる、リードレプリカのみのスケーリングもサポートされています。 参考 : Asymmetric read-only autoscaling Spanner では3種類のレプリカ(読み取り・書き込み、読み取り専用、ウィットネス)を使用することができますが、この中で 読み取り専用レプリカ のみ独立したオートスケーリングを使用することができます。 参考 : Read-only replicas リードレプリカのオートスケーリングは、リージョンごとに以下のパラメータを設定することができます。 スケーリング基準 説明 高優先度CPU使用率ターゲット (High priority CPU utilization target) スケーリングをトリガーする CPU 使用率(10%~90% で設定)。 最小コンピューティング容量制限 (Minimum compute capacity limit) スケールインの下限(ノード数または処理ユニット数)。 最大コンピューティング容量制限 (Maximum compute capacity limit) スケールアウトの上限(ノード数または処理ユニット数)。 費用 Managed autoscaler によるオートスケーリングが行われると、確保されたリソースの分、追加で料金が発生します。 Managed autoscaler を設定すると、スケールインの下限として設定されたコンピューティング容量が常時確保されるため、これが利用料のベースラインとなります。したがって、必要以上に下限を大きくしないように調整する必要があります。 既存のインスタンスにオートスケーリングを設定する場合は、過去の CPU 使用率、ストレージ使用率など各種モニタリング指標を確認し、適切なスケールイン下限、スケールアウト上限を設定します。 制限事項 Managed autoscaler を有効化したインスタンスは、以下の制限があります。 Spanner エディションの Standard を利用できない Managed autoscaler を設定しているインスタンスは 移動 することができない スケールインの下限は最低 1ノード以上、または1,000 処理ユニット以上に設定する必要がある 既存のインスタンスでオートスケーリングを有効にしたとき、既存のインスタンスのコンピューティング容量がスケールインの下限よりも一時的に低くなる可能性がある( 既存のコンピューティング容量 < スケールインの下限 のとき) オートスケーリングの設定方法 Spanner インスタンス作成時または更新時に、Managed autoscaler を有効化することができます。 たとえば gcloud CLI を使用して、既存のインスタンスに対してオートスケーリングを設定する場合、以下のようにコマンドを実行します。CPU 使用率ターゲット値とストレージ使用率ターゲット値は、どちらも必須フラグとなっています。 # インスタンスを更新して Managed autoscaler を有効化する([]内はリードレプリカの設定) # ノード数を指定する場合 $ gcloud spanner instances update < SpannerインスタンスのID > \ --autoscaling-min-nodes =< 最小ノード数 > \ --autoscaling-max-nodes =< 最大ノード数 > \ --autoscaling-high-priority-cpu-target =< CPU使用率ターゲット値 > \ --autoscaling-storage-target =< ストレージ使用率ターゲット値 > \ [ --asymmetric-autoscaling-option \ location =< リードレプリカのロケーション > ,\ min_nodes =< 最小ノード数 > ,\ max_nodes =< 最大ノード数 > ,\ high_priority_cpu_target =< CPU使用率ターゲット値 >] # インスタンスを更新して Managed autoscaler を有効化する([]内はリードレプリカの設定) # 処理ユニット数を指定する場合 $ gcloud spanner instances update < SpannerインスタンスのID > \ --autoscaling-min-processing-units =< 最小処理ユニット数 > \ --autoscaling-max-processing-units =< 最大処理ユニット数 > \ --autoscaling-high-priority-cpu-target =< CPU使用率ターゲット値 > \ --autoscaling-storage-target =< ストレージ使用率ターゲット値 > \ [ --asymmetric-autoscaling-option \ location =< リードレプリカのロケーション > ,\ min_nodes =< 最小処理ユニット数 > ,\ min_processing_units =< 最大処理ユニット数 > ,\ high_priority_cpu_target =< CPU使用率ターゲット値 >] オートスケーリングはコンソールから設定することもできます。 コンソールからオートスケーリングを設定する 参考: Enable or modify managed autoscaler on an instance 検証 サンプルコード(Go) 当記事では Go のコードを使用して Spanner インスタンス内のデータベースに対する操作を行い、Managed autoscaler の挙動を確認します。 以下のコード(main.go)では、実行時の引数に応じてデータベースとテーブルの作成、データの挿入、データの取得などの操作を行います。 // main.go package main import ( "context" "flag" "fmt" "io" "os" "strconv" "sync" "cloud.google.com/go/spanner" "google.golang.org/api/iterator" database "cloud.google.com/go/spanner/admin/database/apiv1" adminpb "cloud.google.com/go/spanner/admin/database/apiv1/databasepb" ) type Database struct { projectId string instanceId string name string } // データベースとテーブルを作成する func createDB(ctx context.Context, w io.Writer , adminClient *database.DatabaseAdminClient, db Database) error { // データベースを作成し、Singners テーブルと Albumsテーブルを作成する op, err := adminClient.CreateDatabase(ctx, &adminpb.CreateDatabaseRequest{ Parent: "projects/" + db.projectId + "/instances/" + db.instanceId, CreateStatement: "CREATE DATABASE `" + db.name + "`" , ExtraStatements: [] string { `CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX) ) PRIMARY KEY (SingerId)` , `CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX) ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE` , }, }) if err != nil { return err } // データベース作成完了を待つ if _, err := op.Wait(ctx); err != nil { return err } fmt.Fprintf(w, "Created database [%s] \n " , db) return nil } // データを挿入する func insertData(ctx context.Context, w io.Writer , client *spanner.Client) error { _, err := client.ReadWriteTransaction(ctx, func (ctx context.Context, txn *spanner.ReadWriteTransaction) error { // Singers テーブルにデータを挿入する _, err := txn.Update(ctx, spanner.Statement{ SQL: `INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (1, 'Marc', 'Richards'), (2, 'Catalina', 'Smith'), (3, 'Alice', 'Trentor'), (4, 'Lea', 'Martin'), (5, 'David', 'Lomond')` , }) if err != nil { return err } // Albums テーブルにデータを挿入する _, err = txn.Update(ctx, spanner.Statement{ SQL: `INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (1, 1, 'Total Junk'), (1, 2, 'Go, Go, Go'), (2, 1, 'Green'), (2, 2, 'Forever Hold Your Peace'), (2, 3, 'Terrified')` , }) if err != nil { return err } return nil }) if err != nil { return err } fmt.Fprintf(w, "data inserted \n " ) return nil } // Singers テーブルと Albums テーブルを結合してデータを取得する func joinData(ctx context.Context, w io.Writer , client *spanner.Client) error { iter := client.Single().Query(ctx, spanner.Statement{ SQL: `SELECT Singers.FirstName, Singers.LastName, Albums.AlbumTitle FROM Singers JOIN Albums ON Singers.SingerId = Albums.SingerId` , }) defer iter.Stop() fmt.Fprintln(w, "SingerId, AlbumId, AlbumTitle" ) for { row, err := iter.Next() if err == iterator.Done { break } if err != nil { return err } var ( firstName, lastName, albumTitle string ) if err := row.Columns(&firstName, &lastName, &albumTitle); err != nil { return err } fmt.Fprintf(w, "%s %s %s \n " , firstName, lastName, albumTitle) } return nil } // Spanner に負荷をかけるため joinData を並行処理で実行する func concJoinData(ctx context.Context, w io.Writer , client *spanner.Client, n int ) error { c := make ( chan bool , 1000 ) // 並行処理数の上限を設定 var wg sync.WaitGroup for i := 0 ; i < n; i++ { c <- true wg.Add( 1 ) go func () { defer wg.Done() if err := joinData(ctx, io.Discard, client); err != nil { fmt.Fprintln(w, err) } <-c }() } wg.Wait() fmt.Fprintln(w, "Concurrent join completed" ) return nil } func run(ctx context.Context, w io.Writer , cmd string , db Database) error { dbStr := fmt.Sprintf( "projects/%s/instances/%s/databases/%s" , db.projectId, db.instanceId, db.name) // コマンドに応じて処理を実行 switch cmd { case "createdb" : ctx := context.Background() adminClient, err := database.NewDatabaseAdminClient(ctx) if err != nil { return err } defer adminClient.Close() if err := createDB(ctx, w, adminClient, db); err != nil { return err } case "insertdata" : ctx := context.Background() dataClient, err := spanner.NewClient(ctx, dbStr) if err != nil { return err } defer dataClient.Close() if err := insertData(ctx, w, dataClient); err != nil { return err } case "joindata" : ctx := context.Background() dataClient, err := spanner.NewClient(ctx, dbStr) if err != nil { return err } defer dataClient.Close() if err := joinData(ctx, w, dataClient); err != nil { return err } case "concjoin" : ctx := context.Background() dataClient, err := spanner.NewClient(ctx, dbStr) if err != nil { return err } defer dataClient.Close() // 環境変数から並行処理数を取得 n, err := strconv.Atoi(os.Getenv( "CONC_NUM" )) if err != nil { return err } if err := concJoinData(ctx, w, dataClient, n); err != nil { return err } default : fmt.Println( "Usage: main.go [createdb|insertdata|joindata|concjoin]" ) return nil } return nil } func main() { // 環境変数からプロジェクトID、インスタンスID、データベース名を取得 projectId := os.Getenv( "PROJECT_ID" ) instanceId := os.Getenv( "INSTANCE_ID" ) dbname := os.Getenv( "DB_NAME" ) db := Database{ projectId: projectId, instanceId: instanceId, name: dbname, } flag.Parse() if len (flag.Args()) == 0 || len (flag.Args()) > 1 { fmt.Println( "Usage: main.go [createdb|insertdata|joindata|concjoin]" ) os.Exit( 1 ) } cmd := flag.Arg( 0 ) ctx := context.Background() if err := run(ctx, os.Stdout, cmd, db); err != nil { fmt.Println(err) os.Exit( 1 ) } } コード実行時の引数と実行される関数、処理内容の対応は以下のようになっています。 引数 実行される関数 処理内容 createdb createDB Spanner インスタンスにデータベースを作成し、その中に Singers テーブルと Albums テーブルを作成する。 insertdata insertData Singers テーブルと Albums テーブルにデータを挿入する。 joindata joinData Singers テーブルと Albums テーブルを結合する SELECT クエリを実行する。 concjoin concJoinData joinData 関数を並行して実行する。Spanner インスタンスに負荷をかけるために使用する。 参考: Go で Spanner を使ってみる 環境変数の設定 実行するコマンドやコード内から参照する環境変数を、ローカルの Linux 実行環境に設定します。 当記事では Spanner インスタンスの名前を test-instance 、データベースの名前を example-db とします。 export PROJECT_ID = < プロジェクトID > export INSTANCE_ID =test-instance export DB_NAME =example-db Spanner インスタンスの作成 Spanner インスタンスを作成します。まずは Standard エディションのインスタンスを最小サイズで作成します。 オートスケーリングの設定はインスタンス作成時でも可能ですが、当記事では後から設定を行います。 # Spanner インスタンスを作成する $ gcloud spanner instances create ${INSTANCE_ID} \ --config = regional-asia-northeast1 \ --description =" Test Instance " \ --processing-units = 100 参考: gcloud spanner instances create データの準備 データベースとテーブルの作成 Spanner インスタンスにデータベースを作成し、2つのテーブルを作成します。 # データベースとテーブルを作成する $ go run main.go createdb このコマンドを実行すると、データベースが作成されたあと、コード内に直書きされた以下のクエリによってテーブルが2つ作成されます。 CREATE TABLE Singers ( SingerId INT64 NOT NULL , FirstName STRING( 1024 ), LastName STRING( 1024 ), SingerInfo BYTES( MAX ) ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL , AlbumId INT64 NOT NULL , AlbumTitle STRING( MAX ) ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE; データの挿入 2つのテーブルに、コード内に直書きされたデータを挿入します。 # 2つのテーブルにデータを挿入する $ go run main.go insertdata 挿入したデータの確認 挿入したデータを確認するため、以下のコマンドでクエリを実行します。 # 2つのテーブルを結合する SELECT クエリを実行する $ go run main.go joindata 以下のようにクエリの結果が返ってきます。 # 出力例 $ go run main.go joindata SingerId, AlbumId, AlbumTitle Marc Richards Total Junk Marc Richards Go, Go, Go Catalina Smith Green Catalina Smith Forever Hold Your Peace Catalina Smith Terrified Managed autoscaler の設定 Spanner インスタンスの設定を変更し、Managed autoscaler を有効化します。 Managed autoscaler はエディションが Enterprise 以上のインスタンスで使用できるため、エディションも変更する必要があります。また、オートスケーリングの下限は 1ノード(1,000処理ユニット)以上にする必要があるため、ここでは1ノードに設定します。 # Spanner インスタンスに Managed autoscaler の設定をする $ gcloud spanner instances update ${INSTANCE_ID} \ --edition = ENTERPRISE \ --autoscaling-max-nodes = 3 \ --autoscaling-min-nodes = 1 \ --autoscaling-high-priority-cpu-target = 10 \ --autoscaling-storage-target = 80 当記事では以下のようにインスタンスを更新します。動作確認のため、オートスケーリングをトリガーする CPU 使用率は低めに設定しておきます。 フラグ 設定値 説明 --edition ENTERPRISE Spanner インスタンスのエディションを設定する。 ENTERPRISE_PLUS でも可。 --autoscaling-max-nodes 3 スケーリングの最大値をノード数で設定する。 処理ユニットで設定する場合は --autoscaling-max-processing-units を使用する。 --autoscaling-min-nodes 1 スケーリングの最小値をノード数で設定する(最小1)。 処理ユニットで設定する場合は --autoscaling-min-processing-units を使用する(最小1,000)。 --autoscaling-high-priority-cpu-target 10 オートスケーリングをトリガーする CPU 使用率の値を設定する。(%) --autoscaling-storage-target 80 オートスケーリングをトリガーするストレージ使用率の値を設定する。(%) 以下のコマンドでオートスケーリング有効化後の設定を確認します。 # Spanner インスタンスの詳細を確認する(出力抜粋) $ gcloud spanner instances describe ${INSTANCE_ID} autoscalingConfig: autoscalingLimits: maxNodes: 3 minNodes: 1 autoscalingTargets: highPriorityCpuUtilizationPercent: 10 storageUtilizationPercent: 80 参考: gcloud spanner instances update オートスケーリングの動作確認 オートスケーリングを設定した Spanner インスタンスに負荷をかけ、スケーリング動作を確認します。 まず、環境変数にクエリの実行数を設定します。 # クエリ実行数を設定する $ export CONC_NUM = 1000000 以下のコマンドを実行し、Spanner インスタンスに負荷をかけるための処理を実行します。 # 並行処理でクエリを実行し、Spanner インスタンスに負荷をかける $ go run main.go concjoin コマンド実行後少し待つと、Spanner の CPU 使用率がターゲット値を超過し、Managed autoscaler によってノードのスケールアウトが行われます。 Managed autoscaler によるスケールアウト その後、CPU 使用率が下がってからしばらく待つと、ノードのスケールインが行われます。スケールアウトと比較して、ターゲット値を下回ってからスケールインが行われるまでに少し長めの間隔があることがわかります。 Managed autoscaler によるスケールイン 後処理 Spanner は個人の検証目的としては高価なサービスのため、動作確認後は忘れずにインスタンスを削除します。 # Spanner インスタンスを削除する $ gcloud spanner instances delete test-instance 参考: Spanner pricing 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
当記事では、Google Kubernetes Engine(GKE)にデプロイした Web アプリケーション Ingress でインターネット公開する方法、またそのアプリに Cloud Armor ポリシーを設定して、アクセス元 IP アドレスを制限する方法を解説します。 概要 検証の概要 Google Kubernetes Engine とは Ingress とは Cloud Armor とは Firestore の準備 データベースの作成 データの準備 アプリケーションの準備 ソースコードの作成 main.py templates/index.html requirements.txt Dockerfile Artifact Registry の作成 Artifact Registry にアップロード GKE クラスタの設定 GKE クラスタの作成 サービスアカウントの設定 ServiceAccount リソースの作成 権限の付与 GKE クラスタにアプリケーションをデプロイ Ingress を設定してアプリケーションを公開 Cloud Armor による アクセス制限を適用 Cloud Armor のセキュリティポリシーを設定 BackendConfig を作成 Service と BackendConfig の関連付け 動作確認 概要 検証の概要 当記事で検証した構成は、以下のとおりです。 この構成では、GKE 上で動作するアプリケーションが、Firestore に保存されたユーザー情報を、入力されたユーザ ID に基づいて表示します。GKE クラスタに対しては、 Ingressリソースとして外部アプリケーションロードバランサを作成します。そのロードバランサに対して、Cloud Armor を用いて IP アドレスによるアクセス制限を適用します。 Google Kubernetes Engine とは Google Kubernetes Engine (以下、GKE)は、Google Cloud(旧称 GCP)が提供する Kubernetes のマネージドサービスです。 以下の記事で GKE について解説していますので、ご参照ください。 blog.g-gen.co.jp Ingress とは Ingress は、Kubernetes クラスタ外部からクラスタ内部への HTTP(S) アクセスを管理する Kubernetes の API オブジェクトです。この Ingress と Service を組み合わせることで、Service の背後にある Pod にデプロイされているアプリケーションへ外部からアクセスできるようになります。 参考 : Ingress | Kubernetes GKE には、組み込みの GKE Ingress コントローラが用意されています。GKE で Ingress リソースを作成すると、このコントローラによってアプリケーションロードバランサが GKE クラスタ外部に自動的に構成されます。 Cloud Armor とは Cloud Armor は、Google Cloud が提供するフルマネージドの WAF(Web Application Firewall)サービスです。Cloud Armor のセキュリティポリシーを作成してアプリケーションロードバランサに関連付けることで、アクセス制限をかけることができます。 以下の記事で Cloud Armor について解説していますので、ご参照ください。 blog.g-gen.co.jp Firestore の準備 データベースの作成 Firestore で (default) データベースを作成します。 (default) データベースは Firestore のデフォルトとなるデータベースで、Firestore クライアントライブラリや Google Cloud CLI から接続するときにデータベース ID を指定しない場合、自動的に (default) データベースに接続されます。 gcloud firestore databases create \ --database =" (default) " \ --location = asia-northeast1 \ --type = firestore-native データの準備 作成した (default) データベースに、コレクション ID が users で、 age , id , name という3つのフィールドを持っているドキュメントを追加します。 アプリケーションの準備 ソースコードの作成 GKE 上で動作するアプリケーションのソースコードを作成します。 ディレクトリ構成は以下の通りです。 . ├── main.py ├── requirements.txt ├── Dockerfile └── templates └── index.html main.py ソースコードは以下のとおりです。 PROJECT_ID には、ご自身のプロジェクト ID を設定してください。 from flask import Flask, render_template, request from google.cloud import firestore PROJECT_ID = "プロジェクト ID に置き換えてください" app = Flask(__name__) # Firestore インスタンス初期化 db = firestore.Client(project=PROJECT_ID) COLLECTION_NAME = "users" # Firestore コレクション名 ID_FIELD_NAME = "id" # Firestore IDフィールド名 @ app.route ( "/" , methods=[ "GET" , "POST" ]) def index (): data = None message = None if request.method == "POST" : try : user_id = request.form.get( "user_id" ) if not user_id: message = "IDを入力してください。" return render_template( 'index.html' , data=data, message=message) doc_ref = db.collection(COLLECTION_NAME).where(ID_FIELD_NAME, "==" , user_id).get() if doc_ref: data = doc_ref[ 0 ].to_dict() else : message = "指定されたIDのデータは見つかりませんでした。" except Exception as e: message = f "エラーが発生しました:{str(e)}" return render_template( "index.html" , data=data, message=message) if __name__ == "__main__" : app.run(host= "0.0.0.0" , port= 8080 , debug= True ) templates/index.html ユーザ ID を入力するフォームが搭載されていて、そのユーザ ID を Firestore で検索して受け取った結果を表示する HTML ファイルを作成します。 <!DOCTYPE html> < html > < head > < title > Firestore Viewer </ title > </ head > < body > < h1 > Firestore Data Viewer </ h1 > < form method = "POST" > < label for = "user_id" > IDを入力: </ label > < input type = "text" id = "user_id" name = "user_id" > < button type = "submit" > 検索 </ button > </ form > < br > {% if data %} < h2 > データ: </ h2 > < p > 名前: {{ data.name }} </ p > < p > 年齢: {{ data.age }} </ p > {% elif message %} < p > {{ message }} </ p > {% endif %} </ body > </ html > requirements.txt 使用するライブラリを、以下の通りに定義します。 Flask==3.1.0 google-cloud-firestore==2.19.0 Dockerfile GKE へデプロイするために Docker イメージを用意する必要があるため、Dockerfile を作成します。 FROM python:3.12-slim WORKDIR /usr/src/app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8080 CMD [ "python", "./main.py" ] Artifact Registry の作成 Docker イメージを保存するための Artifact Registry 標準リポジトリを作成します。 以下のコマンドで、 firestore-app という名前のリポジトリを作成します。 gcloud artifacts repositories create firestore-app \ --repository-format = docker \ --location = asia-northeast1 Artifact Registry にアップロード Cloud Build を利用して Docker イメージをビルドし、作成した Artifact Registry にプッシュします。 プロジェクト ID に置き換えてください の部分を、ご自身のプロジェクト ID に置き換えて、Dockerfile を作成したディレクトリで以下のコマンドを実行します。 PROJECT = " プロジェクト ID に置き換えてください " gcloud builds submit --tag asia-northeast1-docker.pkg.dev/ ${PROJECT} /firestore-app/firestore-app GKE クラスタの設定 GKE クラスタの作成 以下のコマンドで、 firestore-app という名前の Autopilot モードの GKE クラスタを作成します。 Autopilot モードではノード、スケーリング、セキュリティといったクラスタ構成が Google Cloud によって管理されます。GKE のベスト プラクティスと推奨事項を遵守されたクラスタ構成が提供されます。 gcloud container clusters create-auto firestore-app \ --location = asia-northeast1 \ --project = ${PROJECT} サービスアカウントの設定 今回の構成では、GKE クラスタ上で実行されるワークロードから Firestore へのアクセスが必要になります。 GKE Autopilot モード では Workload Identity Federation が常に有効化されており、GKE の ServiceAccount リソースを IAM プリンシパルとして直接関連付けることができます。この機能を利用して、Firestore へのアクセス権を付与します。 Workload Identity Federation についてや、その他の認証方法については以下の記事で解説しておりますので、ご参照ください。 blog.g-gen.co.jp blog.g-gen.co.jp ServiceAccount リソースの作成 以下のコマンドで、Kubernetes ServiceAccout リソース firestore-app を作成します。 kubectl create serviceaccount firestore-app 権限の付与 作成した ServiceAccout を参照する IAM ポリシーを作成します。 以下のコマンドで、作成した ServiceAccout に対して Cloud Datastore 閲覧者 ( roles/datastore.viewer ) ロールを付与します。 プロジェクト番号に置き換えてください の部分を、ご自身のプロジェクト番号に置き換えてください。 PROJECT_NUMBER = " プロジェクト番号に置き換えてください " gcloud projects add-iam-policy-binding projects/ ${PROJECT} \ --role = roles/datastore.viewer \ --member = principal://iam.googleapis.com/projects/ ${PROJECT_NUMBER} /locations/global/workloadIdentityPools/ ${PROJECT} .svc.id.goog/subject/ns/default/sa/firestore-app GKE クラスタにアプリケーションをデプロイ 以前の手順で Artifact Registry にアップロードしたコンテナイメージを使用して、アプリケーションを GKE クラスタに登録します。 以下のマニフェストファイル deployment.yaml を GKE クラスタに適用し、Deployment リソースを作成します。 # deployment.yaml apiVersion : apps/v1 kind : Deployment metadata : name : firestore-app-deployment namespace : default labels : app : firestore-app spec : replicas : 3 selector : matchLabels : app : firestore-app template : metadata : labels : app : firestore-app spec : serviceAccountName : firestore-app # 作成した ServiceAccout の名前 containers : - name : firestore-app image : asia-northeast1-docker.pkg.dev/(プロジェクトID)/firestore-app/firestore-app:latest ports : - containerPort : 8080 resources : requests : cpu : 50m memory : 52Mi 続いて、アプリケーションを公開するための Service を GKE クラスタに登録します。 以下のマニフェストファイル service.yaml を GKE クラスタに適用し、Service リソースを作成します。 # service.yaml apiVersion : v1 kind : Service metadata : name : firestore-app-service namespace : default annotations : cloud.google.com/neg : '{"ingress": true}' spec : selector : app : firestore-app ports : - port : 8080 protocol : TCP targetPort : 8080 type : NodePort Ingress を設定してアプリケーションを公開 最初に Cloud Armor のセキュリティポリシーを構成せずに、アクセス元の制限を設定してしない状態で Ingress リソースを作成してみます。 以下のマニフェストファイル ingress.yaml を GKE クラスタに適用します。 # ingress.yaml apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : firestore-app-ingress namespace : default annotations : kubernetes.io/ingress.class : "gce" spec : defaultBackend : service : name : firestore-app-service port : number : 8080 今回の検証では、Ingress によって作成されるアプリケーションロードバランサは HTTP によってアクセスされます。 HTTPS を使用する場合は、SSL/TLS 証明書を Ingress と関連付ける必要があります。詳細は、以下の記事をご参照ください。 blog.g-gen.co.jp Ingress によって作成されたアプリケーションロードバランサの外部 IP アドレスを確認し、アクセスすると Firestore Viewer というタイトルのアプリケーションの画面が表示されます。 Firestore に追加したユーザ ID を入力すると、そのユーザ ID に対応するユーザ情報が表示されることが確認できます。 Cloud Armor による アクセス制限を適用 Cloud Armor のセキュリティポリシーを設定 アクセス元の IP アドレスを制限する Cloud Armor のセキュリティポリシーを作成します。 まず以下のコマンドで、 firestore-app-policy という名前のセキュリティポリシーを作成します。 gcloud compute security-policies create firestore-app-policy 次に、作成したセキュリティポリシーのデフォルトのルール (優先度 2,147,483,647) を更新し、すべてのアクセス元からのアクセスを制限します。 gcloud compute security-policies rules update 2147483647 \ --security-policy = firestore-app-policy \ --action =" deny-403 " 特定の IP アドレス範囲からのアクセスを許可するルールを作成します。 ルールの優先度はデフォルトのルールよりも高く設定します。以下の例では、優先度 1000 で設定しています。 gcloud compute security-policies rules create 1000 \ --security-policy = firestore-app-policy \ --src-ip-ranges =" <許可する IP アドレス範囲> " \ --action =" allow " BackendConfig を作成 Ingress と Cloud Armor のセキュリティポリシーを関連付けるために、GKE のカスタムリソースである BackendConfig リソースを作成します。 以下のマニフェストファイル backend.yaml を GKE クラスタに適用します。 apiVersion : cloud.google.com/v1 kind : BackendConfig metadata : name : firestore-app-backendconfig spec : securityPolicy : name : firestore-app-policy # 作成したセキュリティポリシーの名前 Service と BackendConfig の関連付け BackendConfig は Ingress リソースに対してではなく、 Service リソースの Service ポートに関連付けられます。GKE Ingress コントローラはアプリケーションロードバランサを作成する際に、この関連付けられた BackendConfig の設定を利用します。 マニフェストファイル service.yaml を以下のように更新して、 GKE クラスタに適用します。 # service.yaml apiVersion : v1 kind : Service metadata : name : firestore-app-service namespace : default annotations : cloud.google.com/neg : '{"ingress": true}' cloud.google.com/backend-config : '{"ports": {"8080":"firestore-app-backendconfig"}}' # 追記 spec : selector : app : firestore-app ports : - port : 8080 protocol : TCP targetPort : 8080 type : NodePort 動作確認 まず、Cloud Armor のセキュリティポリシーで許可していない IP アドレス範囲からアクセスしてみます。 Ingress によって作成されたアプリケーションロードバランサの外部 IP アドレスにアクセスすると、以下のようにアクセスが拒否されることが確認できます。 次に、ポリシーで許可された IP アドレス範囲からアクセスしてみます。 すると、以下のように Firestore Viewer アプリケーションの画面が表示されることが確認できます。 G-gen 編集部 (記事一覧) 株式会社G-genは、サーバーワークスグループとして「クラウドで、世界を、もっと、はたらきやすく」をビジョンに掲げ、クラウドの導入から最適化までを支援している Google Cloud 専業のクラウドインテグレーターです。
G-gen の三浦です。当記事では Microsoft OneDrive から Google ドライブへの移行ツールの検証結果を紹介します。 概要 Microsoft OneDrive からのデータ移行とは 前提条件 制約 検証概要 検証環境 検証の流れ 設定手順 [Google Workspace] 移行用の csv の準備 [Google Workspace] データ移行の実施 [Microsoft 365] 移行後に OneDrive のファイルを更新 [Google Workspace] 差分移行の実施と確認 概要 Microsoft OneDrive からのデータ移行とは 本機能は Google Workspace の管理機能であり、Microsoft OneDrive(以下、OneDrive)のデータを Google ドライブのマイドライブにコピーできます。 参考 : OneDrive からファイルを移行する方法 前提条件 当機能で移行を実施するには、以下2つの上限があります。 Google Workspace 側では 特権管理者ロール が、Microsoft365 側では グローバル管理者ロール が必要です。 以下の特定の Google Workspace エディションでのみ利用可能です。 Business Starter / Standard / Plus Enterprise Standard / Plus Education Fundamentals / Standard / Plus, Teaching and Learning Upgrade Essentials Starter, Essentials, Enterprise Essentials, Enterprise Essential Plus Nonprofits G Suite Basic / Business 制約 当機能には以下のような制限があります。 外部ユーザーが作成したファイルやフォルダは移行できません。 共有ドライブへの移行はできず、マイドライブにのみ移行されます。 その他の制約については、以下の公式ドキュメントを確認してください。 参考 : ファイル移行で移行されるデータ 検証概要 検証環境 検証環境は以下のとおりです。実際の移行ケースを想定し、OneDrive と Google ドライブのドメインおよびユーザー情報を統一した環境で検証しました。 プラットフォーム ドメイン名 ユーザー名 ライセンス Google Workspace miurak-test.com admin@miurak-test.com Google Workspace Business Starter Microsoft 365 miurak-test.com admin@miurak-test.com Microsoft 365 Business Basic OneDrive の構成は以下の通りです。 OneDrive構成1 OneDrive構成2 検証の流れ 以下の手順でデータの移行を実施します。 項目 作業 プラットフォーム 1 移行用の csv の準備 Google Workspace 2 データ移行の実施 Google Workspace 3 移行後に OneDrive のファイルを更新 Microsoft 365 4 差分移行の実施と確認 Google Workspace 設定手順 [Google Workspace] 移行用の csv の準備 Google Workspace の管理コンソール( https://admin.google.com )にログインします。 参考 : 管理コンソールにログインする [データ] > [データのインポートとエクスポート] > [データ移行(新規)] から Microsoft OneDrive の [移行] を選択します。 OneDrive の移行を選択 [手順 2] の [サンプル csv をダウンロード] を選択します。 サンプルcsvのダウンロード ダウンロードした csv を開き、以下のとおりに移行対象の OneDrive のユーザーのメールアドレス を入力し、保存します。 ユーザー移行用の csv の編集 [手順 3] の [サンプル csv をダウンロード] を選択します。 サンプルcsvのダウンロード ダウンロードした csv を開き、以下のとおりに OneDrive と Google ドライブのユーザー紐づけ を入力し、保存します。 Source Email :OneDrive のユーザーのメールアドレス Destination Email :Google Workspace のユーザーのメールアドレス ユーザー紐づけ用の csv の編集 [Google Workspace] データ移行の実施 OneDrive の移行の [手順 1] で [Microsoft OneDriveに接続] を選択し、移行ツールに権限を付与します。 Microsoft OneDriveに接続 Microsoftアカウントにサインイン アクセス許可内容を確認して承諾 [手順2] の [CSV をアップロード] を選択し、前の手順で作成した csv を選択します。 csvをアップロード csvアップロード完了 [手順3] の [CSV をアップロード] を選択し、前の手順で作成した csv を選択します。 csvをアップロード csvアップロード完了 [ステップ4] の [移行を開始] を選択します。 移行を開始 移行が完了したことを確認します。詳細は [移行レポートをエクスポート] または [ユーザーレポートをエクスポート] から確認できます。 移行完了確認 ユーザーレポート Google ドライブのマイドライブを確認し、ファルダとファイルが移行されていることを確認します。 マイドライブ確認1 マイドライブ確認2 [Microsoft 365] 移行後に OneDrive のファイルを更新 データの移行後に OneDrive のフォルダとファイルを追加します。 OneDrive更新1 OneDrive更新2 [Google Workspace] 差分移行の実施と確認 OneDrive の移行の [ステップ 4] の [差分移行を実行] を選択します。 差分移行を実行 移行が成功したことを確認します。 差分移行の成功確認 ユーザーレポート マイドライブを確認し、前手順で追加したフォルダとファイルが存在することを確認します。 差分移行確認1 差分移行確認2 全ての移行が完了したら、[移行を終了する] > [移行を終了して削除] を選択し、移行を終了します。 移行を終了するを選択 移行を終了して削除 三浦 健斗 (記事一覧) クラウドソリューション部 2023年10月よりG-genにジョイン。元オンプレ中心のネットワークエンジニア。ネットワーク・セキュリティ・唐揚げ・辛いものが好き。
G-gen の佐々木です。当記事では Cloud Run から Secret Manager に格納したシークレットを利用する方法を解説します。 事前知識 Cloud Run Secret Manager Cloud Run で Secret Manager を利用する ユースケース 2つの方法 事前準備 シェル変数の設定 シークレットの準備 シークレット作成時に読み込むファイルを作成する シークレットを作成する サービスアカウントの準備 サービスアカウントを作成する サービスアカウントに権限を付与する 環境変数を使用したアクセス サンプルコード(Go) コンテナイメージのビルド Cloud Run のデプロイ 動作確認 ボリュームマウントを使用したアクセス サンプルコード(Go) コンテナイメージのビルド Cloud Run のデプロイ 動作確認 シークレット更新時の動作検証 シークレット更新前の確認 シークレットの更新 動作確認 シークレットをボリュームマウントしたサービスの動作 シークレットを環境変数として読み込むサービスの動作 事前知識 Cloud Run Cloud Run は Google Cloud のマネージドなコンテナ実行環境でアプリケーションを実行することができる、サーバレス コンテナコンピューティング サービスです。 Cloud Run には Cloud Run services、Cloud Run jobs、Cloud Run functions(旧称:Cloud Functions)の3種類がありますが、当記事の内容はこれら3種類で共通のため、記事内では区別せずに Cloud Run と表記しています。 当記事では、 Cloud Run services を例として手順を説明していきます。 それぞれの詳細については以下の記事を参照してください。 参考 : Cloud Runを徹底解説! - G-gen Tech Blog 参考 : Cloud Run jobsを徹底解説! - G-gen Tech Blog 参考 : Cloud Run functionsを徹底解説! - G-gen Tech Blog Secret Manager Secret Manager は、API キーやパスワード、証明書といった機密情報( シークレット )を安全に格納するためのサービスです。Secret Manager に格納されたシークレットはバージョン管理され、IAM を用いてアクセス制御を行うことができます。 Secret Manager に格納されたすべてのシークレットはデフォルトで AES256ビット暗号化が施され、読み取りアクセスはすべて TLS で暗号化されます。 参考 : Secret Manager の概要 Cloud Run で Secret Manager を利用する ユースケース Cloud Run 上のアプリケーションからデータベースにアクセスする場合や、外部 API を利用する場合などの認証情報は、Cloud Run の環境変数に格納することができます。この場合、Cloud Run の設定を閲覧できるユーザーであれば、誰でも認証情報にアクセスすることができてしまいます。 環境変数の代わりに Secret Manager のシークレットとして認証情報を管理することで、そのシークレットに対する IAM 権限を持つプリンシパル(ユーザー、アプリケーションなど)のみにアクセスを制限することができます。また、Cloud Run 側の設定を変えることなく、シークレットのバージョニングやローテーションを容易に行うことができます。 参考 : サービスのシークレットを構成する (Cloud Run services) 参考 : ジョブのシークレットを構成する (Cloud Run jobs) 2つの方法 Cloud Run で Secret Manager を使用する場合、以下に示す2種類の方法のいずれかを用いてシークレットを読み込むことができます。 シークレットの読み込み方法 特徴 Cloud Run の環境変数として読み込む プログラムから環境変数を読み取ることでシークレットの値にアクセスできる。 シークレットの値はコンテナインスタンス起動時に環境変数として読み込まれるため、 シークレットの更新は起動中のコンテナインスタンスに反映されない 点に注意が必要。 シークレットのバージョンを latest ではなく特定のバージョンで固定することで、コンテナインスタンスごとに異なる値が参照されないようにすることが推奨される。 Cloud Run のボリュームとしてマウント シークレットをコンテナインスタンスにボリュームとしてマウントし、ファイルシステム経由で値を読み込む。 シークレットの値は、起動中のインスタンスであっても常に最新のものが読み込まれる。 シークレットを環境変数として読み込む場合、シークレットの値を更新したときにすぐに反映されず、データベース接続不可などの障害を引き起こしてしまう可能性があります。そのため、Cloud Run 上のアプリケーションが頻繁に呼び出されるユースケースではボリュームマウントの使用が推奨されます。 バッチ処理など Cloud Run を定期的に実行するようなユースケースでは、都度コンテナインスタンスが起動されるため、シークレットを環境変数として読み込む方法を使用しても更新時の影響は起こりにくいでしょう。 当記事では、それぞれの設定方法を紹介し、シークレット更新時の動作についても実際に確認してみます。 事前準備 シェル変数の設定 当記事では gcloud CLI を使用して各種リソースの作成を行っていきます。gcloud CLI のインストールについては ドキュメント を参照してください。 まず、実行するコマンドで何度か使用する値をシェル変数として設定しておきます。 PROJECT_ID = { プロジェクトID } # リソースを作成するプロジェクトの ID SERVICE_ACCOUNT_NAME = { サービスアカウントの名前 } # 任意の文字列 REPO_NAME = { Artifact Registry リポジトリの名前 } # 使用するリポジトリの名前 REGION =asia-northeast1 # 東京リージョン(別のリージョンを使いたい場合は変更する) Cloud Run のコンテナイメージを格納する Artifact Registry リポジトリがない場合は事前に作成してください。 参考 : 標準リポジトリを作成する 当記事では、リポジトリが東京リージョン(asia-northeast1)に存在する前提で進めていきます。 シークレットの準備 シークレット作成時に読み込むファイルを作成する まず、シークレットを作成する際に読み込むテキストファイルを作成します。このファイルには、シークレットの値を記述しておきます。 # シークレットの値を記述したファイルを作成 $ echo " hello " > secret.txt シークレットの値はシークレット作成時に直接指定することもできますが、入力した値はプロセスのリストに平文で表示され、コマンドの実行履歴としても残ってしまいます。そのため、ファイルから値を読み込む方法が推奨されています。 シークレットを作成する 作成したテキストファイルを使用して、Cloud Run からアクセスする Secret Manager のシークレットを作成します。 当記事では mysecret という名前でシークレットを作成します。このシークレットの名前は、値を参照する際にキーとして使用されます。 # ファイルを指定してシークレットを作成する $ gcloud secrets create mysecret \ --project = ${PROJECT_ID} \ --data-file = secret.txt 参考: gcloud secrets create サービスアカウントの準備 サービスアカウントを作成する Cloud Run に設定するサービスアカウントを作成します。 # サービスアカウントを作成する $ gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \ --project = ${PROJECT_ID} 参考: gcloud iam service-accounts create サービスアカウントに権限を付与する 作成したサービスアカウントに対して以下の IAM ロールを紐付け、シークレットのアクセス権限を付与します。 Secret Manager のシークレット アクセサー ( roles/secretmanager.secretAccessor ) # サービスアカウントに対してシークレットへのアクセス権を付与する $ gcloud secrets add-iam-policy-binding mysecret \ --member =" serviceAccount: ${SERVICE_ACCOUNT_NAME} @ ${PROJECT_ID} .iam.gserviceaccount.com " \ --role =" roles/secretmanager.secretAccessor " 環境変数を使用したアクセス サンプルコード(Go) まずは、シークレットを Cloud Run の環境変数として読み込む方法を試してみます。 以下のサンプルコード( main.go )は、環境変数 SECRET から読み込んだ値を表示するだけのウェブサーバーを実行します。 // main.go package main import ( "fmt" "net/http" "os" ) func main() { http.HandleFunc( "/" , func (w http.ResponseWriter, r *http.Request) { // Read the secret from the environment variable SECRET secretVal := os.Getenv( "SECRET" ) fmt.Fprintf(w, "Environment Secret: %s" , secretVal) }) http.ListenAndServe( ":8080" , nil ) } コンテナイメージのビルド Cloud Build を使用してコンテナイメージをビルドし、Artifact Registry のリポジトリにプッシュします。 先ほどの main.go ファイルがあるディレクトリで、以下のコマンドを実行します。コンテナイメージ名は env-secret とします。 # Cloud Build で Buildpack を使用してコンテナイメージをビルドする $ gcloud builds submit --pack image = ${REGION} -docker.pkg.dev/ ${PROJECT_ID} / ${REPO_NAME} /env-secret このコマンドでは Buildpack を使用することで、Dockerfile を用意することなく、ソースコードからコンテナイメージをビルドしています。 参考: Buildpack を使用してアプリケーションをビルドする Cloud Run のデプロイ Artifact Registry にプッシュしたコンテナイメージを使用して、Cloud Run サービスをデプロイします。サービス名はコンテナイメージと同じ env-secret とします。 # Secret を環境変数として読み込む Cloud Run サービスをデプロイする $ gcloud run deploy env-secret \ --image = ${REGION} -docker.pkg.dev/ ${PROJECT_ID} / ${REPO_NAME} /env-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --service-account = ${SERVICE_ACCOUNT_NAME} @ ${PROJECT_ID} .iam.gserviceaccount.com \ --allow-unauthenticated \ --set-secrets = SECRET =mysecret:latest シークレットは --set-secrets フラグを使用して、以下の形式で設定することができます。 --set-secrets={任意の環境変数名}={シークレットの名前}:{シークレットのバージョン} Cloud Run の環境変数を確認すると、値としてシークレットが設定されていることがわかります。この環境変数のキー( SECRET )を使用してシークレットの値を読み込むことができます。 シークレットを環境変数として読み込む場合 参考: gcloud run deploy 動作確認 curl コマンドやブラウザを使用して、env-secret サービスにアクセスしてみます。 # env-secret の URL にアクセスする $ curl $( gcloud run services describe env-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --format =' value(status.url) ' ) 環境変数から読み込まれたシークレットの値を含む、以下のレスポンスが返ってきます。 Environment Secret: hello ボリュームマウントを使用したアクセス サンプルコード(Go) 次に、シークレットを Cloud Run のコンテナインスタンスにボリュームマウントし、ファイルシステムからシークレットの値を読み込む方法を試してみます。 以下のコード( main.go )は、 /mnt ディレクトリにマウントしたシークレットの値を読み込み、表示するだけのウェブサーバーを実行します。 // main.go package main import ( "fmt" "net/http" "os" ) func main() { http.HandleFunc( "/" , func (w http.ResponseWriter, r *http.Request) { // Read the secret from the file /mnt/secret secretVal, err := os.ReadFile( "/mnt/secret" ) if err != nil { fmt.Fprintf(w, "Error reading secret: %v" , err) return } fmt.Fprintf(w, "Mount Secret: %s" , secretVal) }) http.ListenAndServe( ":8080" , nil ) } コンテナイメージのビルド main.go があるディレクトリで以下のコマンドを実行し、コンテナイメージをビルドします。イメージ名は mnt-secret とします。 # Cloud Build で Buildpack を使用してコンテナイメージをビルドする $ gcloud builds submit --pack image =asia-northeast1-docker.pkg.dev/ ${PROJECT_ID} / ${REPO_NAME} /mnt-secret Cloud Run のデプロイ サービス名をコンテナイメージと同じ mnt-secret として、新たな Cloud Run サービスをデプロイします。 # Secret をボリュームマウントする Cloud Run サービスをデプロイする $ gcloud run deploy mnt-secret \ --image = ${REGION} -docker.pkg.dev/ ${PROJECT_ID} / ${REPO_NAME} /mnt-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --service-account = ${SERVICE_ACCOUNT_NAME} @ ${PROJECT_ID} .iam.gserviceaccount.com \ --allow-unauthenticated \ --set-secrets = /mnt/ secret =mysecret:latest シークレットをボリュームマウントする場合、 --set-secrets フラグを使用して、以下の形式で設定することができます。 --set-secrets={マウントするパス}={シークレットの名前}:{シークレットのバージョン} シークレットは Cloud Run の環境変数ではなく、ボリュームとしてマウントされています。当記事の設定の場合、マウントパス /mnt/secret からシークレットの値を読み込むことができます。 シークレットをボリュームマウントする場合 動作確認 curl コマンドやブラウザを使用して、mnt-secret サービスにアクセスしてみます。 # mnt-secret の URL にアクセスする $ curl $( gcloud run services describe mnt-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --format =' value(status.url) ' ) ボリュームマウントされたシークレットの値を含む、以下のレスポンスが返ってきます。 Mount Secret: hello シークレット更新時の動作検証 シークレット更新前の確認 シークレットの読み込み方法ごとの、シークレット更新時の動作を確認してみます。 まず、シークレット更新前にそれぞれのサービスにアクセスし、コンテナインスタンスを起動状態にします。 # env-secret の URL にアクセスする $ curl $( gcloud run services describe env-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --format =' value(status.url) ' ) # mnt-secret の URL にアクセスする $ curl $( gcloud run services describe mnt-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --format =' value(status.url) ' ) シークレットの更新 シークレットの新しい値を記述したファイルを用意します。 # シークレットの値を記述したファイルを作成する $ echo " world " > newsecret.txt 以下のコマンドで、シークレットに新しいバージョンを追加します。 # シークレットを更新する $ gcloud secrets versions add mysecret \ --project = ${PROJECT_ID} \ --data-file = newsecret.txt Cloud Run からはシークレットの latest バージョンを参照するようにしているため、サービスを編集することなくシークレットの更新が自動で反映されます。 動作確認 シークレットをボリュームマウントしたサービスの動作 先に、mnt-secret の動作確認を行います。以下のコマンドでサービスにアクセスします。 # mnt-secret の URL にアクセスする $ curl $( gcloud run services describe mnt-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --format =' value(status.url) ' ) レスポンスを確認すると、以下のように更新後のシークレットの値が表示されます。このように、 シークレットをボリュームマウントした場合はシークレットの値は常に最新のものが読み込まれます。 Mount Secret: world シークレットを環境変数として読み込むサービスの動作 env-secret の動作確認を行います。以下のコマンドでサービスにアクセスします。 # env-secret の URL にアクセスする $ curl $( gcloud run services describe env-secret \ --project = ${PROJECT_ID} \ --region = ${REGION} \ --format =' value(status.url) ' ) レスポンスを確認すると、以下のように 更新前 のシークレットの値が表示されます。 シークレットの値はコンテナインスタンス起動時に環境変数として読み込まれる ため、起動中のコンテナインスタンスは更新前の値を使用してしまいます。 Environment Secret: hello しばらく待機し、コンテナインスタンスがすべて停止したあと改めてサービスにアクセスすると、更新後のシークレットが読み込まれることがわかります。 Environment Secret: world 佐々木 駿太 (記事一覧) G-gen 最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月に G-gen にジョイン。Google Cloud Partner Top Engineer に選出(2024 / 2025 Fellow / 2026)。好きな Google Cloud プロダクトは Cloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
G-gen の杉村です。Google Cloud の Cloud Run functions を使い、Slack のスラッシュコマンドを作ってみました。主に Google Cloud 側の開発に関する概要を解説します。 はじめに 当記事について 免責事項 構成 構成図 レシーバー関数とバックエンド関数を分ける理由 Slack の署名検証 Slack へのメッセージ返信 レシーバー関数の開発 Slack からの HTTP リクエスト ソースコード Pub/Sub クライアントの生成 Slack からの署名を検証 Slack からのリクエスト body を取得 環境変数からトピック ID を取得 エラーメッセージ バックエンド関数の開発 Pub/Sub トリガー関数のデプロイ Pub/Sub から受け取るメッセージ ソースコード Pub/Sub メッセージの取得 response_url への返信 Slack 側の設定 はじめに 当記事について Google Cloud(旧称 GCP)の Cloud Run functions で Slack のスラッシュコマンドを開発した際の事例を紹介します。なお当記事では Slack アプリの設定方法の詳細などは解説せず、Cloud Run functions 側のソースコードを中心に解説します。 Cloud Run functions (旧称 Cloud Functions)は、サーバーレスなプログラム実行基盤です。ソースコードを開発してアップロードするだけで、最長60分間(第2世代、HTTP 関数の場合)のプログラム実行が可能です。詳細は以下の記事をご参照ください。 blog.g-gen.co.jp スラッシュコマンド とは、Slack から / で始まるコマンドを実行することで、様々なタスクを実行できる Slack の機能です。組み込み済みのスラッシュコマンドの例として、指定した時間にユーザーにリマインダー通知をしてくれる /remind などがあります。ユーザーはバックエンドプログラムを用意することで、独自のカスタムコマンドを定義できます。 参考 : Enabling interactivity with Slash commands 参考 : 組み込みショートカット 免責事項 当記事で紹介するプログラムのソースコードは、ご自身の責任のもと、使用、引用、改変、再配布して構いません。 ただし、同ソースコードが原因で発生した不利益やトラブルについては、当社は一切の責任を負いません。 当記事で紹介するプログラムのソースコードは検証のために作成されたものであり、セキュリティやエラーハンドリング等の運用性が十分考慮されたものではありません。利用する際はこれらを十分考慮の上、ご自身の状況にあわせてご利用ください。 構成 構成図 当記事では、以下のような環境を開発しました。 Slack にはアプリを設定し、スラッシュコマンドから呼び出せるように設定します。スラッシュコマンドのバックエンドプログラムとして、Slack からのリクエストを受け取る「レシーバー関数」を配置します。レシーバー関数はメッセージキューである Pub/Sub トピックにメッセージを送信します。メッセージを検知すると、「バックエンド関数」が起動します。バックエンド関数はメインの処理を行い、Slack に返信を返します。 構成図 レシーバー関数とバックエンド関数を分ける理由 途中にメッセージキューを挟み、レシーバー関数とバックエンド関数を分けている理由は、スラッシュコマンドのタイムアウト仕様にあります。スラッシュコマンドは、バックエンドプログラムに処理を送ってから 3秒以内 に HTTP 200のレスポンスを受け取らないと、タイムアウトしてエラー終了します。 これを防ぐため、まずレシーバー関数でスラッシュコマンドを受け取り、いったんメッセージキューに処理要求を送ってから、Slack に HTTP 200を返します。これにより、バックエンド関数は3秒以上の処理を行うことができます。なおバックエンド関数は返信先のチャンネルやユーザーを、メッセージ内の情報から知ることができます。 なお、Cloud Run functions がコールドスタート(ゼロスケールから最初のコンテナインスタンスが起動するまでの遅延)する際に3秒のタイムアウトに抵触する場合があります。コールドスタート時の初回レスポンスを早くするには、function の割り当て CPU 量を増やしたり、重い処理を避けたり、Python の場合は不要な import を避けるなどの対策をしてください。 Slack の署名検証 Slack のスラッシュコマンドがバックエンドプログラムに HTTP リクエストを送信するとき、Slack は Signing Secret を使ってリクエストを署名し、 x-slack-signature ヘッダーに格納します。Signing Secret は Slack アプリごとに発行されます。この署名をバックエンドプログラム側(当環境ではレシーバー関数)で検証することで、リクエストが確かに想定した Slack アプリから発信されていることを確かめられます。これにより、想定しない利用者からのリクエストを拒否することができます。 当環境では、Signing Secret を Secret Manager に格納して Cloud Run functions から参照しています。Signing Secret は、Slack アプリ作成後に「Basic Information」欄から取得できます。 参照 : Verifying requests from Slack この署名検証があるため、Cloud Run functions に認証をかける必要はありません。Cloud Run functions は未認証リクエスト許可する HTTP トリガー関数としてデプロイします。 Slack へのメッセージ返信 Slack からバックエンドプログラムに送信される HTTP リクエストには、channel_id、user_id、command(スラッシュコマンドのコマンドライン)、text(コマンドラインに付加されたパラメータ)などに加え、 response_url と呼ばれる HTTP エンドポイント URL が含まれています。 この response_url は、スラッシュコマンドが実行されるたびにユニークに発行される一時的な URL です。30分間のみ有効で、この URL に対して POST リクエストを送信することで、認証なしで、スラッシュコマンドの実行者にだけ見える形式で表示されます(「 あなただけに表示されています 」)。 後者が response_url で投稿されたコメント 当環境ではこの response_url を使い、Slack の認証情報(トークン)を保持することなく、バックエンド関数から Slack にコメントを投稿しています。 なお全員から見える通常のコメントとして返信したい場合は、OAuth トークンを使い認証したうえでコメントを投稿します。 参照 : Handling user interaction in your Slack apps レシーバー関数の開発 Slack からの HTTP リクエスト Slack のスラッシュコマンドからレシーバー関数に送られる HTTP POST リクエストの body は、以下のようになります(Slack 公式ドキュメントから引用)。 token =gIkuvaNzQIHg97ATvDxqgjtO & team_id =T0001 & team_domain =example & enterprise_id =E0001 & enterprise_name =Globular%20Construct%20Inc & channel_id =C2147483705 & channel_name =test & user_id =U2147483697 & user_name =Steve & command= /weather & text = 94070 & response_url =https://hooks.slack.com/commands/ 1234 / 5678 & trigger_id = 13345224609 . 738474920 .8088930838d88f008e0 & api_app_id =A123456 参考 : Enabling interactivity with Slash commands - 2. Preparing your app to receive commands このうち、 command=/weather の部分が入力されたコマンド本体で、 text の部分がそれに続いて入力された引数です。 response_url が、返信に使える response_url であり、この URL に以下のように POST リクエストを送ることで、チャンネルに返信することができます。 POST https://hooks.slack.com/commands/ 1234 / 5678 Content-type: application/json { " text " : " 返信内容のテキスト " } ソースコード 以下は、レシーバー関数のソースコードです。前掲の「免責事項」をご確認のうえご利用ください。 GitHub - slack-slash-commands-with-cloud-run-functions/backend-example/ なお、ソースコードは Python 3.12.3 の環境で開発されています。 以下で、重要なポイントのみを解説します。 Pub/Sub クライアントの生成 28-30行目 # 環境変数の取得、Pub/Sub クライアントの生成 PROJECT_ID = os.environ.get( "PROJECT_ID" , None ) PUBSUB_CLIENT = google.cloud.pubsub_v1.PublisherClient() PUBSUB_CLIENT をグローバルスコープで生成しています。コストが高い代わりに結果を再利用できる処理は、グローバルスコープで実行することで、Cloud Run functions のコンテナインスタンスが残っている限り再利用できるため、パフォーマンスが向上します。 参考 : グローバル変数を使用して将来の呼び出しでオブジェクトを再利用する Slack からの署名を検証 33-40行目 # Slack からの署名を検証する関数 def verify_signature (request): request.get_data() verifier = SignatureVerifier(os.environ[ "SLACK_SIGNING_SECRET" ]) if not verifier.is_valid_request(request.data, request.headers): raise ValueError ( "Invalid request/credentials." ) Slack からの署名を検証するために、関数 verify_signature を呼び出しています。同関数では、Cloud Run functions 環境変数 SLACK_SIGNING_SECRET を取得し、POST リクエストの署名を検証して、正当な署名を確認できなければ ValueError を返します。 SLACK_SIGNING_SECRET は環境変数に直接定義するのではなく、Secret Manager から取得するのが望ましいでしょう。 参考 : シークレットを構成する なお、この関数の実装は Google Cloud が公開するチュートリアルドキュメントとソースコードを参考にしました。使用するライブラリは Slack 公式の slackclient です。 参考 : Slack のチュートリアル - スラッシュ コマンド 参考 : PyPI - Python slackclient また、この関数のを呼び出し元の50-62行目では、テストモードのときに例外を無視するコードを入れています。これは functions_framework を使いローカルでテストする場合を想定しています。 blog.g-gen.co.jp Slack からのリクエスト body を取得 64-66行目 # Slack からのリクエストを辞書型変数と JSON に格納 body_dict = request.form.to_dict(flat= True ) body_json = json.dumps(body_dict) この部分で、POST リクエストの body を辞書型変数および JSON 形式の文字列として変数に格納しています。このレシーバー関数では、Slack からのリクエスト body を JSON 形式にしてそのまま Pub/Sub にパブリッシュしています。JSON は、のちにバックエンド関数がパースして処理に使います。 環境変数からトピック ID を取得 69-72行目 # コマンド名に応じた環境変数から Pub/Sub トピック ID を取得 command = body_dict[ "command" ].lstrip( "/" ).replace( "-" , "_" ).upper() ENV_NAME = f "TOPIC_ID_{command}" TOPIC_ID_FOR_COMMAND = os.environ.get(ENV_NAME, None ) レシーバー関数を、複数のスラッシュコマンドとバックエンド関数のために使い回せる汎用的なものにするために、リクエスト内のスラッシュコマンドに応じた Pub/Sub トピック ID を取得できるようにしています。規模が大きくなればコマンド名とトピック ID の対応を Firestore などのデータベースに保持しても良いですが、ここでは簡略化のために環境変数に保持しています。 エラーメッセージ 74-77行目 # 環境変数が定義されていない場合はエラー終了。Slack にメッセージを返すため 200 で終了 if TOPIC_ID_FOR_COMMAND is None : logger.exception(f "環境変数 {ENV_NAME} が設定されていません。" ) return f ":warning: コマンド {body_dict['command']} は未対応です。" , 200 87-89目 except Exception as e: # Slack にメッセージを返すため 200 で終了 logger.exception(e) return f ":bomb: 予期せぬエラーが発生しました。エラーメッセージ : {e}" , 200 ここで、エラー(例外)であるにも関わらずレスポンスのステータスコードとして 200 を使用しているのには理由があります。Slack のスラッシュコマンドでは、バックエンドプログラムが 200 以外のステータスコードを返した場合、関数からのレスポンスは Slack チャンネル側に表示されず、 /(コマンド名) はエラー「dispatch_failed」により失敗しました というメッセージに統一されてしまいます。 ここでは Slack 側に任意のメッセージを返すために、ステータスコードを 200 としています。逆に認証エラーやメソッド違反の場合は、Slack にメッセージを返すことが適切ではありませんので、400番台のステータスコードを返しています。 ステータスコード 200 でレスポンスした場合 ステータスコード 400 でレスポンスした場合 なお上記のスクリーンショットからわかるように、バックエンドプログラムからのレスポンスはコマンドの実行者にだけ見える形式で表示されます(「 あなただけに表示されています 」)。 バックエンド関数の開発 Pub/Sub トリガー関数のデプロイ レシーバー関数が Pub/Sub にパブリッシュしたメッセージをトリガーとしてバックエンド関数を起動するには、バックエンド関数を Pub/Sub トリガーの関数としてデプロイします。gcloud コマンドでのデプロイ方法を例に挙げると、以下のようになります。 FUNCTION = " backend-sample " PROJECT_ID = " my-project " TOPIC_ID = " backend-sample " TRIGGER_SA = " receive-slash-command " gcloud functions deploy ${FUNCTION} \ --gen2 \ --project = ${PROJECT_ID} \ --region = asia-northeast1 \ --runtime = python312 \ --memory = 128Mi \ --entry-point = main \ --trigger-topic = ${TOPIC_ID} \ --trigger-service-account =" ${TRIGGER_SA} @ ${PROJECT_ID} .iam.gserviceaccount.com " このコマンドを使ってデプロイすると、Eventarc トリガーというオブジェクトが作成されます。この Eventarc トリガーが、 --trigger-topic で指定した Pub/Sub トピックとCloud Run functions を仲介して、関数を起動します。Eventarc トリガーは --trigger-service-account で指定したサービスアカウントの認証情報を利用して関数を起動しますので、このサービスアカウントには Cloud Run サービス起動元( roles/run.servicesInvoker )ロールが必要です。ここでは、レシーバー関数にアタッチしたサービスアカウントを使うように指定していますが、独立したサービスアカウントを作成しても構いません。 Pub/Sub から受け取るメッセージ バックエンド関数は、以下のようなメッセージを Pub/Sub から受信し、main 関数の引数の cloud_event として受け取ります。 [ { " ackId ": " BhYsXUZIUTcZCGhRDk9eIz81IChFFwkDxxxxx.... ", " message ": { " data ": " ewogICJ0b2tlbiI6ICJnSWt1dmFOelFJSGc5N0FUdkR4cWdqdE8iLAogICJ0ZWFtX2lkIjogIlQw MDAxIiwKICAidGVhbV9kb21haW4iOiAiZXhhbXBsZSIsCiAgImNoYW5uZWxfaWQiOiAiQzIxNDc0 ODM3MDUiLAogICJjaGFubmVsX25hbWUiOiAidGVzdCIsCiAgInVzZXJfaWQiOiAiVTIxNDc0ODM2 OTciLAogICJ1c2VyX25hbWUiOiAiU3RldmUiLAogICJjb21tYW5kIjogIi93ZWF0aGVyIiwKICAi dGV4dCI6ICI5NDA3MCIsCiAgImFwaV9hcHBfaWQiOiAiQTEyMzQ1NiIsCiAgImlzX2VudGVycHJp c2VfaW5zdGFsbCI6ICJmYWxzZSIsCiAgInJlc3BvbnNlX3VybCI6ICJodHRwczovL2hvb2tzLnNs YWNrLmNvbS9jb21tYW5kcy8xMjM0LzU2NzgiLAogICJ0cmlnZ2VyX2lkIjogIjEzMzQ1MjI0NjA5 LjczODQ3NDkyMC44MDg4OTMwODM4ZDg4ZjAwOGUwIiwKfQo =", " messageId ": " 13511712435836909 ", " publishTime ": " 2025-01-12T05:21:28.259Z " } } ] data の内容は base64 エンコードされています。上記の data を base64 でデコードすると、以下のような JSON になります。Slack からのリクエスト body が、そのまま JSON になっています。バックエンド関数では、これをパースすればよいことになります。 { " token ": " gIkuvaNzQIHg97ATvDxqgjtO ", " team_id ": " T0001 ", " team_domain ": " example ", " channel_id ": " C2147483705 ", " channel_name ": " test ", " user_id ": " U2147483697 ", " user_name ": " Steve ", " command ": " /weather ", " text ": " 94070 ", " api_app_id ": " A123456 ", " is_enterprise_install ": " false ", " response_url ": " https://hooks.slack.com/commands/1234/5678 ", " trigger_id ": " 13345224609.738474920.8088930838d88f008e0 " , } ソースコード 以下は、バックエンド関数のソースコードです。前掲の「免責事項」をご確認のうえご利用ください。 GitHub - slack-slash-commands-with-cloud-run-functions/backend-example/ 以下、重要なポイントのみ解説します。 Pub/Sub メッセージの取得 28-32行目 @ functions_framework.cloud_event def main (cloud_event): Pub/Sub から受け取ったメッセージの data を JSON として取得して辞書型に変換 request = base64.b64decode(cloud_event.data[ "message" ][ "data" ]).decode() request_dict = json.loads(request) ここでは前述のとおり、Pub/Sub から受け取ったメッセージを base64 デコードして、辞書型変数として格納しています。 response_url への返信 45-48行目 # response_url に対して返信 headers = { 'Content-type' : 'application/json' } data = { 'text' : post_text} requests.post(response_url, headers=headers, data=json.dumps(data)) ここでは、response_url に対して HTTP POST リクエストを送信して、Slack チャンネルにコメントを投稿しています。 Content-type を application/json にし、 {'text': '投稿する内容'} とするのが決まりです。response_url は30分間限定で認証なしでコメントを受け付ける URL なので、Slack の認証情報は必要ありません。 前者がレシーバー関数からのレスポンス、後者がバックエンド関数から投稿されたコメント ただし、この response_url を使って送信された返信は、コマンド実行者にだけ「あなただけに表示されています」と表示されるメッセージです。チャンネル全体に見えるコメントを投稿するには、OAuth トークンを使って Slack API に対してコメントを投稿します。その方法はこの記事では詳細は解説しませんが、公式ドキュメント等をご参照ください。 参考 : Send or schedule a message Slack 側の設定 Slack 側の設定については、インターネット上に多くの解説があるため、当記事では深く触れません。大まかに言うと、以下の手順となります。 Slack アプリを作成(作成後、Signing Secret 等が取得可能になる) アプリにスラッシュコマンドを追加 Slack ワークスペースにアプリをインストール 以下の公式ドキュメントも参考にしてください。 参考 : Slack - Enabling interactivity with Slash commands 参考 : Google Cloud - Slack のチュートリアル - スラッシュ コマンド 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 12資格、Google Cloud認定資格11資格。X (旧 Twitter) では Google Cloud や AWS のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-gen の杉村です。Google ドライブの 共有ドライブ でファイルやフォルダを、他の共有ドライブやマイドライブに移動するために必要な権限について紹介します。 概要 はじめに 共有ドライブの権限 同一共有ドライブ内 マイドライブから共有ドライブ 共有ドライブからマイドライブ 共有ドライブ間 概要 はじめに 当記事では、Google ドライブの 共有ドライブ でファイルやフォルダを、他の共有ドライブやマイドライブに移動するために必要な権限について紹介します。 移動する対象がファイルであるか、フォルダであるかによって、必要な権限が異なります。また、移動元や移動先がマイドライブであるか、共有ドライブであるかによっても異なります。 公式ドキュメントには、マイドライブから共有ドライブへファイルやフォルダを移動するときに必要な権限については記載があります。しかし、逆に共有ドライブからマイドライブへの移動の場合や、共有ドライブから他の共有ドライブへの移動の場合については、記載がありません。そのため当記事では、当社で実施した検証の内容も含まれます(検証は2025年2月に実施)。 参考 : 組織のコンテンツを共有ドライブに移動する 参考 : 共有ドライブにファイルやフォルダを移動する 共有ドライブの権限 共有ドライブには、 メンバー として、Google アカウントや Google グループを追加できます。その際に、閲覧者、閲覧者(コメント可)、投稿者、コンテンツ管理者、管理者の中から、メンバーに与える権限を選択します。 共有ドライブの権限 各権限では、以下のような作業を行うことができます。 名称 含まれる権限の概要 閲覧者 ファイルやフォルダの閲覧 閲覧者(コメント可) 上記に加え、コメントの追加 投稿者 上記に加え、ファイルやフォルダの新規作成、 編集、ファイルへの権限追加 コンテンツ管理者 上記に加え、ファイルやフォルダの削除、 共有ドライブ内でのファイルやフォルダの移動、 フォルダへの権限追加 管理者 上記に加え、ほとんどの権限 参考 : 共有ドライブのファイルへのアクセスの仕組み 同一共有ドライブ内 1つの共有ドライブの中でファイルやフォルダを移動するには、 コンテンツ管理者 権限が必要です。 共有ドライブに対してコンテンツ管理者権限を持っていれば、その共有ドライブ内で自由にファイルやフォルダを移動可能です。 マイドライブから共有ドライブ ファイル をマイドライブから共有ドライブへ移動するには、移動先の共有ドライブに 投稿者以上 の権限が必要です。移動元は、自分のマイドライブのほか、編集者権限が付与されていれば他人のマイドライブのファイルも移動できます。 移動先\移動元 自分のマイドライブ 他人のマイドライブ(共有アイテム) 管理者 ◯ ◯ コンテンツ管理者 ◯ ◯ 投稿者 ◯ ◯ 一方で フォルダ の場合は、移動先の共有ドライブに 管理者 の権限が必要です。ファイルの場合は投稿者以上があれば十分でしたが、フォルダの移動にはより強い権限が必要になっています。 移動先\移動元 自分のマイドライブ 他人のマイドライブ(共有アイテム) 管理者 ◯ ◯ コンテンツ管理者 ✕ ✕ 投稿者 ✕ ✕ 共有ドライブからマイドライブ ファイルやフォルダを共有ドライブからマイドライブへ移動するには、移動元の共有ドライブに 管理者 の権限が必要です。移動先としては自分のマイドライブが選択できるほか、自分に編集者が付与されていれば他人のマイドライブにあるフォルダも選択できます。 移動先\移動元 管理者 コンテンツ管理者 投稿者 自分のマイドライブ ◯ ✕ ✕ 他人のマイドライブ(共有されたフォルダ) ◯ ✕ ✕ 移動の対象がファイルであるかフォルダであるかによって、必要な権限は変わりません。 共有ドライブ間 ファイル を共有ドライブから別の共有ドライブへ移動するには、移動元の共有ドライブには 管理者 権限が、移動先の共有ドライブには 投稿者以上 の権限が必要です。 移動先\移動元 管理者 コンテンツ管理者 投稿者 管理者 ◯ ✕ ✕ コンテンツ管理者 ◯ ✕ ✕ 投稿者 ◯ ✕ ✕ 移動の対象が フォルダ の場合、共有ドライブから別の共有ドライブへ移動するには、移動元と移動先の両方に 管理者 の権限が必要です。ファイルの場合は、移動先の共有ドライブには投稿者以上の権限があれば十分だったのに対して、フォルダの場合はより強い権限が必要です。 移動先\移動元 管理者 コンテンツ管理者 投稿者 管理者 ◯ ✕ ✕ コンテンツ管理者 ✕ ✕ ✕ 投稿者 ✕ ✕ ✕ なお、移行元の共有ドライブの権限が投稿者である場合、「移動」のメニューがグレーアウトしていて選択できません。投稿者には、そもそもファイルやフォルダの移動権限がないためです。 投稿者で移動を試みた場合 移行元にコンテンツ管理者を持っている場合、「移動」自体は選択できるものの、移動先の選択ダイアログで他の共有ドライブがグレーアウトされて選択できないようになっています。 コンテンツ管理者で移動を試みた場合 なお当記事で紹介したファイル移動は、 異なる Google Workspace 組織(ドメイン)間 でも実行可能です。 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 12資格、Google Cloud認定資格11資格。X (旧 Twitter) では Google Cloud や AWS のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-gen の杉村です。2025年1月のイチオシ Google Cloud(旧称 GCP)アップデートをまとめてご紹介します。記載は全て、記事公開当時のものですのでご留意ください。 はじめに 2つの新しい Google Cloud 認定資格が一般公開(GA)に Vertex AI RAG Engine が一般公開(GA) Vertex AI Search for retail が 〜 for commerce に改名 Cloud Run からコンテナイメージの暗黙的な読み取り権限が終了 Cloud Run jobs でサイドカーコンテナのデプロイが可能に(Preview) VPC で RDMA 対応 NIC が使用可能に Google Workspace で AI 機能が標準に。同時に大幅な料金改定 Compute Engine で C4A インスタンスタイプが登場 BigQuery Data Transfer Service が MySQL と PostgreSQL に対応(Preview) BigQuery でコンソール画面から個人別の設定が可能に BigQuery metastore が Public Preview 公開 Gemini in BigQuery の有償化が延期 Gemini サイドパネルで日本語での画像生成が可能に Google Sheets の Gemini でデータ説明やチャート生成が可能に Spanner に index advisor が登場(GA) Imagen 3 の新バージョン「imagen-3.0-generate-002」 Cloud DNS で DNS64 機能が Preview 公開 はじめに 当記事では、毎月の Google Cloud(旧称 GCP)や Google Workspace(旧称 GSuite)のアップデートのうち、特に重要なものをまとめます。 また当記事は、Google Cloud に関するある程度の知識を前提に記載されています。前提知識を得るには、ぜひ以下の記事もご参照ください。 blog.g-gen.co.jp リンク先の公式ガイドは、英語版で表示しないと最新情報が反映されていない場合がありますためご注意ください。 2つの新しい Google Cloud 認定資格が一般公開(GA)に Google Cloud 認定資格 (2025-01) 以下の2つの新しい Google Cloud 認定資格が一般公開(GA)になった。いずれも Associate レベルの試験。 Associate Google Workspace Administrator Associate Data Practitioner いずれも、G-gen Tech Blog で対策記事が公開されている。 blog.g-gen.co.jp blog.g-gen.co.jp Vertex AI RAG Engine が一般公開(GA) Introducing Vertex AI RAG Engine: Scale your Vertex AI RAG pipeline with confidence (2025-01-10) Vertex AI RAG Engine が一般公開(GA)。Gemini 等を使った生成 AI アプリケーションから RAG を行うための API。 Cloud Storage、Google ドライブ、Vertex AI Search データストア等の情報を使ってグラウンディング。 Vertex AI RAG Engine Vertex AI Search for retail が 〜 for commerce に改名 Vertex AI Search for commerce release notes - January 10, 2025 (2025-01-10) Vertex AI Search for retail が改名して「Vertex AI Search for commerce」になった。かつては Retail Search と呼ばれていた。名称変遷は Retail Search → Vertex AI Search for retail(VAISR)→ Vertex AI Search for commerce。 Vertex AI Search for commerce は、EC サイトなど小売向けの検索エンジン。商品カタログをもとに意味論検索を実装できる。 Cloud Run からコンテナイメージの暗黙的な読み取り権限が終了 Cloud Run release notes - January 13, 2025 (2025-01-13) 以前から予告されていたとおり、Cloud Run 管理者ロールとCloud Run デベロッパーロールがもともと持っていた Artifact Registry のコンテナイメージに対する暗黙的な読み取り権限が消滅した。 適切に対応していないと、CI/CD パイプラインなどが権限不足でエラー終了する可能性がある。詳細は以下の記事を参照。 blog.g-gen.co.jp Cloud Run jobs でサイドカーコンテナのデプロイが可能に(Preview) Deploy multiple containers to a job (sidecars) (2025-01-14) Cloud Run jobs でサイドカーコンテナのデプロイが可能に(Preview)。 これまでは Cloud Run services のみ、サイドカーコンテナに対応していた。Prometheus によるモニタリングなどがユースケース。 VPC で RDMA 対応 NIC が使用可能に RDMA network profile (2025-01-15) Google Cloud の VPC で RDMA 対応 NIC が使えるようになった。 RDMA(Remote Direct Memory Access)とは、別々の筐体に搭載されたメモリ間で、ネットワークを経由し、かつ CPU や OS をバイパスして直接データを転送する技術。HPC や AI ワークロードで、分散処理のための高速なメモリ間データ共有に使われる。 Google Workspace で AI 機能が標準に。同時に大幅な料金改定 Google Workspace Business エディションの AI 機能と料金改定 (2025-01-16) Business Starter や Enterprise Starter など一部のエディションを除き、AI 機能(Gemini for Google Workspace)がアドオンライセンス不要になる。これにより Gmail や Docs、Sheets、Meet などでの Gemini 機能が標準になる。また、Gemini Advanced とのチャット、Gems、Notebook LM Plus なども含まれる。 機能は順次ロールアウト。 これにより Gemini アドオンライセンスは2025年1月31日以降、請求されなくなる。 また、Google Workspace ライセンスが全体的に価格改定される。 Compute Engine で C4A インスタンスタイプが登場 C4A machine series (2025-01-16) Compute Engine で C4A インスタンスタイプが登場(GA)。 Google が開発した Arm ベースの CPU である Axion を搭載。まず Singapore、Iowa リージョン等で利用可能に。東京・大阪未対応。 BigQuery Data Transfer Service が MySQL と PostgreSQL に対応(Preview) What is BigQuery Data Transfer Service? (2025-01-17) BigQuery Data Transfer Service で MySQL と PostgreSQL をデータ転送元としてサポート(Preview)。これらの DB から BigQuery へ容易にデータ転送ジョブを設定できる。 BigQuery Data Transfer Service が他に対応しているデータソースは、Cloud Storage、Azure Blob Storage、Amazon S3、Amazon Redshift、Oracle、Salesforce、Salesforce Marketing Cloud など。 BigQuery でコンソール画面から個人別の設定が可能に BigQuery release notes - January 17, 2025 (2025-01-17) BigQuery でコンソール画面(BigQuery Studio)から個人別の設定が可能に(Preview)。 組織やプロジェクトから継承されたデフォルト設定値をオーバーライドできる。デフォルトロケーション、キャッシュ無効化、バイト数制限、Gemini 補助有効化などを設定可能。 BigQuery metastore が Public Preview 公開 Introducing BigQuery metastore, a unified metadata service with Apache Iceberg support (2025-01-23) BigQuery metastore が Public Preview 公開。 Apache Spark、Hive、Iceberg 等に対応したメタデータ管理サービス。異なるメタストアのデータを BigQuery 側でテーブル再定義なしに統合管理してクエリ可能。 Gemini in BigQuery の有償化が延期 Gemini in BigQuery Pricing Overview (2025-01-27) Gemini in BigQuery の有償化は 2025-01-27 からと予告されていたが、無償期間が延長。 Gemini in BigQuery では、生成AIによるSQL生成やデータキャンバス、推奨事項などの機能が利用可能。いつまで延期されるかは明示されていない。 Gemini サイドパネルで日本語での画像生成が可能に Use Gemini in the side panel of Workspace apps to generate images in seven additional languages (2025-01-29) Gemini サイドパネルで日本語での画像生成が可能に。Gmail、ドキュメント、スプレッドシート、ドライブのサイドパネルが対象。 今後、順次ロールアウトされる。ただし Google スライドのサイドパネルでは、引き続き英語のみ対応のため注意。 Google Sheets の Gemini でデータ説明やチャート生成が可能に Generate charts and valuable insights using Gemini in Google Sheets (2025-01-29) Google スプレッドシートで Gemini によるデータのインサイト説明やチャート(図表)の生成が可能に。 スプシの中のデータにもとづき分析してくれたり、図や表を生成してくれる。今後、順次ロールアウトされる。 Spanner に index advisor が登場(GA) Use the Spanner index advisor (2025-01-30) Spanner に index advisor が登場(GA)。 クエリを分析して適切なセカンダリインデックスを推奨してくれる。GoogleSQL-dialect と PostgreSQL-dialect の両方のデータベースに対応。 Imagen 3 の新バージョン「imagen-3.0-generate-002」 Prompt enhancement using prompt rewriter (2025-01-30) Vertex AI で画像生成AIモデル Imagen 3 の新バージョン「imagen-3.0-generate-002」が使用可能になった。 Prompt enhancement 機能があり、自動的にプロンプトに詳細を追加して、画像生成の質を向上する。Prompt enhancement はデフォルトで有効化。 Cloud DNS で DNS64 機能が Preview 公開 DNS64 (2025-01-30) Cloud DNS で DNS64 機能が Preview 公開。 IPv6-only な Compute Engine VM が A レコードしかない名前を解決しようとすると、合成 IPv6 アドレスに解決され、Cloud NAT を通して IPv4 アドレスの宛先に通信できる。 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 12資格、Google Cloud認定資格11資格。X (旧 Twitter) では Google Cloud や AWS のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-gen の佐々木です。当記事では、 gcloud config set コマンドでデフォルトのリージョンやゾーンを設定する際に表示される警告メッセージについて解説します。 はじめに デフォルトのリージョン・ゾーン設定時の警告メッセージ 警告メッセージの意味 対処法 はじめに 当記事では、以下のバージョンの Google Cloud SDK で検証を実施しています。 $ gcloud version Google Cloud SDK 502 . 0 . 0 デフォルトのリージョン・ゾーン設定時の警告メッセージ gcloud config set コマンドでは、gloud コマンドを実行する際に指定するリージョンやゾーンなどのプロパティの デフォルト値 を事前に設定しておくことができます。 デフォルト値を設定しておくことで、 --region フラグや --zone フラグを省略してコマンドを実行することができます。 たとえば、以下のコマンドを実行することで、Cloud Run のリソースを操作(作成、更新、削除など)する際、デフォルト値に設定したリージョンを使いたい場合に限り --region フラグを指定する必要がなくなります。 # gcloud run コマンドのデフォルトのリージョンを設定 $ gcloud config set run/region asia-northeast1 Updated property [ run/region ] . ところで、gcloud config set コマンドでデフォルト値を設定しようとすると、以下のような警告が表示される場合があります。 WARNING: Property validation for compute/region was skipped. この警告文は、たとえば gcloud compute コマンドのデフォルトのリージョンやゾーンを設定する場合などに表示されます。 # gcloud compute コマンドのデフォルトのリージョンを設定 $ gcloud config set compute/region asia-northeast1 WARNING: Property validation for compute/region was skipped. Updated property [ compute/region ] . # gcloud compute コマンドのデフォルトのゾーンを設定 $ gcloud config set compute/zone asia-northeast1-b WARNING: Property validation for compute/zone was skipped. Updated property [ compute/zone ] . 警告は出るものの、デフォルトの値は問題なく設定されます。 # デフォルトの値を確認(出力抜粋) $ gcloud config list [ compute ] region = asia-northeast1 zone = asia-northeast1-b 警告メッセージの意味 このメッセージは、gcloud config set コマンドで指定した値が、実際に使用できる値かどうかの検証はされていない、ということを示しています。 たとえば、gcloud compute コマンドのデフォルトのリージョンとして、実際に存在しないリージョンを設定してみます。指定した値が正しいリージョン名かどうかは検証されないため、エラーは発生せず、デフォルトの値として設定できてしまいます。 # 存在しないリージョンをデフォルトのリージョンとして設定する $ gcloud config set compute/region hokkaido WARNING: Property validation for compute/region was skipped. Updated property [ compute/region ] . # 存在しないリージョンでも設定できてしまう(出力抜粋) $ gcloud config list [ compute ] region = hokkaido zone = asia -northeast1 -b ちなみに、コマンドによっては警告メッセージが出ない場合もあります。記事の冒頭に記載した gcloud run コマンドのデフォルトのリージョンを設定するコマンドでは。警告メッセージが出ません。 # gcloud run コマンドのデフォルトのリージョンを設定 $ gcloud config set run/region asia-northeast1 Updated property [ run/region ] . しかし、この場合でも、存在しないリージョンを設定できてしまいます。 # 存在しないリージョンをデフォルトのリージョンとして設定する $ gcloud config set run/region ggen-northeast1 Updated property [ run/region ] . # 警告が出ない場合もエラーが出ずに設定できてしまう(出力抜粋) $ gcloud config list [ run ] region = ggen-northeast1 対処法 警告メッセージはどうしても気になってしまいますが、設定値が正しくても誤っていても警告メッセージは表示されるため、気にする必要はありません。 たとえ設定値が誤っている場合でもコマンドは成功してしまいますので、十分に気をつけましょう。 利用可能なリージョンの名称は、 gcloud {サービス} regions list コマンドで確認できます。たとえば、Cloud Run が利用できるリージョンは以下のように確認できます。 # Cloud Run を利用できるリージョンの一覧を表示する $ gcloud run regions list NAME africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-southwest1 europe-west1 europe-west10 europe-west12 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
G-gen の佐々木です。当記事では Kubernetes のためのオープンソースのログビューアである、 Kubernetes History Inspector を使用してみます。 Kubernetes History Inspector とは KHI に必要な IAM 権限 クエリの実行 KHI ファイルのインポート 事前準備 当記事で利用する環境 シェル変数の設定 Pod 用の ServiceAccount リソースの作成 Workload Identity Federation の設定 IAM ロールの付与 Pod のデプロイ KHI の Pod にアクセス KHI の操作 ログのクエリ ビューの表示 KHI ファイルのエクスポート・インポート Kubernetes History Inspector とは Kubernetes History Inspector (以下、 KHI )は Google Cloud が OSS(オープンソースソフトウェア)として公開している Kubernetes クラスタ用のログ可視化ツールです。 Kubernetes はシステムコンポーネントも含め非常に多くのログを出力するため、クラスタ上で問題が発生した際には、膨大なログとリソースの関連性を読み解く労力が必要です。 KHI を使用することで、クラスタから出力される大量のログをインタラクティブな GUI でクエリ・可視化し、問題のトラブルシューティングを効率的に行うことができます。 Kubernetes History Inspector の GUI KHI には以下の特徴があり、Google Cloud で Google Kubernetes Engine(GKE)を利用している環境では手軽に導入することができます。 クラスタに対するエージェント等の導入は不要(事前設定不要) GUI を使用した簡素なクエリ実行・ログの可視化 ログがバックエンド(Cloud Logging)に保存されている限り、過去に遡ったログの分析が可能 KHI ファイルを使用したクエリ結果の保存・共有 また、ログ可視化の対象は GKE だけでなく、Cloud Composer、GKE on AWS、GKE on Azure などの環境にも対応しています。 KHI は Google Cloud の商用プロダクトではなく、GitHub リポジトリでソースコードが公開されています。KHI は、Docker イメージもしくはソースコードから実行することができます。 GitHub - Kubernetes History Inspector KHI に必要な IAM 権限 クエリの実行 クエリの実行には、GKE クラスタのログが記録されている Cloud Logging に対する閲覧者権限が必要です。当記事では ログ閲覧者 ( roles/logging.viewer )ロールを付与した Google アカウントで操作しています。 Cloud Logging の閲覧権限がない場合、以下のようにクエリ実行時にエラーが出てしまいます。 Cloud Logging の閲覧権限がない場合、クエリが失敗する 当記事では Kubernetes Engine Cluster 閲覧者 ( roles/container.clusterViewer )ロールも使用しますが、こちらは必須ではありません。クラスタの閲覧権限があると、クエリ設定で対象クラスタを入力する際に、候補となるクラスタが表示されます。この権限がなくてもクラスタ名は手動で入力することができ、クエリの実行も成功します。 クラスタの閲覧権限がないと、クエリ対象のクラスタ候補が表示されない(クエリ実行は可能) KHI ファイルのインポート クエリした結果は KHI ファイル としてエクスポートすることで、クエリ結果の保存、共有を簡単に行うことができます。 KHI ファイルをインポートする際は Cloud Logging に対するクエリが実行されないため、 Cloud Logging の読み取り権限を持っていなくてもビュー(クエリ結果)を確認することができます 。つまり、KHI を実行することができる環境であれば、同じビューを表示できるということになります。 このことから、KHI ファイルはログを外部に共有する際に役立ちますが、エクスポートしたファイルの取り扱いには十分な注意が必要となります。 事前準備 当記事で利用する環境 当記事では、KHI の Docker イメージを使用して、GKE クラスタ上の Pod としてデプロイしていきます。 Kubernetes は以下のバージョンを使用しています。 $ kubectl version Client Version: v1. 29 . 2 Server Version: v1. 30 .8-gke. 1128000 シェル変数の設定 事前準備で何度か使用する値を、シェル変数として設定しておきます。 # シェル変数の設定 PROJECT_ID = { プロジェクトID } SERVICE_ACCOUNT =khi-serviceaccount NAMESPACE =default Pod 用の ServiceAccount リソースの作成 KHI は Cloud Logging からログを読み込むため、Pod 上で実行する場合は、Pod に紐付けるサービスアカウントに対して IAM 権限を付与する必要があります。 まず、GKE クラスタ上に Pod に紐付けるための ServiceAccount リソースを作成します。 # ServiceAccount リソースを作成 $ kubectl create serviceaccount ${SERVICE_ACCOUNT} Workload Identity Federation の設定 Workload Identity Federation を使用し、先ほど作成した ServiceAccount に対して IAM 権限を付与します。 GKE における Workload Identity Federation の詳細については、以下の記事をご一読ください。 blog.g-gen.co.jp もし Kubernetes History Inspector の Pod に default 以外の Namespace を使用する場合は、 NAMESPACE 変数の値も変更してください。 Workload Identity Federation の設定にはプロジェクト番号を使用する必要があるため、以下のコマンドでプロジェクト番号も取得して変数に設定しておきます。 # シェル変数にプロジェクト番号を設定する $ PROJECT_NUM = $( gcloud projects describe ${PROJECT_ID} --format =" value(projectNumber) " ) IAM ロールの付与 Workload Identity Federation を使用して、ServiceAccount に IAM ロールを付与していきます。 まず、ログ取得のための ログ閲覧者 ( roles/logging.viewer )ロールを付与します。 # ServiceAccout にログ閲覧者ロールを紐づけ $ gcloud projects add-iam-policy-binding projects/ ${PROJECT_ID} \ --role = roles/logging.viewer \ --member = principal://iam.googleapis.com/projects/ ${PROJECT_NUM} /locations/global/workloadIdentityPools/ ${PROJECT_ID} .svc.id.goog/subject/ns/ ${NAMESPACE} /sa/ ${SERVICE_ACCOUNT} また、ログ取得対象のクラスタの情報を取得するため、 Kubernetes Engine Cluster 閲覧者 ( roles/container.clusterViewer )ロールも付与します。前述したように、このロールは付与しなくても問題ありません。 # ServiceAccout に Kubernetes Engine Cluster 閲覧者ロールを紐づけ $ gcloud projects add-iam-policy-binding projects/ ${PROJECT_ID} \ --role = roles/container.clusterViewer \ --member = principal://iam.googleapis.com/projects/ ${PROJECT_NUM} /locations/global/workloadIdentityPools/ ${PROJECT_ID} .svc.id.goog/subject/ns/ ${NAMESPACE} /sa/ ${SERVICE_ACCOUNT} Pod のデプロイ 以下のマニフェストファイルを使用して、Kubernetes History Inspector を実行する Pod を GKE クラスタ上にデプロイします。 # khi-pod.yaml apiVersion : v1 kind : Pod metadata : name : khi-pod spec : serviceAccountName : khi-serviceaccount containers : - name : khi-container image : asia.gcr.io/kubernetes-history-inspector/release:latest ports : - containerPort : 8080 KHI の Pod にアクセス Kubernetes では、LoadBalancer や Ingress などのリソースを使用しなくても、ポートフォワードを使用して Service や Pod にアクセスすることができます。 以下のコマンドを実行し、 127.0.0.1:8080 から Kubernetes History Inspector の Pod にポートフォワードできるようにします。 $ kubectl port-forward pods/khi-pod 8080:8080 ブラウザから 127.0.0.1:8080 にアクセスすると、KHI の GUI が表示されます。 ブラウザから KHI の GUI にアクセスする KHI の操作 ログのクエリ ユーザーガイド に従って操作を進めていきます。 [New inspection] からログのクエリを行います。 [New inspection] を選択する 当記事では GKE のログをクエリするため、クラスタタイプとして「Google Kubernetes Engine」を選択します。 「Google Kubernetes Engine」を選択する 次の画面では、取得対象のログの種類を選択します。Kubernetes リソースの作成や GKE クラスタ自体の監査ログや、ワーカーノードのログ、コンテナ上のアプリケーションログなどのカテゴリから、必要となる種類のログをここで選択します。当記事ではデフォルトの設定値のまま進めていきます。 クエリ対象のログの種類を選択して [Next] を押下する 最後に、ログを取得する期間と、対象のプロジェクト、GKE クラスタ名、名前空間などの情報を設定します。 End time 項目で「いつまでのログを取得するか」を指定し、 Duration 項目で「Endtime に設定した時間からどれくらい遡ってログを取得するか」を指定します。 たとえば、Endtime に 2025-01-29T20:30:00+09:00 、Duration に 1h を設定すると、 2025-01-29T19:30:00+09:00 ~ 2025-01-29T20:30:00+09:00 のログを取得することになります。 ログ取得対象の期間を入力する 同じ画面で、対象の GKE クラスタや名前空間などの情報を入力します。プロジェクト ID を入力すると、候補となるクラスタの一覧が表示されます。 ログ取得対象のクラスタの情報を入力する [Run] を押下すると、ここまで入力した情報を元にクエリが実行されます。クエリが完了するまで待ちます。 クエリの実行状況が表示される クエリが完了したら、[Open] からビューを開きます。 [Open] からビューを開く ビューの表示 ビューは タイムラインビュー 、 ログビュー 、 ヒストリービュー の3つのコンポーネントから構成されています。 コンポーネント 説明 タイムラインビュー ログ取得時に指定した期間を タイムライン として帯状に表示し、クラスタ上のリソースごとのステータスやログの発生状況を可視化する。 ログビュー クラスタ上で発生したログの内容を表示する。タイムラインビューでリソースを選択すると、選択したリソースでフィルタリングされたログビューが表示される。 ヒストリービュー タイムラインビューで選択したリソースの変更履歴が差分表示される。 ビューのコンポーネント 例として、あらかじめクラスタにデプロイしていた Deployment リソースをタイムラインビューで選択し、ヒストリービューを確認してみます。ここでは事前にレプリカ数の変更を行っていたため、それを行った時刻・ユーザーの情報と、変更差分がヒストリービューに表示されています。 ヒストリービューの表示例 各コンポーネントの詳細な説明については、以下のユーザーガイドも参照してください。 Kubernetes History Inspector - ユーザーガイド KHI ファイルのエクスポート・インポート クエリした結果は KHI ファイル としてエクスポートすることで、クエリ結果の保存、共有を簡単に行うことができます。 メニュー画面から、対象のビューの KHI ファイルをエクスポートします。 メニュー画面から KHI ファイルをエクスポートする 過去のクエリ結果を削除するため、一度 KHI の Pod を削除してから再作成します。 メニュー画面から [Open .khi file] を選択し、先ほどエクスポートした KHI ファイルをインポートします。 [Open .khi file] から KHI ファイルをインポートする インポート後、クエリが実行されることなく、インポートしたビューが即座に表示されます。 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
G-gen の杉村です。料金が安くなることを期待して Cloud Storage オブジェクトのオブジェクトクラス変更を実施したところ、料金が安くなるどころか逆に高くなってしまいました。この事象の原因と、対処方法をご共有します。 事象 原因 対処法 検証(手動でストレージクラスを変更) オブジェクトのアップロード ストレージクラスの変更 Soft delete 状態のオブジェクトの確認 削除ができないことを確認 検証(オブジェクトライフサイクルで変更) オブジェクトのアップロード ライフサイクルルールの設定 Soft delete 状態のオブジェクトの存在確認 事象 Cloud Storage バケット上の複数(数百程度)のオブジェクトに対して、gcloud コマンドを使って Standard クラスから Nearline クラスへのストレージクラス変更を行いました。 $ gcloud storage objects update gs:// ${BUCKET_NAME} / ${OBJECT_NAME} --storage-class = nearline これにより、以降はより安価な Nearline クラスの単価で課金されるようになることを期待しました。 しかし、数日後に請求先アカウントの課金レポートを確認したところ、Standard クラスの保管料金と Nearline クラスの保管料金の 両方が課金されている ことが確認されました。料金が安価になることを期待したのに、二重に課金されているような状態となっています。 なお前述のコマンド例では gcloud storage コマンドを利用していますが、gsutil rewrite コマンドでも同様の事象が発生しました。 原因 gcloud storage objects update や gsutil rewrite によるオブジェクトのストレージクラスの変更は、 オブジェクトの書き換え という挙動になります。 この挙動は「変更後のストレージクラスでオブジェクトを上書きする」という処理を行っています。これにより、上書き前の古いオブジェクトは Soft delete 状態 で、数日間(デフォルトで7日間)残り続けます。 Soft delete は、削除または上書きされた Cloud Storage オブジェクトを一定期間保持し、復元可能にする機能です。デフォルトでは、7日間の保持期間が設定されており、7日間から90日間の間で設定できるほか、明示的に無効にすることもできます。Soft delete が有効化されているバケットでは、上書きまたは削除された古いオブジェクトは Soft delete 状態として保持されます。 なお Soft delete は日本語ドキュメントで「削除(復元可能)」と表記されますが、当記事ではわかりやすくするため Soft delete という表記で統一します。 参考 : 削除(復元可能) Soft delete 状態のオブジェクトには、課金が発生します。今回のケースでは、コマンドによりオブジェクトを上書きしてストレージクラスを変更したため、 Standard クラスの古いオブジェクトが Soft delete 状態で残り続けて いました。そのため Soft delete 状態の Standard クラスの古いオブジェクトと、Nearline クラスの新しいオブジェクトが同時に存在していることになり、両方に課金が発生していました。 対処法 Soft delete 状態のオブジェクトを明示的に削除する方法はありません。バケットに設定した Soft delete 期間が経過すると、Soft delete 状態のオブジェクトは自然に削除されます。 あとからバケットの Soft delete を無効化したり、Soft delete 期間を短くしても、オブジェクトを削除または上書きしたときに設定されていた Soft delete 期間の設定が有効なため、当初に設定されていた Soft delete 期間の経過を待つ必要があります。 この事象の発生を 予防 するには、ライフサイクルルールや Autoclass 機能を使ってストレージクラスを変更する必要があります。 オブジェクトのライフサイクル は、事前に定義したルールに基づいて、例えば「作成から30日間経過したオブジェクトは Nearline クラスに移行する」「90日間経過したオブジェクトは削除する」のような自動処理を定義できる機能です。 参考 : オブジェクトのライフサイクル管理 Autoclass は、オブジェクトのアクセス状況に基づいて、自動的にオブジェクトのストレージクラスを変更する機能です。 参考 : Autoclass いずれの機能も、ストレージクラスの変更は「オブジェクトの書き換え」とは異なる処理で行われるため、オブジェクトが Soft delete 状態になることはなく、二重課金を回避できます。またいずれの機構も、オブジェクト取得料金や早期削除料金が発生しないなどのコストメリットがあります。よって 大量の (またはサイズが大きい) オブジェクトのストレージクラスを変更する場合は、ライフサイクルルールや Autoclass 機能を使うことが推奨 されます。 検証(手動でストレージクラスを変更) オブジェクトのアップロード 以下のコマンドで、ローカルマシンにあるテスト用ファイルを Cloud Storage バケットにアップロードします。 $ gcloud storage cp ./test-object.txt gs://my-test-bucket Copying file://./test-object.txt to gs://my-test-bucket/test-object.txt Completed files 1 / 1 | 21 .0B/ 21 .0B ls コマンドで、オブジェクトが正しくアップロードできていることを確認します。また describe コマンドで、オブジェクトのストレージクラスを確認します。このバケットはデフォルトのストレージクラスが Standard なので、アップロードしたオブジェクトのストレージクラスも Standard になっています。 $ gcloud storage ls gs://my-test-bucket gs://my-test-bucket/test-object.txt $ $ gcloud storage objects describe gs://my-test-bucket/test-object.txt --format =" value(storage_class) " STANDARD ストレージクラスの変更 update コマンドで、オブジェクトのストレージクラスを Nearline に変更します。 $ gcloud storage objects update gs://my-test-bucket/test-object.txt --storage-class = nearline Rewriting gs://my-test-bucket/test-object.txt... Completed 1 $ $ gcloud storage objects describe gs://my-test-bucket/test-object.txt --format =" value(storage_class) " NEARLINE Soft delete 状態のオブジェクトの確認 gcloud storage objects update コマンドでオブジェクトのストレージクラスを変更したため、オブジェクトは上書きされ、Standard クラスの古いオブジェクトが Soft delete 状態で残っているはずです。 ls コマンドに --soft-deleted オプションを付けることで、Soft delete 状態のオブジェクトのみを一覧表示できます。 $ gcloud storage ls gs://my-test-bucket --soft-deleted --recursive gs://my-test-bucket/: gs://my-test-bucket/test-object.txt# 1732163813118979 上記のように、 test-object.txt#1732163813118979 という名称で、Soft delete 状態のオブジェクトが存在していることが確認できました。このオブジェクトのストレージクラスを以下のコマンドで確認します。 $ gcloud storage objects describe gs://my-test-bucket/test-object.txt# 1732163813118979 --soft-deleted --format =" value(storage_class) " STANDARD Soft delete 状態のオブジェクトが Standard クラスであることが確認できました。このSoft-delete 状態のオブジェクトは、Nearline クラスに変更した新オブジェクトとは 別のオブジェクトとして存在 しているため、Nearline に変更した新オブジェクトと、Standard の旧オブジェクトで二重課金状態になっていることがわかります。 この検証により、 gcloud storage objects update によるオブジェクトクラスの変更を行うと、既存オブジェクトが新しいストレージクラスで上書きされ、古いオブジェクトが Soft delte 状態で残ることが確認できました。 削除ができないことを確認 なお、この Soft delte 状態のオブジェクトは gcloud storage rm コマンド等で削除することはできません。保持日数が経過するのを待つ必要があります。 $ gcloud storage rm gs://my-test-bucket/test-object.txt# 1732163813118979 Removing objects: Completed 0 ERROR: ( gcloud.storage. rm ) The following URLs matched no objects or files: gs://my-test-bucket/test-object.txt# 1732163813118979 $ $ gcloud storage rm gs://my-test-bucket/test-object.txt# 1732163813118979 --soft-deleted ERROR: ( gcloud.storage. rm ) unrecognized arguments: --soft-deleted To search the help text of gcloud commands, run: gcloud help -- SEARCH_TERMS 検証(オブジェクトライフサイクルで変更) オブジェクトのアップロード 次に、オブジェクトライフサイクル機能を用いてストレージクラスを変更した場合を検証してみます。 以下のコマンドで、ローカルマシンにあるテスト用ファイルを Cloud Storage バケットにアップロードします。 $ gcloud storage cp ./test-object-lifecycle.txt gs://my-test-bucket Copying file://./test-object-lifecycle.txt to gs://my-test-bucket/test-object-lifecycle.txt Completed files 1 / 1 | 21 .0B/ 21 .0B $ gcloud storage objects describe gs://my-test-bucket/test-object-lifecycle --format =" value(storage_class) " STANDARD アップロード直後は、対象オブジェクトのストレージクラスが Standard であることも確認します。 ライフサイクルルールの設定 バケットのオブジェクトライフサイクルを、以下のように設定します。 特定日付より以前に作成されたオブジェクトを Nearline クラスに変更するルールとしました。即時にルールを適用したいので、検証を行った日は2024-11-21ですが、それより先の日付を指定日付としました。 ルールを設定してから、実際に適用されるまでは最大で24時間程度のラグがあります。 Soft delete 状態のオブジェクトの存在確認 しばらく待ったあと、ライフサイクルルールが適用され、オブジェクトのストレージクラスが Nearline に変更されたことを確認します。 $ gcloud storage objects describe gs://my-test-bucket/test-object-lifecycle.txt --format =" value(storage_class) " NEARLINE 以下のように、Soft delete 状態のオブジェクトがあるかどうかを確認します。 $ gcloud storage ls gs://my-test-bucket --soft-deleted --recursive gs://my-test-bucket/: Soft delete 状態のオブジェクトが1つも存在しないことが確認できました。つまり、ライフサイクルルールによってオブジェクトのストレージクラスが変更された場合、オブジェクトの書き換えとは異なる動作のため、Soft delete 状態のオブジェクトは生まれないことがわかりました。 gcloud コマンド等によるストレージクラスの変更は「オブジェクトの書き換え」の動作であり、古いオブジェクトの削除が発生することに対して、ライフサイクルルールは違う挙動であるということは、以下のドキュメントにも記載されています。 参考 : SetStorageClass の費用に関する考慮事項 ただし、オブジェクトのストレージ クラスを手動で変更する場合と異なり、SetStorageClass を使用してもオブジェクトは書き換えられません。 またライフサイクルルールによるストレージクラスの変更では、以下のようなその他の料金面でのメリットがあることも記述されています。 ストレージ クラスの変更に関連するリージョン間のレプリケーション料金、取得料金、早期削除料金は発生しません。 なおライフサイクルルールでオブジェクトクラスを変更されたオブジェクトを describe すると、以下のように、 creation_time は最初にオブジェクトをアップロードした時間のまま変わりませんが、 storage_class_update_time が変更されています。オブジェクトの上書きを行わずに、ストレージクラスのみが変更されていることがわかります。 $ gcloud storage objects describe gs://my-test-bucket/test-object-lifecycle.txt bucket: my-test-bucket content_type: text/plain crc32c_hash: Sd5KXw = = creation_time: 2024-11-21T03:00:34+ 0000 etag: CKKH9cK37IkDEAI = generation: ' 1732158034887586 ' md5_hash: QGEgRtde1doCj1rGmxWK6w = = metageneration: 2 name: test-object-lifecycle.txt size: 80 storage_class: NEARLINE storage_class_update_time: 2024-11-21T06:58:34+ 0000 storage_url: gs://my-test-bucket/test-object-lifecycle.txt# 1732158034887586 update_time: 2024-11-21T06:58:34+ 0000 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 12資格、Google Cloud認定資格11資格。X (旧 Twitter) では Google Cloud や AWS のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-gen の杉村です。当記事では、Google Cloud の請求先アカウントに標準付属されている 異常検知 (Anomaly Detection)機能について紹介します。 異常検知(Anomaly Detection)とは 異常検知 検知結果の閲覧 異常しきい値 通知 メール通知内容 通知の宛先 通知の頻度 異常検知(Anomaly Detection)とは Google Cloud(旧称 GCP)の請求先アカウントには、 異常検知 (Anomaly Detection)機能があります。 異常検知は、Google Cloud の突発課金を検知できる機能です。請求先アカウント単位で過去の使用傾向が機械学習により学習され、普段と異なるパターンの課金が発生すると異常(anomaly)として検知されます。検知結果は、E メールや Pub/Sub に通知することができます。異常が検知されるのは、 6ヶ月間以上の利用実績があるプロジェクトのみ です。 検知された異常には、根本原因(root cause)が表示されます。根本原因として、どの SKU が課金に関係しているか、どのリージョンのどのサービスか、などが表示されます。 参考 : View and manage cost anomalies なお、請求先アカウントの仕組み等の基礎知識については、以下の記事をご参照ください。 blog.g-gen.co.jp 異常検知 検知結果の閲覧 検知された異常は、指定した通知先にメール等で発報することもできますし、Google Cloud コンソール画面から確認することもできます。 Google Cloud コンソールの「お支払い>異常」から、検知された異常の一覧が確認できます。 検知した異常の一覧 異常の詳細画面では、 根本原因の分析 (root cause analysis、RCA)が閲覧できます。ここでは、発生した課金額、その SKU の内訳、通常レベルだと想定される課金額などが表示されます。また、Google の製品改善のために、実際にこの検知が想定外の課金であるかどうか、フィードバックするボタンもあります。 根本原因の分析(RCA) 異常しきい値 コンソールからアクセスできる設定画面には「 異常しきい値 」を設定する箇所があります。このしきい値を設定すると、異常が検知されても、費用への影響(機械学習が推定した通常の費用と、実際の費用の差)が設定したしきい値より下回った場合、その検知は表示されません。 このしきい値はあくまで、検知された異常のリストをフィルタリングするために使われます。この値を設定しても、 検知のしきい値自体が変わるわけではありません 。異常検知はあくまで機械学習によって過去実績に応じて行われます。 しきい値の設定 しきい値設定は、金額の絶対値で指定することもできますし、通常の想定費用とのずれの割合(%)で指定することもできます。また過去の使用パターンに基づいて毎日自動的に更新されるよう「しきい値の自動生成」を設定することもできます。 しきい値を設定すると、コンソール画面の異常の一覧がその値でフィルタリングされます。フィルタを削除すれば、すべての異常が表示されます。ただし、設定したしきい値は E メールや Pub/Sub 通知にも適用されます 。しきい値を下回る検知は、一覧から非表示になるだけでなく、E メール通知等が行われなくなるため、注意が必要です。 フィルタ 通知 メール通知内容 異常が検知されると、以下のような E メールが指定した宛先に送信されます。 異常検知の E メール 通知の宛先 宛先は、以下のいずれかから選択できます。 通知先 説明 Pub/Sub 選択した Pub/Sub トピックに通知 課金管理者 当該請求先アカウントに「請求先アカウント管理者」ロールを持っているアカウントに通知 重要な連絡先(エッセンシャルコンタクト) エッセンシャルコンタクトで「課金」カテゴリの対象になっているアカウントに通知 プロジェクト オーナー 異常課金が発生したプロジェクトに対して「オーナー」ロールを持つアカウントに通知 以下は、通知の設定画面です。 通知の設定 Pub/Sub トピックに通知すると、後続処理として Cloud Run functions を動作することができるため、チャットツールやチケットシステムなどへの通知に繋げられます。 課金管理者、重要な連絡先(エッセンシャルコンタクト)、プロジェクト オーナーにはそれぞれ「個別の異常」を通知するか、「1 日のまとめ」を通知するかが選択できます。 なお重要な連絡先(エッセンシャルコンタクト)の「個別の異常」を選んだ場合はプロジェクトレベルに設定したエッセンシャルコンタクトの「課金」カテゴリの連絡先に、「1 日のまとめ」を選んだ場合は組織レベルのエッセンシャルコンタクトの「課金」カテゴリの連絡先に、それぞれ通知が発報されます。 エッセンシャルコンタクトについては、以下の記事も参照してください。 blog.g-gen.co.jp 通知の頻度 以下の公式記事では「コスト異常検出は支出を 1 時間ごとに監視するため、ほとんどのサービスで 24 時間以内に予期しない上昇スパイクを識別し、ほぼリアルタイムで異常を検出できます。」の旨の記載があります。 参考 : Reduce unexpected costs with the new AI-powered Cost Anomaly Detection ただし2024年10月の当社検証では、突発課金が発生してから通知されるまで、1日程度のラグがありました。正確なラグについてはドキュメントに記載がなく、幅があると想定されます。 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
G-gen の杉村です。Google Cloud リソースへの詳細なアクセス制御を実現する VPC Service Controls には、Ingress rules(内向きルールまたは上りルール)と Egress rules(外向きルールまたは下りルール)の設定が存在します。これらの仕様と、適切な設定方法を解説します。 はじめに 境界とルール Ingress rules Ingress rules とは Ingress rules の設定値 Egress rules Egress rules とは Egress rules の設定値 サポートされている ID サンプルアーキテクチャ 概要 アクセスユースケース1. 境界内リソースへのアクセス アクセスユースケース2. 境界外リソースへのアクセス(失敗パターン) アクセスユースケース3. 境界外リソースへのアクセス(成功パターン) Google ストアなど一部 Web サイトへのアクセス異常 はじめに VPC Service Controls は、Google Cloud リソースへの詳細なアクセス制御を実現するサービスです。詳細は、以下の記事で解説しています。当記事は、以下の記事の内容を概ね理解している前提で記載されています。 blog.g-gen.co.jp VPC Service Controls には、内向き(上り)ルールと外向き(下り)ルールの設定が存在します。英語では、内向きルールは Ingress rules 、外向きルールは Egress rules と表記されます。また Google Cloud コンソール画面では「内向きポリシー(Ingress policy)」「外向きポリシー(Egress policy)」と表記されている箇所もあります。 表記揺れを防ぐため、当記事ではこれ以降、英語版ドキュメントで採用されている Ingress rules、Egress rules という表記を用います。 参考 : Service perimeter details and configuration 参考 : Ingress and egress rules 当記事では、はじめに Ingress rules と Egress rules の仕様を解説し、その後、理解を深めるためにサンプルアーキテクチャを用いて図説します。 境界とルール VPC Service Controls の 境界 (perimeter)でプロジェクトを保護すると、境界の外から中への API リクエストや、中から外への API リクエストが拒否されます。これにより、データの持ち出しを防ぐことができます。 境界には、 Ingress rules や Egress rules を追加することができます。Ingress rules と Egress rules は、いずれも「本来拒否されるはずの境界をまたいだ API リクエストを例外的に許可するためのルール」です。Ingress rules や Egress rules を追加すると、境界に例外を設けて、境界の中から外、または外から中への API リクエストを許可することができます。 Ingress rules Ingress rules とは Ingress rules(または上りルール、内向きルール)は、境界 外 の API クライアントから境界 内 の Google Cloud リソースへの API リクエストを許可するルールです。 例えば、ある Google Cloud プロジェクトを境界で保護し、VPC 内部やオンプレミスからのアクセスだけに制限するとします。しかし、特定の外部ベンダーの開発チームだけは境界内へのアクセスを許可したいとします。このような場合は、境界の外から中へのリクエストが発生するため、Ingress rules を設定します。 Ingress rules の例 Ingress rules の設定値 Ingress rules には From 属性 と To 属性 を設定することができます。 From 属性には、API リクエストを行うクライアントの属性を指定します。以下の設定項目があります。 設定項目 説明 Identity(ID) 許可する Google アカウントやサービスアカウント、Google グループ、等を指定 ソース 許可する API リクエストの発信元として以下のいずれかを指定 ・すべて ・アクセスレベル ・組織/フォルダ/プロジェクト ・VPC ネットワーク ・Private Service Connect エンドポイント なおアクセスレベルとは、Access Context Manager で作成する、許可条件の設定オブジェクトのことです。特定の IP アドレス帯やデバイスポリシーなどを許可条件として指定できます。 To 属性には、アクセス先のリソースの存在するプロジェクトや、Google Cloud API、そのメソッドなどを指定します。以下の設定項目があります。 設定項目 説明 プロジェクト/フォルダ/組織 許可する Google Cloud プロジェクト、フォルダ、または組織を指定。「すべてのリソース」を指定すると境界内の全プロジェクトがアクセス先として許可される サービス・メソッド 許可する Google Cloud API やメソッドを指定。IAM ロールを指定して、そのロールに紐づくすべてのメソッドを許可することも可能 これらの設定により、例えばあるプロジェクトの Cloud Storage API の google.storage.objects.list と google.storage.objects.get へのリクエストを許可する、といった指定の仕方ができます。許可対象の API メソッドは「ストレージ管理者( roles/storage.admin )ロール」のようにロール単位で指定することもできます。 また、プロジェクトや API メソッドを限定せず、境界内の全プロジェクト・全サービス・全メソッドへのアクセスを許可するといった設定も可能です。 Egress rules Egress rules とは Egress rules(または下りルール、外向きルール)は、境界 内 の API クライアントから境界 外 のリソースへの API リクエストを許可するルールです。 例えば、ある Google Cloud プロジェクトを境界で保護するとします。境界内の VM 等の上で動作するクライアント(アプリケーションや gcloud コマンドなど)は、境界外のプロジェクトにある Google Cloud リソースにアクセスすることはできません。境界外のプロジェクトの Cloud Storage バケットにアクセスしたい場合は、Egress rules を設定する必要があります。 Egress rules の例 Egress rules の設定値 Egress rules にも、 From 属性 と To 属性 を設定します。 From 属性には、API リクエストを行うクライアントの属性を指定します。以下の設定項目があります。 設定項目 説明 Identity(ID) 許可する Google アカウントやサービスアカウント、Google グループ等を指定 ソース 許可する API リクエストの発信元として以下のいずれかを指定 ・すべて ・アクセスレベル ・組織/フォルダ/プロジェクト ・Private Service Connect エンドポイント なお「サンプルアーキテクチャ」の項でも述べますが、境界内には Private Service Connect や限定公開の Google アクセスを用いてオンプレミスのデバイスを含めることができます。このときに、デバイスポリシーを満たしたデバイスだけを接続元とすることができます。 To 属性には、アクセス先のリソースの存在する場所を指定します。アクセス先として「Google Cloud サービス/リソース」「外部リソース」から選択します。 「Google Cloud サービス/リソース」には以下の設定項目があり、Ingress rules と同様です。 設定項目 説明 プロジェクト/フォルダ/組織 許可する Google Cloud プロジェクト、フォルダ、または組織を指定。「すべてのリソース」を指定すると境界内の全プロジェクトがアクセス先として許可される オペレーションまたは IAM ロール 許可する Google Cloud API やメソッド、または IAM ロールを指定 「オペレーションまたは IAM ロール」で特定の IAM ロールを選択すると、その IAM ロールが持つ権限に対応するオペレーションが許可されます。 一方の「外部リソース」には以下の設定項目があります。 設定項目 説明 外部リソース Google Cloud 外部のリソースを指定。Amazon S3 のバケット名や、Azure Blob Storage または Azure Data Lake Storage Gen2 のコンテナ名が指定可能 オペレーション 許可する Google Cloud API とメソッドを指定 サポートされている ID Ingress rules や Egress rules で指定可能な ID のうち代表的なものとして、以下のようなものが挙げられます。 Google アカウント Google グループ サービスアカウント Workforce identity pool の全体、単一アカウント、グループ Workload identity pool の全体、単一アカウント、グループ Agent Identity Workforce identity / Workload identity で連携された SPIFFE フォーマットの ID 上記のように、Ingress rules や Egress rules は多くのフォーマットの ID に対応しています。Agent Identity に対応していることがわかるように、VPC Service Controls は AI エージェントのアクセス制御にも対応しています。 参考 : Supported identities for ingress and egress rules 参考 : Google CloudのAgent Identityを解説 サンプルアーキテクチャ 概要 ここでサンプルとして、あるマルチクラウド環境のアーキテクチャを例に取り、Egress rules が必要なケースを解説します。 以下のような環境があります。 サンプルアーキテクチャ AWS 環境と Google Cloud 環境が、インターネット VPN で接続されています。図中の「Cloud VPN」「AWS Site-to-Site VPN」はいずれも IPSec VPN のサービスで、前者は Google Cloud の、後者は AWS のサービスです。このアーキテクチャでは AWS とインターネット VPN を用いましたが、 オンプレミスや専用線の場合でも同様の結果になる と考えて差し支えありません。 AWS と接続された Google Cloud プロジェクト project-01 には Private Service Connect エンドポイント が設置されています。この仕組みにより、AWS の EC2 インスタンス(仮想マシン)上で稼働するクライアント(gcloud コマンドや Google Cloud クライアントライブラリなど)は、Private Service Connect エンドポイントを経由して、プライベートネットワーク内で Google Cloud APIs にアクセスできます。同様の仕組みは Private Service Connect のほか、「限定公開の Google アクセス」という仕組みでも実現できます。 Private Service Connect の詳細や、これを使って AWS やオンプレミスから Google Cloud APIs へプライベート接続する方法については、以下の記事も参照してください。 blog.g-gen.co.jp Google Cloud プロジェクト project-01 は VPC Service Controls 境界によって保護されています。また、境界の外にある project-02 も用意されています。各プロジェクトには、Cloud Storage バケットを準備しました。 この構成において、AWS の EC2 インスタンス上で稼働する gcloud コマンド等の API クライアントから、境界内外のリソースへアクセスさせるための設定を、いくつかのケースにわけて解説します。 アクセスユースケース1. 境界内リソースへのアクセス 重要なポイントとして、境界内部にある Private Service Connect エンドポイント経由で AWS やオンプレミス等から Google Cloud APIs にリクエストした場合、リクエストは 境界内からのリクエストとして扱われます 。 先ほどの構成が適切に設定されている場合、EC2 インスタンス上のクライアントからのリクエストは Private Service Connect エンドポイント経由のため、境界内からのリクエストとしてみなされます。アクセス先が境界内リソースであれば、 Ingress rules も Egress rules も必要ありません 。 境界内から境界内リソースへは例外ルールなしでアクセス可能 上記の図では矢印が簡易化されていますが、実際には EC2 インスタンス ←→ Private Service Connect エンドポイント ←→ Cloud Storage バケットという L 字型のアクセス経路です。 アクセスユースケース2. 境界外リソースへのアクセス(失敗パターン) では、EC2 インスタンスから、境界外の Google Cloud プロジェクト上のリソースへのアクセスはどうなるでしょうか。 境界内から境界外のリソースへのリクエストは原則拒否 上記の図のように、境界内から境界外のリソースへのリクエストは拒否されます。図では矢印が簡易化されていますが、実際には EC2 インスタンス ←→ Private Service Connect エンドポイント ←→ project-02 の Cloud Storage バケットというアクセス経路です。 このようなリクエストがされた場合は、以下のようなエラーメッセージが表示されます。 { " protoPayload ": { " @type ": " type.googleapis.com/google.cloud.audit.AuditLog ", " status ": { " code ": 7 , " message ": " PERMISSION_DENIED ", " details ": [ { " @type ": " type.googleapis.com/google.rpc.PreconditionFailure ", " violations ": [ { " type ": " VPC_SERVICE_CONTROLS ", " description ": " (略) " } ] } , { " @type ": " type.googleapis.com/google.rpc.ErrorInfo ", " reason ": " SECURITY_POLICY_VIOLATED ", " domain ": " googleapis.com ", " metadata ": { " uid ": " (略) ", " service ": " storage.googleapis.com " } } ] } , " authenticationInfo ": {} , " requestMetadata ": { " callerIp ": " 192.168.2.3 ", " callerNetwork ": " //compute.googleapis.com/projects/project-01/global/networks/__unknown__ ", " requestAttributes ": {} , " destinationAttributes ": {} } , " serviceName ": " storage.googleapis.com ", " methodName ": " google.storage.objects.get ", " resourceName ": " projects/(project-01のプロジェクト番号) ", " metadata ": { " @type ": " type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata ", " violationReason ": " NETWORK_NOT_IN_SAME_SERVICE_PERIMETER ", " vpcServiceControlsUniqueId ": " (略) ", " securityPolicyInfo ": { " servicePerimeterName ": " accessPolicies/(略)/servicePerimeters/my_vpcsc_perimeter ", " organizationId ": " (略) " } , " deviceState ": " Unknown ", " resourceNames ": [ " projects/_/buckets/my-bucket-external/objects/test.txt " ] , " egressViolations ": [ { " targetResource ": " projects/(project-02のプロジェクト番号) ", " source ": " projects/(project-01のプロジェクト番号) ", " sourceType ": " Network ", " servicePerimeter ": " accessPolicies/(略)/servicePerimeters/my_vpcsc_perimeter ", " targetResourcePermissions ": [ " storage.objects.get " ] } ] , " vpcServiceControlsTroubleshootToken ": " (略) " } } , " insertId ": " (略) ", " resource ": { " type ": " audited_resource ", " labels ": { " project_id ": " project-01 ", " method ": " google.storage.objects.get ", " service ": " storage.googleapis.com " } } , " timestamp ": " 2024-12-06T09:50:20.644751574Z ", " severity ": " ERROR ", " logName ": " projects/project-01/logs/cloudaudit.googleapis.com%2Fpolicy ", " receiveTimestamp ": " 2024-12-06T09:50:20.844464826Z " } このログの、 protoPayload.metadata.egressViolations に注目してください。 egressViolations は、外向きのアクセス設定に違反していることを指しています。境界内クライアントから境界外リソースへのアクセスのため、アクセスが 境界によって拒否 されたことを示しています。 アクセスユースケース3. 境界外リソースへのアクセス(成功パターン) 前項のようなアクセスを許可するには、Egress rules を追加します。 以下のように、From 属性を「任意の ID(ANY_IDENTITY)」とし、To 属性に宛先プロジェクトと、今回のアクセス先である storage.googleapis.com を指定しました。このような設定を追加すれば、アクセスは許可されます。 Egress rules を追加することでアクセス可能 なお、任意の ID とせずに、クライアントに設定したサービスアカウントを明示的に指定することもできます。また、Workload Identity で連携した AWS の IAM ユーザー(グループ)を指定することもできます。 参考 : Configure identity groups and third-party identities in ingress and egress rules Google ストアなど一部 Web サイトへのアクセス異常 なお、今回の構成では Private Service Connect の設定に伴い、 *.googleapis.com が Private Service Connect エンドポイントの IP アドレスへ名前解決されるように、DNS が設定されています。 このようなときに Egress rules が設定されていない場合、一部の Google のウェブサイト等へのアクセスがうまくいかないことが分かっています。 例えば、Google ストア( https://store.google.com/ )はその1つです。Google ストアのトップページでは https://mannequin.storage.googleapis.com/ から静的ファイルを取得しているため、境界内からこのサイトへアクセスすると、境界外へのアクセスとみなされて、VPC Service Controls 境界によりリクエストがブロックされます(403 Forbidden)。 静的ファイルが取得できず表示が不完全 Egress rules の From 属性で「任意の ID」、To 属性で「すべてのプロジェクト」「Cloud Storage API」「get メソッド」を許可すると、リクエストが成功し、Web サイトが完全に表示されます。 Egress rules の追加により表示が成功 ただし、この Egress rule を追加することで、境界内の API クライアントは境界外のバケットからデータを持ち込むことが可能になります。メソッドが get 等に限定されていれば情報流出のリスク増大にはなりませんが、仕様とリスクを十分に理解して設定してください。 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it