Cloud RunからAlloy DBに接続する初歩
Cloud RunからAlloy DBに接続する手順についてまとめました。
Table of contents
author: Yoshio
はじめに
こんにちは、GIクラウドのスペランカーYoshioです。
世の中、「出来る気がする」よりも「出来るらしい」と分かるだけで気が楽になることって多いですよね。そういう僕みたいに気は小さいけどなんとかしたいっていう人の励みになればと思って、このCloud RunからAlloy DBに接続する初歩についてを記事にしました。
サマリ
Alloy DBとCloud Runの接続の構成は以下の図のようになります。今回は、このうちの赤枠についての記載となります。
- ※1実際はCloud Runが参入しているサーバレスVPCアクセスコネクタの構築もしています
- ※2便宜上、サーバーレス環境からAlloy DBへのVPC越しのアクセスを、サーバーレスVPCアクセスコネクタの経由ではなく、サーバレスVPCからVPCへの接続と表現しています
- ※3同一プロジェクト内での接続となります
上記構成を以下の手順を追って構築していきます。お察しの方もいらっしゃるでしょうが、Cloud SQLとの接続とほぼ同じです。知見がある方は公式ドキュメントに直接当たった方が回り道をしなくて済みますので、僕が参考にした公式ドキュメントも併記しておきました。
- Alloy DBの構築
- 完了していると想定
- Cloud Runの構築
- サーバレスVPCアクセスコネクタを構成
Alloy DBを構築
弊社ブログAlloy DB試してみたをご参照ください。
Cloud Runの構築
手順としては以下の通りです。
- ローカル開発環境でソースコードを準備
- .dockerignore
- Dockerfile
- main.py
- requirements.txt
gcloud
コマンドでデプロイ
弊社的にはGo推しらしいのですが、Pythonの方が慣れているのでPythonで記述します。
1. ローカル開発環境でソースコードを準備
今回は halloyworld
という名前のディレクトリを切って作成しています。
halloyworld
├ .dockerignore
├ Dockerfile
├ main.py
└ requirements.txt
Pythonプログラムは至って簡単で、DBに対して SELECT NOW();
を投げて現在時刻を取得するだけのプログラムとなっています。
DBサーバから業務時間を取る?う、なにか思い出しそうだ。
.dockerignore
Dockerfile
README.md
*.pyc
*.pyo
*.pyd
__pycache__
.pytest_cache
Dockerfile
FROM python:3.10-slim
ENV PYTHONUNBUFFERED True
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./
RUN pip install --no-cache-dir -r requirements.txt
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
main.py
import os
import ssl
import sqlalchemy
from flask import Flask
app = Flask(__name__)
db = None
@app.route("/")
def hello_world():
now = get_now()
return now
def get_now() -> str:
with db.connect() as conn:
record = conn.execute("select now()").one()
return str(record[0])
return "Wow, ah Red, you look great. Everything looks great. 01:24, I still got time. Oh my god."
def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
db_host = "xxx.xxx.xxx.xxx" # ダメ絶対
db_user = "postgres" # STOP
db_pass = "**********" # リテラル書き
db_name = "postgres" # Secret Managerとか
db_port = 5432 # 使いましょう
pool = sqlalchemy.create_engine(
sqlalchemy.engine.url.URL.create(
drivername="postgresql+pg8000",
username=db_user,
password=db_pass,
host=db_host,
port=db_port,
database=db_name,
),
pool_size=1, # サンプルだしプールサイズは最小でええやろ
max_overflow=1, # サンプルだしオーバーフローは(以下略
pool_timeout=5, # サンプルだし5秒もあれば(以下略
pool_recycle=60,# サンプルだし適t(以下略
)
return pool
@app.before_first_request
def init_db() -> sqlalchemy.engine.base.Engine:
global db
db = connect_tcp_socket()
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
requirements.txt
Flask==2.1.0
gunicorn==20.1.0
sqlalchemy==1.4.41
cloud-sql-python-connector[pg8000]
2. gcloud
コマンドでデプロイ
gcloud run deploy
gcloud
コマンドでRunをデプロイすると以下のようなメッセージが表示されるので、適宜回答を入力していってください。以下は僕の入力例です。
- ソースコードの場所を求められたら、Enterキーを押して現在のフォルダにデプロイ
- サービス名の入力を求められたら、Enterキーを押して、デフォルト名(フォルダ名)を設定
- Artifact Registry APIを有効にするよう求められたら、「y」と入力
- リージョンの入力を求められたら、適当なリージョンを選択
- 未認証の呼び出しを許可するように求めらたら「y」と入力
ガイドに従ってひとしきり入力してしばらく待つと、デプロイが完了します。
Building using Dockerfile and deploying container to Cloud Run service [halloyworld] in project [xxxxx] region [asia-northeast1]
✓ Building and deploying... Done.
✓ Uploading sources...
✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/xxx?project=nnnn].
✓ Creating Revision...
✓ Routing traffic...
Done.
Service [halloyworld] revision [halloyworld-00002-soj] has been deployed and is serving 100 percent of traffic.
Service URL: https://halloyworld-xxxxx-xx.x.run.app
URLを確認してみる(500 Internal Server Error)
サーバレスVPCの設定が済んでいないためデプロイされたサイトを確認しても、この時点ではDBアクセス失敗によるInternalServerErrorが発生します。Loggingにて以下のログが出力されているのが確認できます。
sqlalchemy.exc.InterfaceError: (pg8000.exceptions.InterfaceError) Can't create a connection to host xxx.xxx.xxx.xxx and port 5432 (timeout is None and source_address is None).
サーバレスVPCアクセスコネクタを構成
手順としては以下のようになります。
- サーバーレスVPCアクセス コネクタの作成
- サービス プロジェクトでCloud Runを有効にする
- コネクタへのアクセス権を設定
- コネクタを使用するサービスを構成する
- ※1今回はデプロイするアカウントとホストプロジェクトを操作するアカウントが同じため、デプロイアカウントにロールを付与する手順を割愛しています。必要に応じて手順3と4の間にて、コネクタを検出可能にするを実施してください。
事前準備
ホストするプロジェクトで操作するアカウントに以下のロールが付与されていることを確認してください。
- Computeネットワーク閲覧者(compute.networkViewer)
- プロジェクトIAM管理者(resourcemanager.projectIamAdmin)
- Service Usage管理者(serviceuseage.serviceUsageAdmin)
- サーバーレスVPCアクセス管理者(vpcaccess.admin)
ロールの付与が確認出来たら、こちらからプロジェクトでサーバーレスVPCアクセスのAPIを有効にしてください。有効となっている場合、以下のように表示されます。
サーバーレス VPC アクセス コネクタの作成
ナビゲーションメニューから VPCネットワーク を選択し、 サーバレスVPCアクセス に移動し、そこで コネクタを作成 を選択してください。
今回はAlloy DBを作成した際に使用したdefaultネットワークをそのまま使うため以下のような設定になっています。
コネクタの作成画面に注意書きされているように、サブネットが利用するネットワークのいずれのサブネットのCIDR範囲と重複しないように注意して設定してください。(重複した場合はメッセージとともにコネクタの作成に失敗する親切設計となっています)
サービス プロジェクトで Cloud Run を有効にする
こちらからCloud Run APIを有効にしてください。有効になっている場合、以下のように表示されます。
コネクタへのアクセス権を設定
ナビゲーションメニューから IAM を選択し、そこで アクセス権を付与 を選択してください。
「新しいプリンシパル」に service-{SERVICE_PROJECT_NUMBER}@serverless-robot-prod.iam.gserviceaccount.com
のようなCloud Runサービス エージェントのメールアドレスを入力します。
ここで {SERVICE_PROJECT_NUMBER}
はプロジェクトの設定に記載されている プロジェクト番号 となります。
コネクタを使用するサービスを構成する
ナビゲーションメニューから Cloud Run を選択すると、先ほどデプロイしたCloud Runサービスが表示されます。そのリンクを辿りって サービスの詳細 画面を表示し、 新しいリビジョンの編集とデプロイ を選択してください。
コンテナ、接続、セキュリティの3つのタブのうち 接続 タブを選択し、 VPC フィールドで先ほど作成したコネクタを指定して デプロイ します。
サービスの詳細 画面に表示されているURLを選択するとAlloy DBから取得した時刻が表示されるはずです。(ここちょっと消えてますね)
お金もかかりますし、動作確認が済んだらサーバレスVPCアクセスコネクタとCloud Runを削除しておきましょう。
おまけ(GCEからAlloy DB Auth Proxyを使って接続する)
Alloy DB Auth Proxy越しにPostGIS拡張を突っ込んだりしようかなって思ったのですが、長くなりそうなので別の記事にします。
おわりに
今はまだAWSのAuroraやAzureのHyperscaleに後れをとってはいますが、クラウドネイティブDBのPostgreSQLの中で最もパフォーマンスが高いAlloy DB for PostgreSQLはこれからが楽しみなプロダクトです。
個人的にはPostGIS拡張を使うプロダクトをクラウド化する選択肢の本命な気がしているので、これからも積極的に使ってみようと思ってます。
GI Cloud は事業の拡大に向けて一緒に夢を追う仲間を募集しています
当社は「クラウドで日本のIT業界を変革し、世の中をもっとハッピーに」をミッションに掲げ、Google Cloudに特化した技術者集団として、お客様にコンサルティングからシステム開発、運用・保守まで一気通貫でサービスを提供しています。
まだ小規模な事業体ですが、スタートアップならではの活気と成長性に加えて、大手総合商社である伊藤忠グループの一員としてやりがいのある案件にもどんどんチャレンジできる環境が整っています。成長意欲の高い仲間と共にスキルを磨きながら、クラウドの力で世の中をもっとハッピーにしたい。そんな我々の想いに共感できる方のエントリーをお待ちしています。
※本記事は、ジーアイクラウド株式会社の見解を述べたものであり、必要な調査・検討は行っているものの必ずしもその正確性や真実性を保証するものではありません。
※リンクを利用する際には、必ず出典がGIC dryaki-blogであることを明記してください。
リンクの利用によりトラブルが発生した場合、リンクを設置した方ご自身の責任で対応してください。
ジーアイクラウド株式会社はユーザーによるリンクの利用につき、如何なる責任を負うものではありません。