Cloud SQL Auth Proxy を使用して Cloud Run から Cloud SQL に接続する

記事タイトルとURLをコピーする

G-gen の佐々木です。当記事では、Google Cloud (旧称 GCP) のサーバーレスコンテナサービスである Cloud Run から、マネージドなリレーショナルデータベースサービスの Cloud SQL に安全に接続する方法を紹介します。

使用するサービス

Cloud Run

Cloud Run はサーバーレスな環境でコンテナを実行できるサービスです。
詳細については以下の記事で解説していますので、ご一読ください。

blog.g-gen.co.jp

Cloud SQL

今回は PostgreSQL データベース のマネージドサービスである Cloud SQL for PostgreSQL を使用します。
Cloud SQL の詳細については以下の記事で解説しています。

blog.g-gen.co.jp

Cloud Run から Cloud SQL に接続する方法

Cloud Run でリレーショナルデータベースを使用したい場合、最初に検討することになるのが Cloud SQL です。
Cloud SQL のインスタンスは Google Cloud のマネージド VPC ( サービスプロデューサーネットワーク ) に配置され、Cloud Run から接続する場合は、以下に示す 2 種類の方法のいずれかを使用します。

サーバーレス VPC アクセスコネクタ の使用

プライベート IP を使用して Cloud SQL に接続したい場合、サーバーレス VPC アクセスコネクタ を使用します。
自身のプロジェクト内にある VPC と Cloud SQL インスタンスが存在するサービスプロデューサーネットワークを プライベートサービスアクセス を使用してピアリング接続し、VPC 内に作成したコネクタを使用して Cloud SQL に接続するように Cloud Run を構成します。

サーバーレス VPC アクセスコネクタを使用した接続

Cloud SQL Auth Proxy の使用

Cloud SQL Auth Proxy というプロキシソフトウェアを使用することで、Cloud SQL インスタンスのパブリック IP を使用しつつ、TLS 暗号化による安全な接続を実現できます。
また、Cloud SQL Auth Proxy を使用した場合、データベースの接続元を IAM で制御することができるため、Cloud SQL Auth Proxy を使用し、かつ Cloud SQL インスタンスにアクセスする IAM 権限を持っているクライアントに接続元を制限することができます。

Cloud Run では、パブリック IP を使用する Cloud SQL インスタンスに接続する場合、あらかじめ Cloud Run 実行環境にある Cloud SQL Auth Proxy を使用するように構成することができ、UNIX ドメインソケットを使用して高速な通信を行うことができます。

なお、Cloud SQL にパブリック IP を使用したくない場合は、先述のサーバーレス VPC アクセスコネクタと Cloud SQL Auth Proxy を併用することで、プライベート IP を使用したプロキシ経由の接続も可能となっています。

当記事では、パブリック IP アドレスを使用する Cloud SQL に対して、Cloud SQL Auth Proxy 経由の接続を実際に試してみます。

Cloud SQL Auth Proxy を使用した接続

Cloud SQL の作成と設定

Cloud SQL インスタンスを作成する

当記事では PosgreSQL の Cloud SQL インスタンスを使用します。
任意の インスタンス ID 、パスワード、リージョン等を設定し、パブリック IP を有効化 して作成します。

パブリック IP を有効にして Cloud SQL インスタンスを作成する

デフォルトのマシンタイプは 4 vCPU 、メモリ 26 GB となっており、検証目的の場合は少々高めの課金がされてしまうため、必要に応じて調整すると良いでしょう。

データベースを作成する

インスタンスが作成されたら、データベース タブからデータベースを作成していきます。
ここで設定したデータベース名は、後ほど Cloud Run の環境変数に設定します。

データベースの作成①

データベースの作成②

ユーザーを作成する

ユーザー タブからデータベースのユーザーアカウントを作成します。
ここで設定したユーザー名、パスワードも、後ほど Cloud Run の環境変数に設定します。

ユーザーアカウントを追加①

ユーザーアカウントを追加②

Cloud SQL に接続する Cloud Run サービスを作成

Cloud Run サービスに紐付けるサービスアカウントを作成する

Cloud Run から Cloud SQL にアクセスできる権限を持ったサービスアカウントを作成します。
サービスアカウントには以下のロールを付与します。

  • Cloud SQL クライアント ( Cloud SQL Client )

Cloud Run 用サービスアカウントの作成

サンプルアプリケーションを Cloud Run にデプロイする

サンプルアプリケーションの Git リポジトリを使用する

Google Cloud によって、Cloud SQL Auth Proxy を使用するように構成された Cloud Run のサンプルアプリケーションが提供されています。
当記事では Python のサンプルアプリケーションを使用します(GitHub リポジトリ)。

$ git clone git@github.com:GoogleCloudPlatform/python-docs-samples.git

サンプルアプリのコンテナイメージをビルドする

python-docs-samples/cloud-sql/postgres/sqlalchemy/ に、Dockerfile を含む、サンプルアプリケーションの各種ファイルが配置されているので、当該ディレクトリに移動します。

$ cd python-docs-samples/cloud-sql/postgres/sqlalchemy/

Cloud Build を使用して、Dockerfile を元に Docker コンテナのイメージをビルドします。

$ gcloud builds submit --tag gcr.io/{コンテナイメージ作成先のプロジェクトID}/{任意の名前}

ビルドしたコンテナイメージは、指定したプロジェクトの Container Registry に格納されます。

ビルドしたコンテナイメージ

Cloud Run サービスをデプロイする

各種設定値を入力する

ビルドしたコンテナイメージから Cloud Run サービスをデプロイしていきます。

コンテナイメージを Cloud Run にデプロイ

ビルドしたコンテナイメージが入力されていることを確認し、任意のサービス名とリージョンを設定します。

Cloud Run サービスの作成①

今回は Cloud Run サービスに対するアクセス制御はしないので、すべてのトラフィックを許可する未認証の呼び出しを許可 にチェックを入れます。

Cloud Run サービスの作成②

Cloud SQL の接続情報を環境変数に設定する

Cloud SQL に接続するための情報を Cloud Run の環境変数として設定します。
サンプルアプリケーションでは、UNIX ソケットを使用する場合、以下のモジュールを使用して接続が行われます。

def connect_unix_socket() -> sqlalchemy.engine.base.Engine:
    # Note: Saving credentials in environment variables is convenient, but not
    # secure - consider a more secure solution such as
    # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
    # keep secrets safe.
    db_user = os.environ["DB_USER"]  # e.g. 'my-database-user'
    db_pass = os.environ["DB_PASS"]  # e.g. 'my-database-password'
    db_name = os.environ["DB_NAME"]  # e.g. 'my-database'
    unix_socket_path = os.environ["INSTANCE_UNIX_SOCKET"]  # e.g. '/cloudsql/project:region:instance'
 
    pool = sqlalchemy.create_engine(
        # Equivalent URL:
        # postgresql+pg8000://<db_user>:<db_pass>@/<db_name>
        #                         ?unix_sock=<INSTANCE_UNIX_SOCKET>/.s.PGSQL.5432
        # Note: Some drivers require the `unix_sock` query parameter to use a different key.
        # For example, 'psycopg2' uses the path set to `host` in order to connect successfully.
        sqlalchemy.engine.url.URL.create(
            drivername="postgresql+pg8000",
            username=db_user,
            password=db_pass,
            database=db_name,
            query={"unix_sock": "{}/.s.PGSQL.5432".format(unix_socket_path)},
        ),
        # [START_EXCLUDE]
        # Pool size is the maximum number of permanent connections to keep.
        pool_size=5,
 
        # Temporarily exceeds the set pool_size if no connections are available.
        max_overflow=2,
 
        # The total number of concurrent connections for your application will be
        # a total of pool_size and max_overflow.

        # 'pool_timeout' is the maximum number of seconds to wait when retrieving a
        # new connection from the pool. After the specified amount of time, an
        # exception will be thrown.
        pool_timeout=30,  # 30 seconds
 
        # 'pool_recycle' is the maximum number of seconds a connection can persist.
        # Connections that live longer than the specified amount of time will be
        # re-established
        pool_recycle=1800,  # 30 minutes
        # [END_EXCLUDE]
    )
    return pool

コンテナ、接続、セキュリティ 項目の コンテナ タブから環境変数を設定することができるので、以下の環境変数に対応する値を Cloud Run サービスに設定していきます。

環境変数名 設定値
INSTANCE_UNIX_SOCKET 作成した Cloud SQL インスタンスの情報を元に、以下の値を設定
/cloudsql/{プロジェクト名}:{リージョン}:{インスタンスの名前}
INSTANCE_CONNECTION_NAME Cloud SQL の インスタンス接続名
Google Cloud コンソールの Cloud SQL インスタンス一覧画面から確認可能
DB_NAME Cloud SQL インスタンスに作成したデータベースの名前
DB_USER 作成したデータベースユーザーの名前
DB_PASS 作成したデータベースユーザーのパスワード

Cloud SQL のインスタンス接続名

Cloud Run サービスの環境変数を設定

コード内コメントに記載がある通り、データベースの接続情報をよりセキュアに Cloud Run に渡したい場合は、Secret Manager を使用することもできます。

接続する Cloud SQL インスタンスを設定する

コンテナ、接続、セキュリティ 項目の 接続 タブを開き、Cloud SQL 接続 で環境変数に設定したものと同じ インスタンス接続名 を選択します。
これにより、Cloud Run サービスで Cloud SQL Auth Proxy が有効化され、プロキシを用いたデータベース接続が可能になります。

接続する Cloud SQL インスタンスを設定

サービスアカウントを設定する

コンテナ、接続、セキュリティ 項目の セキュリティ タブで Cloud SQL インスタンスへの接続を許可したサービスアカウントを設定します。

サービスアカウントを設定

ここまで設定したら 作成 を押下して Cloud Run サービスを作成します。

サンプルアプリケーションの動作確認

ブラウザから Cloud Run サービスの URL にアクセスし、サンプルアプリケーションを動かしてみます。

ブラウザからサンプルアプリケーションにアクセス

当記事で使用するサンプルアプリケーションでは、TABSPACE のどちらかに投票することで、投票結果がデータベースに記録されるようになっています。

サンプルアプリケーションの画面

投票ボタンを何度か押下します。

投票するたびに数字が加算される

データベースに投票結果が保持されているか確認するため、Cloud Run サービスのコンテナがすべて破棄されるのを待ってから、もう一度 URL にアクセスします。
サービスの詳細指標 タブから コンテナ インスタンス数 を確認できます。
active と idle の値が 0 になるまで少し待ちます。

コンテナ インスタンス数が 0 になったことを確認

2 つの値が 0 になったら、もう一度サービスの URL にアクセスします。
このとき、先程とは別のコンテナが起動されますが、投票結果はデータベース側で保持されているため、投票後と同じ投票数が画面に表示されます。

佐々木 駿太 (記事一覧)

G-gen最北端、北海道在住のクラウドソリューション部エンジニア

2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。

趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。