😶

オンプレミスで動かしていた postgres インスタンスを Cloud SQL に移行した時のメモ

2023/02/06に公開

公式手順もあるし何番煎じか分かりませんが、自分用にメモとして残しておきます。

やりたいこと

タイトルの通り、オンプレミスで動いていた postgres のインスタンスを Cloud SQL に移行するのですが、オンプレミス上にはその postgres インスタンスを参照しているアプリが多数おり、単純に移行してしまうとそれらが動かなくなってしまいます。

最終的には各アプリを改修して正規の接続を目指すものの、リソースの関係でそれらを一気に行うのは難しいため、各アプリからはあたかも何も変更されていないかのように見せる事にしました。

GCP の外から Cloud SQL へ接続しようと思うと Cloud SQL Proxy を使用する必要があります。これを利用して、今まで postgres インスタンスを動かしていたホストを Cloud SQL へのプロキシサーバーのようなものに仕立て上げます。

プロキシに関してはバイナリをDLして来ても良いのですが、公式で Docker イメージが提供されているので、今回はそちらを使用します。また、データの移行に関してもコンテナの中で完結するようにしたいと思います。

前提

  • Cloud SQL インスタンスは作成済み
  • オンプレミス上の postgres のホストは docker-compose が使用できる状態
  • 移行元からデータベースのダンプファイルが取得出来る

構成ファイル

docker-compose を使用して必要なイメージやコマンドをまとめます。
必要なファイルは以下の通りです。

docker-compose.yml

services:
  proxy:
    image: "gcr.io/cloudsql-docker/gce-proxy"
    command:
      [
        "/cloud_sql_proxy",
        "-instances=${CLOUDSQL_INSTANCE_NAME}=tcp:0.0.0.0:5432",
        "-credential_file=/config",
      ]
    volumes:
      - "${PATH_TO_KEY_FILE}:/config"
    ports:
      - "5432:5432"
  db:
    image: postgres
    user: postgres
    volumes:
      - ./data:/data
      - ./shell:/shell
    env_file: .postgres.env

proxy サービスで tcp:0.0.0.0:5432 となっている箇所は、tcp:127.0.0.1:5432 とする事でその端末内での接続に限定することも出来ます。

db サービスで userpostgres にしているので、psql 実行時のユーザーが postgres となります。他のユーザーで接続する場合は適宜変更して下さい。

.env

PATH_TO_KEY_FILE=<キーファイルまでのパス>
CLOUDSQL_INSTANCE_NAME=<Cloud SQL の接続名>

以下を参考にサービスアカウントを作り、キーとなる json ファイルを取得しておいてください。
サービスアカウントは Cloud SQL クライアント のロールを持っていれば問題ありません。

https://cloud.google.com/sql/docs/sqlserver/connect-docker?hl=ja

キーを作成したら、任意の場所に置いておきます。
例えば同階層の config フォルダ内に key.json を配置したなら PATH_TO_KEY_FILE

PATH_TO_KEY_FILE=./config/key.json

となります。

.postgres.env

PGHOST=proxy
PGPORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<任意のパスワード>
PGPASSWORD=<Cloud SQL インスタンスのパスワード>

PGHOSTproxy サービスを指定しているので、デフォルトの接続先が Cloud SQL になります。

今回は docker-compose 内でデフォルトユーザーを postgres にしているので、PGPASSWORDCloud SQL インスタンスの postgres のパスワードにしておくと、 psql 使用時に postgres を使用する場合にパスワードを聞かれずにログインできます。別のユーザーにする場合は、この変数も適宜書き換えてください。

shell/install.sh

#!/bin/bash

cd `dirname $0`
cd ../data

for f in * ; do 
  name=`echo $f | sed 's/\.[^\.]*$//'`
  echo $name
  dropdb -U postgres $name
  createdb -U postgres $name
  psql -U postgres $name < $f
done

data フォルダにあるファイルを使用して Cloud SQL 上のデータベースを作成します。
data フォルダ内には移行元 DB のダンプファイルが <DB名>.sqlの形で格納されているとします。

data フォルダ

前項の通り、<DB名>.sqlの形でダンプファイルを格納します。

起動、接続、移行

後は普通に docker-compose を起動します。

docker-compose up -d

起動が終わると、 Cloud SQL への接続がこの docker-compose を動かしているホストを経由して行えるようになります。

接続

postgres コンテナも動かしているので、ホストに postgres 環境が無くても Cloud SQL に接続できます。
以下のコマンドでコンテナに入れば、以降は普通に psql コマンドが使用できます。

docker-compose exec db bash

移行

前項のコマンドでコンテナに入った後、先程のスクリプトを実行してデータを流し込みます。

/shell/install.sh

おわりに

今回は移行のためにオンプレミス内における踏み台のようなものを作りましたが、運用によってはかなりのセキュリティリスクになります。
参考するに当たっては、案件のセキュリティ要件等にご注意ください🙇

Discussion