TECH PLAY

株式会社G-gen

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

734

G-gen の杉村です。Cloud Run services や Cloud Run functions などでは、文字列を標準出力に出力することで、Cloud Logging にログを出力できます。その際に文字列を JSON で構造化して出力することで、Cloud Logging でログがパースされ、ログが閲覧しやすくなります。この仕組みについて解説します。 Google Cloud サービスと Cloud Logging 構造化ロギング 検証 前提条件 検証1. 単純なテキスト 検証2. JSON で構造化した出力 検証3. 複数行の出力 検証4. 複数行の出力を JSON で構造化 検証5. 辞書型変数を print 関数で出力 検証6. 様々な severity 検証7. 追加の JSON キー 検証8. Cloud Logging クライアントライブラリと Python ロガーの併用 検証9 : Python 標準ロガーのみの使用 Google Cloud サービスと Cloud Logging Cloud Run services や Cloud Run functions などでは、 文字列を標準出力や標準エラー出力に出力するだけ で、Cloud Logging にログを出力できます。 つまり、これらのサービス上で稼働するプログラムから Cloud Logging にログを出力したいときは、Cloud Logging の API リクエストを行ったり、エージェントプログラムをインストールする必要はなく、標準出力や標準エラー出力にテキストを出力するだけでよいことになります。この方法に対応しているサービスには、以下が挙げられます。 Cloud Run(services、jobs、worker pools) Cloud Run functions App Engine Google Kubernetes Engine(GKE) これらのサービスで標準出力や標準エラー出力にテキストを出力すると、ランタイムにプリインストールされている統合 Logging エージェント(integrated logging agent)により、テキストは自動的に Cloud Logging に送信されます。 参考 : Cloud Run でのログの記録と表示 - コンテナログを書き込む 参考 : GKE ログについて - Google Kubernetes Engine(GKE) 構造化ロギング 前述の仕様を使い、Cloud Logging にログを送出するとき、単に文字列を出力することでも Cloud Logging ログエントリとして記録されますが、 JSON 形式でログを構造化 することで、複数行に渡るログを見やすく表示したり、severity(重要度)を明示したり、その他の要素を構造的にログエントリに含ませてクエリしやすくしたりすることができます。 参考 : 構造化ロギング - Google Cloud Observability 構造化して出力されたログエントリ JSON で構造化したログ出力方法 log_dict = { "message" : "exp 8-2: Output with another keys" , "my_key_1" : "my_value_1" , "my_key_2" : "my_value_2" , } message_json = json.dumps(log_dict) logging.warning(message_json) 検証 前提条件 当記事で後述する検証結果はすべて、以下の条件で実行されたものです。 Cloud Run(services) ベースイメージは python:3.12-slim 検証1. 単純なテキスト 以下のようなソースコードで、単純な文字列を print 関数で標準出力に出力します。 # 検証1 : シンプルな文字列の出力(非構造化) message= "exp 1/2: hello, world" print (message) 出力結果を Cloud Logging のログエクスプローラーで閲覧すると、以下のようになります。 検証1 print 関数による出力内容は、ログエントリの textPayload として記録されています。またその内容は、ログエントリのプレビュー(画像上部の赤枠)として表示されています。 severity アイコン(画像の青枠)は DEFAULT (特に設定されていないことを意味する)が表示されています。ログエントリ内の要素としては、severity は存在していません。 severity の一覧 検証2. JSON で構造化した出力 次に、以下のようなソースコードで、JSON で構造化した文字列を print 関数で標準出力に出力します。 # 検証2 : シンプルな文字列の出力(構造化) import json log_dict = { "message" : message, "severity" : "INFO" , } message_json = json.dumps(log_dict) print (message_json) ソースコードは先程の「検証1」に続けて書かれているので、 message 変数の中身は、検証1と同様です。まずは message と severity というキーを持つ辞書型変数を作成し、それを json.dumps で JSON 型にしたものを print しています。 出力結果をログエクスプローラーで閲覧すると、以下のようになります。 検証2 検証1との違いは、severity が反映されていることです。先程のログエントリには severity 要素が存在せず、アイコン表示は DEFAULT でしたが、今回はログエントリに severity が存在し、INFO が格納されています。またログエントリのプレビューの左端にあるマーク(画像上部の青枠)もそれに応じたアイコンになっています。 検証3. 複数行の出力 次に以下のようなソースコードで、複数行の文字列を、構造化せずに print 関数で標準出力に出力します。 # 検証3 : 改行がある文字列の出力(非構造化) message= """exp 3/4/5: Here are multiple lines""" print (message) 出力結果は、以下のようになります。 検証3 文字列の各行が、改行コード区切りで別々のログエントリとして解釈されてしまい、閲覧性が悪くなっています。 検証4. 複数行の出力を JSON で構造化 次に、以下のようなソースコードで、先程と同じ複数行の文字列を JSON で構造化して出力します。 # 検証4 : 改行がある文字列の出力(構造化) log_dict = { "message" : message, "severity" : "WARNING" , } message_json = json.dumps(log_dict) print (message_json) ソースコードは先程の「検証1」に続けて書かれているので、 message 変数の中身は、検証3のままです。 出力結果は、以下のようになります。 検証4 複数行の文字列は1個のログエントリとして適切に解釈され、 textPayload に格納されています。 検証5. 辞書型変数を print 関数で出力 実験として、以下のようなソースコードで、検証4で構造化した辞書型変数を、JSON 化せずに print 関数に渡してみます。 # 検証5 : 改行がある文字列の出力(辞書型のまま) print (log_dict) 出力結果を Cloud Logging で閲覧すると、以下のようになります。 検証5 辞書型が文字列型にキャストされた結果は Cloud Logging には適切に解釈されず、severity もログエントリに反映されていません。このような出力の仕方は適切ではありません。 検証6. 様々な severity 以下のようなソースコードで、様々な severity のログエントリを出力して、ログエクスプローラーでの見え方を確認します。リスト severities の最後には、存在しない severity である MYSEVERITY を紛れ込ませてあります。 # 検証6 : 様々な Severity message = "exp 6: This is a message" severities = [ "DEFAULT" , "DEBUG" , "INFO" , "NOTICE" , "WARNING" , "ERROR" , "CRITICAL" , "ALERT" , "EMERGENCY" , "MYSEVERITY" ] for severity in severities: log_dict = { "message" : message + " with severity: " + severity, "severity" : severity, } message_json = json.dumps(log_dict) print (message_json) 出力結果は、以下のようになります。 検証6 各ログエントリに設定された severity はグラフィカルにアイコンで表示されています。存在しない severity である MYSEVERITY は正しく解釈されず、当該ログエントリの severity 要素は存在せず、アイコンは DEFAULT になっていました。Cloud Logging で使用可能な severity は以下のとおりです。 参考 : LogEntry - LogSeverity 検証7. 追加の JSON キー 以下のソースコードでは、JSON の中に message キーのほか、 my_key_1 、 my_key_2 という独自のキーも含ませています。 # 検証7 : message と追加のキー log_dict = { "message" : "exp 7: This is the main message text." , "severity" : "WARNING" , "my_key_1" : "my_value_1" , "my_key_2" : "my_value_2" , } message_json = json.dumps(log_dict) print (message_json) 出力結果は以下のようになりました。 検証7 ここまでの検証では、 message キーで渡された文字列は、ログエントリでは textPayload 要素として解釈されていました。しかし今回のようにカスタムキーが1個でも含まれると、 message キーも含めたすべてのキーが、ログエントリの jsonPayload 要素の中に格納されます。そのようなときも、 message は画像上部赤枠のプレビューで表示されています。また severity キーだけは jsonPayload から除外されて、ログエントリの最上位要素である severity として格納されます。 このように独自のキーを含ませることで、ログエントリを構造化でき、ログの閲覧のしやすさや検索性を向上できます。 検証8. Cloud Logging クライアントライブラリと Python ロガーの併用 以下では、Python の標準ライブラリである logger と、Cloud Logging のクライアントライブラリを使って、実用的な使い方を紹介します。 # 検証8 : Python のロガーを使用 import logging import os import google.cloud.logging client = google.cloud.logging.Client() client.setup_logging(log_level=logging.DEBUG) # Cloud Run 環境でなければ(ローカル環境であれば)ハンドラを追加、ログが画面出力される if not os.getenv( 'K_SERVICE' ): handler = logging.StreamHandler() formatter = logging.Formatter( '[%(asctime)s][%(name)s][%(levelname)s] %(message)s' ) handler.setFormatter(formatter) logging.getLogger().addHandler(handler) message = "exp 8-1: Output with logger." logging.info(message_json) 参考 : Python 用 Cloud Logging の設定 上記のソースコードでは、 client.setup_logging() によって Cloud Logging ハンドラを Python ルートロガーに接続しています。これにより、以下のような挙動になります。 ロガー(ここでは logging )に JSON 形式でなく単純な文字列を渡すだけで、適切に Cloud Logging ログエントリに出力される(複数行の文字列のハンドリングなど) ロガーで指定したログレベルが Cloud Logging のログエントリの severity に反映される ログを出力したファイル、関数、ソースコードの行数がログエントリに自動的に出力される 以下は、検証8-1として出力した結果です。 検証8-1 上記のように、検証8-1では、logging に渡した引数は単純な文字列型でありながら、severity が反映されています。また、 sourceLocation がログエントリに自動的に追加されており、ログが出力されたファイル名、関数、行数などがわかるようになっています。 なお、 if not os.getenv('K_SERVICE'): からの行では、環境変数 K_SERVICE を確認しています。この環境変数は、Cloud Run service ランタイム上では自動的にサービス名が代入されます。環境変数が存在しない場合はローカル環境での実行とみなし、画面に見やすい形でログを出力するようにしています。環境変数 K_SERVICE を確認せずに無条件に StreamHandler (標準出力にログを出力するハンドラ)を追加していまうと、Cloud Run 環境で実行された場合にも標準出力にログが出力されてしまうことから、先程の Cloud Logging 用のハンドラとあわせて、2行のログエントリが重複して Cloud Logging に記録されてしまいます。 参考 : コンテナ ランタイムの契約 - サービスの環境変数 続いて以下は、検証8-2のソースコードと出力結果です。 log_dict = { "message" : "exp 8-2: Output with another keys" , "my_key_1" : "my_value_1" , "my_key_2" : "my_value_2" , } message_json = json.dumps(log_dict) logging.warning(message_json) 検証8-2 検証8-2では、logging に渡した引数は JSON です。 jsonPayload にカスタムキーを含めた要素が入っています。 最後に、以下のような検証8-3も実行します。 message = "exp 8-3: This is a message with extra fields" extra_fields = { "my_key_1" : "my_value_1" , "my_key_2" : "my_value_2" , } logging.error(message, extra={ "json_fields" : extra_fields}) ロガー(ここでは logging )に第1引数として文字列を与え、extra として辞書型で json_fields をキーとしてカスタムフィールドを与えると、以下のような結果になります。 検証8-3 このようにして、ログの主たるメッセージを文字列で指定し、それ以外の付加的な情報を extra として辞書型で与えることができます。 検証9 : Python 標準ロガーのみの使用 以下のソースコードは、Python 標準の logging ライブラリのみを使用しています。カスタムフォーマッタを定義してハンドラにセットすることで、ロガーにテキストを渡すだけで出力が JSON 形式になり、Cloud Logging で適切に解釈されるようになります。 # 検証9 : カスタムフォーマッターを作成して JSON 化する import json import logging class FormatToJson (logging.Formatter): def format (self, log): return json.dumps({ "message" : log.getMessage(), "severity" : log.levelname, "app" : log.name, }) formatter = FormatToJson(datefmt= "%Y-%m-%dT%H:%M:%S%z" ) handler = logging.StreamHandler() handler.setFormatter(formatter) logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) logger.addHandler(handler) logger.info( "exp 9: This is a message with a custom formatter." ) この方法では、Cloud Logging ログエントリは以下のようになります。 検証9 Cloud Logging クライアントライブラリを使用しないため軽量ではありますが、フォーマッタで定義されていないキーを追加できないほか、自動的にソースコードの行数がログに出力されることはありません。 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の杉村です。2025年8月のイチオシ Google Cloud(旧称 GCP)アップデートをまとめてご紹介します。記載は全て、記事公開当時のものですのでご留意ください。 はじめに Google Cloud Next Tokyo '25 開催 Google Agentspace が一般公開(GA) Google Agentspace で Data agent が Private Preview 開始 Cloud SQL for MySQL / PostgreSQL で AI model endpoint が Preview 公開 Vertex AI Search の回答モデルのデフォルトが gemini-2.5-flash に変更 Google Workspace で Gemini ログが BigQuery Export できるように バーチャル試着 API が利用可能に(Preview) Vertex AI Model Garden で OpenAI の gpt-oss が利用可能に Gemini アプリで学習支援機能が強化 Gemini CLI GitHub Actionsが発表(Preview) Vertex AI Search で高度なオートコンプリートが利用可能に Vertex AI でプロンプトオプティマイザが一般公開(GA) Google Meet 自動議事メモの「ネクストステップの提案」が日本語に対応 Gemini 2.5 Flash-Lite と Pro でファインチューニングが可能に コンテキストアウェアアクセスで警告モードが使用可能に BigQuery 関数の呼出時に Chained function calls が使用可能に BigQuery のクエリ結果を Cloud Storage に直接エクスポートできるように Gemini CLI が Cloud Shell でデフォルトで使用可能に Cloud Run で環境変数を .env ファイルで設定できるように(Preview) Imagen 4 が Preview -> GA AI Protection が Preview 公開 BigQuery コンソールに Reference パネルが登場 Google ドキュメントで Gemini による文書読み上げが利用可能に Google スライドで矢印キーによるオブジェクトの移動が1ピクセル単位に BigQuery のメタデータ自動生成が Preview → GA(一般公開) IPv6-only なサブネットや VM、NAT インスタンスが作成可能に Vertex AI で gemini-2.5-flash-image-preview が Preview 公開 Gemini アプリでプロンプトによる画像の編集が可能に コンテキストアウェアアクセスが OIDC アプリに適用可能に Google Vids に生成 AI 機能が複数追加 Podcast API が許可リスト制で公開 はじめに 当記事では、毎月の Google Cloud(旧称 GCP)や Google Workspace(旧称 GSuite)のアップデートのうち、特に重要なものをまとめます。 また当記事は、Google Cloud に関するある程度の知識を前提に記載されています。前提知識を得るには、ぜひ以下の記事もご参照ください。 blog.g-gen.co.jp リンク先の公式ガイドは、英語版で表示しないと最新情報が反映されていない場合がありますためご注意ください。 Google Cloud Next Tokyo '25 開催 2025年8月5日(火) 〜 6日(水)、東京ビッグサイトで Google Cloud Next Tokyo '25 が開催された。Google Cloud の年次旗艦イベントである Google Cloud Next の東京版。基調講演のレポートは以下の記事を参照。 blog.g-gen.co.jp blog.g-gen.co.jp その他の関連記事は以下のリンクから参照。 blog.g-gen.co.jp Google Agentspace が一般公開(GA) Google Agentspace release notes - July 31, 2025 (2025-07-31) Google Agentspace が一般公開(GA)。 Google Agentspace は、様々なデータソースに対応した横断検索と AI エージェントのプラットフォーム。詳細は以下の記事を参照。 blog.g-gen.co.jp Google Agentspace で Data agent が Private Preview 開始 Google Agentspace release notes - August 01, 2025 (2025-08-01) Google Agentspace で Data agent が Private Preview 開始。 自然言語で質問をすると BigQuery に対してクエリを投入してくれる。Private Preview のため、利用するには Google への連絡が必要。 Cloud SQL for MySQL / PostgreSQL で AI model endpoint が Preview 公開 Register and call remote AI models in Cloud SQL overview (2025-08-04) Cloud SQL for MySQL / PostgreSQL で AI model endpoint が Preview 公開。 SQL を使い AI モデルを呼び出せる。エンベディング作成や、生成 AI モデルによる推論などをデータベースからシームレスに実行。BigQuery ML の RDBMS 版といえる。 Vertex AI Search の回答モデルのデフォルトが gemini-2.5-flash に変更 AI Applications release notes - August 04, 2025 (2025-08-04) Vertex AI Search の回答生成用モデルのデフォルトが gemini-2.0-flash から gemini-2.5-flash に変更。より高い精度での回答生成が期待される。 Google Workspace で Gemini ログが BigQuery Export できるように Export Gemini Audit logs to BigQuery (2025-08-04) Google Workspace で Gemini ログが BigQuery Export できるようになった。 先日のアップデートでは、管理コンソールと API で取得できるようになっていたが、今回、BigQuery への自動エクスポートも可能になった。監査ログの BigQuery Export は以下のエディションで可能。 Frontline Standard and Plus Enterprise Standard and Plus Education Standard and Plus Enterprise Essentials Plus バーチャル試着 API が利用可能に(Preview) Generate Virtual Try-On Images (2025-08-06) バーチャル試着 API が利用可能に(Preview)。 Vertex AI API の1つ。人物画像と衣服画像を Base64 エンコードして投入すると、その衣服を着た人物画像が Cloud Storage バケットに出力される。以下の記事も参照。 blog.g-gen.co.jp Vertex AI Model Garden で OpenAI の gpt-oss が利用可能に Vertex AI release notes - August 6, 2025 (2025-08-06) Vertex AI Model Garden で OpenAI の gpt-oss が利用可能に。 gpt-oss はツール使用、Chain of Thought、reasoning 調整などの特徴があるオープンウェイト言語モデル。ライセンス費用は無しでコンピュート費用のみ。 Gemini アプリで学習支援機能が強化 New study tools in the Gemini app to help you learn more effectively (2025-08-06) Gemini アプリで学習支援機能が強化。 Guided Learning(ガイド付き学習) Canvas でのクイズ作成で質問数や質問タイプをカスタム可能 画像、図表、YouTube 動画で学習を支援 Gemini CLI GitHub Actionsが発表(Preview) AI コーディングの新たなパートナー:Gemini CLI GitHub Actions を発表 (2025-08-06) Gemini CLI GitHub Actionsが発表(Preview)。Issue 振り分け、自動的な PR レビュー、Issue/PR 内で Gemini CLI にメンションして作業指示など。無料枠あり。 Vertex AI Search で高度なオートコンプリートが利用可能に Configure advanced autocomplete (2025-08-06) Vertex AI Search で高度なオートコンプリートが利用可能に。 クエリの最初の数文字を入力すると残りがサジェストされる。「基本」との違いは以下の通り。 Blended Search アプリに対応 データソースへのアクセス制御 候補のブースト 最近のクエリが提案される Vertex AI でプロンプトオプティマイザが一般公開(GA) Optimize prompts (2025-08-07) Vertex AIでプロンプトオプティマイザが一般公開(GA)。 zero-shot optimizer と data-driven optimizer がある。ユーザのプロンプトを自動で書き換えてモデルが理解しやすく変換してくれる。 Google Meet 自動議事メモの「ネクストステップの提案」が日本語に対応 Language expansion for “suggested next steps” when using “Take Notes for Me” (2025-08-07) Google Meetの自動議事メモ機能の「ネクストステップの提案」が日本語に対応。 次のステップ、フォローアップ事項、ネクストアクションなどを会話内容から自動的にまとめてくれる。15日間かけて順次ロールアウト。 Gemini 2.5 Flash-Lite と Pro でファインチューニングが可能に Supported models (2025-08-08) Gemini 2.5 Flash-Lite と Pro でファインチューニングが可能になった。 このアップデートにより、Pro、Flash、Flash-Lite のいずれもファインチューニングが可能になった。 コンテキストアウェアアクセスで警告モードが使用可能に Deploy Context-Aware Access levels in “Warn” mode (2025-08-11) Google Workspace のコンテキストアウェアアクセスで警告モードが使用可能に。 アクセス要件を満たしていないクライアントがアクセスすると、ブロックされず、警告が表示される。アクセス自体は可能。移行過渡期の設定周知などに用いることができる。 画像は公式ドキュメントから引用 BigQuery 関数の呼出時に Chained function calls が使用可能に Chained function calls (2025-08-11) BigQuery 関数の呼出時に Chained function calls が使用可能になった。 ネストされた関数呼び出しをドット(.)で繋いで呼び出せる。SQL の可読性の向上に繋がる。 BigQuery のクエリ結果を Cloud Storage に直接エクスポートできるように Save query results to Cloud Storage (2025-08-12) BigQuery のクエリ結果を Cloud Storage に直接エクスポートできるようになった。 CSV、JSONL、Avro、Parquet 形式に対応。これまでのエクスポート先であるローカル、Google ドライブ、スプレッドシートなどに加えて利用可能になった。 Gemini CLI が Cloud Shell でデフォルトで使用可能に Gemini CLI (アップデート時期不明) Gemini CLI が Cloud Shell(Google Cloud コンソールで利用可能な仮想 Linux ターミナル)でデフォルトで使用できるようになった。 追加セットアップは必要なし。 Cloud Shell 上のメッセージ Cloud Run で環境変数を .env ファイルで設定できるように(Preview) Set multiple environment variables using the .env file (2025-08-13) Cloud Run で環境変数を .env ファイルで設定できるようになった(Preview)。 版管理や共同開発もしやすくなる。以下の記事も参照。 blog.g-gen.co.jp Imagen 4 が Preview -> GA Vertex AI release notes - August 14, 2025 (2025-08-14) Imagen 4 が Preview -> GA。Preview 時代からある Imagen 4 に加え、Fast と Ultra が増えた。利用可能モデルは以下のとおり。 Imagen 4 Generate Imagen 4 Fast Generate Imagen 4 Ultra Generate AI Protection が Preview 公開 AI Protection overview (2025-08-15) AI Protection が Preview 公開。 Next 等でも紹介されていたソリューション。AI 関係リソースのリスクや脅威を可視化するためのツールで、Security Command Center Enterprise Tier で使用可能。Model Armor とも統合されている。 BigQuery コンソールに Reference パネルが登場 Use the Reference panel (2025-08-18) BigQuery コンソールに Reference パネルが登場。 テーブルのスキーマを確認したりクリックで列名を SQL に挿入したり中身のプレビューができる。最近見たテーブルにすぐに飛べるなど、SQL の記述が効率的になる。 Reference パネル Google ドキュメントで Gemini による文書読み上げが利用可能に Listen to your documents using Gemini in Google Docs (2025-08-18) Google ドキュメントで Gemini による文書読み上げが利用可能になる。 ただし、まずは英語のみ対応。読み上げのためのボタンも挿入可能。 Google スライドで矢印キーによるオブジェクトの移動が1ピクセル単位に Arrow keys now move an object by a pixel distance in Google Slides (2025-08-19) Google スライドで矢印キーによるオブジェクトの移動が1ピクセル単位に。 従来は細かい位置揃えには座標を手入力して微調整していた。 BigQuery のメタデータ自動生成が Preview → GA(一般公開) Generate table and column descriptions (2025-08-25) BigQuery のメタデータ自動生成が Preview → GA(一般公開)。 テーブルの中身をAIが読み取り、テーブルとカラムのビジネスメタデータ(Description)を自動生成する。 ただし現在、英語の生成のみに対応。また、コンソールで1テーブルずつ生成する必要あり。 IPv6-only なサブネットや VM、NAT インスタンスが作成可能に VPC release notes - August 26, 2025 (2025-08-26) VPC と Compute Engine で、IPv6-only なサブネットや VM、NAT インスタンスの作成が可能になった。IPv4 の枯渇に対する対応策に。 Vertex AI で gemini-2.5-flash-image-preview が Preview 公開 Vertex AI release notes - August 26, 2025 (2025-08-26) Vertex AI で gemini-2.5-flash-image-preview が Preview 公開。通称「Nano Banana」。 画像生成と編集の機能があり、参照画像をもとに新規画像を生成したり、マルチターンで画像を編集したりできる。Gemini アプリでも、プロンプトで指示するだけで簡単に使えるようになった。 Gemini アプリでプロンプトによる画像の編集が可能に Image editing now available in the Gemini app (2025-08-26) Gemini アプリでプロンプトによる画像の編集が可能になった。全ユーザーにロールアウト済。gemini-2.5-flash-image-preview、通称「Nano Banana」を使った機能。 添付画像は、Gemini アプリに G-gen のロゴ画像を与えて「ノベルティのトートバッグに印刷して」と指示して実際に生成された画像。 コンテキストアウェアアクセスが OIDC アプリに適用可能に Context-Aware Access policies can now be applied to all internal and third-party apps using OpenID Connect (2025-08-26) Google Workspace のコンテキストアウェアアクセスが、Workspace と OIDC 連携しているアプリにも適用できるようになった。 現在のところすべての OIDC アプリに同じポリシーが適用される(個別設定はできない)。順次ロールアウト。 Google Vids に生成 AI 機能が複数追加 Edit videos more easily using the transcript in Google Vids (2025-08-27) Deliver your message with AI avatars in Google Vids (2025-08-27) Convert images to video with Veo 3 in Google Vids (2025-08-27) Google Workspace 付属の動画編集ツール Google Vids に、生成 AI 機能が複数追加。 撮影した動画の文字起こしからフィラー(「えー」など)を文字で確認して、動画から削除できる(現在は英語のみ対応) AI アバターによる説明動画の生成。架空の人物が台本を読み上げて説明する動画を生成できる(現在は英語のみ対応) 画像を入力すると8秒間の動画へ変換できる。動画生成モデルVeo 3を使用 Podcast API が許可リスト制で公開 Generate podcasts (API method) (2025-08-28) Podcast API が許可リスト制で公開。利用にはGoogleへの申請が必要。 ポッドキャスト風音声がAPI経由で生成できる。テキスト、画像、音声、動画をインプットして、MP3 音声を出力。 製品ラインとしては NotebookLM Enterprise だが、NotebookLM Enterprise や Agentspace のライセンスは不要。API endpoint は以下。 https://discoveryengine.googleapis.com/v1/projects/PROJECT_ID/locations/global/podcasts 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen のkiharuです。当記事では、reCAPTCHA の料金体系について解説します。 はじめに reCAPTCHA とは Classic と Enterprise 料金ティア 3つの料金ティア ティアの適用 料金単価と無料枠 料金表 無料枠 はじめに reCAPTCHA とは reCAPTCHA は、スパムや不正アクセスからウェブサイトやモバイルアプリを保護するための Google Cloud サービスです。 ログイン時などに「画像認証のクイズ」や「私はロボットではありません」といったチェックを求める形で利用されています。選択できるタイプの1つである v3 では、ユーザーの操作なしでやり取りが正当かどうかを検証できます。 参考 : reCAPTCHA のタイプを選択する 参考 : 適切な reCAPTCHA キーのタイプを選択する チェックボックスキーの例 CAPTCHA チャレンジの例 Classic と Enterprise reCAPTCHA Classic は、Google Cloud サービスではなく Google サービスとして提供されてきた、従来型のサービスです。 「以前の管理コンソール」でキーが作成されており、かつ Google Cloud プロジェクトに紐付けられていない場合は、reCAPTCHA Classic が利用されています。reCAPTCHA Classic のすべての reCAPTCHA キーは、2025年末までに使用不可となるため、Google Cloud プロジェクトへ移行する必要があります。 参考 : 以前の管理コンソール 参考 : reCAPTCHA migration overview 参考 : reCAPTCHA Classic から移行する 一方で reCAPTCHA は、Google Cloud サービスとして提供されています。2025年末以降は、こちらが唯一の提供形態です。 かつては、Google サービスとして提供される旧来サービスを「reCAPTCHA Classic」、Google Cloud サービスとして提供される新サービスを「reCAPTCHA Enterprise」と表記されていましたが、現在では 後者を指して reCAPTCHA と呼称します。 当記事では、後者の reCAPTCHA の料金体系について解説しています。 料金ティア 3つの料金ティア reCAPTCHA には以下の 3 つのティアがあります。 Essentials Standard Enterprise ティアによって料金体系が異なるほか、特に Essentials と Standard 以上では利用可能な機能も異なっています。以下は、機能差異から一部を抜粋したものです。 機能 Essentials Standard / Enterprise 有償サポート 利用不可 利用可能 WAF との統合 なし あり パスワード漏洩検出 なし あり bot スコアの粒度 4 11 iOS SDK なし あり Android SDK なし あり ログ なし あり リアルタイムの統計情報 なし あり SLA なし 可用性 99.9% SLO なし あり 参考 : reCAPTCHA の各ティア間の機能の比較 ティアの適用 reCAPTCHA に適用される料金ティアは、Google Cloud プロジェクトの請求の有効化の有無や、使用量に応じて自動的に切り替わります。 請求が有効になっていない Google Cloud プロジェクトでキーを作成すると Essentials が適用 Google Cloud プロジェクトで請求を有効にすると、 Standard が適用 100,001 件以上の評価が発生すると Enterprise が適用 ただし、事前に Google Cloud や販売パートナーに相談することで、年単位等のボリュームディスカウント契約を締結することも可能です。 ティアの自動移行の流れ 参考 : 請求の仕組み 料金単価と無料枠 料金表 以下は、2025年9月現在の料金です。最新の料金は、必ず英語版の公式ドキュメントを参照してください。 参考 : Compare features between reCAPTCHA tiers 参考 : reCAPTCHA Pricing ティア 料金体系 Essentials 無料評価枠内での利用のみ Standard 無料評価枠 (10,000 件/月) + 100,000件まで $8 Enterprise 無料評価枠 (10,000 件/月) + 100,000件まで $8 + 超過した1,000件ごとに $1 料金体系とティア自動移行のイメージ 無料枠 reCAPTCHA には無料評価枠があり、 1 か月あたり10,000件 の評価まで無料です。請求が有効化されていない Essentials ティアでは、この無料枠を超えると、新しいリクエストはエラーとして返されます。 なお、月間無料枠のカウントは Google Cloud 組織全体で共有されます。また、月の評価回数は、毎月1日にリセットされます。 kiharu (記事一覧) クラウドソリューション部 クラウドエンジニアリング課。 2024年8月G-genにジョイン。 手芸好きなエンジニアです。Follow @kiharuco_
アバター
G-gen の三浦です。当記事では Microsoft SharePoint Online から Google ドライブへの移行ツールの検証結果を紹介します。 概要 Microsoft SharePoint Online からのデータ移行とは 前提条件 制約 検証概要 検証環境 検証の流れ 設定手順 [Microsoft 365] 移行対象サイトの URL の確認 [Google Workspace] 移行先の共有ドライブ ID の確認 [Google Workspace] 移行用の CSV の準備 [Google Workspace] データ移行の実施 [Microsoft 365] 移行後に SharePoint のファイルを追加 [Google Workspace] 差分移行の実施と確認 概要 Microsoft SharePoint Online からのデータ移行とは 当機能は Google Workspace の管理機能であり、Microsoft SharePoint Online(以下、SharePoint)のデータを Google ドライブの共有ドライブにコピーできます。 参考 : Microsoft SharePoint から Google Workspace に移行する 参考 : SharePoint Online からファイルを移行する 前提条件 当機能で移行を実施するには、以下の要件があります。 Google Workspace 側では 特権管理者ロール が必要です。 Microsoft 365 側では グローバル管理者ロール が必要です。 以下の特定の Google Workspace エディションでのみ利用可能です。 対応エディション Business Starter / Business Standard / Business Plus Enterprise Standard / Enterprise Plus Education Fundamentals / Education Standard / Education Plus Essentials Starter / Essentials Enterprise Essentials / Enterprise Essential Plus Nonprofits G Suite Basic / G Suite Business / G Suite Essentials 参考 : SharePoint Online からのファイルの移行について 制約 当機能には以下のような制限があります。 一度に移行可能な SharePoint Online サイト数は 100 です。 移行先は 共有ドライブ となり、特定の Google Workspace ユーザーのマイドライブへの移行はできません。 その他の制約については、以下の公式ドキュメントを確認してください。 参考 : SharePoint Online からのファイルの移行について 参考 : SharePoint Online のファイル移行で移行されるデータ 検証概要 検証環境 検証環境は以下のとおりです。実際の移行ケースを想定し、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 移行テスト用の SharePoint Online のサイトおよび移行先の共有ドライブは以下のとおりです。 サイト名 種類 配置ファイル 共有ドライブ名 管理者ユーザー gws-test-team チームサイト gws-test-team.xlsx gws-test-team-drive admin@miurak-test.com gws-test-communication コミュニケーションサイト gws-test-communication.pptx gws-test-communication-drive admin@miurak-test.com テストサイト情報1 テストサイト情報2 テストサイト情報3 検証の流れ 以下の手順でデータの移行を実施します。 項目 作業 プラットフォーム 1 移行対象サイトの URL の確認 Microsoft 365 2 移行先の共有ドライブ ID の確認 Google Workspace 3 移行用の CSV の準備 Google Workspace 4 データ移行の実施 Google Workspace 5 移行後に SharePoint のファイルを追加 Microsoft 365 6 差分移行の実施と確認 Google Workspace 設定手順 [Microsoft 365] 移行対象サイトの URL の確認 SharePoint 管理センター( https://go.microsoft.com/fwlink/?linkid=2185219 )にログインします。 参考 : SharePoint 管理センターのサイトを管理する [アクティブなサイト] から移行対象サイトの URL を確認し、控えておきます。 URLの確認 [Google Workspace] 移行先の共有ドライブ ID の確認 共有ドライブの管理画面( https://admin.google.com/ac/drive/manageshareddrives )にアクセスします。 ※ Google Workspace の管理コンソールのため、ログインが必要です。 画面を右にスクロールすることで、共有ドライブ ID が確認できるので、控えておきます。 共有ドライブIDの確認 [Google Workspace] 移行用の CSV の準備 Google Workspace の管理コンソール( https://admin.google.com )にログインします。 参考 : 管理コンソールにログインする [データ] > [データのインポートとエクスポート] > [データ移行(新規)] から Microsoft SharePoint Online の [移行] を選択します。 SharePoint Onlineの移行を選択 ステップ2の [サンプル CSV をダウンロード] を選択します。 サンプルCSVのダウンロード ダウンロードした CSV を開き、以下のとおりに入力し、保存します。 Source SharePoint URL : 項目1で確認した移行対象サイトの URL Target Drive FolderID : 項目2で確認した共有ドライブ ID Target GUser : 共有ドライブへ管理者権限をもつ Google Workspace ユーザーのメールアドレス ※ Target GUser のユーザーが SharePoint からコピーしたファイルの所有者となります。 移行用のCSV入力 ステップ3の [サンプル CSV をダウンロード] を選択します。 サンプルCSVのダウンロード ダウンロードした CSV を開き、以下のとおりに SharePoint と Google ドライブのアドレスの紐付け を入力し、保存します。 Source Entity : SharePoint のユーザーまたは Microsoft 365 グループ または SharePoint Online サイトグループ Destination Email : Google Workspace のユーザーまたは Google グループのメールアドレス 紐付け用のCSV入力 [Google Workspace] データ移行の実施 Microsoft SharePoint Online の移行のステップ1の [Microsoft SharePoint Online に接続] を選択し、移行ツールに権限を付与します。 SharePointへの接続とMicrosoftアカウントの選択 アクセス許可内容を確認して承諾 接続完了確認 ステップ2の[CSV をアップロード] を選択し、前の手順で作成した CSV を選択します。 CSVをアップロード CSVアップロード完了 ステップ3の[CSV をアップロード] を選択し、前の手順で作成した CSV を選択します。 CSVをアップロード CSVアップロード完了 ステップ4はステップ3の CSV でマッピングされていないアドレスの処理方法を選択します。今回は特に変更せずにデフォルトの設定とし、[移行を開始] を選択します。 移行を開始を選択 移行が完了したことを確認します。詳細は [移行レポートをエクスポート] または [サイトレポートをエクスポート] から確認できます。 移行完了確認 移行レポートサンプル サイトレポートサンプル 共有ドライブを確認し、サイト名のフォルダが新規で作成され、その配下にファイルがコピーされていることを確認します。 移行確認1 移行確認2 [Microsoft 365] 移行後に SharePoint のファイルを追加 データの移行後に、gws-test-communication サイトへ新規で Excel ファイルをアップロードします。 ファイルの追加 [Google Workspace] 差分移行の実施と確認 [差分移行を実行] を選択します。 差分移行を実行 移行が成功したことを確認します。 差分移行完了確認 移行レポートサンプル サイトレポートサンプル 共有ドライブを確認し、追加した Excel がコピーされていることを確認します。 差分移行確認 移行が完了したら、[移行を終了する] > [移行を終了して削除] を選択し、移行を終了します。 移行を終了するを選択 移行を終了して削除を選択 三浦 健斗 (記事一覧) クラウドソリューション部 2023年10月よりG-genにジョイン。元オンプレ中心のネットワークエンジニア。ネットワーク・セキュリティ・唐揚げ・辛いものが好き。
アバター
G-gen の佐々木です。当記事では、GKE で Gateway API を使用して作成したアプリケーションロードバランサーに対して、HTTP リクエストを HTTPS にリダイレクトするように設定する手順を解説します。 はじめに Gateway API について アプリケーションロードバランサーの HTTPS リダイレクト機能 Gateway API における HTTPS リダイレクト機能 当記事の構成について HTTPS リダイレクト構成前の動作確認 HTTPS リダイレクト専用の Namespace を作成する Gateway リソースに HTTP 用のリスナーを記述する リダイレクト用の HTTPRoute リソースを作成する 動作確認 はじめに Gateway API について Gateway API は、Kubernetes でレイヤ7の高度なトラフィックルーティングを提供するための Kubernetes アドオンであり、Google Cloud では GKE で L7 ロードバランサー(アプリケーションロードバランサー)を利用したい場合に使用されます。 従来から同様の用途で使用されていた Ingress API に様々な改良が加えられたものであり、高度なルーティング(ヘッダーベース、重み付けなど)や、異なる Namespace にあるリソースへのアクセスなどがネイティブにサポートされています。 Gateway API の基本については以下の記事を参照してください。 blog.g-gen.co.jp アプリケーションロードバランサーの HTTPS リダイレクト機能 Google Cloud で提供されているアプリケーションロードバランサーには、ロードバランサーに対する HTTP リクエストを HTTPS にリダイレクトする(HTTPS を強制する)機能があります。 この機能では、HTTPS リクエストを処理するように構成されたロードバランサーに加えて、そのロードバランサーに対して HTTP リクエストをリダイレクトするためのロードバランサー が構成されます。この2つのロードバランサーは同一の IP アドレスを持ちます。 リダイレクト用のロードバランサーは HTTP リクエストを受信し、そのリクエストを HTTPS リクエストを処理するロードバランサーにリダイレクトする役割を持ちます。これにより、バックエンドサービスのユーザーに HTTPS の使用を強制することができます。 HTTPS リダイレクトの動作イメージ 参考 : Set up an HTTP-to-HTTPS redirect for global external Application Load Balancers Gateway API における HTTPS リダイレクト機能 GKE で Gateway API を使用してアプリケーションロードバランサーを作成する場合でも、HTTPS リダイレクト機能を利用することができます。 Gateway API で作成されるロードバランサーの種類を定義する GatewayClass と、それぞれの HTTPS リダイレクト機能のサポート状況を以下の表に示します。 GatewayClass ロードバランサーの種類 HTTPS リダイレクトのサポート gke-l7-global-external-managed グローバル外部アプリケーション ロードバランサー ○ gke-l7-global-external-managed-mc グローバル外部アプリケーション ロードバランサー(マルチクラスタ) ○ gke-l7-regional-external-managed リージョン外部アプリケーション ロードバランサー ○ gke-l7-regional-external-managed-mc リージョン外部アプリケーション ロードバランサー(マルチクラスタ) ○ gke-l7-rilb 内部アプリケーション ロードバランサー ○ gke-l7-rilb-mc 内部アプリケーション ロードバランサー(マルチクラスタ) ○ gke-l7-gxlb 従来のアプリケーション ロードバランサー × gke-l7-gxlb-mc 従来のアプリケーション ロードバランサー × 参考 : Deploying Gateways - Configure HTTP-to-HTTPS redirects 参考 : GatewayClass capabilities - Frontend security 当記事の構成について 当記事では、以下の記事で作成した Gateway API リソースと nginx のバックエンドを持つ環境に対して、HTTPS リダイレクトを追加で構成していきます。以降の手順の前提となるサンプル環境を構成するためのマニフェストファイルについては、同記事を参照してください。 blog.g-gen.co.jp 当記事で前提となるサンプル構成 HTTPS リダイレクト用の HTTPRoute リソースを追加する HTTPS リダイレクト構成前の動作確認 サンプル構成では HTTPS リダイレクトを構成しておらず、また Gateway リソースに HTTP リスナーを設定していないため、HTTP リクエストがロードバランサーを通過することはありません。 HTTPS リダイレクトを構成していない場合は HTTP でサービスにアクセスできない HTTPS リダイレクト専用の Namespace を作成する まず、HTTPS リダイレクト用の HTTPRoute を作成するための Namespace を作成します。 HTTPS リダイレクト用の HTTPRoute リソースは、 Gateway リソースと別の Namespace に作成する 必要があります。もし両方とも同じ Namespace に作成した場合、Gateway が受信した HTTP リクエストは HTTPS にリダイレクトされず、そのままバックエンドサービスにルーティングされてしまいます。 # redirect-namespace.yaml apiVersion : v1 kind : Namespace metadata : name : http-redirect labels : otherInfra : httpToHttps Gateway リソースに HTTP 用のリスナーを記述する Gateway リソースを定義している サンプル構成のマニフェストファイル(gateway.yaml) に対して、以下のように HTTP 用のリスナーを追記します。HTTP のリスナーとして、先ほど作成した HTTPS リダイレクト用 Namespace の HTTPRoute リソースを指定しておくことがポイントです。 # gateway.yaml apiVersion : gateway.networking.k8s.io/v1 kind : Gateway metadata : name : external-https-gateway annotations : networking.gke.io/certmap : "my-cert-map" spec : gatewayClassName : gke-l7-global-external-managed listeners : - name : https-listener protocol : HTTPS port : 443 - name : http-listener # HTTP 用のリスナーを追加する protocol : HTTP port : 80 allowedRoutes : kinds : - kind : HTTPRoute namespaces : from : Selector selector : matchLabels : otherInfra : httpToHttps # リダイレクト用 Namespace のラベル このマニフェストファイルを適用すると、HTTPS 用のロードバランサーとは別に、HTTP をリダイレクトするためのロードバランサーも作成されます。 リダイレクト用のロードバランサーが作成される リダイレクト用の HTTPRoute リソースを作成する HTTPS リダイレクト用の設定を定義した、新たな HTTPRoute リソースを作成します。マニフェストファイルは以下のようになります。 # http-redirect.yaml kind : HTTPRoute apiVersion : gateway.networking.k8s.io/v1 metadata : name : http-redirect namespace : http-redirect # リダイレクト用 Namespace に作成する spec : parentRefs : - name : external-https-gateway # Gateway リソースの名前 sectionName : http-listener # Gateway リソースで定義している HTTP リスナーの名前 rules : - filters : - type : RequestRedirect # リクエストをリダイレクトする設定 requestRedirect : scheme : https # HTTPS にリダイレクトする 作成した HTTPRoute リソースの設定を確認すると、 Spec.Rules にリダイレクトの設定が存在することが確認できます。 # 作成した HTTPS リダイレクト用 HTTPRoute の設定を確認する $ kubectl describe httproutes -n http-redirect Name: http-redirect Namespace: http-redirect Labels: < none > Annotations: < none > API Version: gateway.networking.k8s.io/v1 Kind: HTTPRoute Metadata: Creation Timestamp: 2025-08-31T07:47:01Z Generation: 2 Resource Version: 1756626613357455008 UID: 143532f1-8f96-4b95-bd28-8294d21e38eb Spec: Parent Refs: Group: gateway.networking.k8s.io Kind: Gateway Name: external-https-gateway Namespace: default Section Name: http-listener Rules: Filters: Request Redirect: Scheme: https Status Code: 302 Type: RequestRedirect Matches: Path: Type: PathPrefix Value: / 動作確認 まず、ブラウザから HTTP でアクセスしてみます。HTTPS でサービスに接続できていることがわかります。 HTTP リクエストが HTTPS にリダイレクトされている リダイレクトの動作を確認するため、curl コマンドで HTTP リクエストを送信してみます。 HTTP/1.1 302 Found 、 https://example.com:443/ より、リクエストが HTTPS にリダイレクトされていることがわかります。 # ロードバランサーに HTTP リクエストを送信してリダイレクトの動作を確認する $ curl -v http://example.com ----- 出力例 ----- * Trying xxx.xxx.xxx.xxx:80... * Connected to example.com ( xxx.xxx.xxx.xxx ) port 80 ( #0) > GET / HTTP/ 1 . 1 > Host: example.com > User-Agent: curl/ 7 . 88 . 1 > Accept: */* > < HTTP/ 1 . 1 302 Found < Cache-Control: private < Location: https://example.com:443/ < Content-Length: 0 < Date: Sun, 31 Aug 2025 07:53:13 GMT < Content-Type: text/html ; charset =UTF -8 < * Connection #0 to host example.com left intact 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
アバター
G-genの min です。本記事では、BigQuery の INFORMATION_SCHEMA に対するクエリ例を紹介します。コスト管理、開発の効率化、運用のために活用してください。 仕様 INFORMATION_SCHEMA とは 料金 必要な権限 制約事項 注意点 コスト・リソース管理 高額クエリを特定する ユースケース SQL スロット使用量の推移を分析し、ボトルネックを特定する ユースケース SQL 組織全体のストレージ使用量をプロジェクト別に把握する ユースケース SQL 開発・デバッグ効率化 テーブルのスキーマ情報を素早く確認する ユースケース SQL テーブルの DDL(テーブル作成クエリ)を取得する ユースケース SQL パーティションテーブルの情報を調査する ユースケース SQL データセット内のビュー定義を一覧で確認する ユースケース SQL クエリのエラー履歴を確認する ユースケース SQL 運用 ストアドプロシージャの実行履歴を調査する ユースケース SQL プロシージャや UDF の定義と引数を調査する ユースケース SQL 仕様 INFORMATION_SCHEMA とは INFORMATION_SCHEMA とは、BigQuery のジョブ履歴、テーブルやビューのメタデータ、ストレージ使用量などを保持するシステムビューです。 これらのビューに対して SQL クエリを実行することで、BigQuery に関するメタデータを網羅的に取得できます。コスト管理、パフォーマンスチューニングなど、データ基盤の運用にあたって INFORMATION_SCHEMA の理解は必須です。 参考 : INFORMATION_SCHEMA の概要 料金 INFORMATION_SCHEMA のビューに対するクエリは、通常のテーブルへのクエリと同様に課金対象となります。 クエリは キャッシュされない ため、同じクエリを繰り返し実行した場合でも、その都度クエリ料金が発生します。またプロジェクトの BigQuery 課金設定がオンデマンドの場合、通常のクエリと同様、 最低 10 MB が課金バイトとしてカウントされます。 参考 : INFORMATION_SCHEMA の概要 - 料金 必要な権限 INFORMATION_SCHEMA の各ビューをクエリするには、特定の IAM 権限が必要です。本記事に登場するビューとそれに必要な権限は以下の通りです。 対象ビュー スコープ      必要な権限(Permission) 主な事前定義ロール(Role) JOBS_BY_USER プロジェクト bigquery.jobs.list BigQuery ユーザー(roles/bigquery.user) JOBS_BY_PROJECT JOBS_TIMELINE_BY_PROJECT プロジェクト bigquery.jobs.listAll BigQuery リソース閲覧者(roles/bigquery.resourceViewer) COLUMNS PARTITIONS VIEWS プロジェクト bigquery.tables.get bigquery.tables.list BigQuery データ閲覧者(roles/bigquery.dataViewer) PARAMETERS プロジェクト bigquery.routines.get bigquery.routines.list BigQuery データ閲覧者(roles/bigquery.dataViewer) TABLE_STORAGE_BY_ORGANIZATION 組織 bigquery.tables.get bigquery.tables.list BigQuery データ閲覧者(roles/bigquery.dataViewer) 組織やフォルダレベルのビューをクエリするには、権限がそれぞれのレベルで付与されている必要があります。また、これらのビューは、プロジェクトが組織に所属している場合にのみ利用可能です。 詳細については、公式ドキュメントをご参照ください。 参考 : JOBS ビュー - 必要なロール 参考 : JOBS_TIMELINE_BY_USER ビュー - 必要な権限 参考 : COLUMNS ビュー - 必要な権限 参考 : PARTITIONS ビュー - 必要な権限 参考 : PARAMETERS ビュー - 必要な権限 参考 : TABLE_STORAGE_BY_ORGANIZATION ビュー - 必要な権限 制約事項 INFORMATION_SCHEMA を用いたコスト分析にはいくつかの制約事項があります。これらの点を考慮した上で、本記事のクエリ例をご利用ください。 行レベルセキュリティ が設定されたテーブルに対するクエリでは、課金対象バイト数などの一部の統計情報が隠される場合があります。 BigQuery ML のモデル作成ジョブではモデルの種類によって料金が異なりますが、 INFORMATION_SCHEMA.JOBS ではモデルの種類を判別できないため、本記事のようなコスト計算は概算値となります。 Apache Spark プロシージャ の利用料金も INFORMATION_SCHEMA.JOBS では total_bytes_billed に含まれる場合がありますが、通常のクエリ利用と区別することはできません。 上記は INFORMATION_SCHEMA.JOBS ビューの注意点を例として挙げました。詳細は各ビューのドキュメントを参照してください。 参考 : JOBS ビュー - 制限事項 注意点 多くの INFORMATION_SCHEMA ビューは、 region-asia-northeast1.INFORMATION_SCHEMA.JOBS_BY_PROJECT のようにリージョン修飾子を付けてアクセスする必要があります。クエリを実行する際は、対象リソースが存在するリージョンを正しく指定してください。 本記事のサンプルクエリでは、 region-asia-northeast1 と記載している箇所をご自身の環境に合わせて書き換えてください。 参考 : INFORMATION_SCHEMA の概要 - 構文 コスト・リソース管理 高額クエリを特定する ユースケース 予期せぬ高額クエリ(スキャン量が多いクエリ)が実行されていないか定期的にチェックし、コストを最適化したい。 SQL 過去30日間でスキャン量が多かったクエリ TOP 20を、実行ユーザーやクエリ内容とともにリストアップします。 -- 過去30日間でスキャン量が多かったクエリ TOP 20 SELECT user_email, job_id, -- TB単位に変換 ROUND (total_bytes_billed / POW( 1024 , 4 ), 4 ) AS terabytes_billed, -- オンデマンド料金(東京リージョン: $7.5/TB)でコストを概算 ※2025年8月時点 (total_bytes_billed / POW( 1024 , 4 )) * 7.5 AS estimated_cost_usd, creation_time, -- クエリ内容を確認しやすくするために改行をスペースに置換 REGEXP_REPLACE (query, r ' \n ' , ' ' ) AS query_oneline FROM `region-asia-northeast1`.INFORMATION_SCHEMA.JOBS_BY_PROJECT WHERE creation_time BETWEEN TIMESTAMP_SUB( CURRENT_TIMESTAMP (), INTERVAL 30 DAY) AND CURRENT_TIMESTAMP () AND total_bytes_billed > 0 AND job_type = ' QUERY ' ORDER BY total_bytes_billed DESC LIMIT 20 ; スロット使用量の推移を分析し、ボトルネックを特定する ユースケース 特定の時間帯にクエリが遅くなることがあるため、時間帯ごとのリソース(スロット)消費量の傾向を分析し、負荷の高い時間帯を特定したい。 SQL JOBS_TIMELINE_BY_PROJECT を使って、1時間ごとの合計スロット使用時間( total_slot_ms )を集計し、負荷の高い時間帯を特定します。 -- 過去24時間の時間帯別(1時間ごと)の合計スロット使用時間を集計 SELECT -- 時間を切り捨ててグルーピング TIMESTAMP_TRUNC(period_start, HOUR) AS usage_hour, -- スロット使用時間(秒)に変換 SUM (period_slot_ms) / 1000 AS total_slot_seconds FROM `region-asia-northeast1`.INFORMATION_SCHEMA.JOBS_TIMELINE_BY_PROJECT WHERE period_start >= TIMESTAMP_SUB( CURRENT_TIMESTAMP (), INTERVAL 24 HOUR) GROUP BY usage_hour ORDER BY usage_hour; 組織全体のストレージ使用量をプロジェクト別に把握する ユースケース 複数のプロジェクトをまたいで、組織全体のストレージ使用量をプロジェクト別に集計し、コスト管理に役立てたい。 SQL TABLE_STORAGE_BY_ORGANIZATION ビューを使い、組織内のプロジェクト別ストレージ使用量ランキングを作成します。 -- 組織内のプロジェクト別ストレージ使用量ランキング SELECT project_id, ROUND ( SUM (total_physical_bytes) / POW( 1024 , 4 ), 2 ) AS total_physical_tb FROM `region-asia-northeast1`.INFORMATION_SCHEMA.TABLE_STORAGE_BY_ORGANIZATION GROUP BY project_id ORDER BY total_physical_tb DESC ; 開発・デバッグ効率化 テーブルのスキーマ情報を素早く確認する ユースケース 開発中に、参照したいテーブルのカラム名、データ型、NULL許容かなどをSQLエディタから離れずに確認したい。 SQL COLUMNS ビューで、特定テーブルのカラム情報を一覧表示します。 -- 特定テーブルのカラム詳細を取得 SELECT column_name, ordinal_position, data_type, is_nullable, column_default FROM `my-project.my_dataset.INFORMATION_SCHEMA.COLUMNS` WHERE table_name = ' my_table ' ; テーブルの DDL(テーブル作成クエリ)を取得する ユースケース 既存のテーブル定義を元に新しいテーブルを作成したい場合などに、テーブルの DDL( CREATE TABLE 文)を直接取得します。 SQL TABLES ビューの ddl カラムから、特定のテーブルのDDLを取得します。 -- 特定テーブルのDDLを取得 SELECT table_name, ddl FROM `my-project.my_dataset.INFORMATION_SCHEMA.TABLES` WHERE table_name = ' my_table ' ; パーティションテーブルの情報を調査する ユースケース パーティションプルーニング が意図通りに機能しているか確認したい。また、どのパーティションにどれくらいのデータが入っているか調査したい。 SQL PARTITIONS ビューで、パーティションごとの行数やデータサイズを確認します。 PARTITIONS ビューは 2025年8月現在、プレビュー機能です。仕様が変更される可能性がある点にご注意ください。 -- パーティションテーブルのパーティションごとの情報を取得 SELECT table_name, partition_id, total_rows, -- MB単位に変換 ROUND (total_logical_bytes / POW( 1024 , 2 ), 2 ) AS logical_mb, last_modified_time FROM `my-project.my_dataset.INFORMATION_SCHEMA.PARTITIONS` WHERE table_name = ' my_partitioned_table ' -- 古いパーティションから表示 ORDER BY partition_id ASC ; データセット内のビュー定義を一覧で確認する ユースケース データセット内にどのようなビューが存在し、どのテーブルを参照しているのかを、定義 SQL(ソースコード)とあわせて一覧で確認したい。 SQL VIEWS から、ビューの定義を直接取得します。 -- 特定のデータセット内のビュー一覧とその定義を取得 SELECT table_name AS view_name, view_definition FROM `my-project.my_dataset.INFORMATION_SCHEMA.VIEWS`; クエリのエラー履歴を確認する ユースケース 「先ほど実行したクエリがエラーになったが、エラーメッセージを見失ってしまった」という状況で、エラーの原因を素早く特定したい。 SQL JOBS_BY_USER を使い、自分が実行してエラーになったクエリの履歴を遡ります。 -- 過去7日間で自分が実行し、エラーになったクエリの一覧 SELECT creation_time, job_id, error_result.reason, error_result.message, query FROM `region-asia-northeast1`.INFORMATION_SCHEMA.JOBS_BY_USER WHERE creation_time BETWEEN TIMESTAMP_SUB( CURRENT_TIMESTAMP (), INTERVAL 7 DAY) AND CURRENT_TIMESTAMP () AND state = ' DONE ' AND error_result IS NOT NULL ORDER BY creation_time DESC ; 運用 ストアドプロシージャの実行履歴を調査する ユースケース 特定のバッチ処理として実装されたストアドプロシージャが、いつ、誰によって実行されたか、またはエラーになっていないかを監査したい。 SQL JOBS_BY_PROJECT の query カラムをフィルタリングして、特定のプロシージャの呼び出し履歴を抽出します。 -- 特定のプロシージャの実行履歴を取得 SELECT job_id, creation_time, start_time, end_time, TIMESTAMP_DIFF(end_time, start_time, SECOND) AS execution_seconds, user_email, statement_type, -- エラーが発生した場合は理由とメッセージを表示 error_result.reason, error_result.message FROM `region-asia-northeast1`.INFORMATION_SCHEMA.JOBS_BY_PROJECT WHERE -- 調査したいプロシージャ名でフィルタ query LIKE ' %CALL `my-project.my_dataset.my_procedure`% ' AND creation_time >= TIMESTAMP_SUB( CURRENT_TIMESTAMP (), INTERVAL 30 DAY) ORDER BY creation_time DESC ; プロシージャや UDF の定義と引数を調査する ユースケース リージョン内にどのようなプロシージャや UDF(ユーザー定義関数)が定義されているか網羅的に棚卸ししたい。また、特定のプロシージャや UDF について、その引数の詳細を調査したい。 SQL ROUTINES ビューを使うと、リージョン内のプロシージャや関数の一覧を取得できます。一方、 PARAMETERS ビューでは、特定のルーチンの引数の詳細を確認できます。 -- プロジェクト内の全データセットのプロシージャと UDF を一覧表示 SELECT routine_schema, routine_name, specific_name, -- パラメータ検索用に specific_name を取得 routine_type, -- PROCEDURE または FUNCTION data_type, -- 関数の戻り値の型 routine_definition FROM `region-asia-northeast1`.INFORMATION_SCHEMA.ROUTINES ORDER BY routine_schema, routine_name; -- 上記クエリで取得した specific_name を使い、特定の関数の引数情報を取得 SELECT parameter_name, data_type, parameter_mode -- IN, OUT, INOUT FROM `my-project.my_dataset.INFORMATION_SCHEMA.PARAMETERS` WHERE specific_name = ' my_function_name ' ; 佐々木 愛美 (min) (記事一覧) クラウドソリューション部 データアナリティクス課。2024年7月 G-gen にジョイン。G-gen 最南端、沖縄県在住。最近覚えた島言葉は、「マヤー(猫)」。
アバター
G-genの杉村です。今回は、生成 AI に関してよくある誤解と、それに対する事実を紹介します。これらは生成 AI と AI エージェントを、組織の業務に適用していくうえで知っておくべき基本的な知識です。 生成 AI に関するよくある誤解 生成 AI は確率的にテキスト等を生成するだけ 生成 AI とは 生成 AI の学習 確率的な特性 モデルは「今」を知らない 思考/推論 誤解と事実 生成 AI モデルは1+1すらできない 計算も Web サイト読み込みもできない AI を助ける tools Gemini アプリや ChatGPT の挙動 誤解と事実 モデルは「学習しない」 モデルの使用と学習 学習に見える挙動 サービス改善に使われるデータ 精度を上げるには 誤解と事実 AI エージェントの業務適用 AI エージェントとは AI エージェントと tools AI エージェントができること ノーコードエージェント AI の業務適用 本当に AI である必要があるのか AI の業務導入 AI アプリケーションの開発 生成 AI に関するよくある誤解 以下の表に、生成 AI に関してよく聞かれる誤解と、それに対する事実をまとめました。 誤解 事実 生成 AI は思考する。 生成 AI は確率的にテキスト等を生成するだけ。 ただし思考しているかのような挙動を見せることはできる 生成 AI は複雑な問題に対処できる。 生成 AI は単体では1+1すらできない。 tools の助けが必要。 生成 AI は学習する。 生成 AI モデルは、新しいデータを学ぶことは原則的にない。 ただし AI サービス提供ベンダーが、ユーザーの使用履歴を新しいモデルの学習に利用する可能性はある。 また AI サービスの使用履歴をコンテキストとして読み込むことで、学習したかのように見えることはある。 生成 AI と AI エージェントを適切に組織の業務に適用していくためには、上記に対する適切な理解が必要です。 当記事では上記について、生成 AI に関する基本的な知識と共に解説します。 生成 AI は確率的にテキスト等を生成するだけ 生成 AI とは 生成 AI (Generative AI)とは、テキスト、画像、音声、ソースコードなど、新しいコンテンツを生成することができる人工知能の一種です。 従来の AI が主にデータの分類や予測、画像認識などを得意としていたのに対し、生成 AI は学習したデータに基づいて、これまで存在しなかった新しいコンテンツを生成する能力を持ちます。生成 AI を利用した代表的なサービスとして、Google の Gemini アプリ や OpenAI の ChatGPT などが挙げられます。 参考 : Google Gemini 参考 : ChatGPT これらの AI サービスの中核となっているのは、 大規模言語モデル (LLM)です。LLM は、膨大なテキストデータを学習し、ある単語の次にどの単語が来る確率が最も高いかを 統計的に予測 することで文章を生成します。 生成 AI の学習 前述の通り、LLM は膨大なテキストデータを学習しています。このとき、「この単語の後には、次はこの単語が来やすい」という傾向を 統計的に学習 します。また LLM は学習時に、単純に隣接した単語の関係性を学ぶだけでなく、Transformer という仕組みを使って、文章全体の文脈を「理解」します。 参考 : 大規模言語モデルの概要 - Google for Developers この学習の結果として、LLM(あるいは単に モデル )が誕生します。代表的なモデルとして、Google の Gemini 2.5 Pro や Gemini 2.5 Flash 、また OpenAI の GPT-4o 、 GPT-5 、 GPT-5 mini などがあります。 参考 : Google models - Google Cloud 参考 : Models - OpenAI API ここで挙げたモデルの名称と、AI サービスの名称を混同しないように注意してください。Gemini 2.5 Pro、GPT-5 といったモデルを搭載し、ユーザーに AI チャットを提供するサービスの名前が、Gemini アプリや ChatGPT です。 サービス名 サービスが使うモデル名 Gemini アプリ Gemini 2.5 Pro、Gemini 2.5 Flash 等 ChatGPT GPT-5、GPT-5 mini 等 上記を模式図にすると以下のようになります。以下は Gemini アプリの例ですが、ChatGPT でも似た図になります。 AI サービスとモデルの関係 確率的な特性 人間が プロンプト と呼ばれるテキスト(あるいは時には画像、音声、動画)をモデルに渡すことで、モデルは処理を開始します。モデルは、ある単語の次にどの単語が来る確率が最も高いかを、 統計的に予測 することで文章を生成します。 以下の Google の公式記事は、生成 AI モデルは 確率エンジンである としています。あくまでモデルは、過去に学習したデータに基づいて確率的に文章を生成しているのだ、という点に注意が必要です。本質的に、そこに論理や思考は存在していません。モデルは人間のように意味を理解して対話しているわけではなく、あくまで確率に基づいた「それらしい」応答を生成しているに過ぎません。また同じ質問を複数回すると、返って来る答えが同じになるとは限りません。 参考 : The Prompt: 確率、データ、そして生成 AI に向き合うマインドセットとは この特性により、生成AIはいわゆる ハルシネーション (もっともらしい嘘)を生成することがあります。入力された情報や学習データにない事柄について質問された場合でも、モデルは最も確率の高い単語を繋ぎ合わせて、事実に基づかない情報を生成してしまう可能性が十分にあるのです。 参考 : AI ハルシネーションとは - Google Cloud 最新のモデルや AI サービスでは、生成結果の正しさを検証するプロセスが実行されたり、後述の「RAG」といった技術により正しさを補強する機能が備わったことにより、ハルシネーションを軽減する試みがなされています。とはいえ、生成された内容は必ずファクトチェック(事実確認)を行う必要があります。 モデルは「今」を知らない また、モデルは過去に学習したデータをもとに生成を行います。よってモデルは、「現在の天気」や「最新の Web ページの内容」などを知ることはできません。モデルは、 学習が行われた時期より後に起こった出来事を知らない のです。 Gemini シリーズのモデルでは、モデルがいつの時点のデータを使って学習されたかが明示されています。例えば Gemini 2.5 Pro は2025年1月時点のデータを使って学習しているので、それ以降の世の中の情報を知りません。 参考 : Google models - Google Cloud しかし、Gemini アプリや ChatGPT に、最近の時事について質問すると、適切に答えることがあります。この挙動は、後述する「tools」や「RAG」といったテクニックにより、モデルが 現実世界の新しい情報を随時取得 していることにより実現しています。モデル自体は最近のニュースを知らないため、外部から情報を取得しているのです。 思考/推論 生成 AI モデルや AI サービスの中には、あたかも思考しているかのような挙動を見せるものもあります。これらの挙動は思考(thinking)や推論(reasoning)と呼ばれ、モデルの特徴として位置づけられています。 Gemini 2.5 Pro/Flash/Flash-Lite や、GPT-5、GPT-5 mini はいずれもこれらの思考/推論の機能を備えたモデルです。 この機能の中核にあるのは、Chain-of-Thought(CoT、思考の連鎖)と呼ばれる技術です。この技術では、モデルは思考の途中プロセスをテキストとして生成し、それを次の生成へのインプットにして、また次の生成を行います。この連鎖を行うことで、多段階の思考を実現しています。 例えば、「太郎君はリンゴを5個持っていました。花子さんから3個もらい、その後2個食べました。残りは何個ですか?」という問題に対して、LLMは次のように思考を文章化します。 初期状態: 太郎君は最初にリンゴを5個持っている。 変化1: 花子さんから3個もらったので、5 + 3 = 8個になる。 変化2: その後2個食べたので、8 - 2 = 6個になる。 結論: したがって、残りのリンゴは6個である。 このアプローチは、人間が複雑な問題を解く際に、頭の中や紙の上で段階的に考えるプロセスを模倣しています。ポイントは、あくまで LLM の基本である「確率的にテキストを生成する」という挙動しか行っていないことです(途中で後述の「tools」を使うことはあります)。 誤解と事実 誤解 事実 生成 AI は思考する。 生成 AI は確率的にテキスト等を生成するだけ。 ただし思考しているかのような挙動を見せることはできる これを理解すれば、以下のような誤謬を回避することができます。 生成 AI は思考しており、「正しい」答えを導いてくれる 生成 AI は想定どおりの答えを毎回同じように回答してくれる 生成 AI は感情を持つかもしれない 上記の誤謬を避けられれば、AI の適用対象業務の選定や適用のさせ方を適切に検討できます。 生成 AI モデルは1+1すらできない 計算も Web サイト読み込みもできない 前述した「生成 AI は確率的にテキスト等を生成するだけ」という特性から、生成 AI モデルは「1+1」という 簡単な計算すら行うことはできません 。とはいえ「1+1」であれば、学習した言語的なデータに基づいてあたかも計算をしたかのような回答をすることはありますが、複雑な計算はできません。 当記事ならではの言い回しですが、「 生成 AI は根っからの文系である 」ということもできます。 同様に、以下のような作業は、いずれも生成 AI モデル単体では、正確に行うことはできません。 数値の計算や集計 URL に基づいた Web サイトの読み込み 外部のアプリケーションやデータベースとの連携 モデルが実行できるのは、 確率的にテキスト等を生成することだけである と考えればわかりやすいと言えます。 AI を助ける tools しかし、Gemini アプリや ChatGPT に数学の問題を与えると、高度な問題も解けることがあります。また難しい質問や時事に関する質問をすると、Web サイトの情報を取得してそれに基づいて回答してくれることもあります。 これが実現可能なのは、これらの Web サービスに tools という仕組みが組み込まれているからだと考えられます。 tools は、その名のとおり、生成 AI が使う道具です。その実体はいわゆる 通常のコンピュータプログラム です。通常のプログラムであれば、四則演算や Web サイトの取得などを、速く正確に行うことができます。Gemini アプリや ChatGPT などの Web サービスは、人間から与えられた指示に応じて、tools(= 外部プログラム)を呼び出し、必要な計算を行ったり、Web サイト検索を行ったりすることで、タスクを遂行しています。この tools を「いつ呼び出すか」「どのように使うか」という一見論理的な判断は、文系脳の生成 AI モデルでも行うことができます。これは、プロンプトに含まれるキーワードや文脈から、どの tool が最適かを確率的に判断しているためです。 なおモデルが tools としてプログラムを呼び出す機能のことを function calling と呼びます。例として Gemini や GPT シリーズは、function calling 機能を持っています。 参考 : Introduction to function calling - Google Cloud 参考 : Function calling - OpenAI API Gemini アプリや ChatGPT の挙動 Gemini アプリや ChatGPT といった各社が提供する AI サービスでは、以下のような処理が行われていると考えることができます。 ユーザーが「345 × 123は?」などとプロンプトを入力する モデルがプロンプトの意図を言語的に解釈する モデルが tools を選択。「これは計算が必要なタスクだ」と判断し、内蔵されている計算ツールを選択する モデルが tools を実行。モデルが計算ツールに「345 * 123」という計算を実行させ、42435 という結果を受け取る モデルが応答を生成。計算ツールから受け取った結果を基に「345 × 123 の答えは 42,435 です。」といった自然な文章を生成してユーザーに返す Gemini アプリや ChatGPT といったサービスは、単にモデルへの入出力インターフェイスではなく、様々な tools などの仕組みが組み込まれたチャット型アプリケーションである、と言えます。 誤解と事実 誤解 事実 生成 AI は複雑な問題に対処できる。 生成 AI は単体では1+1すらできない。 tools の助けが必要。 これを理解すれば、以下のような誤謬を回避することができます。 tools を用意していないのにも関わらず、生成 AI モデルに外部サイトの URL を与えて読み込ませようとする tools を用意していないのにも関わらず、生成 AI モデルに数値の計算や分析をさせようとする 上記の誤謬を避けられれば、AI エージェントや AI アプリケーションを開発する際に、適切に仕様を検討したり、Gemini Enterprise(旧称 Google Agentspace)や Dify といった AI プラットフォームやローコード/ノーコードエージェント開発ツールで、適切に開発を行うことができます。 モデルは「学習しない」 モデルの使用と学習 生成 AI に関するよくある誤解の1つとして、「Gemini アプリや ChatGPT といったサービスを使っていると、入力したデータがモデルに随時、学習される」といったものがあります。 これは、使っていくうちにモデルがユーザーのことを理解して、より使い勝手がよくなるのであるというポジティブな見方の側面もあれば、逆に顧客データや機密データを学習されてしまう、というネガティブな捉え方をしている人もいます。 しかし実際には、生成 AI モデルは入力されたデータを学習するということは ありません 。「生成 AI の学習」の項で説明したように、モデルは大量のデータに基づいた学習のアウトプットとして誕生します。そして一度誕生したモデルは、原則的に追加のデータを学習することはありません(後述のファインチューニングといった手法を除く)。よって、Gemini アプリや ChatGPT に入力したデータや、出力されたアウトプットが随時学習され、見ず知らずの他人に提供されてしまうということはありえません。 学習に見える挙動 一方で、Gemini アプリや ChatGPT がユーザーとのやり取りを学習したと思える挙動を見せることがあります。 これは、以下のいずれかの機能に由来しています。 コンテキスト メモリ コンテキスト とは、モデルが生成を行う際に、背景情報として使う情報です。Gemini アプリや ChatGPT で、会話スレッドを始めると、同じスレッド内であれば前の会話を AI が覚えていて、一貫性のある会話が成り立ちます。これは、AI が生成を行う際に、都度以前の会話をコンテキスト(背景情報)として参照して生成を行っているためです。生成の都度、コンテキストを読み込んでいるため、これは学習ではありません(モデル自体は何も変化していません。モデルへのインプットが変化しています)。 また メモリ とは、Gemini アプリや ChatGPT の Web アプリケーションに組み込まれた機能であり、過去のスレッドでの会話を AI が覚えているかのように会話が行える機能です。AI が最近の会話を自動的に参照するため、使えば使うほど AI がパーソナライズされていき、使い勝手がよくなります(Gemini アプリの場合はこの機能は「パーソナルコンテキスト」と呼ばれており、2025年12月現在、個人向けプラン・一部の地域でのみ利用可能です)。 参考 : Gemini アプリでのエクスペリエンスをパーソナライズする - Gemini アプリ ヘルプ 参考 : ChatGPT のメモリと新しいコントロール この機能は、モデルが最近の会話の内容を都度コンテキストとして使っている、もしくは RAG(後述)の対象として使用することで実現していると考えられます。 これらの手段は、モデルが学習していない、外部データを使用するため インプットを充実させる 手法であり、 モデルが学習して変化するわけではありません 。よって、データへのアクセス権限が適切に管理されている限り、これらの機能によってモデルを通じて他人にデータが漏洩してしまう心配もありません。 サービス改善に使われるデータ それでは、生成 AI サービスを使う際によく話題になる「入力したデータや出力されたデータが、サービス提供事業者によってサービスの改善やモデルの学習に使われるかどうか」という議論は、何のためのものなのでしょうか。 これは、Google や OpenAI といったサービス提供事業者が、 新しいモデルを開発 したり、Gemini アプリや ChatGPT といった AI サービスの改善にデータを利用するかどうかを指しています。つまり、ユーザーが入力したデータや AI によって出力されたデータは、直ちにそのモデルが学習するわけではありませんが、データがサービス提供事業者によって蓄積され、 新しいモデルの学習に使われる可能性 がある、ということを指しています。 これにより、新しく開発されるであろう次期モデルの学習には、無償版の AI サービスのユーザーが入力したデータ等が学習に使われる可能性が十分あります。機密データが次期モデルの学習に使われると、次期モデルではそのアウトプットに学習データが含まれる可能性がゼロではありません。これが、企業の AI 利用者がデータのプライバシーポリシーを適切に理解しなければならない理由です。 なお Google が提供するモデルに関しては、有償のサービス(Google Cloud や Google Workspace) に含まれる AI 機能について、入出力データはモデルの学習やサービス改善に使われることはない、とドキュメントや利用規約に明記されています。 参考 : 生成 AI とデータ ガバナンス - Google Cloud 参考 : Service Specific Terms - Google Cloud 参考 : Google Workspace with Gemini に関するよくある質問 - Google Workspace 管理者ヘルプ 参考 : Google Workspace の生成 AI に関するプライバシー ハブ - Google Workspace 管理者ヘルプ 一方で、個人向け・無償版の Google アカウントで使用する Gemini アプリ等では、データはサービス改善に使われる可能性があります。 精度を上げるには 既存のモデルが学習して変化するわけではないとしたら、モデルの精度を上げたり、自社の業務への適応度を向上させるにはどうすればよいでしょうか。 いくつかの方法がありますが、以下のような代替手段が考えられます。 コンテキストを与える Retrieval-Augmented Generation(RAG) ファインチューニング 上記を、順番に説明します。 1. コンテキストを与える 最も簡単な方法は、モデルへのインプットに コンテキスト (背景情報)を与えることです。AI への指示だけではなく、その指示の背景情報を含ませてプロンプトとしてモデルに与えることで、モデルは過去に学習していないデータも使用して生成を行うことができます。このように、特に背景情報として読み込ませるプロンプトのことを システム指示 (System Instruction)と呼ぶこともあります。 例えば、モデルに日報を書かせる場合は、以下のような情報をコンテキストとしてプロンプトに含ませることが有用です。 ペルソナ(どういった人物の立場から記述するか) 日報を書いている背景(誰のために、何のためになど) 日報の基になる業務履歴(メールのやりとり、カレンダーの予定、成果物等) 日報の体裁 特に Gemini はロングコンテキストモデルと呼ばれています。Gemini 2.5 Pro や Flash は100万トークンのコンテキストを受け付けることができます。 トークン とは、LLM が入出力する文字を理解するために分割した結果をカウントする単位です。Gemini の場合、英語の処理では概ね「約4文字が1トークン」「約60~80単語が100トークン」とされています。 参考 : トークンを理解してカウントする - Google AI for Developers つまりGemini は、英語でいうと80万単語ほどのプロンプトを一度に受け取ることができます。コンテキストとして十分な情報をインプットすることで、アウトプットの精度が向上します。 2. Retrieval-Augmented Generation(RAG) Retrieval-Augmented Generation (RAG)は、生成 AI モデルが外部のデータを参照するための手法、またはアーキテクチャのことです。RAG では、モデルにプロンプトとして直接情報を与えるのではなく、外部のデータベースを参照させます。例として、API 経由で Gemini を呼び出す場合、Google Cloud と組み合わせることで、Cloud Storage に格納した文書や BigQuery テーブルを RAG の対象として使用できます。 特に AI アプリケーションを開発したり、AI エージェントを開発するときに、RAG は重要です。AI が自社の業務やデータに適応した振る舞いをするには、RAG を構成することが有効に働きます。また、そのためには RAG の対象とするデータの整備が必要です。すなわち、文書が一箇所のストレージに集約されていたり、あるいはデータベースにきれいなフォーマットで格納されている必要があります。 3. ファインチューニング ファインチューニング は、モデルに追加の学習を施すことです。特定の業務に特化させたり、振る舞いを特定させることができます。この手法は前述の2つの手法と違い、実際に学習を行い、派生版のモデルを作成する作業です。しかし、前述の2つの手法よりも、より労力が大きいものになります。Gemini の場合、有意なファインチューニングを行うには、学習用データとしてプロンプトと応答のセットを数百個用意する必要があります。また一度モデルを開発すると、精度を維持するためには、継続してデータセットを準備して学習し続ける必要があるため、その労力は大きいものとなります。 参考 : About supervised fine-tuning for Gemini models - Google Cloud 参考 : Gemini の教師ありファインチューニング: ベスト プラクティス ガイド - Google Cloud 誤解と事実 誤解 事実 生成 AI は学習する。 生成 AI モデルは、新しいデータを学ぶことは原則的にない。 ただし AI サービス提供ベンダーが、ユーザーの使用履歴を新しいモデルの学習に利用する可能性はある。 また AI サービスの使用履歴をコンテキストとして読み込むことで、学習したかのように見えることはある。 これを理解すれば、以下のような誤謬を回避することができます。 ツールを使っているうちに AI が徐々に賢くなるのを期待する AI が入力情報を学習することを恐れて、業務導入に否定的になる 上記の誤謬を避けて、AI サービスのプライバシーポリシーやデータの扱いに関する規約を適切に理解しましょう。さらに、AI への適切なコンテキスト情報のインプットを図ったり、データの整備と RAG 構成を構築することにより、AI の精度を上げ、実業務に適用させることができます。 AI エージェントの業務適用 AI エージェントとは 生成 AI の業務適用を語るにあたり、 AI エージェント の概念も解説します。AI エージェントとは、特定の目標を達成するために、自律的に状況を判断し、計画を立てて、遂行するシステムのことです。特に、その思考エンジンとして生成 AI モデルを使用しているものを指します。 参考 : AI エージェントとは - Google Cloud 単にユーザーの指示に応答を返すだけの生成 AI チャットボット等とは異なり、AI エージェントは「出張の手配をする」といった曖昧な指示に対して、必要なタスク(航空券の予約、ホテルの予約、スケジュールの登録など)を自ら分解し、それぞれに対応する tools を順番に実行することで、目標を達成します。 AI エージェントと tools ここで重要なのが、前述の tools です。繰り返しになりますが、基本的にモデルが実行できるのは、確率的なテキスト生成です。生成 AI は、1+1という簡単な計算すら行うことはできません。AI エージェントは、生成 AI モデルを思考エンジンとして、tools、すなわち外部プログラムを自律的に判断して実行することでタスクを実行していきます。 また、AI エージェントは時として複数のエージェントを内包したマルチエージェントとして実装されます。以下は、 マルチエージェント として構成された AI エージェントの例です。 出張手配のためのマルチエージェント AI エージェントができること AIエージェントは、人間が行っていた定型的な業務や、複数のシステムを横断して行われる複雑なタスクを自動化することができます。例えば、以下のようなことが可能です。 情報収集と分析 : 複数のWebサイトや社内データベースから情報を収集し、レポートとして要約する タスクの自動化 : 経費精算システムへの入力、顧客情報のCRMへの登録、カレンダーへの予定登録などを自動で行う 顧客対応 : 顧客からの問い合わせ内容を解釈し、FAQデータベースを検索して回答したり、必要に応じて担当者へエスカレーションしたりする 2025年12月現在、AI エージェントはまだ多くの組織で実験段階であり、業務改善や大きな RoI に繋がった事例は限定的です。以下は、株式会社G-genが商用環境で AI エージェントを公開している事例です。 参考 : ナレッジ検索・回答AIエージェントG-gen Tech AgentをADKで開発した事例 - G-gen Tech Blog 参考 : 株式会社G-gen、新サービス G-gen Tech Suite を提供開始 - 株式会社G-gen ノーコードエージェント ソースコードを記述することなく AI エージェントを開発できるノーコードエージェントソリューションも存在します。 Gemini Enterprise のノーコードエージェント機能はその代表です。ノーコードエージェントは、Gemini Enterprise に接続された外部データソースを取得したうえで、コンテンツ生成や要約などのタスクを行わせることができます。 Gemini Enterprise のノーコードエージェント AI の業務適用 本当に AI である必要があるのか 生成 AI や AI エージェントは強力なツールですが、あらゆる課題に対する万能薬ではありません。逆説的ではありますが、AI の導入を検討する前に、その課題が本当に 生成 AI で 解決すべきものなのかを考えるべきです。 課題によっては、生成 AI を使わずに従来の技術で十分に、あるいはより効率的に解決できる場合があります。 例えば、特定のキーワードが含まれていたら定型文を返すような単純な応答であれば、ルールベースのチャットボットで十分です。また、Excel のデータを別のシステムに転記するような作業は、RPA(Robotic Process Automation)の方が精度が高い可能性があります。商品カタログからあいまいな言葉で検索をかけて、迅速に商品ページの URL を返すようなシステムでは、セマンティック検索(意味論検索)機能を備えた検索システムが適切です。 生成 AI の出力結果は、不確実性を伴うため、より単純で確実な方法がある場合はそちらを優先すべきです。ミスが許されない業務を、生成 AI で完全に自動化するのは困難です。一方で、 人間の業務時間を短縮するための便利な道具 あるいは 人間の判断等を補助するアシスタント としての用途であれば、検討の余地はあります。 また現状、例えば後述の Agent Development Kit(ADK)を使って実装した Gemini 2.5 Flash ベースの AI エージェントにおいて、2〜3のエージェントがシーケンシャル(直列)に動いた場合、クエリ開始からレスポンスまで、20秒〜40秒のレイテンシがかかります。こういった処理時間が許容できるかどうかも、生成 AI や AI エージェントを採用するかどうかの検討要素になります。 AI の業務導入 ある程度は生成 AI による効果が見込めそうだと考えられる場合、まずは Google Workspace に組み込まれている AI 機能(Gemini for Google Workspace)など、ライセンスを購入すれば開発不要ですぐに使える(Out-of-the-box な)サービスの使用を検討します。 Gemini for Google Workspace は、Gmail、Google ドキュメント、スプレッドシートなどの日常的に利用する Google Workspace アプリに組み込まれた生成 AI 機能の総称です。メールの文面作成、文書の要約、議事録の作成、関数やマクロの自動生成など、専門的な知識がなくても、誰もがすぐに生成 AI の恩恵を受けることができます。 参考 : Gemini for Google Workspace 以下の記事も参照してください。 blog.g-gen.co.jp どうしても既存サービスで実現できない独特な要件がある場合に、AI アプリケーションの独自開発を検討します。この考え方については、以下の記事も参照してください。 blog.g-gen.co.jp AI アプリケーションの開発 AI アプリケーションの開発を決断する場合、Google Cloud や OpenAI など、AI モデル提供事業者等が提供する API を、インターネット越しにアプリケーションから呼び出す形で実現します。 参考 : 全Geminiプロダクトを徹底解説! - G-gen Tech Blog あるいは、オープンモデルと呼ばれるようなモデルを直接サーバーに配置するような実現方法もあります。どのようにモデルを呼び出すかは、扱うデータの機密性、データの所在に関する規定、許容されるレイテンシなどから判断します。 また前述の AI エージェントを実装するには、例として以下のような方式が考えられます。 1. Agent Development Kit(ADK) Agent Development Kit (ADK)は、AI エージェントの開発、デプロイ、評価を効率化するために Google が開発したオープンソースのフレームワークです。ADK を利用することで、開発者は通常のソフトウェア開発と同じような感覚で、モジュール化された再利用可能なコンポーネントを組み合わせて AI エージェントを開発できます。ADK は Google の生成 AI モデル Gemini や Vertex AI などのエコシステムに最適化されていますが、特定のモデルやデプロイ環境に依存しない設計思想を持っており、高い柔軟性と拡張性を備えています。 参考 : Agent Development Kit ADK の仕様や実装例については、以下の記事を参照してください。 blog.g-gen.co.jp blog.g-gen.co.jp 2. Gemini Enterprise - ノーコードエージェント Gemini Enterprise は、Google(Google Cloud)が提供する生成 AI サービスです。組織内に分散しているドキュメント、メール、チャット履歴などのデータを横断検索し、情報の発見を手助けします。また AI エージェント機能により、カレンダーの登録やその他のタスクなどを人間の代わりに行います。 参考 : Gemini Enterprise とは何ですか? Gemini Enterprise の Enterprise Plus ライセンスには、 ノーコードエージェント 開発機能が搭載されています。ユーザーの1人1人が手元で、ソースコードを書くことなく、エージェントを開発できます。 例えば以下のようなエージェントを開発可能です。 Cloud Storage 上の社内規定集から情報を取得して、社内規定の質問に答えてくれるエージェント Jira から情報を取得して、指定された名称の開発プロジェクトの状況をタイムライン順に報告するエージェント Gemini Enterprise 自体は Out-of-the-box なソリューションです。その中に含まれるノーコード開発機能は、ユーザーが自らノーコードでエージェントを開発できるため、「Out-of-the-box なソリューションの利用」と「独自アプリ開発」の中間的な選択肢と言えます。以下の記事も参考にしてください。 blog.g-gen.co.jp 杉村 勇馬 (記事一覧) 執行役員 CTO 元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の菊池です。Looker Studio の期間のディメンションについて解説します。 期間のディメンションとは ディメンションと指標 期間のディメンションとは 期間のディメンションの用途 期間設定 期間設定とは 期間設定の適用範囲 デフォルトの期間 デフォルトの期間の設定 比較期間 期間グラフの特長 期間設定とデフォルトの期間の使用例 コントロールで期間を設定したい場合 特定のグラフはコントロールの対象外にしたい場合 期間のディメンションとは ディメンションと指標 Looker Studio では、Google スプレッドシートや BigQuery をデータソースとして使用できます。レポート上では、フィールド(列)は ディメンション と 指標 の2種類に分けられます。 ディメンション とは、データをグループ化するためのフィールドです。例として「商品名」「商品ID」「国名」などが挙げられます。これらのフィールドは、数値として集計(合計や平均、カウント等)されることはありません。 指標 とは、集計して使用するフィールドです。例として「金額」「購入数」「人数」などがあります。ディメンションでグループ化され、合計値や平均値、あるいは件数としてカウントされるフィールドです。 グラフの作成後、右側のプロパティパネルで、フィールドをディメンションまたは指標として選択し、追加します。 参考 : データをモデル化する - フィールドの種類 右側プロパティパネルでディメンションや指標を選択 期間のディメンションとは 期間のディメンションとは、グラフのデータ表示期間を絞る際に使われる日付データのディメンションです。レポート上で、 期間設定 コントロールと呼ばれるフィルタを使って表示期間を設定(例えば「2025年4月から2025年9月末までの間にデータを絞り込んで表示」など)する際などに、基準となります。 期間のディメンション 期間のディメンションとして有効なのは「年、月、日」を含む日付型のデータです。ただし、元のデータソースに完全な日付型のフィールドがなくても、計算フィールド関数で日付型に変換することで、期間のディメンションとして使用することもできます。 一部のデータソースタイプ(Google 広告や Google アナリティクスなど)では、期間のディメンションは自動的に設定されてしまうため、ユーザーが変更することはできません。 グラフを作成する際、データソースに日付データのフィールドがあれば、それが自動的に期間のディメンションとして選択されます。 参考 : レポートの期間を設定する - 期間のディメンションを選択 期間のディメンションの用途 期間のディメンションはグラフにおいて、期間を指定する際の基準になります。主に以下の用途で使われます。 期間設定コントロールをグラフに反映する グラフにデフォルトの期間を設定する 前者は前述のとおり、レポート上に「期間設定」コントロールを配置した場合に、表示期間を絞るときに使われるケースです。 後者は、グラフに「デフォルトの期間(そのグラフに常に適用される期間)」を設定するときに使われるケースです。 期間設定 期間設定とは 期間設定 コントロールは、データの表示期間を設定(例えば「2025年4月から2025年9月末までの間にデータを絞り込んで表示」など)するためのコントロールです。コントロールとは、レポートに表示するデータをフィルタできる制御 UI のことです。 期間設定コントロール 期間設定コントロールでは、カレンダー形式の画面で日付を選択することで、レポートの表示する期間を調整できます。 開始日と終了日を選択して期間を設定するだけでなく、[昨日]、[直前の 7 日間(今日を含む)]、[直前の四半期] など、事前に定義された期間を選択することも可能です。 期間設定コントロールは、レポート編集時に「コントロールの追加」から「期間設定」を選択することで追加できます。 参考 : 期間設定 期間設定の適用範囲 デフォルトでは、期間設定はページ上のすべてのグラフに適用されます。期間設定コントロールを適用する対象のグラフを制限したい場合は、次のいずれかの方法を用います。 期間プロパティを個々のグラフに設定する 期間設定とグラフをグループ化する 編集画面でグラフをクリックして選択し、プロパティパネルの「デフォルトの期間のフィルタ」の設定値を『自動』から『カスタム』に変更してグラフごとに期間設定を行うことで、期間設定コントロールによる期間設定を上書きできます。 デフォルトの期間のフィルタ また期間設定コントロールとグラフをシフトキーを押しながらクリックして2つとも選択した状態で、[配置] > [グループ] を選択することで、期間設定とグラフをグループ化できます。 グループ化 期間設定とグラフをグループ化すると、期間設定によるフィルタはグループ内のグラフにのみ適用されます。 グループ化の結果 期間設定が反映されるのは、期間のディメンションを持つデータソースで作成されたグラフのみです。期間のディメンションが設定されていないと、期間設定コントロールは機能しません。 デフォルトの期間 デフォルトの期間の設定 グラフに期間のディメンションを設定すると、デフォルトの期間のフィルタを設定する項目が表示されるようになります。 デフォルトの期間のフィルタ グラフでデフォルトの期間を設定することで、そのグラフでどの期間のデータを表示するか指定できるようになります。 この設定は後述する期間設定コントロールよりも優先されるため、個々のグラフで表示する期間をカスタマイズできます。グラフにデフォルトの期間を設定すると、期間設定コントロールは効かなくなります。 比較期間 デフォルトの期間のフィルタには、前の期間とデータを比較できる比較期間という機能があります。 比較期間は、デフォルトの期間のフィルタの下にある比較期間をオンにすることで有効になります。 比較期間を使用できるコンポーネントは期間グラフ、表グラフ、面グラフ、スコアカードです。 比較期間の設定 例えば、期間グラフで以下の設定をすると、前期間(8/12〜8/18)のデータが現在のデータとは異なる色の線として表示されます。 デフォルトの期間のフィルタ:過去7日間(今日を含む) 比較期間:前の期間 比較期間の表示 参考 : レポートの期間を設定する - 比較期間を設定する 期間グラフの特長 期間グラフは、一定期間におけるデータの変化を時系列で表示するグラフです。 レポート編集時に「グラフを追加」から「期間」と分類されているグラフを選択することで追加できます。 期間グラフの追加 横軸(X軸)が時間のディメンションで、縦軸(Y軸)が変化を表示したい指標になります。例えば、過去1ヶ月間のユーザー数の推移などを表示できます。 期間グラフ 折れ線グラフも同様の目的で使用されますが、期間グラフの主な利点は、比較期間を設定できる点です。 また、日付の間が空いていても、横軸の時系列は自動で埋められます。 参考 : 折れ線グラフと複合グラフのリファレンス - Looker Studio の折れ線グラフ 期間設定とデフォルトの期間の使用例 コントロールで期間を設定したい場合 期間設定コントロールとグラフのデフォルトの期間をどのように使い分けるか、具体例を交えて解説します。 以下の要件を実現したいとします。 レポートを開いた初期状態では、設定した期間(過去7日間)を表示 ユーザーが期間設定コントロールで任意の期間を指定した際には、指定された期間のデータを表示 上記を実現するには、以下のように設定します。 期間設定コントロール : デフォルトの期間で「過去7日間」を設定 グラフ : デフォルトの期間で「自動」を設定 この設定でレポートを開いた初期状態では、グラフは期間設定コントロールの期間(過去7日間)が表示されます。 レポートを開いた初期状態 ユーザーが期間設定コントロールで任意の期間(過去14日間)を設定すると、グラフにもその期間が表示されます。 期間設定コントロールの期間を変更 デフォルトの期間を期間設定コントロールのみに適用すれば、期間設定コントロールで指定した期間を常にレポート上のグラフに反映できます。 特定のグラフはコントロールの対象外にしたい場合 ユーザーがコントロールで任意の期間を指定したとしても、特定のグラフにその期間を反映したくない場合は、以下のように設定します。 期間設定コントロール : デフォルトの期間で「過去7日間」を設定 グラフ1 : デフォルトの期間で「自動」を設定 グラフ2 : デフォルトの期間で「今月」を設定 この設定でレポートを開いた初期状態では、グラフ1は期間設定コントロールの期間(過去7日間)が表示されますが、グラフ2はグラフで設定したデフォルトの期間(今月)が表示されます。 特定のグラフを期間設定コントロールの対象外にする(初期状態) ユーザーが期間設定コントロールで任意の期間(過去14日間)を設定すると、グラフ1はその期間(過去14日間)が表示されますが、グラフ2はグラフで設定したデフォルトの期間(今月)が表示されたままです。 特定のグラフを期間設定コントロールの対象外にする(期間変更後) グラフにデフォルトの期間を設定すれば、そのグラフだけ期間設定コントロールの対象外にできます。 菊池 健太 (記事一覧) クラウドソリューション部データエンジニアリング課。2024年7月より、G-genに入社。群馬出身のエンジニア。前職でLookerの使用経験はあるが、GCPは未経験なので現在勉強中。
アバター
G-gen の西田です。Cloud Storage にアップロードした CSV ファイルをデータソースとして、自動で更新される Looker Studio レポートを作成する手順を解説します。 はじめに 当記事の概要 構成図 サンプルデータの内容 構築手順の概要 Cloud Storage の構築 バケットの作成 CSV ファイルの保存 BigQuery の構築 データセットの作成 テーブルの作成 Looker Studio の作成 動作確認 はじめに 当記事の概要 当記事では、オブジェクトストレージの Cloud Storage 、データウェアハウスの BigQuery 、BI ツールの Looker Studio の3つのサービスを利用します。Cloud Storage に保存した CSV ファイルを BigQuery の外部テーブルとして参照し、そのデータを Looker Studio で可視化します。 ① Cloud Storage テキストや画像、動画などの非構造化データなど様々な形式のデータを、容量無制限で保存できるオブジェクトストレージサービスです。 参考 : Cloud Storage の料金 blog.g-gen.co.jp ② BigQuery BigQuery とは、Google Cloud のフルマネージドな分析用データベースです。BigQuery のデータは表形式で保存され、SQL や Web API 経由でデータを操作できます。 参考 : BigQuery の概要 blog.g-gen.co.jp ③ Looker Studio Looker Studio とは、Google Cloud が提供する完全クラウドベースのダッシュボードツールであり、当記事で取り扱う BigQuery 以外にも、Google アナリティクスや Google スプレッドシート等、様々なデータソースへ接続でき、SQL 等の専門知識がなくてもダッシュボード作成が可能です。 参考 : Looker Studio へようこそ なお名前がよく似ている Looker と Looker Studio は、それぞれ別製品ですのでご注意ください。当記事では Looker Studio を扱います。これらの2製品の違いは、以下の記事も参照してください。 blog.g-gen.co.jp 構成図 このシステムでは、ユーザーは Looker Studio レポートを通じて、Cloud Storage 上の CSV ファイルを可視化できます。システム構成は次の通りです。 データの可視化は Looker Studio レポートによって行われます。 このレポートからは、BigQuery の 外部テーブル をデータソースとして指定します。外部テーブルとは、BigQuery の外部にあるファイルを BigQuery からクエリできるようにする機能です。 この BigQuery 外部テーブルは、Cloud Storage バケットの所定のパスをデータソースとしています。このパスには、社内システムなどからエクスポートした CSV ファイルが管理者または自動ジョブによりアップロードされる想定です。 これにより、ユーザーが Looker Studio レポートへアクセスすると、Looker Studio から BigQuery 外部テーブルに SQL が発行されます。外部テーブルからは Cloud Storage 上のファイルが直接参照されるため、Cloud Storage から BigQuery へのデータ転送は不要です。また、常に最新のファイルが参照されることになります。 BigQuery の外部テーブルについては、以下の記事でも解説されています。 blog.g-gen.co.jp サンプルデータの内容 当記事では、文房具やPCサプライ品を販売する架空の会社の、販売実績や見込金額のサンプルデータを使います。データは、月ごとに別々の CSV ファイルに格納されています。 CSV ファイルのスキーマは、以下のようなものです。 customer_id customer_name stationery pc_supplies estimate industory GS00001 株式会社アルファネクスト 4,178 6,153 8,000 情報通信 GS00003 株式会社シーウェーブソリューションズ 1,790 2,623 3,000 サービス ・・・ ・・・ ・・・ ・・・ ・・・ ・・・ 列名は、左から「顧客 ID」「顧客名」「文房具の売上」「PC サプライ品の売上」「見込金額」「業種」を示しています。 構築手順の概要 構築は以下の3ステップで完了します。 Cloud Storage : CSV ファイルを保管する環境を構築する BigQuery : Cloud Storage に保存した CSV ファイルのデータを Looker Studio で表示するための外部テーブルを構築する Looker Studio : BigQuery テーブルのデータをレポートで可視化する Cloud Storage の構築 バケットの作成 まずは、CSV ファイルを保存する Cloud Storage の準備をします。Cloud Storage では、データを バケット と呼ばれるコンテナに格納します。バケットの中にフォルダやファイルを保存できます。このバケット単位でアクセス権の制御を行うことができます。 Cloud Storage > バケット のページにアクセスして、[バケットを作成]をクリックします。 バケット名やデータの保存場所を指定して [作成] ボタンをクリックします。バケットの名称は、グローバルで一意となるようにする必要があります。 当記事では、その他の設定項目はデフォルトのままで最下部の [作成] ボタンをクリックします。 「公開アクセスの防止」というポップアップが表示された場合は、右下の [続行] ボタンをクリックします。 CSV ファイルの保存 バケットが作成できたら、CSV ファイルを保存する準備をします。 作成したバケットにアクセスし、[フォルダの作成] をクリックします。 Cloud Storage に保存した CSV データを BigQuery の外部テーブルとして扱う際、フォルダ名を Key=Value の形式(例: ym=202504 )で作成すると、そのキー(この場合は ym )をテーブルの列として自動的に認識させることができます。これを外部データの パーティション分割 (または Hive パーティショニング)と呼びます。当記事で扱う CSV データには年月を表す列がないため、この仕組みを利用してデータを分割します。 外部データをパーティション分割することにより、データを月別にフィルタして表示した際に、Cloud Storage 上のすべてのファイルがフルスキャンされるのではなく、特定の月のファイルのみがスキャンされることになります。これはパフォーマンス向上と、コスト効率の向上に繋がります。 参考 : 外部でパーティションに分割されたデータを使用する 作成したフォルダにアクセスし、[アップロード] をクリックし、CSV ファイルをアップロードします。アップロードは、画面にファイルをドラッグアンドドロップする方法もあります。 BigQuery の構築 データセットの作成 次に、BigQuery で先程の CSV を読み取るための、 外部テーブル を作成します。 BigQuery のテーブルは、データセットという論理的な入れ物の配下に作成します。 BigQuery のコンソール画面で、プロジェクトIDの右側にある3点リーダーをクリックし、[データセットを作成] をクリックします。 データセットIDやリージョンを指定して、[データセットを作成] ボタンをクリックします。 テーブルの作成 作成したデータセットの中に、テーブルを作成します。 設定手順は表の通りです。 [Create table from] で Google Cloud Storage を選択 [GCS バケットからファイルを選択するか URI パターンを使用します] の欄に <作成したバケット名>/* を入力 (/* をつけることで、バケット配下の全てのファイル(フォルダを含む)を対象に指定しています。) (例) sales-data-csv-mnishida-blog/* [ファイル形式] で CSV を選択 [ソースデータ パーティショニング] のチェックをオン [ソース URI の接頭辞を選択] の欄に、 gs://<作成したバケット名> を入力 (例) gs://sales-data-csv-mnishida-blog [パーティション推論モード] で [独自に指定します] を選択する [フィールドを追加] をクリックし、[フィールド名] に ym を入力 (4~7の設定で、先ほど Cloud Storage で ym=202504 のように作成したフォルダ名をパーティション列として認識させています。) [テーブル] 欄にテーブル名を入力 (例) t_sales_data [テーブルタイプ] で 外部テーブル を選択 スキーマの [自動検出] のチェックをオン 詳細オプションを開き、[スキップするヘッダー行] に 1 を入力 (CSV ファイルの1行目が見出し行であるため、データとして読み込まないように設定しています。) [テーブルを作成] ボタンをクリック Looker Studio の作成 作成したテーブルを選択し、[次で開く] の中から [Looker Studio] を選択します。 Looker Studio のレポート画面は、画面上部のメニューから任意のグラフやコントロールを追加します。 以下は、サンプルレポートの画面と設定内容です。 ① テキスト ② グラフ > スコアカード ③ グラフ > スコアカード ④ コントロール > プルダウン リスト ⑤ コントロール > プルダウン リスト ⑥ グラフ > 円グラフ ⑦ グラフ > 棒グラフ ⑧ グラフ > 表 動作確認 現時点では4月分のデータのみ保存しているため、レポートでも4月分のデータしか閲覧できません。 他の月のデータを表示するためには、Cloud Storage のバケット内に4月分のフォルダを作成した時と同様に、 ym=202505 、 ym=202506 などのフォルダを作成してファイルを保存するだけでデータの更新できます。 各月のファイルを保存した後に Looker Studio でデータを更新することで、追加した月の選択やデータの閲覧が可能となります。 西田 匡志 (記事一覧) クラウドソリューション部ソリューションアーキテクト課 美容商社→物流→情シスを経て、2025年6月G-genにジョイン。Google Cloud を通じて多くの人に貢献できるよう日々精進!
アバター
G-gen の佐々木です。当記事では、GKE で Gateway API を使用する際に、作成されたアプリケーションロードバランサーに対して Cloud Armor セキュリティポリシー と IAP を構成する方法を解説します。 はじめに GKE における Gateway API Cloud Armor とは Identity-Aware Proxy(IAP)とは 当記事の構成 GCPBackendPolicy に関する注意点 Gateway リソースに対して Cloud Armor セキュリティポリシーを構成する手順 Cloud Armor セキュリティポリシーの作成 GCPBackendPolicy の作成 動作確認 Gateway リソースに対して IAP を構成する手順 OAuth 同意画面の構成 バックエンドサービスで IAP を有効化 OAuth 2.0 クライアント ID とシークレットの発行 Secret の作成 GCPBackendPolicy の作成 動作確認 Cloud Armor セキュリティポリシーと IAP を同時に構成する手順 Ingress API を使う場合 はじめに GKE における Gateway API Gateway API は、Kubernetes でレイヤ7の高度なトラフィックルーティングを提供するための Kubernetes アドオンであり、Google Cloud では GKE で L7 ロードバランサー(アプリケーションロードバランサー)を利用したい場合に使用されます。 従来から同様の用途で使用されていた Ingress API に様々な改良が加えられたものであり、高度なルーティング(ヘッダーベース、重み付けなど)や、異なる Namespace にあるリソースへのアクセスなどがネイティブにサポートされています。 Gateway API の基本については以下の記事を参照してください。 blog.g-gen.co.jp 当記事では、この Gateway API から作成したアプリケーションロードバランサーに対して、 Cloud Armor セキュリティポリシー によるバックエンド保護と、 Identity-Aware Proxy (IAP)による IAM 認証機能を構成していきます。 Cloud Armor とは Cloud Armor は Google 製のクラウド型 WAF であり、Cloud Armor の セキュリティポリシー をアプリケーションロードバランサのバックエンドに紐づけることで、バックエンドに対するアクセス元の制限をかけることができます。 Cloud Armor の詳細については、以下の記事で解説しています blog.g-gen.co.jp Identity-Aware Proxy(IAP)とは IAP は、Cloud Run や GKE、Compute Engine 上で実行されているアプリケーションに対して、IAM による認証機能を提供するサービスです。アプリケーションにアクセスできるユーザーを特定の IAM ロールがアタッチされた Google アカウント/グループに制限することができます。 IAP の基本については、以下の記事で解説しています。 blog.g-gen.co.jp 当記事の構成 当記事では、以下の記事で作成した Gateway API リソースと nginx のバックエンドを持つ環境に対して、Cloud Armor セキュリティポリシーと IAP を追加で構成していきます。以降の手順の前提となるサンプル環境を構成するためのマニフェストファイルについては、同記事を参照してください。 blog.g-gen.co.jp 当記事で前提となるサンプル構成 GCPBackendPolicy を使用して Cloud Armor や IAP を構成する GCPBackendPolicy に関する注意点 Gateway API で作成したロードバランサーに対して Cloud Armor セキュリティポリシーや IAP を構成したい場合、Gateway API リソースの1つである Policy を使用します。 GKE で利用できる Gateway API の Policy には以下のような種類があります。 GCPGatewayPolicy GCPBackendPolicy HealthCheckPolicy Cloud Armor や IAP を利用する場合は、 GCPBackendPolicy を定義し、Gateway のバックエンド(ルーティング先)である Service リソースに紐付けます。 注意点として、GCPBackendPolicy は 1つの Service に対して1つしか紐付けることはできません。そのため、 1つの Service に対して Cloud Armor セキュリティポリシーと IAP の両方を構成したい場合、その両方の定義を1つの BackendPolicy 内に記述する必要があります。 2つの GCPBackendPolicy を紐づけると、 kubectl describe gcpbackendpolicies コマンドの出力として以下のエラーメッセージが確認できます。 Warning SYNC 14s (x2 over 63s) sc-gateway-controller Conflicted: Application of GCPBackendPolicy "default/nginx-backend-policy" failed: conflicted with GCPBackendPolicy "default/my-backend-policy" of higher precedence, hence not applied 参考 : Configure Gateway resources using Policies Gateway リソースに対して Cloud Armor セキュリティポリシーを構成する手順 Cloud Armor セキュリティポリシーの作成 ここでは、サンプル構成に対して Cloud Armor のセキュリティポリシーを適用し、許可された IP アドレスからのみ、バックエンドのサービスにアクセスできるようにします。 まず、Cloud Armor のセキュリティポリシーを作成します。 # セキュリティポリシーの作成 $ gcloud compute security-policies create my-sec-policy 作成したポリシーのデフォルトルール(優先度2,147,483,647)では全ての通信が許可されているため、デフォルトルールを更新して全てのアクセス元を拒否します。 # デフォルトルールの更新 $ gcloud compute security-policies rules update 2147483647 \ --security-policy my-sec-policy \ --action " deny-403 " 特定の IP アドレス範囲からのアクセスを許可するルールを追加します。 ルールの優先度は全拒否のデフォルトルールより高ければよいので、ここでは優先度1000で設定します。 # 許可ルールの追加 $ gcloud compute security-policies rules create 1000 \ --security-policy my-sec-policy \ --src-ip-ranges " <許可する IP アドレス範囲> " \ --action " allow " 特定の IP アドレス範囲のみ許可するセキュリティポリシー 参考 : gcloud compute security-policies create 参考 : gcloud compute security-policies update GCPBackendPolicy の作成 作成した Cloud Armor セキュリティポリシーを Gateway のバックエンドサービスに紐づけるための GCPBackendPolicy を作成します。 以下のマニフェストを使用して、バックエンドの Service リソースに対してセキュリティポリシーを紐づけます # backend-policy.yaml apiVersion : networking.gke.io/v1 kind : GCPBackendPolicy metadata : name : nginx-backend-policy spec : default : securityPolicy : my-sec-policy # Cloud Armor セキュリティポリシーの名前 targetRef : group : "" kind : Service name : nginx-service # ルールを紐づけるバックエンドの Service リソース 動作確認 Cloud Armor セキュリティポリシーで許可していない IP アドレスから、ロードバランサーに設定しているドメインにアクセスしてみます。 セキュリティポリシーにより、アクセスが拒否されていることがわかります。 セキュリティポリシーで許可されてない IP アドレスからのアクセスが拒否される 許可した IP アドレスからのアクセスは成功する このまま続けて次の IAP の構成手順に進む場合、一度 GCPBackendPolicy リソースを削除してください(Service に対して1つしか紐づけられないため)。 Gateway リソースに対して IAP を構成する手順 OAuth 同意画面の構成 使用しているプロジェクトで OAuth 同意画面 をまだ構成していない場合は、設定を行います。 手順は以下のドキュメントや記事を参照してください。 参考 : Configure the OAuth consent screen and choose scopes 参考 : GoogleAPI、OAuth2.0の有効化の手順 - サーバーワークスエンジニアブログ バックエンドサービスで IAP を有効化 Google Cloud コンソールから、バックエンドサービスに対して IAP を有効化します。 対象のサービスのトグルスイッチを ON にし、「IAP をオンにする」を選択します。 バックエンドサービスで IAP を有効化する 「IAP をオンにする」を選択 サービスへのアクセスを許可する Google アカウントに対して、 IAP で保護されたウェブアプリ ユーザー (IAP-secured Web App User)ロールを付与します。 アカウント、グループに対してサービスへの IAP 経由のアクセスを許可する OAuth 2.0 クライアント ID とシークレットの発行 Google Cloud コンソールの「API とサービス」から、OAuth 2.0 クライアント ID を作成していきます。 「OAuth クライアント ID」を選択する 以下の項目を入力し、「作成」を選択します。 項目 値 アプリケーションの種類 ウェブ アプリケーション 名前 任意の名前 OAuth クライアント ID を作成する 作成後、 クライアント ID と クライアントシークレット が表示されるので、この2つはメモしておきます。なお、メモするのを忘れてもクライアントの詳細画面から後で確認できます。 クライアント ID とクライアントシークレットをメモしておく 作成したクライアント ID の編集画面を開き、「承認済みのリダイレクト URI」項目を設定します。 値には、先ほどメモしておいたクライアント ID を含む以下の URI を設定します。 「承認済みのリダイレクト URI」の設定値 https://iap.googleapis.com/v1/oauth/clientIds/{クライアント ID の値}:handleRedirect 承認済みのリダイレクト URI を設定する Secret の作成 メモしておいた OAuth クライアント シークレットを以下のようにテキストファイルにそのまま記述します。当記事では iap-secret.txt という名前でファイルを作成します。 <クライアント シークレットの値> このテキストファイルを使用して、以下のコマンドで Secret リソースを作成します。 # Secret の作成 $ kubectl create secret generic my-secret --from-file = key =iap-secret.txt GCPBackendPolicy の作成 作成した Secret リソースと、メモしておいた OAuth クライアント ID を使用し、バックエンドの Service に紐づける GCPBackendPolicy を作成します。 マニフェストファイルは以下のようになります。 # backend-policy.yaml apiVersion : networking.gke.io/v1 kind : GCPBackendPolicy metadata : name : nginx-backend-policy spec : default : iap : enabled : true # IAP を有効化 oauth2ClientSecret : name : my-secret # 作成した Secret リソースの名前 clientID : <OAuth クライアント ID> # メモしておいた OAuth クライアント ID targetRef : group : "" kind : Service name : nginx-service # ルールを紐づけるバックエンドの Service リソース 動作確認 マニフェストファイル適用後、ロードバランサーに設定しているドメインにアクセスすると、IAP のログイン画面が表示されます。 IAP が有効化されたサービスにアクセスする IAM で許可された Google アカウントでログインすることで、サービスにアクセスすることができます。 Cloud Armor セキュリティポリシーと IAP を同時に構成する手順 先述したように、バックエンドサービスである Service に対して、GCPBackendPolicy リソースは1つしか紐づけることができません。 Cloud Armor セキュリティポリシーと IAP を同時に構成したい場合、以下のように1つのマニフェストファイルに対してそれぞれの定義をします。 # backend-policy.yaml apiVersion : networking.gke.io/v1 kind : GCPBackendPolicy metadata : name : nginx-backend-policy spec : default : securityPolicy : my-sec-policy # Cloud Armor セキュリティポリシーの名前 iap : enabled : true # IAP を有効化 oauth2ClientSecret : name : my-secret # 作成した Secret リソースの名前 clientID : <OAuth クライアント ID> # メモしておいた OAuth クライアント ID targetRef : group : "" kind : Service name : nginx-service # ルールを紐づけるバックエンドの Service リソース なお、Cloud Armor セキュリティポリシーと IAP を同時に構成した場合、 先にセキュリティポリシーによるアクセス許可/拒否が評価 され、ポリシーで許可されたアクセスに対して 後から IAP による認証 が行われます。 Ingress API を使う場合 GKE で Cloud Load Balancing のアプリケーションロードバランサーを使用する場合、従来は Ingress API を使用していました。 Ingress API を使用している場合、ロードバランサーに対して Cloud Armor や IAP を構成するには BackendConfig リソースをバックエンドの Service リソースに紐付けます。 Ingress API を使用する場合の詳細な手順については、以下の記事を参照してください。 blog.g-gen.co.jp 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 の佐々木です。当記事では、Kubernetes で展開しているサービスの外部公開用 API リソースである Gateway API について、特に GKE で使用する場合における基本的な仕様を解説します。 Gateway API の概要 Ingress API との違い Ingress からの改良点 GKE における違い Gateway API のリソース リソースの構成 GatewayClass Gateway HTTPRoute Policy ReferenceGrant Gateway API を使ってみる サンプル構成 Gateway API の有効化 SSL 証明書の作成 サンプル Pod、Service のデプロイ Gateway のデプロイ DNS レコードの設定 HTTPRoute のデプロイ 動作確認 Gateway API の概要 Gateway API は、Kubernetes でレイヤ7の高度なトラフィックルーティングを提供するための Kubernetes アドオンであり、 Ingress API 同様、レイヤ7ロードバランサーをデプロイすることでバックエンドのサービスを公開することができます。 GKE における Gateway API では、GKE クラスタで使用できる Cloud Load Balancing の各種アプリケーションロードバランサーを定義、デプロイすることができます。 参考 : Gateway API(Kubernetes ドキュメント) 参考 : About Gateway API(Google Cloud ドキュメント) Ingress API との違い Ingress からの改良点 一般的に、Kubernetes では外部公開するアプリケーションにトラフィックをルーティングしたい場合、 Ingress を使用することができます。 Gateway は Ingress よりも後発の API リソースであり、以下のような改良が加えられています。 改良点 Ingress API の課題 Gateway API の特徴 ロール志向 1つのリソースにインフラの設定とアプリケーションのルーティング設定をまとめて定義する必要がある。そのため、インフラ担当者とアプリケーション開発者の責任範囲が曖昧になっている。 リソース定義を Gateway(インフラ定義)、HTTPRoute(ルーティング定義) のように分割することで、インフラ担当者とアプリケーション開発者がそれぞれの担当領域(ロール)でリソースを管理できる。 移植性・表現性 パスベース以外のルーティングなど、高度な機能はネイティブでサポートされておらず、GKE なら GKE 用の Ingress Controller が独自に定義したアノテーションを用いて実装する必要がある。 多くの高度な機能がネイティブでサポートされており、リソース定義がクラウドプロバイダーやオンプレミスなど環境に依存しない。 Namespace 間アクセス Ingress 単体の機能では、異なる Namespace にあるバックエンドサービスや Secret にアクセスすることができない。たとえばマイクロサービスごとに Namespace を割り当てている環境などで、1つの Ingress からそれぞれのサービスにルーティングするような構成ができない。 Gateway は異なる Namespace のリソースにアクセスすることができる。 参考 : Ingress の進化版 Gateway API を解説する Part 1 (シングルクラスタ編) GKE における違い GKE における Ingress では、外部アプリケーションロードバランサー向けの Ingress と、内部アプリケーションロードバランサー用の Ingress を使用することができます。前者は Cloud Load Balancing の 従来の外部アプリケーションロードバランサー を、後者は 内部アプリケーションロードバランサー をデプロイします。 後述するように、Gateway API では GatewayClass により、新しい世代の(「従来の」ではない)外部アプリケーションロードバランサーや、マルチクラスタで利用できるロードバランサーをデプロイすることができるようになっています。 Google Cloud の Cloud Load Balancing を利用する場合、ロードバランサーの各コンポーネントと Ingress API、Gateway API の関係は以下の図のようになっています。 Cloud Load Balancing の各コンポーネントと Ingress API、Gateway API の関係 参考 : GKE Ingress for Application Load Balancers Gateway API のリソース リソースの構成 Gateway API は主に以下のリソースから構成されます。 GatewayClass Gateway HTTPRoute Gateway API の基本的なリソース構成 また、以下のような補助的なリソースがあります。 Policy RefernceGrant GatewayClass Gateway から参照されるリソースで、クラスタに作成するロードバランサーのテンプレートとして機能します。GKE の場合、Google Cloud によってクラスタで利用できるロードバランサーが GatewayClass として事前定義されています。 以下は、GKE クラスタで利用可能な GatewayClass の例です。 GatewayClass の名前 対応する Cloud Load Balancing のロードバランサー gke-l7-global-external-managed グローバル外部アプリケーションロードバランサ gke-l7-regional-external-managed リージョン外部アプリケーションロードバランサ gke-l7-rilb 内部アプリケーションロードバランサ gke-l7-global-external-managed-mc マルチクラスタ用のグローバル外部アプリケーションロードバランサ gke-l7-regional-external-managed-mc マルチクラスタ用のリージョン外部アプリケーションロードバランサ gke-l7-rilb-mc マルチクラスタ用の内部アプリケーションロードバランサ 上記の GatewayClass の名前を Gateway のリソース定義で指定することで、対象のロードバランサーを作成することができます。 apiVersion : gateway.networking.k8s.io/v1 kind : Gateway metadata : name : internal-http spec : gatewayClassName : gke-l7-rilb # 内部アプリケーションロードバランサを作成する listeners : - name : http protocol : HTTP port : 80 詳細な仕様やその他の GatewayClass については、以下の公式ドキュメントもご一読ください。 参考 : GatewayClass capabilities Gateway トラフィックを処理するロードバランサーの種類(GatewayClass)、プロトコル、ポート、TLS 設定などを定義します。 apiVersion : gateway.networking.k8s.io/v1 kind : Gateway metadata : name : external-http spec : gatewayClassName : gke-l7-global-external-managed # ロードバランサーの種類(GatewayClass) listeners : # プロトコル、ポート、TLS 設定など、リスナーの設定 - name : https protocol : HTTPS port : 443 tls : mode : Terminate certificateRefs : - name : store-example-com HTTPRoute Gateway が受信したリクエストを、バックエンドの Service リソースにルーティングするためのルールを定義します。 apiVersion : gateway.networking.k8s.io/v1 kind : HTTPRoute metadata : name : store-external labels : gateway : external-http spec : parentRefs : - name : external-http # ルーティング設定を紐付ける Gateway リソースの名前 hostnames : # ルーティング設定を適用するホスト名 - "store.example.com" rules : - backendRefs : # Gateway が受信したリクエストをルーティングするバックエンドサービス - name : store-v1 # Service リソースの名前 port : 8080 Policy バックエンドサービスに対するヘルスチェックやトラフィック分散の方法、リクエストのタイムアウト、Identity-Aware Proxy や Cloud Armor バックエンドセキュリティポリシーの紐付けなどを定義します。 設定する Policy の種類によって、Policy リソースを Gateway リソースや Service リソースに対して紐付けます。 例えば以下のマニフェストファイルでは、Gateway リソースとして作成したロードバランサーに対する SSL ポリシーの紐付けが定義されています。 apiVersion : networking.gke.io/v1 kind : GCPGatewayPolicy metadata : name : my-gateway-policy namespace : team1 spec : default : sslPolicy : gke-gateway-ssl-policy # SSL ポリシーの名前 targetRef : group : gateway.networking.k8s.io kind : Gateway name : my-gateway # Policy を紐付ける Gateway リソースの名前 参考 : Configure Gateway resources using Policies ReferenceGrant Gateway や HTTPRoute が、異なる Namespace にあるバックエンドサービス、Secret などを参照できるようにするリソースです。 以下のマニフェストファイルは、 frontend Namespace の HTTPRoute から backend Namespace の Service にトラフィックをルーティングできるような ReferenceGrant を定義しています。 apiVersion : networking.gke.io/v1 kind : ReferenceGrant metadata : name : allow-frontend-to-access-backend namespace : backend # Namespace間アクセスを許可するアクセス先のNamespace spec : from : # どこからのアクセスを許可するか - group : gateway.networking.k8s.io kind : HTTPRoute namespace : frontend to : # 何に対するアクセスを許可するか - group : "" kind : Service Gateway API を使ってみる サンプル構成 当記事ではサンプル構成として、nginx をバックエンドサービスとする Gateway、HTTPRoute リソースを作成していきます。Gateway には Certificate Manager で作成した Google マネージド SSL 証明書を紐づけ、Gateway で作成されたロードバランサーに HTTPS でアクセスできるようにします。 当記事のサンプル構成 Gateway API の有効化 GKE クラスタで Gateway API が有効化されていない場合は有効化します。 # クラスタで Gateway API を有効化する $ gcloud container clusters update < GKEクラスタ名 > \ --location =< クラスタのロケーション > \ --gateway-api = standard SSL 証明書の作成 Gateway API で作成するロードバランサーで TLS を設定するために、Certificate Manager 管理の証明書を作成します。 当記事では Google マネージド SSL 証明書を使用します。 # Google マネージド SSL 証明書を作成する $ gcloud certificate-manager certificates create my-cert \ --domains =" <使用するドメイン> " \ --scope = DEFAULT # 証明書マップを作成する $ gcloud certificate-manager maps create my-cert-map # 証明書マップのエントリーを作成する $ gcloud certificate-manager maps entries create [ ENTRY_NAME ] \ --map =" my-cert-map " \ --certificates =" my-cert " \ --hostname =" <使用するドメイン> " 参考 : Manage certificates サンプル Pod、Service のデプロイ サンプルアプリケーションとして、以下のマニフェストを使用して nginx の Pod と Service をデプロイします。 # deployment.yaml apiVersion : apps/v1 kind : Deployment metadata : name : nginx-deployment spec : replicas : 2 selector : matchLabels : app : nginx-server template : metadata : labels : app : nginx-server spec : containers : - name : nginx image : nginx:latest ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : nginx-service spec : selector : app : nginx-server ports : - protocol : TCP port : 80 targetPort : 80 Gateway のデプロイ ロードバランサーのフロントエンドとして機能する Gateway リソースを作成します。 以下のサンプルマニフェストでは、先ほど作成した証明書を使用するグローバル外部アプリケーションロードバランサーを作成する Gateway リソースをデプロイします。 # gateway.yaml apiVersion : gateway.networking.k8s.io/v1 kind : Gateway metadata : name : external-https-gateway annotations : networking.gke.io/certmap : "my-cert-map" # 作成した証明書マップの名前 spec : gatewayClassName : gke-l7-global-external-managed # グローバル外部アプリケーションロードバランサーを使用 listeners : - name : https-listener protocol : HTTPS port : 443 デプロイした Gateway リソースは以下のコマンドで確認できます。 # デプロイした Gateway の確認 $ kubectl get gateways NAME CLASS ADDRESS PROGRAMMED AGE external-https-gateway gke-l7-global-external-managed xxx.xxx.xxx.xxx True 74s Google Cloud コンソールを確認すると、アプリケーションロードバランサーが作成されていることがわかります。 Gateway のデプロイ後、ロードバランサーが作成されている DNS レコードの設定 使用するドメインに対して、先ほど kubectl get gateways コマンドで確認したロードバランサーの外部 IP アドレスを解決できる A レコードを作成します。 以下のスクリーンショットは、Cloud DNS を使用する場合のレコードの設定例です。 DNS で A レコードを設定する HTTPRoute のデプロイ Gateway が受信したトラフィックをバックエンドサービスにルーティングするために、HTTPRoute をデプロイします。 以下のサンプルマニフェストでは、バックエンドである nginx サービスの80番ポートにトラフィックをルーティングする HTTPRoute リソースを作成します。 apiVersion : gateway.networking.k8s.io/v1 kind : HTTPRoute metadata : name : nginx-http-route spec : parentRefs : - name : external-https-gateway # Gatewayリソースの名前 hostnames : - "<使用するドメイン>" rules : - matches : - path : type : PathPrefix value : / backendRefs : - name : nginx-service # バックエンドの Service の名前 port : 80 デプロイした HTTPRoute リソースは以下のコマンドで確認できます。 $ kubectl get httproutes NAME HOSTNAMES AGE nginx-http-route [" <使用するドメイン> "] 13s 動作確認 作成した Gateway 関連リソースは、GKE のコンソールからも確認することができます。 GKE コンソールから Gateway の設定を確認する それでは、使用しているドメインに対して、curl コマンドやブラウザから HTTPS でアクセスしてみます。 Gateway API で作成したアプリケーションロードバランサー経由で、HTTPS でバックエンドサービスにアクセスできています。 Gateway API で作成したロードバランサー経由で HTTPS アクセスができている 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
アバター
G-gen の min です。BigQuery のためのデータ変換ワークフローサービスである Dataform における、「ワークスペースコンパイルオーバーライド」「リリース構成」「ワークフロー構成」という3つの機能について解説します。 はじめに 当記事について Dataform のワークフローライフサイクル 構成機能 ワークスペースコンパイルオーバーライド 機能概要 設定方法 注意点 リリース構成 機能概要 設定方法 ワークフロー構成 機能概要 設定方法 開発と管理 ライフサイクルの全体像 ベストプラクティス 必要なロール リソースの有効期限 はじめに 当記事について BigQuery のためのデータ変換ワークフローサービスである Dataform における、コンパイルと実行のライフサイクル管理について解説します。 具体的には、「 ワークスペースコンパイルオーバーライド 」「 リリース構成 」「 ワークフロー構成 」という3つの機能を用いて、開発環境と本番環境を分離し、実行を自動化する仕組みを詳しく説明します。 Dataform の基本的な概念や使い方については、以下の記事で解説しています。 blog.g-gen.co.jp Dataform のワークフローライフサイクル まず、Dataform におけるワークフローのライフサイクルを理解することが重要です。ライフサイクルは、大きく分けて「 開発 」「 コンパイル 」「 実行 」の3つのフェーズで構成されます。 1 開発 Dataform のワークスペースで SQLX ファイルを記述し、データ変換のロジックを開発します。 2 コンパイル Dataform は、ワークスペースに記述されたコードをリアルタイムで SQL にコンパイルします。このコンパイル結果は、実際に BigQuery で実行される SQL の集合体です。Dataform のコンパイルは密閉されたサンドボックス環境で行われ、毎回同じコードからは同じコンパイル結果が生成される整合性が保証されます。 3 実行 生成されたコンパイル結果を、Dataform が BigQuery 上で実行します。これにより、テーブルやビューが作成・更新されます。 この記事で紹介する機能は、主に「コンパイル」と「実行」のフェーズを、要件に合わせて柔軟にカスタマイズするためのものです。 参考 : Dataform のワークフロー ライフサイクルの概要 構成機能 Dataform で開発したデータ変換ロジックを実際の環境(開発環境、本番環境など)でどのようにコンパイルして実行するかを規定する一連の流れを「ライフサイクル」と呼びます。このライフサイクルを管理・自動化するために、Dataform では主に以下の3つの機能が提供されています。 これらの機能は、SQLX ファイルを記述するといった「開発」そのものとはレイヤーが異なり、完成したコードを本番環境へ安全にデプロイし、定期実行するための「仕組み」を構築する役割を担います。それぞれの目的と役割は以下のとおりです。 機能名 主な目的 利用フェーズ ワークスペースコンパイルオーバーライド 開発者ごとの 開発環境を分離 する 開発(手動) リリース構成 本番/ステージング用 コンパイル結果をテンプレート化 する コンパイル(自動) ワークフロー構成 コンパイル結果を スケジュール実行 する 実行(自動) これらの機能を組み合わせることで、開発者は個別のサンドボックス環境で開発を進め、完成したコードを Git 経由で本番環境へ安全にデプロイし、定期実行する、といった一連のワークフローを Dataform 内で完結できます。 ワークスペースコンパイルオーバーライド 機能概要 ワークスペースコンパイルオーバーライド は、リポジトリ内のすべてのワークスペースに適用されるコンパイル設定の上書き機能です。主に、開発者ごとに独立した 開発環境を分離する ために使用します。 この機能を使うと、 workflow_settings.yaml (または dataform.json )で定義されたデフォルト設定を、ワークスペースでの手動実行時に限り上書きできます。上書きできる設定は以下の3つです。 Google Cloud プロジェクト テーブルの接頭辞 スキーマの接尾辞 動的変数を使用できる点が特徴です。例えば、スキーマの接尾辞に ${workspaceName} と設定すると、 msasaki という名前のワークスペースで実行した際には、スキーマ名が (デフォルトスキーマ)_msasaki となります。 これにより、各開発者は他の開発者の作業に影響を与えることなく、自分専用のスキーマにテーブルやビューを作成して開発やテストができます。 設定方法 Dataform リポジトリの [設定] > [編集] をクリックします。 [ワークスペース コンパイル オーバーライド] ペインで、プロジェクト ID や接頭辞、接尾辞を設定します。 [保存] をクリックします。 注意点 ワークスペースコンパイルオーバーライドによって生成されたコンパイル結果は、あくまで開発時の手動実行を想定したものです。そのため、このコンパイル結果を スケジュール実行(後述のワークフロー構成)の対象にすることはできません 。 参考 : ワークスペース コンパイルのオーバーライドを構成する リリース構成 機能概要 リリース構成 は、リポジトリのコンパイル結果を作成するための設定をテンプレート化する機能です。本番環境(production)やステージング環境(staging)など、特定の実行環境向けの コンパイル結果を定義する ために使用します。 リリース構成では、 production や staging といった構成の一意な名前である リリース ID を定義します。そして、コンパイルの元となる Git のブランチやコミット SHA である Git Commitish を指定し、コンパイル結果を自動で再作成する 頻度 を設定します。 必要に応じて、Google Cloud プロジェクト ID、テーブルの接頭辞、スキーマの接尾辞などの コンパイルのオーバーライド も設定可能です。 例えば、「 main ブランチの最新のコードを元に、1時間ごとに本番環境(production)用のコンパイル結果を自動生成する」といった設定が可能です。ここで生成されたコンパイル結果が、後述するワークフロー構成による定期実行の対象となります。 この仕組みは、CI/CD パイプラインにおける「ビルド」のプロセスに相当します。 設定方法 Dataform リポジトリの [リリースとスケジュール] に移動します。 [製品版 リリースの作成](または、[カスタム リリースの作成]) をクリックします。 リリースID、Git Commitish(ブランチ名など)、頻度、各種オーバーライド設定を入力し、 [作成] をクリックします。 参考 : リリース構成を作成する ワークフロー構成 機能概要 ワークフロー構成 は、リリース構成で作成されたコンパイル結果の 実行をスケジュールする ための機能です。 ワークフロー構成では、以下の項目を設定します。 リリース構成の選択 : どのリリース構成(例: production )のコンパイル結果を実行するかを選択 実行するアクションの選択 : すべてのアクションを実行するか、特定のタグが付いたアクションのみを実行するかなどを選択 実行スケジュール : 実行頻度(日次、週次など)とタイムゾーン これにより、「毎日午前3時に、 production リリース構成で生成されたコンパイル結果を使って、 daily タグが付いたアクションを実行する」といった定期実行を構成できます。 この仕組みは、CI/CD パイプラインにおける「デプロイ」や「ジョブ実行」のプロセスに相当します。リリース構成とワークフロー構成を組み合わせることで、追加のサービス(Cloud Scheduler や Cloud Composer など)を使わずに、Dataform 内で完結した自動実行パイプラインを構築できます。 設定方法 Dataform リポジトリの [リリースとスケジュール] に移動します。 [ワークフロー構成] セクションで [作成] をクリックします。 実行対象のリリース構成、実行するアクション、スケジュールなどを設定し、 [作成] をクリックします。 参考 : ワークフロー構成を作成する 開発と管理 ライフサイクルの全体像 ここまで解説した3つの機能を組み合わせた、一般的な開発から本番実行までの流れは以下のとおりです。 1 開発フェーズ (個人のワークスペース) 開発者は、各自の ワークスペース で SQLX ファイルを開発・編集します。 ワークスペースコンパイルオーバーライド を利用して、個別のサンドボックス環境(例: msasaki スキーマ)で手動実行し、動作を確認します。 2 リリースフェーズ (Git とリリース構成) 開発が完了したコードを、Git リポジトリの main ブランチ(本番用)や staging ブランチ(ステージング用)にマージします。 リリース構成 がスケジュールに従い、 main ブランチから本番用のコンパイル結果を、 staging ブランチからステージング用のコンパイル結果をそれぞれ自動で作成します。 3 実行フェーズ (ワークフロー構成) ワークフロー構成 が、定義されたスケジュール(例: 毎日午前3時)になると、本番用のリリース構成によって作成された最新のコンパイル結果を BigQuery 上で実行します。 このように、各機能が明確な役割を担うことで、安全で再利用性の高いデータパイプラインのライフサイクル管理が実現されます。 ベストプラクティス Dataform で開発から本番までのワークフローを管理する際は、環境を分離することがベストプラクティスとされています。 開発環境では、本番データに影響を与えないよう「ワークスペースコンパイルオーバーライド」を活用して、各開発者が個別のスキーマで作業します。 一方、本番環境やステージング環境では、「リリース構成」と「ワークフロー構成」を組み合わせ、Git の特定ブランチを元にしたコンパイルと実行を自動化します。これにより、コードの変更が自動的に本番環境へ反映される、統制の取れたパイプラインを構築できます。 詳細は公式ドキュメントをご参照ください。 参考 : 分離された実行環境のベスト プラクティス 必要なロール Dataform でこれらの構成を管理するには、リポジトリに対して適切な IAM ロールが必要です。 ロール名(ロール ID) 説明 Dataform 管理者( roles/dataform.admin ) リリース構成やワークフロー構成の作成・編集・削除などの管理操作に必要 ロールの付与に関する詳細は、公式ドキュメントをご参照ください。 参考 : 必要なロール リソースの有効期限 Dataform によって作成されるコンパイル結果やワークフローの実行履歴(呼び出し)には、有効期限が設定されています。 ワークフローの呼び出し実行履歴は、90日後に自動で削除されます。 コンパイル結果の有効期限は、その生成方法によって異なります。ワークスペースで開発中に生成されたものは24時間で失効します。リリース構成によって生成されたものは、新しいコンパイル結果が作成されると置き換えられ、最大24時間後に失効します。ワークフロー呼び出しで使われたコンパイル結果は、その呼び出しが有効な期間(最大90日)保持されます。 参考 : ライフサイクル リソースの有効期限 佐々木 愛美 (min) (記事一覧) クラウドソリューション部 データアナリティクス課。2024年7月 G-gen にジョイン。G-gen 最南端、沖縄県在住。最近覚えた島言葉は、「マヤー(猫)」。
アバター
G-gen の佐々木です。当記事では Firestore におけるデータベースのクローン機能を紹介します。 Firestore データベースのクローンとは 手順 ポイントインタイムリカバリの有効化 クローン作成(Google Cloud コンソール) クローン作成(gcloud CLI) Firestore データベースのクローンとは Firestore におけるデータベースの クローン 機能では、1つのデータベースを対象に、 同じプロジェクト 、 同じリージョン にデータベースのクローン(複製)を作成します。クローンによって作成されたデータベースには、ソースデータベース内の全てのデータ、インデックスがコピーされます。 データベースのクローンには ポイントインタイムリカバリ (PITR)が使用されます。ポイントインタイムリカバリが有効化されているデータベースでは、過去7日間の任意のタイミング(分単位)のコピーを作成することができます。 また、ポイントインタイムリカバリが有効化されていない場合は、過去1時間の任意のタイミング(分単位)のクローンを作成することができます。 デフォルトの動作では、クローンされたデータベースはソースデータベースと同じ方式の暗号化が使用されます。暗号化方式はデータベースのクローン時に Google 管理の暗号鍵 (Google のデフォルトの暗号化)と 顧客管理の暗号鍵 (CMEK)のいずれかを選択することができます。 Create and manage databases - Clone a database Point-in-time recovery (PITR) overview 手順 ポイントインタイムリカバリの有効化 過去1時間よりも前のクローンが必要な場合、あらかじめデータベースでポイントインタイムリカバリを有効化しておく必要があります。 ポイントインタイムリカバリの有効化はコンソールや gcloud CLI で可能です。 # Firestoreデータベースでポイントインタイムリカバリを有効化する $ gcloud firestore databases update \ --database =< データベース名 > \ --enable-pitr なお、ポイントインタイムリカバリを有効にすると、データベースのサイズに応じてポイントインタイムリカバリの料金が追加で発生します。 参考 : Work with point-in-time recovery (PITR) 参考 : gcloud firestore databases update 参考 : Firestore pricing クローン作成(Google Cloud コンソール) クローンの作成は Google Cloud コンソールまたは gcloud CLI から可能です。 コンソールを使用する場合、クローンで作成されたデータベースの暗号化方式を、ソースデータベースの暗号化方式から変更することはできません。 コンソールから作成する場合、対象のデータベースから、[クローンを作成] を選択します。 コンソールからデータベースのクローンを作成する 「クローンの作成」で、作成されるデータベースの ID と、クローン元となるデータベースの任意の時点を分単位で選択します。どの時点まで遡ってクローンできるかは「最も古いバージョンの時刻」として表示されています。 コピーする任意の時点を選択してクローンを作成する クローン作成(gcloud CLI) gcloud CLI を使用する場合、必要に応じて、どの時点までクローンを作成できるのか(「最も古いバージョンの時刻」)を確認します。 # データベースの「最も古いバージョンの時刻」を確認する $ gcloud firestore databases describe \ --database =" (default) " \ --format =" table(earliestVersionTime) " # 出力例(UTC) EARLIEST_VERSION_TIME 2025-08-20T13:22:00Z データベースのクローンは gcloud firestore databases clone コマンドで行います。 2025年10月現在では gcloud alpha コマンドを使用する必要があります。 $ gcloud alpha firestore databases clone \ --source-database =" projects/<プロジェクトID>/databases/<ソースデータベース名> " \ --snapshot-time =< クローンする時点のタイムスタンプ(RFC3339形式) > \ --destination-database =" <作成するデータベース名> " --snapshot-time には、RFC-3339形式でクローンする時点のタイムスタンプを指定します。コンソールと異なり、CLI では UTC でタイムスタンプを指定する点には注意が必要です。 # 実行例 $ gcloud alpha firestore databases clone \ --source-database =" projects/myproject/databases/(default) " \ --snapshot-time = 2025-08-20T13:22:00Z \ --destination-database =" default-clone " クローンで作成するデータベースの暗号化方式をソースデータベースから変更したい場合、 --encryption-type で暗号化方式( google-default-encryption or customer-managed-encryption )を、 --kms-key-name で使用する鍵の ID を指定します。 # 暗号化方式を変更してクローンする場合の実行例 $ gcloud alpha firestore databases clone \ --source-database =" projects/myproject/databases/(default) " \ --snapshot-time = 2025-08-20T13:22:00Z \ --destination-database =" default-clone " --encryption-type =' customer-managed-encryption ' \ --kms-key-name =' projects/myproject/locations/asia-northeast1/keyRings/my-key-ring/cryptoKeys/my-key ' 参考 : gcloud alpha firestore databases clone 佐々木 駿太 (記事一覧) G-gen最北端、北海道在住のクラウドソリューション部エンジニア 2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。 趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。 Follow @sasashun0805
アバター
G-genの杉村です。Vertex AI の API 経由で Gemini を呼び出す際に、 URL context tool を使って、明示的にスクレイピングをしなくても Web サイトの内容を取得してコンテキストとして利用する方法について解説します。 概要 URL context tool とは ユースケース サポートされているモデル 使用方法 URL context tool の検証 tools 不使用時との比較 Google Search tool との比較 Google Search tool との併用 概要 URL context tool とは URL context tool とは、Vertex AI の API 経由で Gemini を呼び出す際に、Web サイトの内容を取得してコンテキストとして利用できるようになるツールです。 本来、外部 Web サイトの内容を生成 AI のコンテキストとして使うためには、Web スクレイピング(プログラムでウェブサイトからデータを取得すること)を行うソースコードを記述して、Web サイトの内容を取得してから、プロンプトとしてモデルに読み込ませる必要があります。 URL context tool を使うと、そのようなスクレイピングプログラムを記述しなくても、Gemini が自動的に Web サイトのコンテンツを取得して、コンテキストとして利用してくれます。 参考 : URL context 同機能は、2025年8月現在で試験運用版(Experimental)の扱いです。一般提供(GA)されている機能ではないため、公式のサポート対象外であるほか、予告なく仕様が変更されたり廃止になる可能性があります。 また当記事の検証結果は、2025年8月現在の試験運用版(Experimental)の API を使用した結果であり、機能改善により結果や特性が変化する場合があることにご留意ください。 ユースケース URL context tool は、以下のようなユースケースに適しています。 Web 上の記事から重要なポイントを抽出する 複数のリンク間で情報を比較したり、統合する 特定のページの内容に基づいて質問に答える 特定の目的(職務記述書の作成やテスト問題の作成など)のためにコンテンツを分析する サポートされているモデル URL context tool は、以下のモデルで使用できます。 Gemini 2.0 Flash Gemini 2.5 Flash-Lite Gemini 2.5 Flash Gemini 2.5 Pro 使用方法 URL context tool は、以下の Python サンプルコードのように、tools として UrlContext を指定することで使用できます。 from google import genai from google.genai.types import Tool, GenerateContentConfig, HttpOptions, UrlContext client = genai.Client( http_options=HttpOptions(api_version= "v1" ), vertexai= True , project= "sugimura" , location= "global" , ) model_id = "gemini-2.5-flash" url_context_tool = Tool( url_context = UrlContext ) url_1 = "https://www.city.shinjuku.lg.jp/seikatsu/seiso01_001025.html" # 新宿区のごみ分別辞典 url_2 = "https://www.city.shinjuku.lg.jp/seikatsu/file09_01_00001.html" # 新宿区の町名別のごみ収集日一覧 contents = f """ パソコンのキーボードをゴミとして出したいです。 居住地域は、新宿区の揚場町です。 ゴミの区分は何で、収集日はいつですか? 以下の URL を参考にしてください。 * 新宿区のごみ分別辞典: {url_1} * 新宿区の町名別のごみ収集日一覧: {url_2} """ response = client.models.generate_content( model=model_id, contents=contents, config=GenerateContentConfig( tools=[url_context_tool], response_modalities=[ "TEXT" ], ) ) # Generated contents print ( "===== content.parts =====" ) for each in response.candidates[ 0 ].content.parts: print (each.text) # URLs retrieved for context print ( " \n ===== url_context_metadata =====" ) print (response.candidates[ 0 ].url_context_metadata) URL context tool の検証 前述の Python コードを実行すると、以下のような結果になりました。 ===== content.parts ===== 新宿区揚場町にお住まいの場合、パソコンのキーボードは**金属・陶器・ガラスごみ**として出すことができます。 収集日は、その月の**第2・第4水曜日**です。 ===== url_context_metadata ===== url_metadata=[UrlMetadata( retrieved_url='https://www.city.shinjuku.lg.jp/seikatsu/seiso01_001025.html', url_retrieval_status=<UrlRetrievalStatus.URL_RETRIEVAL_STATUS_SUCCESS: 'URL_RETRIEVAL_STATUS_SUCCESS'> ), UrlMetadata( retrieved_url='https://www.city.shinjuku.lg.jp/seikatsu/file09_01_00001.html', url_retrieval_status=<UrlRetrievalStatus.URL_RETRIEVAL_STATUS_SUCCESS: 'URL_RETRIEVAL_STATUS_SUCCESS'> )] この生成結果は、実際に2025年8月現在の新宿区の Web サイトの記載内容と一致しています。 url_metadata として、実際にどの Web サイトからデータを取得してコンテキストとして利用したかが記録されています。 tools 不使用時との比較 Tools を使わない場合の実行結果と比較してみます。 (略) config=GenerateContentConfig( # tools=[url_context_tool], response_modalities=[ "TEXT" ], ) (略) 上記のように、コードから tools の指定をコメントアウトして実行すると、以下のような結果になりました。 ===== content.parts ===== パソコンのキーボードを新宿区揚場町でゴミとして出す場合、以下のようになります。 1. **ゴミの区分:** パソコンのキーボードは、通常「**不燃ごみ(燃えないごみ)**」として出すことができます。 * **注意点:** ただし、縦・横・高さの合計が30センチメートルを超える場合は「粗大ごみ」扱いとなります。一般的なサイズのキーボードであれば、不燃ごみで問題ありません。 2. **収集日:** 揚場町の不燃ごみの収集日は「**第2・第4火曜日**」です。 --- **まとめ:** * **区分:** **不燃ごみ** * **収集日:** **第2・第4火曜日** ===== url_context_metadata ===== None 上記は、事実とは異なる結果となっています。Web サイトがコンテキストとして与えられていないため、ハルシネーションが発生していることがわかります。 Google Search tool との比較 次に、比較のために Tools として Google Search tool(Google 検索でグラウンディングするツール)を指定して実行してみます。 from google import genai from google.genai.types import Tool, GenerateContentConfig, HttpOptions, UrlContext, GoogleSearch # GoogleSearch を追加で import (略) # Google Search tool を定義 google_search_tool = Tool( google_search=GoogleSearch ) (略) config=GenerateContentConfig( # tools=[url_context_tool], tools=[google_search_tool], # Google Search tool を使うよう指定 response_modalities=[ "TEXT" ], ) (略) Google Search tool が優位だったケース まずは、同じプロンプト(ごみの出し方に関する質問)で実行します。結果は、以下の通りでした。 ===== content.parts ===== 新宿区揚場町にお住まいの場合、パソコンのキーボードのゴミの区分と収集日は、キーボードのサイズによって異なります。 **1. ゴミの区分** パソコンのキーボードは、その大きさによって以下のいずれかに分類されます。 * **粗大ごみ**: キーボードの一辺の長さが30cmを超える場合、粗大ごみとなります。一般的なパソコンのキーボードは、この粗大ごみに該当することが多いです。粗大ごみとして出す場合、事前申し込みと手数料が必要です。 * **金属・陶器・ガラスごみ**: キーボードの一辺の長さが30cm以下の場合は、「金属・陶器・ガラスごみ」に分類されます。ただし、「硬質で厚さが5㎜以上のもの、30cm角 以上の大きさのものは対象外」という規定もあるため、小型のキーボードであっても形状によっては注意が必要です。 **2. 収集日** * **粗大ごみとして出す場合(一辺の長さが30cm超)** 粗大ごみは事前申し込み制で有料です。収集日は申し込み時に決定されます。 * **手数料**: パソコン用キーボードは1点につき400円です。 * **申し込み方法**: * **インターネット**: 新宿区粗大ごみ受付センターのウェブサイト(https://www.shinjuku-sodai.com)から24時間申し込み可能です。 * **電話**: 粗大ごみ受付センター(電話番号: 03-5304-8080)へ連絡してください。受付時間は月曜日から土曜日の午前8時から午後7時までです(年末年始を除く)。 * **金属・陶器・ガラスごみとして出す場合(一辺の長さが30cm以下)** 揚場町における「金属・陶器・ガラスごみ」の収集日は、**毎月第2・第4水曜日**です。 収集日の朝8時までに、決められた集積所に出してください。 ===== url_context_metadata ===== None これは、実際の Web サイトの掲載内容と同じ結果が返りました。むしろ、Google Search tool を使ったほうが詳細な結果が得られました。新宿区の Web サイトは、Google 検索でも容易に発見できる内容であったためと考えられます。 URL context tool が優位だったケース 次に、URL context tool の優位性が出るケースを検証するため、もう少し Google で検索しづらい複雑な内容を生成させてみます。 (略) # G-gen Tech Blog の Google Agentspace 解説記事 url_1 = "https://blog.g-gen.co.jp/entry/google-agentspace-explained" contents = f """ Google Agentspace において、Agentspace Enterprise ライセンスでは、ノーコードエージェントを開発することはできますか? 以下の URL を参考にしてください。 {url_1} """ (略) まずは、URL context tool ではなく、Google Search tool を使った実行結果を見てみます。 ===== content.parts ===== はい、Google Agentspace の Enterprise ライセンスでは、ノーコードエージェントを開発できます。 Google Agentspace は、企業がAIエージェントを構築、管理、導入するための単一かつ安全なプラットフォームを提供しており、個人、チーム、そして企業全体の可能性を解き放つことを目指しています。Enterprise エディションは月額25ドルから利用可能です。 特に、**Agent Designer** というノーコードツールが提供されており、技術的な専門知識がなくてもカスタムAIエージェントを作成できます。このツールは、日常業務を自動化するエージェントを構築するために、直感的な会話型インターフェースを使用します。 検索結果では、**Agent DesignerはAgentspace Enterprise Plusエディションで利用可能である**と明記されています。Agent Designerを使用すると、プログラミングを必要としない自然言語の記述を使って、カスタムAIエージェントを作成できます。これらのノーコードエージェントは、Agentspace環境内で設定されたすべてのデータソースやツールと連携してワークフローを自動化します。 Google Cloud Next 2025で発表されたAgentspaceのAgent Designerは、ノーコードツールであり、ユーザーが繰り返し発生するタスクを支援するエージェントを構築できます。 したがって、Google AgentspaceのEnterpriseライセンス、特にEnterprise Plusエディションでは、ノーコードツールであるAgent Designerを使用してノーコードエージェントを開発することが可能です。 ===== url_context_metadata ===== None 上記の生成結果は、ハルシネーションを起こしています。実際には Enterprise ライセンスではノーコードエージェントの開発を行うことはできません。また、最後の文では Enterprise ライセンスと Enterprise Plus ライセンスは別々のものであるのにも関わらず、混同しています。 次に、同じプロンプトで URL context tool を使った結果を見てみます。 ===== content.parts ===== Google Agentspace の Agentspace Enterprise ライセンスでは、ノーコードエージェントを開発することはできません。 参照した記事の「ライセンス体系」の項目にある表によると、Agentspace Enterprise ライセンスには「ノーコードエージェント」の機能が含まれていないと明記されています。 ノーコードエージェントの作成機能を含むのは、最上位プランである Agentspace Enterprise Plus ライセンスです。 Agentspace Frontline ライセンスでは、ノーコードエージェントは配布物の利用のみに制限されます。 ===== url_context_metadata ===== url_metadata=[UrlMetadata( retrieved_url='https://blog.g-gen.co.jp/entry/google-agentspace-explained', url_retrieval_status=<UrlRetrievalStatus.URL_RETRIEVAL_STATUS_SUCCESS: 'URL_RETRIEVAL_STATUS_SUCCESS'> )] 今回は、解説記事の内容を正確に参照して、正しい答えが生成されました。 特定の Web サイトのコンテンツのみ に基づいて生成させたい場合は、URL context tool が優位であると考えられます。 Google Search tool との併用 URL context tool は、Google Search tool と併用することが可能です。これにより、特定の URL に加えて、インターネットから広く情報を収集してコンテンツを生成できます。 参考 : URL context - Grounding with Google Search with URL context Python の場合、ソースコードは以下のようになります。 from google import genai from google.genai.types import Tool, GenerateContentConfig, HttpOptions, UrlContext, GoogleSearch client = genai.Client( http_options=HttpOptions(api_version= "v1beta1" ), vertexai= True , project= "sugimura" , location= "global" , ) model_id = "gemini-2.5-flash" tools = [] tools.append(Tool(url_context=UrlContext)) tools.append(Tool(google_search=GoogleSearch)) url_1 = "https://www.serverworks.co.jp/corporate/about.html" # 株式会社サーバーワークスの会社概要ページ contents = f """ 株式会社 G-gen と、株式会社サーバーワークスの関係性を教えてください。 また、両社のビジョンを比較してください。 以下の URL を参考にしてください。 {url_1} """ response = client.models.generate_content( model=model_id, contents=contents, config=GenerateContentConfig( tools=tools, response_modalities=[ "TEXT" ], ) ) # Generated contents print ( "===== content.parts =====" ) for each in response.candidates[ 0 ].content.parts: print (each.text) # URLs retrieved for context print ( " \n ===== url_context_metadata =====" ) print (response.candidates[ 0 ].url_context_metadata) ポイントは、tools に辞書型で URL context tool と Google Search tool の両方を格納している点と、Client 生成時に api_version として v1beta1 を指定している点です。これらのツールの併用は、ベータ版の API でのみ提供されている点に注意してください。 今回はプロンプトとして、株式会社サーバーワークスと株式会社 G-gen の関係性やビジョンについて質問します。参考 URL として、株式会社サーバーワークスの会社概要ページのみを与えました。 出力結果は以下のようになりました。 ===== content.parts ===== 株式会社G-genと株式会社サーバーワークスの関係性、および両社のビジョンの比較は以下の通りです。 **株式会社G-genと株式会社サーバーワークスの関係性** 株式会社G-genは、株式会社サーバーワークスがGoogle Cloud™事業へ本格参入するために、2021年8月に設立した合弁会社です。サーバーワークスはG-genの親会社にあたります。 G-genは、サーバーワークスと、アジアトップクラスのクラウドベンダーであるBespin Global Inc.とのジョイントベンチャーとして設立されました。 2024年7月1日には、株式会社G-genと株式会社トップゲート(これもサーバーワークスのグループ会社でGoogle Cloudパートナー)が合併し、新生G-genとして事業を拡大しています。 **両社のビジョンの比較** 両社は全く同じビジョンを掲げています。 * **株式会社サーバーワークス**: 「クラウドで、世界を、もっと、はたらきやすく」 * **株式会社G-gen**: 「クラウドで、世界を、もっと、はたらきやすく」 この共通のビジョンは、「より多くの企業がクラウドによって競争力を高め、そこで働く従業員が『働きやすい環境になった』と思えるような社会にすること」を目指しています。 ただし、このビジョンを実現するための主要な手段と焦点が異なります。 * **株式会社サーバーワークス**は、主に**AWS(Amazon Web Services)**に特化したインテグレーション事業とサービスの提供を通じて、このビジョンの実現を目指しています。オンプレミス環境の運用負荷やコストを軽減し、企業の働き方をクラウドで進化させることを重視しています. * **株式会社G-gen**は、主に**Google Cloud™**および**Google Workspace**を専門とするクラウドインテグレーターとして、このビジョンの実現に取り組んでいます。Google Cloudが持つ生成AIやデータ分析などのユニークな技術を活用し、場所にとらわれない、高セキュリティでアジリティの高いITシステムの提供を通じて、顧客のDX(デジタルトランスフォーメーション)とビジネス成功を支援することを目指しています。また、サーバーワークスのAWSノウハウと連携し、マルチクラウド環境でのカスタマーサクセスも提供しています。 ===== url_context_metadata ===== url_metadata=[UrlMetadata( retrieved_url='https://www.serverworks.co.jp/corporate/about.html', url_retrieval_status=<UrlRetrievalStatus.URL_RETRIEVAL_STATUS_SUCCESS: 'URL_RETRIEVAL_STATUS_SUCCESS'> )] 上記の結果には、コンテキストとして与えていない株式会社 G-gen のビジョンや沿革についての情報が含まれています。 この結果から、コンテキストとして与えた URL の情報と、Google 検索から得た情報の両方をコンテキストとして結果が生成されたことがわかります。 ここに全文は掲載しませんが、 response の全文を確認すると、URL context tool と Google Search tool の両方が使用されたことが確認できました。 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-genの西田です。当記事では、Gemini CLI での対話だけで、To Do タスクを管理するWebアプリケーションの開発手順を紹介します。 はじめに 当記事について 開発ステップ Gemini CLI の起動 要件定義と開発計画の決定 アプリケーションの開発 開発の開始 動作確認 アプリケーションの修正 はじめに 当記事について 当記事では、Webアプリケーションの開発経験が無い方でも、Gemini CLI を利用して To Do タスクを管理するWebアプリケーションを開発する際の進め方をご紹介します。 前編では、アプリケーションの基本的な動作や画面を確認できるプロトタイプを作成することを目的として、Gemini を利用した要件定義から始めて、ローカル環境で動作確認を行うレベルの開発を実施していきます。 この記事では、Gemini CLI や Cloud Shell などを活用し、Web ブラウザだけで要件定義から開発までを一気通貫に行うことを目指します。 Gemini CLI とは、ターミナルから直接 Gemini の機能を利用できるオープンソースのコマンドラインインターフェイスです。詳しくは以下の記事をご覧ください。 blog.g-gen.co.jp Cloud Shell とは、Google Cloud コンソール上で起動する仮想的な Linux ターミナルです。コードエディタも付属しており、Web ブラウザだけで開発を完結させることができます。以下の記事も参考にしてください。 blog.g-gen.co.jp 開発ステップ Gemini CLI で開発を行う際、以下のステップを踏むことで開発をスムーズに進めることができました。 Gemini を壁打ち相手としながら、開発したいアプリケーションの要件定義を行う 壁打ちで決まった要件定義の内容と、開発計画を別のファイルに切り出して管理するよう指示する 要件定義と開発計画のファイルを参照しながらの開発を指示する。開発の進捗は開発計画ファイルに都度記録する アプリケーション画面や動作を確認し、必要があれば機能追加や修正を指示する。その際、要件定義や開発計画ファイルも更新する 開発の初心者にとって特に便利なのは、1つ目の要件定義を Gemini と相談しながら進められる点です。 要件定義に協力してほしい旨のプロンプトを入力するだけで、実装する機能や使用する技術スタックについてなど、必要な要件について質問されるので、それに答えることで要件を決めていくことができます。 また、2つ目の要件定義と開発計画をファイルに切り出して管理しておくことも有効でした。開発作業を一旦中断した後に途中から再開する場合や、最初に決めた要件を変更する際などに、これらのファイルを読み込んでからアクションを実施するように指示することができます。 いずれのステップも Gemini に「要件定義の内容をファイルに切り出して」というような自然言語の指示を出すことで処理が実行されるので、簡単に進めることができます。 Gemini CLI の起動 Google Cloud コンソールにアクセスし、アプリケーションを開発するプロジェクトを選択したら、画面右上の [Cloud Shell をアクティブにする] アイコンをクリックします。 ターミナルが起動したら、 [エディタを開く] をクリックします。 エディタ画面の左上の [Terminal] タブの中の [New Terminal] を選択します。 以下のコマンドを実行して、アプリケーション開発用のディレクトリの作成とカレントディレクトリの移動を行います。 mkdir todo-app-demo cd todo-app-demo 開発用ディレクトリの準備が完了したら、 gemini とコマンドを入力して、Gemini CLI を起動します。 以下のような画面が立ち上がれば成功です。 要件定義と開発計画の決定 アプリケーション開発の最初のステップとして、Gemini を活用して要件定義と開発計画の策定を実施します。 まずは以下のようなプロンプトを入力します。 To Do タスクの管理を行うWebアプリケーションを開発します。要件定義の壁打ち相手になってください。 アプリケーションを開発していく上で、必要な要件を抜け漏れがないように洗い出してください。 まずは画面や動作確認を実施するため、ローカルで動作する構成で開発します。 なおプロンプトは、「Type your message or @path/to/file」と記載されている入力欄から送信します。 プロンプトを送信後、基本機能や画面構成についてなどについての以下のような提案が返ってくるので、自然言語で対話しながら要件を詰めていきます。 ✦ 承知いたしました。ToDoアプリケーションの要件定義、一緒に進めていきましょう。 まずはアプリケーションに必要な最小限の機能を洗い出してみました。抜け漏れや、追加したい項目がないかご確認ください。 --- ToDoアプリケーション 要件定義(案) 1. 基本機能(タスク管理) * タスクの作成 * タスクのタイトルを入力して新しいタスクを追加できる。 * (オプション) タスクの詳細な説明メモを追加できる。 * (オプション) タスクの期限日を設定できる。 * タスクの一覧表示 * 登録したタスクが一覧で表示される。 * 各タスクの「完了/未完了」の状態がわかる。 * タスクの更新 * タスクのタイトルや詳細、期限を編集できる。 * タスクを「完了」状態に変更できる。(チェックボックスなど) * 完了したタスクを「未完了」に戻せる。 * タスクの削除 * 不要になったタスクを削除できる。 2. 画面構成 * メイン画面 * タスクの入力フォーム * タスク一覧 * (オプション) 未完了/完了済みタスクを切り替えて表示するフィルタ 3. 非機能要件(今回はローカル動作が前提) * データ永続化 * ブラウザを閉じてもタスクが消えないように、データをローカルに保存する。(例: ブラウザのローカルストレージ、ローカルファイルなど) * UI/UX * 直感的に操作できるシンプルなデザインにする。 --- いかがでしょうか? 特に、タスクに「優先度(高・中・低など)」や「カテゴリ(仕事・プライベートなど)」といった情報を追加したい、などのご 要望はありますか? まずはこの内容で進めて、開発の途中で必要になった機能を追加していく形でも良いかと思います。 今回は、上記の提案に対し、以下のプロンプトを返して要件定義を進めていきます。 基本機能と画面構成については、提案通りの内容で異論ありません。 データの保存については、 MySQL を使用してください。 Gemini とのやり取りを通じて要件定義の内容が固まったら、ステップの2つ目である要件定義、開発計画の内容を別ファイルに切り出します。 ファイルを切り出して記録することで、作業を途中から再開する際や、要件定義の内容を変更する場合に、これらのファイルを読み込んでからアクションをするように指示することができます。 プロンプト例は以下の通りです。 開発を進める前に、要件定義の内容と開発計画の内容を別のファイルに切り出して、出来るだけ詳細に記録してください。 また、開発計画を記録するファイルで開発作業の進捗も管理できるようにしてください。 ファイルは新しく「docs」というフォルダを作成して、その中に保存してください。 要件定義の内容がまとめられた requirements.md は以下の通りです。 # ToDoアプリケーション 要件定義書 ## 1. 概要 本ドキュメントは、ToDoタスク管理アプリケーションの要件を定義する。 このアプリケーションは、ユーザーが日々のタスクを効率的に管理することを目的とする。 ## 2. データモデル アプリケーションで扱うタスク(Todo)は、以下のデータ項目で構成される。 - **id**: ` Integer ` , 主キー, 自動採番 - **title**: ` String(200) ` , タスクのタイトル, **必須** - **description**: ` Text ` , 詳細な説明, 任意 - **due_date**: ` Date ` , 期限日, 任意 - **completed**: ` Boolean ` , 完了状態 (True: 完了, False: 未完了), デフォルト: ` False ` - **created_at**: ` DateTime ` , 作成日時, 自動記録 - **updated_at**: ` DateTime ` , 更新日時, 自動記録 ## 3. 機能要件 ### 3.1. タスク作成機能 - ユーザーはタスクのタイトルを入力して、新しいタスクを作成できる。 - タイトルは必須入力とし、空の場合は登録できず、エラーメッセージを表示する。 - オプションとして、詳細な説明と期限日を設定できる。 - タスク作成後、ユーザーはタスク一覧画面にリダイレクトされる。 ### 3.2. タスク一覧表示機能 - 登録されているすべてのタスクを一覧で表示する。 - デフォルトの表示順は **作成日時の降順(新しいものが上)** とする。 - 完了済みのタスクは、未完了のタスクと視覚的に区別できるように表示する(例: タイトルに取り消し線、背景色を変更)。 - (将来的な拡張) 「すべて」「未完了」「完了済み」の状態でタスクをフィルタリングして表示する機能。 ### 3.3. タスク更新機能 - **状態の更新**: - 一覧画面上のチェックボックスをクリックすることで、タスクの「完了」「未完了」を即座に切り替えられる。 - **内容の編集**: - 各タスクに編集ボタンを設け、クリックすると編集ページに遷移する。 - 編集ページでは、タイトル、詳細、期限日を変更できる。 - 更新後、タスク一覧画面にリダイレクトされる。 ### 3.4. タスク削除機能 - 各タスクに削除ボタンを設ける。 - 削除ボタンをクリックすると、「本当に削除しますか?」という確認ダイアログを表示する。 - 「OK」を選択した場合、タスクをデータベースから削除し、一覧画面を更新する。 ## 4. 画面仕様 ### 4.1. メイン画面(タスク一覧) - **ヘッダー**: - アプリケーションのタイトル(例: "ToDo App")を表示する。 - **タスク追加フォーム**: - タイトル入力用のテキストフィールド ( ` <input type="text"> ` ) - 追加ボタン ( ` <button type="submit"> ` ) - **タスク一覧**: - タスクが存在しない場合、「登録されているタスクはありません」というメッセージを表示する。 - 各タスクは以下の要素で構成される: - 完了状態を示すチェックボックス - タスクのタイトル - 期限日(設定されている場合) - 編集ボタン - 削除ボタン ### 4.2. 編集画面 - 選択したタスクの現在の内容(タイトル、詳細、期限日)がフォームに設定された状態で表示される。 - 更新ボタンと、一覧に戻るためのキャンセル(または戻る)リンクを配置する。 ## 5. 非機能要件 ### 5.1. URL設計 - ` GET / ` : タスク一覧ページ - ` POST /add ` : 新規タスク作成処理 - ` POST /update/<int:id> ` : タスク完了状態の更新処理 - ` POST /delete/<int:id> ` : タスク削除処理 - ` GET /edit/<int:id> ` : 編集ページの表示 - ` POST /edit/<int:id> ` : タスク内容の更新処理 ### 5.2. データ永続化 - すべてのタスクデータは **MySQL** データベースに永続化する。 ### 5.3. ユーザビリティ - 直感的で、最小限の操作でタスク管理ができるシンプルなUIを提供する。 ### 5.4. エラーハンドリング - データベース接続失敗など、システムレベルのエラーが発生した場合は、汎用的なエラーページを表示する。 - ユーザーの入力エラー(例: タイトルが空)については、フォームの近くにエラーメッセージを表示する。 開発計画が記録される development_plan.md は以下の通りです。 # ToDoアプリケーション 開発計画書 ## 1. 進捗サマリー - [ ] フェーズ1: 基盤構築 - [ ] フェーズ2: 機能実装 - [ ] フェーズ3: 仕上げ ## 2. 技術スタック - **Webフレームワーク**: Python / Flask - **データベース**: MySQL - **DB接続ライブラリ (ORM)**: Flask-SQLAlchemy - **テンプレートエンジン**: Jinja2 - **開発環境**: Docker (MySQL), Python venv ## 3. プロジェクト構成 . ├── docs/ │ ├── development _ plan.md │ └── requirements.md ├── static/ │ └── css/ │ └── style.css ├── templates/ │ ├── base.html │ ├── index.html │ └── edit.html ├── venv/ ├── .gitignore ├── app.py ├── docker-compose.yml └── requirements.txt ## 4. 開発タスク詳細 ### フェーズ0: 計画 (完了) - [x] 要件定義 ( ` docs/requirements.md ` ) - [x] 開発計画策定 ( ` docs/development_plan.md ` ) ### フェーズ1: 基盤構築 - [ ] **1. 環境構築** - [ ] ` docker-compose.yml ` の作成 - [ ] ` requirements.txt ` の作成 - [ ] ` docker-compose up -d ` でMySQLコンテナを起動する - [ ] ` python3 -m venv venv ` で仮想環境を作成し、アクティベートする - [ ] ` pip install -r requirements.txt ` で必要なライブラリをインストールする - [ ] **2. Flaskアプリケーション初期化 (`app.py`)** - [ ] Flaskアプリのインスタンスを作成する - [ ] SQLAlchemyのデータベース接続設定を行う - [ ] SQLAlchemyのインスタンスを初期化する - [ ] **3. データモデル定義 (`app.py`)** - [ ] ` Todo ` モデルクラスを定義する - [ ] **4. データベーステーブル作成** - [ ] ` flask shell ` 等で ` db.create_all() ` を実行し、テーブルを作成する ### フェーズ2: 機能実装 - [ ] **5. HTMLテンプレートの骨格作成 (`templates/`)** - [ ] ` base.html ` の作成 - [ ] ` index.html ` の作成 - [ ] ` edit.html ` の作成 - [ ] **6. タスク一覧表示・追加機能の実装 (`app.py`, `templates/index.html`)** - [ ] ルーティング ( ` GET / ` ) の実装 - [ ] テンプレート ( ` index.html ` ) でのタスク一覧表示 - [ ] テンプレート ( ` index.html ` ) でのタスク追加フォーム作成 - [ ] ルーティング ( ` POST /add ` ) の実装 - [ ] **7. タスク状態更新・削除機能の実装 (`app.py`, `templates/index.html`)** - [ ] ルーティング ( ` POST /update/<int:id> ` ) の実装 - [ ] ルーティング ( ` POST /delete/<int:id> ` ) の実装 - [ ] テンプレート ( ` index.html ` ) での更新・削除ボタンの実装 - [ ] **8. タスク編集機能の実装 (`app.py`, `templates/edit.html`)** - [ ] ルーティング ( ` GET /edit/<int:id> ` ) の実装 - [ ] テンプレート ( ` edit.html ` ) での編集フォーム作成 - [ ] ルーティング ( ` POST /edit/<int:id> ` ) の実装 ### フェーズ3: 仕上げ - [ ] **9. スタイリングと微調整** - [ ] CSS ( ` static/css/style.css ` ) の作成と適用 - [ ] Flaskのflashメッセージ機能等でエラー表示を実装 - [ ] 総合テストとデバッグ アプリケーションの開発 開発の開始 要件定義と開発計画の確認を終えて開発の準備が完了したら、以下のようなプロンプトで開発を開始していきます。 前述の参考ステップ3の通り、要件定義と開発計画を記載したファイルを読み込ませた上で、開発作業を進めるよう指示します。 @docs/requirements.md と @docs/development_plan.md の内容に従って、アプリケーション開発を進めてください。 このように、@マークの後にファイルのパスを記述することで、Gemini に参照してほしいファイルを指示することができます。 Gemini がファイルの作成や更新を実施する前には「〇〇を作成します。よろしいですか?」といったように作業内容を確認されます。 その処理内容に対するリアクションを選択肢の中から選びます。上下の矢印キーで選択肢を切り替えて、Enterを押すことで選択できます。 以降は、Gemini が開発計画に従って処理を進めてくれるので、処理内容の確認に対して都度リアクションを行います。当記事の執筆にあたっては、Gemini から提案された作業内容に対して全て「Yes, allow once」で答えて進めています。 また作業の途中で、以下のように作業進捗を記録する指示を入力して development_plan.md を更新することで、完了した作業を記録することも効果的です。上記の開発計画の中では、各フェーズが完了するたびに、以下のプロンプトを入力しました。 ここまでの作業内容を、@development_plan.md に記録してください。 動作確認 開発計画の作業が最後まで完了したら、ローカルでアプリケーションを起動して画面や動作を確認します。 アプリケーションをローカルで起動してください。 筆者の環境では、 http://127.0.0.1:5000 にアクセスするように促されましたので、アクセスして確認を進めます。 初期画面 タスクを追加後 タスクの編集画面 完了チェックをオン To Do 管理のアプリケーションとしては、まだまだ機能追加が必要ですが、要件として定義していた最低限の機能は想定通りに動作することが確認できました。 アプリケーションの修正 今後、機能を追加する場合を想定して、以下のような指示を出してみます。 追加の機能要件として、タイトルに含まれている文言からタスクを検索する機能を加えてください。 また、その内容を @requirements.md と @development_plan.md に追記してください。 Gemini によるコード修正後、無事に検索ワードの入力欄が追加されていることと、検索ワードによるフィルタリングが機能していることが確認できました。 西田 匡志 (記事一覧) クラウドソリューション部ソリューションアーキテクト課 美容商社→物流→情シスを経て、2025年6月G-genにジョイン。Google Cloud を通じて多くの人に貢献できるよう日々精進!
アバター
G-gen の佐々木です。当記事では Cloud Run における環境変数の設定について解説します。 Cloud Run の環境変数 仕様 暗黙的な環境変数 Dockerfile と重複して定義した場合 環境変数の設定方法 コンソール gcloud CLI --set-env-vars オプション --update-env-vars オプション --env-vars-file オプション 環境変数の削除 YAML ファイル Terraform シークレットのマウント Cloud Run の環境変数 仕様 Cloud Run では、Cloud Run 側の設定項目としてコンテナに環境変数を設定することができます。 Cloud Run 側に設定した環境変数は、コンテナ上で実行するアプリケーションから利用することができます。これは、Dockerfile の ENV から設定した環境変数の挙動と似ています。 環境変数は 最大1000個 まで設定することができ、変数の最大長として 32kb の制限があります。 環境変数のキーには「空の文字列」、「 = を含む文字列」、「 X_GOOGLE_ から始まる文字列」は使用できません。 当記事では Cloud Run services を例として解説しますが、環境変数の設定に関する基本的な仕様は Cloud Run jobs 等、その他の実行モデルでも同様です。 参考 : Configure containers for services (Cloud Run services) 参考 : Configure environment variables for job (Cloud Run jobs) 参考 : Configure environment variables for worker pools (Cloud Run worker pools) 暗黙的な環境変数 Cloud Run では、コンテナに対していくつかの環境変数が自動的に設定されます。 たとえば Cloud Run services では、 K_REVISION 環境変数に実行中のリビジョンの名前が格納されています。また Cloud Run jobs では CLOUD_RUN_TASK_INDEX 環境変数に並列実行されるタスクのインデックスが格納されています。 その他、暗黙的に設定される環境変数のリストについては、以下のドキュメントを参照してください。 参考 : Container runtime contract - Environment variables 参考 : Configure environment variables for services - Best practices - Additional reserved environment variables when deploying functions Dockerfile と重複して定義した場合 前述したように、Cloud Run で設定できる環境変数は、Dockerfile の ENV で設定した環境変数と同様の方法でアクセスできますが、もし Cloud Run 側の設定項目と Dockerfile の ENV で同じキーを持つ環境変数を設定した場合、 Cloud Run 側の設定項目の値が優先 されます。 Dockerfile 側ではコンテナから使用する環境変数のデフォルト値を設定し、Cloud Run 側の設定で必要に応じて上書きするといった使い方ができます。 環境変数の設定方法 コンソール デプロイ方法を問わず、Cloud Run では作成時および更新時に環境変数を設定することができます。 コンソールの場合、コンテナの設定項目として「変数とシークレット」があるため、ここで環境変数の Key/Value を設定します。 コンソールから環境変数を設定する gcloud CLI --set-env-vars オプション gcloud CLI では、 gcloud run deploy コマンドや gcloud run services update コマンドなどで --set-env-vars オプションを使用することで環境変数を設定することができます。 # gcloud CLI で環境変数を設定する $ gcloud run deploy < サービス名 > --image < コンテナイメージ > \ --set-env-vars key1 =value1, key2 =value2 # 複数設定する場合は,(カンマ)で区切る # サービスの更新時に設定する場合 $ gcloud run services update < サービス名 > \ --set-env-vars key1 =value1, key2 =value2 --set-env-vars オプションは、指定した環境変数のリストで現在 Cloud Run に設定されている環境変数を 上書き します。したがって、Cloud Run を更新するときに、現在設定されている環境変数に加えて新たな別の環境変数を設定したい場合、 --set-env-vars オプションには「 現在設定されている環境変数 」と「 新たに設定する環境変数 」を 合わせたリスト を渡す必要があります。 たとえば、環境変数として既に key1=value1 が設定されている Cloud Run に対して新たに key2=value2 の環境変数を追加したい場合、 --set-env-vars key2=value2 ではなく --set-env-vars key1=value1,key2=value2 と記述します。 また、環境変数を複数設定するときは key=value を , (カンマ)区切りに記述しますが、もし , を環境変数の値として使用したい場合は、以下の例のように @ などの別の文字を区切り文字として使用することができます。 # 値に,(カンマ)を含む環境変数を設定する $ gcloud run deploy < サービス名 > --image < コンテナイメージ > \ --set-env-vars " ^@^key1=value1,value11,value111@key2=value2,value22,value222 " $ gcloud run deploy < サービス名 > --image < コンテナイメージ > \ --set-env-vars " ^:^key1=value1,value11,value111:key2=value2,value22,value222 " $ gcloud run deploy < サービス名 > --image < コンテナイメージ > \ --set-env-vars " ^--^key1=value1,value11,value111--key2=value2,value22,value222 " gcloud CLI でカンマを含む環境変数を設定する 参考 : gcloud run deploy 参考 : gcloud run services update 参考 : gcloud topic escaping --update-env-vars オプション 環境変数は、前述の --set-env-vars オプションの他に --update-env-vars を利用して設定することもできます。 --update-env-vars オプションでは、追加・変更したい環境変数のみを指定することができるため、あとから環境変数を追加するケースではこちらを使用したほうが安全でしょう。 $ gcloud run services update dotenv \ --update-env-vars key1 =value100 # 追加・変更したい環境変数だけ指定できる 参考 : Configure environment variables for services - Update environment variables --env-vars-file オプション Cloud Run のデプロイ時にローカルにある .env ファイルの内容を環境変数として設定することもできます。 $ gcloud beta run deploy < サービス名 > --image =< コンテナイメージ > \ --env-vars-file =< .envファイルのパス > # .env のあるパスを指定する .env ファイルは以下のような key=value の形式で記述します。 key1=value1 key2=value2 参考 : Configure environment variables for services - Set multiple environment variables using the .env file 環境変数の削除 環境変数の削除には、 --remove-env-vars オプションと --clear-env-vars オプションが利用できます。 --remove-env-vars オプションでは、指定したキーの環境変数を削除します。 # 指定した環境変数のみ削除する(カンマ区切りで複数指定も可能) $ gcloud run services update < サービス名 > \ --remove-env-vars key1 --clear-env-vars オプションでは、設定されている全ての環境変数を削除します。 # 全ての環境変数を削除する $ gcloud run services update < サービス名 > \ --clear-env-vars 参考 : Configure environment variables for services - Delete environment variables YAML ファイル YAML ファイルを使用して Cloud Run をデプロイする場合、以下のように spec.template.spec.containers の env 属性として環境変数を設定します。 apiVersion : serving.knative.dev/v1 kind : Service metadata : name : <サービス名> spec : template : spec : containers : - image : <コンテナイメージ> env : - name : key1 value : value1 - name : key2 value : value2 Terraform Terraform で環境変数を設定する場合は以下のような記述となります。 # Cloud Run services の場合 resource "google_cloud_run_v2_service" "this" { project = var.project_id name = var.name location = var.location template { containers { image = var.image # 環境変数を設定する env { name = "key1" value = "value1" } env { name = "key2" value = "value2" } } } deletion_protection = var.deletion_protection } 上記の場合、環境変数1つにつき template.containers.env を1つ記述する必要があるため、環境変数を多数設定する必要がある場合、Terraform の記述が冗長になってしまいます。 実際には、以下のように dynamic ブロックと for_each を併用するなどして、変数として渡された環境変数の数だけブロック動的に生成するとよいでしょう、 # Cloud Run services の場合 resource "google_cloud_run_v2_service" "this" { project = var.project_id name = var.name location = var.location template { containers { image = var.image # key/valueが変数として渡されている場合、渡された数だけ繰り返し設定する # 渡されていない場合は何も設定しない dynamic "env" { for_each = coalesce (var.env_vars, {} ) content { name = env.key value = env.value } } } } deletion_protection = var.deletion_protection } 上記のように記述した場合、 variables.tf に定義する変数は以下のように記述します。 # variable.tf(抜粋) variable "env_vars" { type = map ( string ) default = {} } シークレットのマウント Cloud Run では、Secret Manager に格納した機密情報(シークレット)をマウントすることで、環境変数と同様の方法でシークレットの値にアクセスすることができます。 参考 : サービスのシークレットを構成する (Cloud Run services) 参考 : ジョブのシークレットを構成する (Cloud Run jobs) 詳細は以下の記事を参考にしてください。 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 の min です。Google Workspace の Google フォームでは、回答数が上限に達するとリンク先の Google スプレッドシートへデータが同期されなくなることがあります。本記事では、その原因と対処法を解説します。 事象 原因 対処法 その他の上限 事象 本件では、Google フォームで収集した回答を、Google スプレッドシートで集計・分析していました。 フォームへの回答数が10万件を超えたあたりから、新しい回答がスプレッドシートに追記されなくなり、データが同期されない事象が発生しました。 また、同時期にフォームの管理画面で以下の警告が表示されるようになりました。 レスポンスが 10 万件を超えると、リンクされたスプレッドシートは同期されなくなります。 事象の切り分けのため、リンク先の Google スプレッドシートから古い回答データを削除したり、スプレッドシートとのリンクを一度解除して再接続したりしましたが、事象は解消しませんでした。 原因 この事象は、Google フォームに定められている 利用上限 に起因します。 Google の公式ドキュメントには、フォームの安定的な利用を担保するための上限値が記載されています。その中の一つに、スプレッドシートとの連携に関する上限があります。 フォームの回答がスプレッドシートと同期されない場合は、フォームの回答数が 100,000 件を超えている可能性があります。 参考 : フォームの回答数の上限の詳細 この上限は、リンク先の Google スプレッドシートが保持できる行数やセル数の上限とは独立した、 Google フォーム自体が保持する回答データに対する上限 です。 そのため、リンク先の Google スプレッドシートのデータを削除しても、根本原因であるフォーム側の回答データが上限に達している状態は変わらず、同期が再開されることはありません。 対処法 Google フォーム側に蓄積された回答データを削除することで、事象を解消できます。 操作の前に、失われるデータを保護するため、まず 既存の回答をエクスポートしてバックアップする ことを強く推奨します。回答データは、フォームの「回答」タブから CSV ファイルとしてダウンロードできます。 バックアップを取得したあと、以下の手順でフォームの回答を削除します。 対象の Google フォームを編集画面で開きます。 画面上部の「回答」タブをクリックします。 画面右上にある「回答のその他アイコン」(︙)をクリックします。 メニューから「 すべての回答を削除 」を選択します。 確認のダイアログが表示されるので、内容を確認して「OK」をクリックします。 この操作により、Google フォームに保存されているすべての回答データが削除され、内部的なカウンタがリセットされます。その後、新しい回答がフォームに送信されると、スプレッドシートとの同期が正常に再開されます。 なお、Google フォームではなく Google スプレッドシート自体にも、1,000 万セルまたは 1 万 8,278 列までという上限があります。 参考 : Google ドライブに保管可能なファイル 今後も同じフォームを継続して利用する場合は、回答数がフォームの上限に達する前に、定期的にデータをエクスポートし、フォーム上の回答を削除する運用をご検討ください。 その他の上限 本記事で解説した回答数の上限以外にも、Google フォームには質問数やファイルアップロード容量などの上限が定められています。詳細は以下の公式ドキュメントをご参照ください。 参考 : フォームの回答数の上限の詳細 佐々木 愛美 (min) (記事一覧) クラウドソリューション部 データアナリティクス課。2024年7月 G-gen にジョイン。G-gen 最南端、沖縄県在住。最近覚えた島言葉は、「マヤー(猫)」。
アバター
G-gen の高宮です。Google Apps Script(GAS)を用いた Google カレンダーの自動化について解説します。特に、土日祝日や会社休日を考慮した月の第1営業日や最終営業日といった、変則的な日付への定期的な予定追加に焦点を当てます。 はじめに 概要 Google Apps Script(GAS)とは 新しい GAS プロジェクトの作成 営業日計算処理 実装 動作確認 第1営業日のイベント登録処理 実装 動作確認 最終営業日のイベント登録処理 はじめに 概要 Google カレンダー では月ごとの繰り返しの予定を、「毎月25日」や「毎月第3金曜日」などの形式で作成することはできます。しかし、土日祝日・会社休日などを考慮した会社営業日での定期的なスケジュール作成を簡単に行うことはできません。 会社の業務では、月の第1営業日に前月の勤怠の締め作業を依頼したり、月の最終営業日に経費精算の申請をするなどのケースがあります。そのような場合に、手間をかけずに Google カレンダーに定期的な予定を作成したいです。 当記事では、GAS を使用して、土日祝日・会社休日を考慮し、月の第1営業日や最終営業日に Google カレンダーに定期的な予定を追加する具体的な方法を解説します。 Google Apps Script(GAS)とは Google Apps Script (GAS)は、Google Workspace と統合されたアプリケーションを簡単に作成できるアプリケーション開発プラットフォームです。JavaScript でコードを記述し、Gmail、カレンダーなどの Google Workspace アプリ用の組み込みライブラリを使用できます。 参考 : Google Apps Script の概要 参考 : Google Apps Script (GAS) カテゴリーの記事一覧 - G-gen Tech Blog 新しい GAS プロジェクトの作成 以下の URL にアクセスすると、 Apps Script ダッシュボードが表示されます。 https://script.google.com/ 新しいプロジェクト 作成ボタンを押下すると、新しい GAS プロジェクトを作成できます。 営業日計算処理 実装 プロジェクトにファイル date_utils.gs を作成し、第1営業日と最終営業日を計算する処理を実装します。今回の例では、土日、祝日と年末年始に休暇がある会社を想定しています。 /** * 会社休日(月/日形式の文字列配列) * この配列に、固定の会社休日を追加できます。 */ const COMPANY_HOLIDAYS = [ '12/30' , '12/31' , '1/1' , '1/2' , '1/3' , '1/4' ] ; /** * 日本の祝日カレンダーを取得します。 * 繰り返し呼び出されるのを防ぐため、一度だけ取得してキャッシュします。 */ const JAPANESE_HOLIDAY_CALENDAR = CalendarApp . getCalendarById ( 'ja.japanese#holiday@group.v.calendar.google.com' ) ; /** * 指定された日付が休日かどうかを判定します。 * @param {Date} date - 判定対象の日付オブジェクト。 * @return {boolean} - 休日の場合は true、営業日の場合は false を返します。 */ function isHoliday ( date ) { // 1. 土曜日(6)または日曜日(0)か判定 const day = date . getDay () ; if ( day === 0 || day === 6 ) { return true ; } // 2. 日本の祝日か判定 const events = JAPANESE_HOLIDAY_CALENDAR . getEventsForDay ( date ) ; if ( events . length > 0 ) { return true ; } // 3. 会社休日か判定 const month = date . getMonth () + 1 ; // getMonth()は0始まりのため+1 const dateOfMonth = date . getDate () ; const dateString = ` ${ month } / ${ dateOfMonth } ` ; if ( COMPANY_HOLIDAYS . includes ( dateString )) { return true ; } // 上記のいずれにも該当しない場合は営業日 return false ; } /** * 指定された年月の第1営業日を取得します。 * @param {number} year - 年(例: 2025)。 * @param {number} month - 月(1〜12)。 * @return {Date} - 第1営業日の日付オブジェクト。 */ function getFirstBusinessDay ( year , month ) { // 指定された月の1日を開始日として設定 const date = new Date ( year , month - 1 , 1 ) ; // 月は0始まりのため-1 // 休日でなくなるまで日付を1日ずつ進める while ( isHoliday ( date )) { date . setDate ( date . getDate () + 1 ) ; } return date ; } /** * 指定された年月の最終営業日を取得します。 * @param {number} year - 年(例: 2025)。 * @param {number} month - 月(1〜12)。 * @return {Date} - 最終営業日の日付オブジェクト。 */ function getLastBusinessDay ( year , month ) { // 指定された月の末日を開始日として設定 const date = new Date ( year , month , 0 ) ; // 翌月の0日目を指定すると、その月の末日が取得できる // 休日でなくなるまで日付を1日ずつ遡る while ( isHoliday ( date )) { date . setDate ( date . getDate () - 1 ) ; } return date ; } ここでは、Google カレンダーで提供されている「日本の祝日」カレンダーから祝日の情報を取得するため、 CalendarApp クラスを使用しています。 参考 : Class CalendarApp 動作確認 新しいファイル コード.gs に以下の処理を実装し、 main 関数を実行し営業日の計算が正常に実行できているか確認します。 /** * テスト用の対象年月のリスト */ const TARGET_YEAR_MONTH_LIST = [ { // 2024年12月 TARGET_YEAR : 2024 , TARGET_MONTH : 12 , } , { // 2025年1月 TARGET_YEAR : 2025 , TARGET_MONTH : 1 , } , ] /** * 実行テスト用のメイン関数 */ function main () { TARGET_YEAR_MONTH_LIST . forEach ( targetYearMonth => { const firstDay = getFirstBusinessDay ( targetYearMonth . TARGET_YEAR , targetYearMonth . TARGET_MONTH ) ; const lastDay = getLastBusinessDay ( targetYearMonth . TARGET_YEAR , targetYearMonth . TARGET_MONTH ) ; // 結果をログに出力 console . log ( ` ${ targetYearMonth . TARGET_YEAR } 年 ${ targetYearMonth . TARGET_MONTH } 月の第1営業日: ${ Utilities . formatDate ( firstDay , 'JST' , 'yyyy-MM-dd (E)' )} ` ) ; console . log ( ` ${ targetYearMonth . TARGET_YEAR } 年 ${ targetYearMonth . TARGET_MONTH } 月の最終営業日: ${ Utilities . formatDate ( lastDay , 'JST' , 'yyyy-MM-dd (E)' )} ` ) ; }) ; } 初回実行時には、Google アカウントを選択し、権限を付与する必要があります。 正常終了すると、以下のようなログが出力されます。 第1営業日のイベント登録処理 実装 新しいファイル create_event.gs を作成し、以下の処理を実装します。 /** * イベントを作成するカレンダーを指定します。 * デフォルトカレンダー以外を使いたい場合は、'xxxx@group.calendar.google.com' のようなカレンダーIDに書き換えてください。 */ const TARGET_CALENDAR_ID = 'primary' ; // 'primary' はデフォルトカレンダーを意味します /** * カレンダーに作成するイベントの内容をここで定義します。 */ const EVENT_TITLE = '【月次】勤怠締め作業を上長申請' ; const EVENT_DESCRIPTION = '前月分の勤怠の締め作業をシステムを使用して上長に申請する。' ; /** * イベントを作成する開始年月日と終了年月日を定義します。 */ const START_DATE = new Date ( 2025 , 6 , 25 , 0 , 0 , 0 , 0 ) ; // 2025/07/25 const END_DATE = new Date ( 2026 , 1 , 28 , 0 , 0 , 0 , 0 ) ; // 2026/02/28 /** * イベントを作成する時の開始時間と終了時間を定義します。 */ const START_TIME = new Date ( 0 , 0 , 0 , 9 , 0 , 0 , 0 ) ; // 9:00 const END_TIME = new Date ( 0 , 0 , 0 , 9 , 30 , 0 , 0 ) ; // 9:30 /** * 指定された期間内の営業日の定例イベントをGoogleカレンダーに作成します。 * @param {function} getBusinessDay - 営業日を計算する関数(第1引数:年、第2引数:月) */ const createBusinessDayEvents_ = function ( getBusinessDay ) { // 1. 設定のチェック if ( START_DATE > END_DATE ) { console . error ( 'エラー: 開始年月日は終了年月日以前の日付にしてください。' ) ; return; } if ( START_TIME > END_TIME ) { console . error ( 'エラー: 開始時間は終了時間以前の時間にしてください。' ) ; return; } if ( typeof getBusinessDay ! = 'function' ) { console . error ( 'エラー: 引数には営業日を計算する関数を設定してください。' ) ; return; } const calendar = CalendarApp . getCalendarById ( TARGET_CALENDAR_ID ) ; if ( ! calendar ) { console . error ( `エラー: 指定されたカレンダーID ( ${ TARGET_CALENDAR_ID } ) が見つかりません。` ) ; return; } console . log ( '処理を開始します...' ) ; console . log ( `対象期間: ${ Utilities . formatDate ( START_DATE , 'JST' , 'yyyy-MM-dd' )} ~ ${ Utilities . formatDate ( END_DATE , 'JST' , 'yyyy-MM-dd' )} ` ) ; // 2. 指定期間内の営業日を計算 // 月ごとにループ const recurrence = CalendarApp . newRecurrence () ; const recurrenceDaysList = [] ; let currentDate = new Date ( START_DATE ) ; while ( currentDate <= END_DATE ) { const year = currentDate . getFullYear () ; const month = currentDate . getMonth () + 1 ; // 月は1始まりに補正 // 営業日を計算 const businessDay = getBusinessDay ( year , month ) ; const formattedDate = Utilities . formatDate ( businessDay , 'JST' , 'yyyy-MM-dd' ) ; // 計算した営業日が指定期間内にある場合のみタスクを作成 if ( businessDay >= START_DATE && businessDay <= END_DATE ) { recurrence . addDate ( businessDay ) ; recurrenceDaysList . push ( businessDay ) ; console . log ( `対象をリストに追加しました: ${ formattedDate } ` ) ; } else { console . log ( `指定期間外のためスキップしました: ${ formattedDate } ` ) ; } // 次の月へ currentDate . setMonth ( currentDate . getMonth () + 1 ) ; currentDate . setDate ( 1 ) ; // 日を1日にリセット } // 3. 定期的な予定の作成 if ( recurrenceDaysList . length > 0 ) { const initialDay = recurrenceDaysList [ 0 ] ; const startDate = new Date ( initialDay ) ; startDate . setHours ( START_TIME . getHours ()) ; startDate . setMinutes ( START_TIME . getMinutes ()) ; const endDate = new Date ( initialDay ) ; endDate . setHours ( END_TIME . getHours ()) ; endDate . setMinutes ( END_TIME . getMinutes ()) ; calendar . createEventSeries ( EVENT_TITLE , startDate , endDate , recurrence , { description : EVENT_DESCRIPTION } , ) ; console . log ( '定期的な予定を作成しました。' ) ; } else { console . log ( '指定期間に対象の日付がないため、定期的な予定を作成していません。' ) ; } } ; /** * 指定された期間内の各月の第1営業日の定例イベントをGoogleカレンダーに作成します。 */ function createFirstBusinessDayEvents () { createBusinessDayEvents_ ( getFirstBusinessDay ) ; } createBusinessDayEvents_ ではまず、 CalendarApp クラスを使用し、自身の Google カレンダーの情報を取得します。 次に、 RecurrenceRule クラスを使用して、定期的な予定のルールを作成していきます。引数の営業日計算用の関数を使用して営業日の計算を行い、 addDate メソッドを使用して定期的な予定に設定する営業日を追加します。 最後に、 Calendar クラスの createEventSeries メソッドを使用して定期的な予定を登録します。 参考 : Class Calendar 参考 : Class RecurrenceRule 動作確認 createFirstBusinessDayEvents 関数を実行すると、カレンダーに定期的な予定が登録されます。以下のように、 Google カレンダーに指定した期間の予定が登録されていることが確認できます。 Google カレンダー上では登録された予定には繰り返し設定がないと表示されていますが、 スケジュールの削除を実行すると、定期的な予定の削除のダイアログが表示され、定期的な予定となっていることが確認できます。 また、2025年11月や2026年1月を確認すると、土日祝日、会社休日の設定が考慮された、第1営業日が登録されていることを確認できます。 最終営業日のイベント登録処理 最終営業日にタスクを作成したい場合は、 create_event.gs に以下のコードを実装します。 createBusinessDayEvents_ 関数に最終営業日計算用の関数を引数として渡すことで実装できます。 createLastBusinessDayEvents 関数を実行すると、最終営業日に定期的な予定を登録できます。 /** * 指定された期間内の各月の最終営業日の定例イベントをGoogleカレンダーに作成します。 */ function createLastBusinessDayEvents () { createBusinessDayEvents_ ( getLastBusinessDay ) ; } 高宮 怜 (記事一覧) クラウドソリューション部クラウドエクスプローラ課 2025年6月より、G-genにジョイン。前職は四国のSIerで電力、製造業系のお客様に対して、PM/APエンジニアとして、要件定義から運用保守まで全工程を担当。現在はGoogle Cloudを学びながら、フルスタックエンジニアを目指してクラウドエンジニアとしてのスキルを習得中。 Follow @Ggen_RTakamiya
アバター
G-gen の杉村です。当記事は、Google Cloud Next '25 Tokyo の2日目に行われたスポンサーセッション「 我々は、生成 AI アプリを開発するべきなのか 」のレポートです。 他の Google Cloud Next Tokyo '25 の関連記事は Google Cloud Next Tokyo '25 カテゴリ の記事一覧からご覧いただけます。 セッションの概要 Out-of-the-box な AI ソリューション Google Agentspace Google の AI アプリ開発用プラットフォーム 独自 AI アプリ開発へのスタンス セッションの概要 本セッションは、Google Cloud 専業インテグレーターである G-gen 社によるセッションです。 前半では Google Workspace に追加コストなしで組み込まれている生成 AI 関連ソリューション等や、Google Cloud で提供される生成 AI アプリ開発向けプロダクトなどの紹介が行われました。後半では、「我々は、生成 AI アプリを開発するべきなのか」というタイトルに対する考察が行われました。 Out-of-the-box な AI ソリューション Google Workspace には、アカウントさえあれば追加コストなしですぐに使える( Out-of-the-box な )AI ソリューションが多数組み込まれています。 代表的なのものは、 Gemini アプリ と NotebookLM です。 Gemini アプリは、生成 AI との自然言語による対話を通じ、質問や文章の生成、要約、翻訳、ソースコードの生成など多数のタスクを行うことができます。 NotebookLM は、アップロードしたドキュメントに基づいて質問応答や要約、アイデア生成などができる AI ノートブックです。Gemini アプリよりも限定的なデータソース、範囲を絞ったコンテキストに基づいた AI タスクを実行できます。 Gemini アプリや NotebookLM の詳細は、以下の記事も参照してください。 blog.g-gen.co.jp また Google Workspace では、Google Meet、Google ドキュメント、Google ドライブ、Google スプレッドシートといった各種アプリに Gemini が組み込まれており、これらも追加コストなしで利用できます。 これらの Google Workspace 組み込みの AI 機能の利用方法等については、以下の記事も参照してください。 blog.g-gen.co.jp Google Agentspace Google Agentspace は有償の Google サービスです。Google Agentspace は以下のような機能を備えた、AI プラットフォームといえます。 社内の複数のデータソースに対して Google 品質の横断検索 Gemini の高度な推論 自社保有データが統合されたエージェント Google ドライブや Microsoft SharePoint、Microsoft Outlook、Jira、Slack といったデータソースに対して横断検索を行うことができるほか、これらに対して AI が要約や資料作成、アイデア出しなどのタスクを実行できます。自社開発した AI エージェントも統合できるため、AI エージェントのプラットフォームとしても利用可能です。 Google Agentspace の詳細は、以下の記事も参考にしてください。 blog.g-gen.co.jp Google の AI アプリ開発用プラットフォーム Google Cloud では、AI アプリ開発用のプロダクトが多数公開されています。 Generative AI on Vertex AI、Google AI Studio、Vertex AI Search、Agent Development Kit(ADK)、Vertex AI Agent Engine、Model Armor、BigQuery ML、Vertex AI Feature Store などが紹介されました。 独自 AI アプリ開発へのスタンス 「我々は、生成 AI アプリを開発するべきなのか」というセッションタイトルへの回答としては、「この問いへの答えはケースバイケースである」とされました。 Google の Out-of-the-box な AI ツールを使う方がいいケースと、独自アプリを開発したほうがいいケース、両方のケースがあり、それらを適切に判断する判断基準を持つことが重要であるとしました。 Google などの各ベンダーが、AI ソリューションを次から次へと開発・公開している現状から、自社の業務改善などのユースケースであれば、可能な限り Out-of-the-box なツール(できあいの既製品)を使うべきであると述べられました。 一方で、自社特有の独創的なビジネスロジックが必要なケースや、自社アプリとの組み合わせ、ライセンス管理、課金などの追加実装が必要な場合、また生成 AI ではない回帰モデルなどを組み合わせたい場合などに、自社で生成 AI アプリを開発することを検討すべきとされました。 コスト最適の観点からも、まずは Out-of-the-box な既製品が利用できないかを検討し、それが不可な場合に自社アプリの開発を検討するのが望ましいと言えます。 独自アプリの開発が決断されたケースとして、「Gemini アプリ(既製品)では精度が足りないケース」「AI に複雑で多段なタスクをさせたいケース」「セキュリティ要件が厳しいケース」「コンシューマー向けのサービス」のような実例が挙げられました。 具体的な事例として、Vertex AI Search や ADK を使った実装の事例が紹介されました。 また G-gen 社の事例として、同社が提供する AI サービスである G-gen Tech Agent の事例が紹介されました。 参考 : 株式会社G-gen、新サービス G-gen Tech Suite を提供開始 同サービスのアーキテクチャについては、以下の記事で詳細に紹介されています。 blog.g-gen.co.jp 杉村 勇馬 (記事一覧) 執行役員 CTO / クラウドソリューション部 部長 元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。 Follow @y_sugi_it
アバター
G-gen の奥田です。当記事では、 Gemini CLI を利用した開発事例を紹介します。Google Cloud が提供するAPI である Virtual Try on API と、Web UI 用の Python フレームワークである Gradio を使用した、シンプルな画像生成 Web アプリの開発手順を紹介します。 はじめに Gemini CLI Virtual Try on API Gradio Gemini CLI を用いたアプリの開発 初期のディレクトリ構成 Gemini CLI による開発 Cloud Storage バケットの作成 エラー対応 ローカルでテスト Cloud Run にデプロイ 生成されたソースコード requirements.txt app.py Dockerfile はじめに Gemini CLI Gemini CLI とは、ターミナルから直接 Gemini の機能を利用できるオープンソースのコマンドラインインターフェイスです。 詳しくは以下の記事をご覧ください。 blog.g-gen.co.jp なお、Gemini CLI におけるコマンドの紹介や開発事例については以下の記事をご覧ください。 blog.g-gen.co.jp Virtual Try on API Virtual Try on API とは、試着対象の人の画像と、試着したい衣服の画像を入力することにより、着せ替えた写真を出力できる Vertex AI の API です。同機能は2025年8月現在、Preview 公開です。 人物画像と衣服の画像を Base64 エンコードしてリクエストに含ませることで、Cloud Storage バケットに画像を出力できます。使用には、Vertex AI を有効化した Google Cloud プロジェクトが必要です。 参考 : Generate Virtual Try-On Images この API と同様の技術を活用した機能として、Google は2025年5月の Google I/O で「Try It On」(バーチャル試着)機能を Search Labs 内で公開しました。 参考 : Shop with AI Mode, use AI to buy and try clothes on yourself virtually Gradio Gradio は、機械学習 Web アプリを構築するための Python フレームワークです。 参考 : Gradio Docs - Interface Gemini CLI を用いたアプリの開発 初期のディレクトリ構成 まず、アプリケーション用に新しいディレクトリを作成します。 新しいディレクトリを作ることを推奨する理由は、環境や設定を他のプロジェクトと混ざらないように安全に管理するためです。 意図しない挙動を防ぐため、空のディレクトリに公式ドキュメントに記載の Colab ソースコードを保存し、次の手順で Gemini CLI のコンテキストとして与えます。 参考 : Generate Virtual Try-On Images try-app |-- virtual_try_on.py |-- .env Gemini CLI による開発 Gemini CLI を起動し、以下のように初回プロンプトを記入しました。 こちらの Virtual Try-On API を試せる Gradio アプリを作成してください。Cloud Run へのデプロイを想定します。 ソースコードは`virtual_try_on.py`を参考にしてください。 処理の流れは以下のとおりです。 1. 人物の画像を、事前に定義した特定の Cloud Storage バケットへアップロードする。 2. 服の画像を、事前に定義した特定の Cloud Storage バケットへアップロードする。 3. 上記 2 つの画像のパスを使ってリクエストを送信し、Virtual Try-On API を実行する。 4. 生成された画像を Gradio アプリ上で表示する。ダウンロードボタンを押すとローカルにダウンロードできる。ダウンロード形式は JPEG とする。 これにより、以下のファイルが生成されました。 try-app |-- app.py |-- requirements.txt |-- README.md |-- Dockerfile Cloud Storage バケットの作成 人物画像及び服の画像を格納する Cloud Storage バケットを作成します。 export BUCKET_NAME = " risa-test-cloths " export PROJECT_ID = " my-project " export REGION = " us-central1 " gsutil mb -p $PROJECT_ID -l $REGION gs:// $BUCKET_NAME エラー対応 app.py を起動すると以下のエラーが発生しました。 Traceback (most recent call last): File "/Users/r-risa/virtual_try/app.py", line 10, in <module> from google import genai ImportError: cannot import name 'genai' from 'google' (unknown location) 生成された README.md を参照すると、現在は非推奨の google-generativeai がパッケージに含まれていました。 参考 : Google GenAI SDK に移行する gradio google-generativeai #非推奨のパッケージ google-cloud-storage Pillow そのため、現推奨の google-genai パッケージに変更しました。 gradio google-cloud-storage Pillow google-genai #現推奨のパッケージに変更 ローカルでテスト 環境変数をエクスポートした後、 python app.py を実行してローカルでテストします。 左上に人物の画像をアップロードし、左下に服の画像をアップロードします。 左下のオレンジ色のボタン「試着画像を生成する」をクリックすると、数秒で着せ替えた写真が出力されます。ダウンロードボタンを押下することで、ローカルにダウンロードできます。 Cloud Run にデプロイ 環境変数をエクスポートした後、以下のコマンドで Cloud Run にデプロイします。 当記事では検証環境のため未認証の呼び出しを可能としていますが、必要に応じて認証の設定をしてください。 gcloud run deploy $IMAGE_NAME \ --source . \ --image $IMAGE_TAG \ --region $REGION \ --service-account $SERVICE_ACCOUNT_EMAIL \ --set-env-vars =" GCP_PROJECT= ${PROJECT_ID} " \ --set-env-vars =" GCS_BUCKET_NAME= ${BUCKET_NAME} " \ --set-env-vars =" GCP_REGION= ${REGION} " \ --allow-unauthenticated \ --platform managed 生成されたソースコード 参考までに、最終的に生成されたソースコードを記載します。 requirements.txt gradio google-cloud-storage Pillow google-genai app.py import os import uuid import tempfile from datetime import datetime import gradio as gr from PIL import Image as PIL_Image from google.cloud import storage from google import genai from google.genai.types import Image, ProductImage, RecontextImageSource, RecontextImageConfig # --- 環境変数の設定 --- # Google CloudプロジェクトIDとロケーションを設定してください。 # Cloud Run環境では、環境変数として設定することを推奨します。 PROJECT_ID = os.environ.get( "GCP_PROJECT" ) LOCATION = os.environ.get( "GCP_REGION" , "us-central1" ) # 画像をアップロードするGCSバケット名を設定してください。 GCS_BUCKET_NAME = os.environ.get( "GCS_BUCKET_NAME" ) # --- Google Cloud クライアントの初期化 --- client = None storage_client = None try : # Vertex AI用のクライアントを初期化 client = genai.Client(vertexai= True , project=PROJECT_ID, location=LOCATION) storage_client = storage.Client() print ( "Google Cloud クライアントの初期化に成功しました。" ) except Exception as e: print (f "Google Cloud クライアントの初期化に失敗しました: {e}" ) print ( "環境変数 GCP_PROJECT と BUCKET_NAME が正しく設定されているか確認してください。" ) # --- 定数 --- VIRTUAL_TRY_ON_MODEL = "virtual-try-on-preview-08-04" def upload_to_gcs (pil_image: PIL_Image.Image, file_name: str ) -> str : """PillowイメージをGCSにアップロードし、GCS URIを返す""" if not storage_client or not GCS_BUCKET_NAME: raise gr.Error( "GCSクライアントが初期化されていないか、バケット名が設定されていません。" ) bucket = storage_client.bucket(GCS_BUCKET_NAME) # Pillowイメージをバイトデータに変換 with tempfile.SpooledTemporaryFile() as temp_byte_io: pil_image.save(temp_byte_io, "PNG" ) temp_byte_io.seek( 0 ) blob = bucket.blob(file_name) blob.upload_from_file(temp_byte_io, content_type= "image/png" ) return f "gs://{GCS_BUCKET_NAME}/{file_name}" def virtual_try_on (person_pil_image: PIL_Image.Image, clothing_pil_image: PIL_Image.Image): """Virtual Try-On APIを実行して試着画像を生成する""" if not client: raise gr.Error( "Vertex AIクライアントが初期化されていません。アプリケーションのログを確認してください。" ) if not person_pil_image or not clothing_pil_image: raise gr.Error( "人物画像と服の画像を両方アップロードしてください。" ) try : # ファイル名を一意にするためにUUIDとタイムスタンプを使用 timestamp = datetime.now().strftime( "%Y%m%d-%H%M%S" ) unique_id = uuid.uuid4().hex[: 6 ] person_filename = f "person-{timestamp}-{unique_id}.png" clothing_filename = f "clothing-{timestamp}-{unique_id}.png" # GCSに画像をアップロード person_gcs_uri = upload_to_gcs(person_pil_image, person_filename) clothing_gcs_uri = upload_to_gcs(clothing_pil_image, clothing_filename) # Virtual Try-On APIを呼び出し response = client.models.recontext_image( model=VIRTUAL_TRY_ON_MODEL, source=RecontextImageSource( person_image=Image(gcs_uri=person_gcs_uri), product_images=[ ProductImage(product_image=Image(gcs_uri=clothing_gcs_uri)) ], ), config=RecontextImageConfig( base_steps= 32 , number_of_images= 1 , safety_filter_level= "BLOCK_LOW_AND_ABOVE" , person_generation= "ALLOW_ADULT" , ), ) generated_pil_image = response.generated_images[ 0 ].image._pil_image # ダウンロード用にJPEG形式で一時ファイルに保存 with tempfile.NamedTemporaryFile(delete= False , suffix= ".jpeg" ) as temp_file: generated_pil_image.convert( "RGB" ).save(temp_file, "jpeg" ) temp_file_path = temp_file.name return generated_pil_image, temp_file_path except Exception as e: print (f "エラーが発生しました: {e}" ) raise gr.Error(f "画像の生成に失敗しました。詳細: {e}" ) # --- Gradioインターフェースの定義 --- with gr.Blocks() as demo: gr.Markdown( "# Virtual Try-On アプリケーション" ) gr.Markdown( "人物の画像と服の画像をアップロードすると、AIがその服を着用した画像を作成します。" "生成された画像は、表示後にダウンロードできます。" ) with gr.Row(): with gr.Column(): person_image = gr.Image( type = "pil" , label= "人物の画像" ) clothing_image = gr.Image( type = "pil" , label= "服の画像" ) submit_btn = gr.Button( "試着画像を生成する" , variant= "primary" ) with gr.Column(): output_image = gr.Image( type = "pil" , label= "生成された画像" ) download_file = gr.File(label= "画像をダウンロード" ) submit_btn.click( fn=virtual_try_on, inputs=[person_image, clothing_image], outputs=[output_image, download_file] ) if __name__ == "__main__" : # Cloud RunではPORT環境変数が設定される server_port = int (os.environ.get( "PORT" , 8080 )) demo.launch(server_name= "0.0.0.0" , server_port=server_port) Dockerfile # Python 3.10をベースイメージとして使用 FROM python:3.10-slim # 作業ディレクトリを設定 WORKDIR /app # 依存関係をインストールするためにrequirements.txtをコピー COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # アプリケーションコードをコピー COPY . . # Gradioアプリを起動 # Cloud RunはPORT環境変数でリッスンするポートを指定します ENV PORT 8080 CMD [ " python ", " app.py " ] Risa (記事一覧) クラウドソリューション部クラウドデベロッパー課 Google Cloudの可能性に惹かれ、2024年4月G-genにジョイン。 Google Cloud Partner Top Engineer 2025 Google Cloud 11 資格保有。日々修行中です! Follow @risa_hochiminh
アバター