概要
Cloud Run functions を使用すると、VPC ネットワークに直接接続して、関数から Compute Engine VM インスタンス、Memorystore インスタンス、内部 IP アドレスを持つその他のリソースにアクセスできます。
このラボでは、サーバーレス VPC アクセスを使用して関数を VPC ネットワークに接続し、ネットワークで実行されている Memorystore インスタンスのデータにアクセスします。
また、コネクタを使用して、ネットワーク内の VM インスタンスで実行されているウェブサーバーにアクセスします。
目標
このラボでは、次の作業を行います。
Memorystore for Redis インスタンスを設定する。
サーバーレス VPC アクセス コネクタを作成して、サーバーレス VPC アクセスを有効にする。
コネクタを使用して Redis データベースにメッセージ コンテンツを保存する Pub/Sub イベント ドリブン関数を作成する。
コネクタを使用して Redis データベースからデータを取得し、HTTP レスポンスでメッセージ データを返す HTTP 関数を作成する。
VPC ネットワーク内の VM インスタンスで実行されているウェブサーバーにアクセスするための HTTP 関数を作成する。
このラボで作成するリソースの概要は次のとおりです。
設定と要件
[ラボを開始] ボタンをクリックする前に
注: 以下の説明をお読みください。
ラボの時間は計測されており、一時停止することはできません。[ラボを開始 ] をクリックするとスタートするタイマーは、Google Cloud のリソースを利用できる時間を示しています。
この Qwiklabs ハンズオンラボでは、シミュレーションやデモ環境ではなく、実際のクラウド環境を使ってご自身でラボのアクティビティを行うことができます。そのため、ラボの受講中に Google Cloud にログインおよびアクセスするための、新しい一時的な認証情報が提供されます。
必要なもの
このラボを完了するためには、下記が必要です。
標準的なインターネット ブラウザ(Chrome を推奨)
ラボを完了するために十分な時間
注: すでに個人の Google Cloud アカウントやプロジェクトをお持ちの場合でも、ラボでは使用しないでください。
注: Pixelbook を使用している場合は、このラボをシークレット ウィンドウで実施してください。
Google Cloud Shell の有効化
Google Cloud Shell は、開発ツールと一緒に読み込まれる仮想マシンです。5 GB の永続ホーム ディレクトリが用意されており、Google Cloud で稼働します。
Google Cloud Shell を使用すると、コマンドラインで Google Cloud リソースにアクセスできます。
Google Cloud コンソールで、右上のツールバーにある [Cloud Shell をアクティブにする] ボタンをクリックします。
[続行 ] をクリックします。
環境がプロビジョニングされ、接続されるまでしばらく待ちます。接続した時点で認証が完了しており、プロジェクトに各自のプロジェクト ID が設定されます。次に例を示します。
gcloud は Google Cloud のコマンドライン ツールです。このツールは、Cloud Shell にプリインストールされており、タブ補完がサポートされています。
次のコマンドを使用すると、有効なアカウント名を一覧表示できます。
gcloud auth list
出力:
Credentialed accounts:
- @.com (active)
出力例:
Credentialed accounts:
- google1623327_student@qwiklabs.net
次のコマンドを使用すると、プロジェクト ID を一覧表示できます。
gcloud config list project
出力:
[core]
project =
出力例:
[core]
project = qwiklabs-gcp-44776a13dea667a6
注:
gcloud ドキュメントの全文については、
gcloud CLI の概要ガイド
をご覧ください。
タスク 1. API を有効にする
Cloud Run functions の関数を作成する前に、関連する API を有効にする必要があります。
プロジェクト ID
とリージョン
の環境変数を設定するには、Cloud Shell を有効にして、次のコマンドを実行します。
PROJECT_ID=$(gcloud config get-value project)
REGION={{{project_0.default_region|set at lab start}}}
次のコマンドを実行して、必要なすべてのサービスを有効にします。
gcloud services enable \
artifactregistry.googleapis.com \
cloudfunctions.googleapis.com \
cloudbuild.googleapis.com \
eventarc.googleapis.com \
run.googleapis.com \
logging.googleapis.com \
pubsub.googleapis.com \
redis.googleapis.com \
vpcaccess.googleapis.com
タスク 2. Memorystore for Redis インスタンスを設定する
Memorystore は、Redis と Memcached 向けの可用性、スケーラビリティ、安全性に優れたフルマネージドのインメモリ キャッシュ ソリューションを提供する Google Cloud サービスです。
このタスクでは、Google Cloud プロジェクトに Memorystore for Redis インスタンスを設定します。このインスタンスは、このラボの後半で開発するデータを保存するために Cloud Run functions で使用されます。
Memorystore インスタンスを作成する
Memorystore インスタンス名を表す環境変数を設定します。
REDIS_INSTANCE=customerdb
次のコマンドを実行して、2 GiB の Memorystore for Redis インスタンスを作成します。
gcloud redis instances create $REDIS_INSTANCE \
--size=2 --region=$REGION \
--redis-version=redis_6_x
Memorystore for Redis インスタンスの作成には数分かかります。処理を待つ間にタスク 3 に進んでサーバーレス VPC アクセスを設定し、Redis インスタンスが作成された後に、このタスクの残りの手順を完了することもできます。
インスタンスが正常に作成された後にその詳細を表示するには、次のコマンドを実行します。
gcloud redis instances describe $REDIS_INSTANCE --region=$REGION
環境変数を作成する
Memorystore インスタンスのホスト IP アドレスを環境変数に保存します。
REDIS_IP=$(gcloud redis instances describe $REDIS_INSTANCE --region=$REGION --format="value(host)"); echo $REDIS_IP
Memorystore インスタンスのポートを環境変数に保存します。
REDIS_PORT=$(gcloud redis instances describe $REDIS_INSTANCE --region=$REGION --format="value(port)"); echo $REDIS_PORT
このホストとポートの値は、後続のタスクでインスタンスに接続する際に使用します。
[進行状況を確認 ] をクリックして、目標に沿って進んでいることを確認します。
Memorystore for Redis インスタンスを設定する
タスク 3. サーバーレス VPC アクセスを設定する
Cloud Run functions から公共のインターネットを使用せずに VPC ネットワーク内のリソースにリクエストを送信し、対応するレスポンスを受信するには、サーバーレス VPC アクセスを設定する必要があります。
サーバーレス VPC アクセス コネクタを設定する
Google Cloud コンソールのナビゲーション メニュー ( )で、[ネットワーキング ] にある [VPC ネットワーク ] をクリックし、[サーバーレス VPC アクセス ] を選択します。
サーバーレス VPC アクセス コネクタを作成するには、[コネクタを作成 ] をクリックします。
コネクタの [名前 ] に「test-connector 」と入力します。
[リージョン ] で を選択します。
[サブネット ] で [カスタム IP 範囲 ] を選択します。
[IP 範囲 ] に「10.8.0.0 」と入力します。
注: IP 範囲は、予約されていない内部 /28 サブネットを CIDR 表記で指定する必要があります。この IP 範囲は、VPC ネットワーク内の既存の IP アドレス予約と重複してはいけません。この IP アドレス範囲は、スケーリングの際に追加のコネクタ インスタンスを作成するときに使用されます。コネクタに指定するリージョンは、Cloud Run functions がホストされているリージョンと同じでなければなりません。
残りの設定はデフォルトのままにして、[作成 ] をクリックします。
コネクタの使用準備が整うと、コネクタ名の横に緑色のチェックマークが表示されます。
コネクタの詳細を確認するには、Cloud Shell で次のコマンドを実行します。
gcloud compute networks vpc-access connectors \
describe test-connector \
--region $REGION
[進行状況を確認 ] をクリックして、目標に沿って進んでいることを確認します。
サーバーレス VPC アクセス コネクタを作成する
Redis インスタンスの作成中にこのタスクを先に完了した場合は、タスク 2 に戻って残りの手順を完了してください。
タスク 4. Pub/Sub のイベント ドリブン関数を作成する
サーバーレス VPC アクセス コネクタが作成されたので、このコネクタを使用して Memorystore Redis インスタンスのデータにアクセスする関数を開発できます。
このタスクでは、Memorystore インスタンスとの間でデータを保存および取得する Python の Pub/Sub イベント ドリブン関数を作成します。
Pub/Sub トピックを作成する
まず、関数がメッセージをリッスンするトピックを作成する必要があります。トピック名の環境変数を設定します。
TOPIC=add_redis
次のコマンドを実行して、トピックを作成します。
gcloud pubsub topics create $TOPIC
関数のコードを記述する
次のコマンドを実行して関数のフォルダとファイルを作成し、フォルダに移動します。
mkdir ~/redis-pubsub && cd $_
touch main.py && touch requirements.txt
Cloud Shell のツールバーで [エディタを開く ] ボタンをクリックします(必要に応じて [エディタを開く ] および [ターミナルを開く ] を使用して Cloud Shell とコードエディタを切り替えることができます)。
Cloud Shell エディタで、redis-pubsub
フォルダを選択します。
エディタで、redis-pubsub/main.py
ファイルに次のコードを追加します。
import os
import base64
import json
import redis
import functions_framework
redis_host = os.environ.get('REDISHOST', 'localhost')
redis_port = int(os.environ.get('REDISPORT', 6379))
redis_client = redis.StrictRedis(host=redis_host, port=redis_port)
# Pub/Sub トピックのメッセージからトリガーされます。
@functions_framework.cloud_event
def addToRedis(cloud_event):
# Pub/Sub メッセージデータは、cloud_event.data プロパティに base64 でエンコードされた文字列として保存されます。
# 期待される値は JSON 文字列でなければなりません。
json_data_str = base64.b64decode(cloud_event.data["message"]["data"]).decode()
json_payload = json.loads(json_data_str)
response_data = ""
if json_payload and 'id' in json_payload:
id = json_payload['id']
data = redis_client.set(id, json_data_str)
response_data = redis_client.get(id)
print(f"Added data to Redis: {response_data}")
else:
print("Message is invalid, or missing an 'id' attribute")
関数コードの依存関係を指定するには、redis-pubsub/requirements.txt
ファイルに次のコンテンツを追加します。
functions-framework==3.2.0
redis==4.3.4
関数をデプロイしてテストする
関数をデプロイするには、Cloud Shell で次のコマンドを実行します。
gcloud functions deploy python-pubsub-function \
--runtime=python310 \
--region=$REGION \
--source=. \
--entry-point=addToRedis \
--trigger-topic=$TOPIC \
--vpc-connector projects/$PROJECT_ID/locations/$REGION/connectors/test-connector \
--set-env-vars REDISHOST=$REDIS_IP,REDISPORT=$REDIS_PORT
ポップアップの [Bind the role to service account ] で、「n
」と入力します。
関数は、Pub/Sub トリガー トピック、サーバーレス VPC アクセス コネクタ、および Memorystore Redis インスタンスのホスト IP アドレスとポートを関数に提供する環境変数を使用してデプロイされます。
注: 権限エラーが表示された場合は、数分待ってからデプロイを再試行してください。
関数をテストするには、トピックにメッセージを公開します。
gcloud pubsub topics publish $TOPIC --message='{"id": 1234, "firstName": "Lucas" ,"lastName": "Sherman", "Phone": "555-555-5555"}'
関数のログを表示する
Google Cloud コンソールで、Cloud Run functions の概要ページに移動し、python-pubsub-function
の名前をクリックします。
[ログ ] をクリックします。
Pub/Sub メッセージで送信された JSON データ ペイロードが Redis に追加されたことを示すログエントリを確認します。
[進行状況を確認 ] をクリックして、目標に沿って進んでいることを確認します。
Pub/Sub のイベント ドリブン関数を作成する
タスク 5. HTTP 関数を作成する
このタスクでは、Memorystore for Redis インスタンスにクエリを実行し、リクエストで渡された ID に基づいてデータを返す HTTP 関数を Python で作成します。
関数のコードを記述する
次のコマンドを実行して、HTTP 関数のフォルダとファイルを作成し、そのフォルダに移動します。
mkdir ~/redis-http && cd $_
touch main.py && touch requirements.txt
Cloud Shell ツールバーで [エディタを開く ] をクリックします。
Cloud Shell エディタで、redis-http
フォルダを選択します。
エディタで、redis-http/main.py
ファイルに次のコードを追加します。
import os
import redis
from flask import request
import functions_framework
redis_host = os.environ.get('REDISHOST', 'localhost')
redis_port = int(os.environ.get('REDISPORT', 6379))
redis_client = redis.StrictRedis(host=redis_host, port=redis_port)
@functions_framework.http
def getFromRedis(request):
response_data = ""
if request.method == 'GET':
id = request.args.get('id')
try:
response_data = redis_client.get(id)
except RuntimeError:
response_data = ""
if response_data is None:
response_data = ""
return response_data
関数コードの依存関係を指定するには、redis-http/requirements.txt
ファイルに次の行を追加します。
functions-framework==3.2.0
redis==4.3.4
関数インスタンスの起動時に関数に必要なモジュールのみが読み込まれるように、関数の依存関係を関数ごとに分離することをおすすめします。これにより、コールド スタート時の関数のレイテンシが短縮されます。
関数をデプロイしてテストする
関数をデプロイするには、Cloud Shell で次のコマンドを実行します。
gcloud functions deploy http-get-redis \
--gen2 \
--runtime python310 \
--entry-point getFromRedis \
--source . \
--region $REGION \
--trigger-http \
--timeout 600s \
--max-instances 1 \
--vpc-connector projects/$PROJECT_ID/locations/$REGION/connectors/test-connector \
--set-env-vars REDISHOST=$REDIS_IP,REDISPORT=$REDIS_PORT \
--no-allow-unauthenticated
注: 権限エラーが表示された場合は、数分待ってからデプロイを再試行してください。
関数がデプロイされたら、その関数の HTTP URI を取得して環境変数に保存します。
FUNCTION_URI=$(gcloud functions describe http-get-redis --gen2 --region $REGION --format "value(serviceConfig.uri)"); echo $FUNCTION_URI
関数をテストするには、次の curl
コマンドを実行します。
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" "${FUNCTION_URI}?id=1234"
注: 前のタスクで Pub/Sub 関数トリガーをテストしたときに使用したのと同じ id パラメータ値を渡します。
HTTP 関数からのレスポンスが、先ほど Redis インスタンスに保存した JSON データと一致することを確認します。
{"id": 1234, "firstName": "Lucas" ,"lastName": "Sherman", "Phone": "555-555-5555"}
[進行状況を確認 ] をクリックして、目標に沿って進んでいることを確認します。
Redis に接続する HTTP 関数を作成する
タスク 6. HTTP 関数から VM インスタンスに接続する
Cloud Run functions から VPC ネットワーク内のリソースに接続するには、サーバーレス VPC アクセス コネクタを使用する必要があります。
このタスクでは、VM と、その VM インスタンスに接続する HTTP 関数を作成します。
VM 起動スクリプトを作成する
VM を作成する前に、Cloud Shell で、シンプルなウェブサーバーをインストールおよび実行する起動スクリプトをダウンロードします。
gcloud storage cp gs://cloud-training/CBL492/startup.sh .
VM 起動スクリプトのコンテンツを表示するには、次のコマンドを実行します。
cat startup.sh
VM を作成する
VM を作成するゾーンの環境変数を設定します。
ZONE={{{project_0.default_zone|set at lab start}}}
起動スクリプトを使用して VM を作成するには、次のコマンドを実行します。
gcloud compute instances create webserver-vm \
--image-project=debian-cloud \
--image-family=debian-11 \
--metadata-from-file=startup-script=./startup.sh \
--machine-type e2-standard-2 \
--tags=http-server \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--zone $ZONE
HTTP トラフィックが VM に到達できるように、VPC ネットワークにファイアウォール ルールを追加します。
gcloud compute --project=$PROJECT_ID \
firewall-rules create default-allow-http \
--direction=INGRESS \
--priority=1000 \
--network=default \
--action=ALLOW \
--rules=tcp:80 \
--source-ranges=0.0.0.0/0 \
--target-tags=http-server
VM が作成および実行されていることを確認するには、Google Cloud コンソールで [Compute Engine ] に移動し、[VM インスタンス ] をクリックします。
実行中であることを示す緑色のチェックマークが付いた VM が 1 つ表示されているはずです。
VM の内部 IP アドレスと外部 IP アドレスを環境変数に保存します。これらの変数は、後で関数をテストするときに使用します。
VM_INT_IP=$(gcloud compute instances describe webserver-vm --format='get(networkInterfaces[0].networkIP)' --zone $ZONE); echo $VM_INT_IP
VM_EXT_IP=$(gcloud compute instances describe webserver-vm --format='get(networkInterfaces[0].accessConfigs[0].natIP)' --zone $ZONE); echo $VM_EXT_IP
関数のコードを記述する
このサブタスクでは、トリガーされると作成した VM に接続する HTTP 関数を記述します。
次のコマンドを実行して、HTTP 関数コード用のフォルダとファイルを作成し、そのフォルダに移動します。
mkdir ~/vm-http && cd $_
touch main.py && touch requirements.txt
Cloud Shell ツールバーで [エディタを開く ] をクリックします。
Cloud Shell エディタで、vm-http
フォルダを選択します。
エディタで、vm-http/main.py
ファイルに次のコードを追加します。
import functions_framework
import requests
@functions_framework.http
def connectVM(request):
resp_text = ""
if request.method == 'GET':
ip = request.args.get('ip')
try:
response_data = requests.get(f"http://{ip}")
resp_text = response_data.text
except RuntimeError:
print ("Error while connecting to VM")
return resp_text
この関数は、VM で実行されているウェブサーバーに GET HTTP リクエストを送信します。ウェブサーバーのエンドポイント IP アドレスは、関数の URL のクエリ パラメータとして関数に渡されます。
エディタで、vm-http/requirements.txt
ファイルに次のコードを追加します。
functions-framework==3.2.0
Werkzeug==2.3.7
flask==2.1.3
requests==2.28.1
関数をデプロイする
関数をデプロイするには、Cloud Shell で次のコマンドを実行します。
gcloud functions deploy vm-connector \
--runtime python310 \
--entry-point connectVM \
--source . \
--region $REGION \
--trigger-http \
--timeout 10s \
--max-instances 1 \
--no-allow-unauthenticated
関数が正常にデプロイされたら、関数の URL を抽出するために次のコマンドを実行します。
FUNCTION_URI=$(gcloud functions describe vm-connector --region $REGION --format='value(url)'); echo $FUNCTION_URI
関数をテストする
関数 URL に VM の外部 IP アドレスを指定して関数をテストします。
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" "${FUNCTION_URI}?ip=$VM_EXT_IP"
このコマンドは、VM で実行されているウェブサーバーから HTML レスポンスを返します。
<html><body><p>ローカル ファイルからの Linux 起動スクリプト。</p></body></html>
Cloud Run functions はデフォルトで、パブリック外部 IP または URL にアクセスできます。この動作を変更するには、関数の下り(外向き)設定を変更して、コネクタを使用して関数からのトラフィックを VPC ネットワーク経由でルーティングします。
関数の URL に VM の内部 IP アドレスを指定して、テストをもう一度実行します。
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" "${FUNCTION_URI}?ip=$VM_INT_IP"
デフォルトでは、関数は内部 IP アドレス上の VM にアクセスできないため、関数は約 10 秒後にタイムアウトします。
エラーが表示されます。
アップストリーム リクエストのタイムアウト
VPC コネクタを使用する
関数から VPC ネットワーク内の VM やその他の内部リソースにアクセスするには、サーバーレス VPC アクセス コネクタを使用する必要があります。
Cloud Functions API を再度有効にします。
gcloud services disable cloudfunctions.googleapis.com
gcloud services enable cloudfunctions.googleapis.com
HTTP 関数を再デプロイし、このラボで作成した VPC コネクタを設定します。
gcloud functions deploy vm-connector \
--runtime python310 \
--entry-point connectVM \
--source . \
--region $REGION \
--trigger-http \
--timeout 10s \
--max-instances 1 \
--no-allow-unauthenticated \
--vpc-connector projects/$PROJECT_ID/locations/$REGION/connectors/test-connector
注: 権限エラーが表示された場合は、数分待ってからデプロイを再試行してください。
関数が再デプロイされたら、VM への内部接続をテストします。
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" "${FUNCTION_URI}?ip=$VM_INT_IP"
今回は、VM で実行されているウェブサーバーから HTML レスポンスが返されます。
<html><body><p>ローカル ファイルからの Linux 起動スクリプト。</p></body></html>
[進行状況を確認 ] をクリックして、目標に沿って進んでいることを確認します。
VM に接続する HTTP 関数を作成する
お疲れさまでした
このラボでは、Memorystore for Redis インスタンスを作成し、サーバーレス VPC アクセスを設定して、Cloud Run functions を VPC ネットワーク内のインスタンスに接続しました。次に、Redis インスタンスに接続してメッセージのコンテンツを保存する Pub/Sub イベント ドリブン関数を作成しました。また、Redis インスタンスに接続し、関数へのリクエストで渡された ID に基づいてインスタンスからデータを取得する HTTP 関数も作成しました。最後に、VM を作成し、サーバーレス VPC アクセス コネクタを使用して、内部 IP アドレスを介して HTTP 関数を VM に接続しました。
次のステップと詳細情報
Memorystore の詳細については、次のドキュメントをご覧ください。
サーバーレス VPC アクセスの詳細については、次のドキュメントをご覧ください。
Copyright 2020 Google LLC All rights reserved. Google および Google のロゴは Google LLC の商標です。その他すべての企業名および商品名はそれぞれ各社の商標または登録商標です。