Compute EngineインスタンスにPostgreSQLサーバを構築する

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

G-gen の佐々木です。当記事では、Google Cloud の仮想マシンサービスである Compute Engine(Google Compute Engine: GCE)に PostgreSQL サーバを構築していきます。

当記事の目的

当記事では、Google Cloud 上で仮想マシンを利用できるサービスである Compute Engine を利用して、PostgreSQL サーバを構築していきます。

Compute Engine についての詳細は解説は、以下の記事をご参照ください。

blog.g-gen.co.jp

blog.g-gen.co.jp

Google Cloud では Cloud SQLAlloyDB for PostgreSQL などの PostgreSQL 完全互換のデータベース サービスが提供されています。また、無制限のスケーリングとマルチリージョンの展開が可能な非常に強力なデータベース サービスである Cloud Spanner でも、完全互換ではないものの、PostgreSQL との互換性があります。

したがって、Google Cloud において新規にデータベースを利用する際、データベースエンジンとして PostgreSQL を優先的に検討・採用するケースが想定されます。

上記の Google Cloud におけるマネージド データベース サービスは、本番環境向け、エンタープライズ向けの機能を多く持つことから、 個人の PostgreSQL の学習用途や、簡単なテスト用のデータベースとして利用するには性能が過剰で、またコスト(Google Cloud 利用料)が高くついてしまいます。

そこで当記事では、個人による、Google Cloud の環境を利用した PostgreSQL の学習用途を想定して、Compute Engine 仮想マシン上に PostgreSQL サーバを構築していきます。

Compute Engine インスタンスの作成

作業の概要

Google Cloud プロジェクトに Compute Engine 仮想マシン(インスタンス)を作成していきます。

インスタンスは VPC 内のサブネットに作成する必要があるため、それらのリソースを先に作成し、その中にインスタンスを作成します。

そして、インスタンスに PostgreSQL をインストールする際や、インスタンス上に構築した PostgreSQL サーバーを利用する際に VPC の外部から接続できるように、接続を許可するファイアウォールルールを設定しておきます。

当記事で作成する Compute Engine 環境の構成

当記事では gcloud コマンドを用いてリソースの作成を行っていきます。gcloud コマンドのインストールについてはこちらのドキュメントを参照してください。

また、Google Cloud コンソールから利用できる Cloud Shell(ブラウザベースのターミナル環境)には gcloud コマンドがプリインストールされているため、以降の作業をそのまま実施することができます。

シェル変数の設定

コマンドで何度か使用する値をシェル変数に格納しておきます。

SUFFIX={適当な値}
PROJECT={プロジェクトID}
REGION={リソースを作成するリージョン}

VPC・サブネットの作成

VPC の作成

以下のコマンドで VPC を作成します。サブネットを手動で作成するため、--subnet-mode フラグで custom を指定します。

# VPC を作成する
$ gcloud compute networks create vpc-${SUFFIX} \
    --subnet-mode=custom \
    --project=${PROJECT}

サブネットの作成

作成した VPC を指定し、その中にサブネットを作成します。--range フラグではサブネットに割り当てるプライベート IP アドレスの範囲を CIDR で指定します。当記事では 192.168.150.0/28 を割り当てています。

# サブネットを作成する
$ gcloud compute networks subnets create subnet-${SUFFIX} \
    --network=vpc-${SUFFIX} \
    --region=${REGION} \
    --range=192.168.150.0/28 \
    --project=${PROJECT}

インスタンスの作成

作成した VPC とサブネットを指定し、Compute Engine インスタンスを作成します。

当記事では以下の設定値でインスタンスを作成します。

項目 gcloud コマンドのフラグ 備考
インスタンス名 vm-${SUFFIX}
VPC --network vpc-${SUFFIX}
サブネット --subnet subnet-${SUFFIX}
OS イメージ --image-family
--image-project
debian-12
debian-cloud
以降の手順はここで指定した OS を前提とする点に注意
マシンタイプ --machine-type e2-micro 2 vCPU、メモリ1GB
必要に応じて変更可(参考
ネットワークタグ --tags ssh
postgres
後で作成するファイアウォールルールをインスタンスに紐付ける際に使用
# Compute Engine インスタンスを作成する
$ gcloud compute instances create vm-${SUFFIX} \
    --network=vpc-${SUFFIX} \
    --subnet=subnet-${SUFFIX} \
    --zone=${REGION}-a \
    --image-family=debian-12 \
    --image-project=debian-cloud \
    --machine-type=e2-micro \
    --tags=ssh,postgres \
    --project=${PROJECT}

ファイアウォールルールの設定

作成したインスタンスに SSH でアクセスできるように、VPC に内向きのファイアウォールルールを作成します。--target-tags フラグでインスタンスに設定したものと同じタグを指定することで、このルールをインスタンスに紐付けることができます。

なお、当記事では便宜上 --source-ranges フラグ、つまりアクセス元の IP アドレス範囲を 0.0.0.0/0(任意の IP アドレス)に設定していますが、セキュリティを考慮して自身の PC の IP アドレス等を設定することもできます。

# SSH を許可する
$ gcloud compute firewall-rules create vpc-${SUFFIX}-allow-ssh \
    --direction=INGRESS \
    --source-ranges=0.0.0.0/0 \
    --allow=tcp:22 \
    --target-tags=ssh \
    --network=vpc-${SUFFIX} \
    --project=${PROJECT}

次に、インスタンス上に構築する PostgreSQL サーバーに外部からアクセスできるように、ファイアウォールルールを作成します。

# PostgreSQL サーバへの接続を許可する
$ gcloud compute firewall-rules create vpc-${SUFFIX}-allow-postgres \
    --direction=INGRESS \
    --source-ranges=0.0.0.0/0 \
    --allow=tcp:5432 \
    --target-tags=postgres \
    --network=vpc-${SUFFIX} \
    --project=${PROJECT}

インスタンスに SSH 接続

コンソールからインスタンスに接続(GUI の場合)

Google Cloud コンソールからインスタンスに SSH 接続する場合、インスタンス一覧画面で「SSH」を選択します。

Google Cloud コンソールからインスタンスに SSH 接続する

gcloud コマンドで SSH 接続(CLI の場合)

gcloud では、以下のコマンドを使用してインスタンスに SSH 接続できます。

# インスタンスに SSH 接続する
$ gcloud compute ssh vm-${SUFFIX} \
    --zone=${REGION}-a \
    --project=${PROJECT}

PostgreSQL のインストール

パッケージリストの更新

以降の手順については、SSH 接続した Compute Engine VM 上でコマンドを実行してください。

PostgreSQL をインストールする前に、apt のパッケージを最新化しておきます。

# パッケージリストを最新の状態にする
$ sudo apt update
  
# パッケージの最新化(時間がかかる可能性あり)
$ sudo apt upgrade -y

PostgreSQL のインストール

apt install で PostgreSQL をインストールします。

当記事では Debian のデフォルトに設定されているバージョンをインストールします。特定のバージョンを指定したい場合は公式ウェブサイト(postgresql.org)の Linux downloads (Debian) の手順を参照してください。

# PostgreSQL をインストールする
$ sudo apt install postgresql -y
  
# PostgreSQL のバージョンを確認する
$ psql -U postgres -c "SELECT version()"
  
---------- 出力例 ----------
                                                      version                                                      
-------------------------------------------------------------------------------------------------------------------
 PostgreSQL 15.8 (Debian 15.8-0+deb12u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
(1 row)
  

インスタンス内部からデータベースに接続確認

apt install で PostgreSQL をインストールした場合、初期ユーザーとして postgres という名前のユーザーがパスワード無しで設定されています。

ユーザーを切り替えて psql コマンドでデフォルトのデータベースに接続してみます。

# ユーザーの切り替え
$ sudo su - postgres
  
# PostgreSQL に接続する
$ psql

ログインしたら、試しにデータベースの一覧を確認します。

# データベースの一覧を確認する
postgres=# \l

---------- 出力例 ----------
                                             List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  | ICU Locale | Locale Provider |   Access privileges   
-----------+----------+----------+---------+---------+------------+-----------------+-----------------------
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 |            | libc            | 
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 |            | libc            | =c/postgres          +
           |          |          |         |         |            |                 | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 |            | libc            | =c/postgres          +
           |          |          |         |         |            |                 | postgres=CTc/postgres
(3 rows)

確認が終わったら、データベースからはログアウトします。

# データベースからログアウトする
postgres=# \q

PostgreSQL の管理ツールである pg_ctl などのコマンドは /usr/lib/postgresql/15/bin/ にあるため、postges ユーザーの .bash_profile ファイルにパスを設定しておきます。

# 管理ツールがあるディレクトリにパスを設定する
$ echo 'PATH=$PATH:/usr/lib/postgresql/15/bin/' >> ~/.bash_profile
  
# 変更を反映させる
$ source ~/.bash_profile

リモートクライアントからデータベースに接続確認

設定ファイルの編集

postgresql.conf

postgres ユーザーのまま作業を続けていきます。

設定ファイルである postgresql.conf を編集して、ローカル PC や Cloud Shell などのリモートクライアントからデータベースに接続できるようにします。

初期状態では、listen_addresses の項目がコメントアウトされています。この項目では、データベース接続を受け付けるインスタンス側の IP アドレス(接続元 IP アドレスではない)を設定します。

$ cat /etc/postgresql/15/main/postgresql.conf | grep listen_addresses
#listen_addresses = 'localhost'         # what IP address(es) to listen on;

エディタを使用してファイルを編集していきます。

# エディタを使用して postgresql.conf を編集する
$ vi /etc/postgresql/15/main/postgresql.conf

listen_address の行のコメントアウトを外し、以下のように修正してファイルを保存します。

listen_addresses = '*'                  # what IP address(es) to listen on;

インターネットからデータベースに接続するためには、ここで Compute Engine インスタンスの外部 IP アドレスを設定する必要があります。

しかし、当記事ではインスタンスの外部 IP アドレスを固定していないため、インスタンスの停止・起動を行うと IP アドレスが変わってしまう可能性があります。そのため、上記のように「*」を設定することで全ての IP アドレスでデータベース接続を受け付けるようにします。

postgresql.conf の listen_addresses 項目は、設定を反映するためにデータベースの再起動が必要な項目となっているため、後の手順で再起動を実施します。

pg_hba.conf

クライアント認証に関する設定ファイルである pg_hba.conf も編集する必要があります。このファイルでは、1行のレコードでクライアントが利用できるデータベースやデータベースユーザー、アクセス元 IP アドレスなどを設定します。

# エディタを使用して pg_hba.conf を編集する
$ vi /etc/postgresql/15/main/pg_hba.conf

ファイル内の # IPv4 local connections: の下に以下のレコードを追記します。

host    all             all             0.0.0.0/0               trust

上記の記述では、全ての IP アドレス(4列目の 0.0.0.0/0)から、全てのデータベース(2列めの all)に対して、全てのデータベースユーザーを使用して(3列目の all)、パスワード無しで(5行目の trust)接続できるようになります。

よりセキュリティを考慮する場合は、以下のドキュメントを参考に、アクセス元 IP アドレスやパスワード認証の強制等を設定するとよいでしょう。

データベース再起動

編集した設定ファイルを反映させるため、pg_ctl restart でデータベースの再起動を行います。

# データベースを再起動する
$ pg_ctl restart -D /var/lib/postgresql/15/main/

---------- 出力例 ----------
waiting for server to shut down.... done
server stopped
waiting for server to start....2024-10-26 14:34:46.636 UTC [1548] LOG:  starting PostgreSQL 15.8 (Debian 15.8-0+deb12u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
2024-10-26 14:34:46.637 UTC [1548] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2024-10-26 14:34:46.637 UTC [1548] LOG:  listening on IPv6 address "::", port 5432
2024-10-26 14:34:46.640 UTC [1548] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2024-10-26 14:34:46.648 UTC [1551] LOG:  database system was shut down at 2024-10-26 14:34:46 UTC
2024-10-26 14:34:46.657 UTC [1548] LOG:  database system is ready to accept connections
 done
server started

データベースクラスタのパスを PGDATA 環境変数に設定しておくことで、上記コマンドのように -D フラグでデータベースクラスタを指定しなくてもよくなります。必要に応じて環境変数を設定するとよいでしょう。

接続確認

リモートクライアントからデータベースへの接続を行います。以降の手順は全て自身の PC や Cloud Shell のターミナルからコマンドを実行してください。

psql コマンドがない場合はこちらのドキュメント を参考にインストールします。なお、Cloud Shell には psql がプリインストールされています。

まず、Compute Engine インスタンスの外部 IP アドレスをシェル変数 HOST_IP に格納します。

# インスタンスの外部 IP アドレスをシェル変数に格納する
HOST_IP=$(
    gcloud compute instances describe vm-${SUFFIX} \
        --zone=${REGION}-a \
        --project=${PROJECT} \
        --format="value(networkInterfaces[0].accessConfigs[0].natIP)"
)

psql コマンドでデータベース接続を行います。

# データベースに接続する
$ psql -h ${HOST_IP} -U postgres

バックアップの取得とインスタンスの復元

バックアップの目的

PostgreSQL の設定が完了した状態の Compute Engine インスタンスのバックアップを作成します。

今回作成した環境は PostgreSQL の学習用のため、重要なデータなどは格納されない想定ですが、バックアップを取っておくことで以下のようなメリットがあります。

  • 環境を長期間利用しない場合に削除し、必要なときにバックアップから環境を再作成することで、Google Cloud 利用料を節約する。
  • 学習中に環境を壊してしまった場合に、壊れる前の環境をすぐに復元することができる。

Compute Engine のバックアップについてはスナップショット、マシンイメージ、カスタムイメージなどいくつかの方法がありますが、ここではマシンイメージを作成していきます。

それぞれの違いについては、以下の記事で詳しく説明されています。

blog.g-gen.co.jp

マシンイメージの取得

以下のコマンドを使用して、PostgreSQL をインストールしたインスタンスをソースとしてマシンイメージを取得します。

いつの状態のバックアップかを明確にするため、マシンイメージを取得した時刻をイメージの名前に含めておくと便利です。

# マシンイメージの取得
$ gcloud compute machine-images create mimg-${SUFFIX}-$(date '+%Y%m%d%H%M%S') \
    --source-instance=vm-${SUFFIX} \
    --source-instance-zone=${REGION}-a \
    --storage-location=${REGION} \
    --project=${PROJECT}

マシンイメージからインスタンスを復元

古いインスタンスの削除

Compute Engine では同一のゾーンに同名のインスタンスを作成することができないため(参考)、なるべく同じ構成でバックアップからインスタンスを復元したい場合、先に古いインスタンスを削除します。

# インスタンスを削除する
$ gcloud compute instances delete vm-${SUFFIX} \
    --zone=${REGION}-a \
    --project=${PROJECT}

マシンイメージからインスタンスを復元

マシンイメージからのインスタンスの復元は、インスタンス作成時と同じコマンドで --source-machine-image フラグを使用します。

OS やネットワークタグなどの情報はマシンイメージに含まれているため、復元時に設定する必要はありません。

# マシンイメージからインスタンスを復元する
$ gcloud compute instances create vm-${SUFFIX} \
    --source-machine-image={マシンイメージの名前を指定} \
    --network=vpc-${SUFFIX} \
    --subnet=subnet-${SUFFIX} \
    --zone=${REGION}-a \
    --project=${PROJECT}

復元したインスタンスのデータベースに接続

復元したインスタンスの外部 IP アドレスを確認し、psql コマンドでデータベース接続を行います。

# インスタンスの外部 IP アドレスをシェル変数に格納する
$ HOST_IP=$(
    gcloud compute instances describe vm-${SUFFIX} \
        --zone=${REGION}-a \
        --project=${PROJECT} \
        --format="value(networkInterfaces[0].accessConfigs[0].natIP)"
)
  
# データベースに接続する
$ psql -h ${HOST_IP} -U postgres

PostgreSQL インストール後に設定ファイルを編集した状態がマシンイメージに保存されているため、復元したインスタンスであってもリモートクライアントから問題なく接続できます。

佐々木 駿太 (記事一覧)

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

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

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