1. はじめに
本記事では、Google cloudのkubernetes上にSpring Bootで構築したアプリ(Quizアプリ)を動作させるハンズオンをご紹介します。以前、オンプレのKubernetesにてSpring Bootアプリをデプロイする方法を紹介しましたが、実際はクラウドサービスを使うケースが多いかと思います。オンプレとクラウドでやることは大きく変わらないですが、微妙に違う点がありますので紹介させていただきます。今回はStep2としてDBコンテナの作成方法をご説明します。
まだGoogle Cloudにてkubernetesクラスタを作成していないようでしたら、Step1を実施してください。
【初心者向けハンズオン】Google CloudのKuberenetesにJava(Spring Boot)アプリデプロイ ~Step1:Kubernetesクラスタ作成~
2. ハンズオン環境
作業端末:Windows11
Kubernetesクラスタ:GKE Autopilot
仮想サーバ:GCE(CentOS9)
オンプレでKuberntesインストールからやってみたいという方がいれば、下記を参考にして構築してもらえればと思います。
【初心者向け】Kubernetes学習向けのハンズオン(Linux(CentOS))
3. システム構成
Kubernetes上に構築するシステム構成を記載します。Web/AP、DBのシンプルなシステム構成を構築しています。DBについてはデータを永続化したいので、GCEの仮想サーバ1台をNFSサーバとして構築してKubernetes上のPodからマウントする構成にしています。

4. DBコンテナの作成
4.1 NFSサーバの作成
データを永続化するためのボリュームをNFSで作成していきます。NFSを構築することで、すべてのノードから同一ボリュームを参照・更新することができるようになります。
まず、GCEでインスタンスを作成してください。OSの種類は何でもよいですが、ここではCentOS9を選択しています。
作成方法がわからない方は、下記のサイトを参考にして作成してみて下さい。
Compute Engine インスタンスを作成して起動する | Compute Engine Documentation | Google Cloud
GCEインスタンスが作成できたら接続してください。sudo su – でルートユーザにスイッチします。
Linux quizapp-nfs-server 6.1.0-31-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.128-1 (2025-02-07) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
username@quizapp-nfs-server:~$
username@quizapp-nfs-server:~$
username@quizapp-nfs-server:~$ sudo su -
root@quizapp-nfs-server:~#
NFS関連パッケージをすべての仮想サーバにインストールします。
[root@quizapp-nfs-server ~]# dnf -y install nfs-utils
CentOS Stream 9 - BaseOS 9.4 MB/s | 8.7 MB 00:00
CentOS Stream 9 - AppStream 8.4 MB/s | 23 MB 00:02
CentOS Stream 9 - Extras packages 60 kB/s | 20 kB 00:00
Google Compute Engine 22 kB/s | 7.2 kB 00:00
Google Cloud SDK 45 MB/s | 139 MB 00:03
Dependencies resolved.
===============================================================================================
Package Architecture Version Repository Size
===============================================================================================
Installing:
nfs-utils x86_64 1:2.5.4-34.el9 baseos 458 k
Installing dependencies:
~~Omission~~
Verifying : rpcbind-1.2.6-7.el9.x86_64 10/11
Verifying : sssd-nfs-idmap-2.9.6-4.el9.x86_64 11/11
Installed:
gssproxy-0.8.4-7.el9.x86_64 libev-4.33-6.el9.x86_64
libnfsidmap-1:2.5.4-34.el9.x86_64 libtirpc-1.3.3-9.el9.x86_64
libverto-libev-0.3.2-3.el9.x86_64 nfs-utils-1:2.5.4-34.el9.x86_64
python3-pyyaml-5.4.1-6.el9.x86_64 quota-1:4.09-4.el9.x86_64
quota-nls-1:4.09-4.el9.noarch rpcbind-1.2.6-7.el9.x86_64
sssd-nfs-idmap-2.9.6-4.el9.x86_64
Complete!
[root@quizapp-nfs-server ~]#
続いて、idmpd.confファイルのDomainに仮想サーバのホスト名を設定します。
[root@quizapp-nfs-server ~]# cp -p /etc/idmapd.conf /etc/idmapd.conf_bk
[root@quizapp-nfs-server ~]# vi /etc/idmapd.conf
[root@quizapp-nfs-server ~]# diff /etc/idmapd.conf /etc/idmapd.conf_bk
6d5
< Domain = quizapp-nfs-server
[root@quizapp-nfs-server ~]#
データを格納するディレクトリを作成します。
[root@quizapp-nfs-server ~]# mkdir -p /nfs/share/postgresql
[root@quizapp-nfs-server ~]# ls -ld /nfs/share/postgresql
drwxr-xr-x. 2 root root 6 Mar 12 01:21 /nfs/share/postgresql
[root@quizapp-nfs-server ~]#
/etc/exportsファイルに対して、上記で作成したディレクトリを他のサーバ/Podから参照・更新できるように設定を追加します。
・ディレクトリ:/nfs/share/postgresql
・IPアドレス帯:NFSサーバにアクセスする仮想サーバのIPアドレス帯を指定して下さい。
・権限:rw,no_root_squash
rwとすることで読み書き可能とします。no_root_squashを設定することで、他の仮想サーバからルート権限で操作できるようにします。
[root@quizapp-nfs-server ~]# vi /etc/exports
[root@quizapp-nfs-server ~]# cat /etc/exports
/nfs/share/postgresql 10.128.0.0/20(rw,no_root_squash)
[root@quizapp-nfs-server ~]#
続いて必要なサービスを有効化・起動していきます。まず、NFSサーバにてnfs-serverを有効化・起動してください。
[root@quizapp-nfs-server ~]# systemctl enable --now nfs-server
Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service.
[root@quizapp-nfs-server ~]#
[root@quizapp-nfs-server ~]# systemctl status nfs-server
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; preset: disabled)
Drop-In: /run/systemd/generator/nfs-server.service.d
└─order-with-mounts.conf
Active: active (exited) since Wed 2025-03-12 01:40:30 UTC; 9s ago
Docs: man:rpc.nfsd(8)
man:exportfs(8)
Process: 78556 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
Process: 78557 ExecStart=/usr/sbin/rpc.nfsd (code=exited, status=0/SUCCESS)
Process: 78577 ExecStart=/bin/sh -c if systemctl -q is-active gssproxy; then systemctl rel>
Main PID: 78577 (code=exited, status=0/SUCCESS)
CPU: 36ms
Mar 12 01:40:30 quizapp-nfs-server systemd[1]: Starting NFS server and services...
Mar 12 01:40:30 quizapp-nfs-server systemd[1]: Finished NFS server and services.
[root@quizapp-nfs-server ~]#
続いて、rpcbindサービスを有効化・起動してください。NFSはRPC(Remote Procedure Calls)の仕組みを利用してリモートサーバにおける操作を実現しています。nfs-serverサービスを起動すると、rpcbindにプログラム番号と使用するポート番号が登録されます。リモートサーバがNFSサーバに接続する際、まずrpcbindに問い合わせてポート番号を取得することで接続を確立しています。
[root@quizapp-nfs-server ~]# systemctl enable --now rpcbind
[root@quizapp-nfs-server ~]#
[root@quizapp-nfs-server ~]# systemctl status rpcbind
● rpcbind.service - RPC Bind
Loaded: loaded (/usr/lib/systemd/system/rpcbind.service; enabled; preset: enabled)
Active: active (running) since Wed 2025-03-12 01:40:29 UTC; 43s ago
TriggeredBy: ● rpcbind.socket
Docs: man:rpcbind(8)
Main PID: 78549 (rpcbind)
Tasks: 1 (limit: 23097)
Memory: 1.5M
CPU: 39ms
CGroup: /system.slice/rpcbind.service
└─78549 /usr/bin/rpcbind -w -f
Mar 12 01:40:29 quizapp-nfs-server systemd[1]: Starting RPC Bind...
Mar 12 01:40:29 quizapp-nfs-server systemd[1]: Started RPC Bind.
[root@quizapp-nfs-server ~]#
4.2 Namespaceの作成
まず、Quizアプリ用にNamespaceを作成します。他の用途に使うときにNamespaceで区別できるようにしておくと便利ですので、少し手間ですがNamespaceを作っておきましょう。Powershellを起動して下記のとおりNamespaceを作成してください。
PS C:\Windows\system32> kubectl create namespace quizapp
namespace/quizapp created
PS C:\Windows\system32> kubectl get ns
NAME STATUS AGE
default Active 33h
gke-gmp-system Active 33h
gke-managed-cim Active 33h
gke-managed-filestorecsi Active 33h
gke-managed-system Active 33h
gke-managed-volumepopulator Active 33h
gmp-public Active 33h
kube-node-lease Active 33h
kube-public Active 33h
kube-system Active 33h
quizapp Active 4s
PS C:\Windows\system32>
4.3 Persistent Volume (PV)作成
アプリケーションで参照・更新するデータをpod上に格納してしまうと、pod再作成時にデータが削除されてしまいます。データが削除されないようにPVというストレージリソース作成します。下記の通りマニフェストを作成して適用してください。PVのSTATUSがAvailableになっていれば成功です。
PS C:\Program Files\gke\manifest> cat .\psql-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-volume
labels:
type: local
app: postgres
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: standard-rwo
nfs:
server: 10.128.0.22
path: /nfs/share/postgresql
PS C:\Program Files\gke\manifest>
PS C:\Program Files\gke\manifest> kubectl apply -f .\psql-pv.yaml
persistentvolume/postgres-volume created
PS C:\Program Files\gke\manifest>
PS C:\Program Files\gke\manifest> kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
postgres-volume 5Gi RWX Retain Available standard-rwo <unset> 8s
PS C:\Program Files\gke\manifest>
4.4 Persistent Volume Claim(PVC)の作成
続いて、Podがストレージを要求するためのリソースであるPVCを作成します。
PS C:\Program Files\gke\manifest> cat .\psql-claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-volume-claim
namespace: quizapp
labels:
app: postgres
spec:
storageClassName: standard-rwo
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
PS C:\Program Files\gke\manifest>
PS C:\Program Files\gke\manifest> kubectl apply -f .\psql-claim.yaml
persistentvolumeclaim/postgres-volume-claim created
PS C:\Program Files\gke\manifest>
下記の通りPVCリソースが作成できていればOKです。この時点ではSTATUSはpendingで問題ありません。
PS C:\Program Files\gke\manifest> kubectl get pvc -n quizapp
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
postgres-volume-claim Pending standard-rwo <unset> 12s
PS C:\Program Files\gke\manifest>
4.5 DBコンテナ作成
さて、いよいよDBコンテナの作成に着手しましょう。configmapを作成してデータベース接続に関する設定を記載していきます。ご自身の作成したデータベースに合わせて、DB名、ユーザ名、パスワードを設定してください。
PS C:\Program Files\gke\manifest> cat .\postgres-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-secret
namespace: quizapp
labels:
app: postgres
data:
POSTGRES_DB: quiz
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
PS C:\Program Files\gke\manifest>
作成したconfigmapのマニフェストを適用下記のします。下記の通りpostgres-secretのリソースが取得できれば正常です。
PS C:\Program Files\gke\manifest> kubectl apply -f .\postgres-configmap.yaml
configmap/postgres-secret created
PS C:\Program Files\gke\manifest>
PS C:\Program Files\gke\manifest> kubectl get configmap -n quizapp
NAME DATA AGE
kube-root-ca.crt 1 17m
postgres-secret 3 14s
PS C:\Program Files\gke\manifest>
postgresをデプロイするためのマニフェスト例を記載しているので参考にしてみてください。
下記あたりの設定はご自身の要件に応じて適宜変更ください。
・レプリカセット⇒replicas: 1 ※無料枠のKubernetesクラスタだと多くのpodを起動するだけのリソースがないので、最低限にしています。
・Postgresバージョン⇒image: ‘postgres:15’
・マウントパス⇒mountPath: /var/lib/postgresql/data
PS C:\Program Files\gke\manifest> cat .\postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: quizapp
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
sidecar.istio.io/inject: "false"
spec:
containers:
- name: postgres
image: 'postgres:15'
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: postgres-secret
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgresdata
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumes:
- name: postgresdata
persistentVolumeClaim:
claimName: postgres-volume-claim
PS C:\Program Files\gke\manifest>
Postgresのマニフェストをデプロイしていきます。デプロイの状態がREADYになっていること、PodのSTATUSがRunningになっていたら成功です。少し時間がかかるので、正常になっていない場合は時間をおいてから再度コマンド実行してみて下さい。
PS C:\Program Files\gke\manifest> kubectl apply -f .\postgres-deployment.yaml
Warning: autopilot-default-resources-mutator:Autopilot updated Deployment quizapp/postgres: defaulted unspecified 'cpu' resource for containers [postgres] (see http://g.co/gke/autopilot-defaults).
deployment.apps/postgres created
PS C:\Program Files\gke\manifest>
PS C:\Program Files\gke\manifest> kubectl get pod -o wide -n quizapp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
postgres-7667d96d7c-g2k5d 1/1 Running 0 8s 10.117.0.10 gk3-quizapp-cluster-pool-2-7538a23d-q5ph <none> <none>
PS C:\Program Files\gke\manifest>
後続で作成するアプリケーションのPodからPostgresのPodにアクセスするために、Serviceを作成していきます。Serviceを作成することで、アプリケーションPodから複数作成したPostgresのPodに自動で振り分けが行われるようになります。内部アクセスに使用するServiceとなりますので、ここではtypeにLoadBalancerを指定します。
[root@masternode ~]# vi ps-service.yaml
[root@masternode ~]# cat ps-service.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
type: LoadBalancer
ports:
- port: 5432
selector:
app: postgres
[root@masternode ~]#
Postgresサービスのマニフェストを適用してください。下記の通りpostgresのサービスが表示されていれば成功です。外部アクセスは不要ですので、EXTERNAL-IPがpendingとなってますが問題ありません。アプリケーションのデータベース接続定義にサービス名(postgres)を指定することでPostgres Podにアクセスすることができます。アプリケーションの定義についてはStep2でご紹介します。
PS C:\Program Files\gke\manifest> kubectl apply -f .\postgres-service.yaml
service/postgres created
PS C:\Program Files\gke\manifest>
PS C:\Program Files\gke\manifest> kubectl get svc -n quizapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
postgres LoadBalancer 34.118.235.39 <pending> 5432:30530/TCP 15s
PS C:\Program Files\gke\manifest>
Postgresデータベースに接続してみましょう。ひとつPodを選択して、postgresデータベースに接続してください。
PS C:\Program Files\gke\manifest> kubectl exec -it postgres-7667d96d7c-g2k5d -n quizapp -- psql -h localhost -U postgres --password -p 5432 postgres
Password:
psql (15.12 (Debian 15.12-1.pgdg120+1))
Type "help" for help.
postgres=#
postgres-configmap.yamlにて指定して作成したデータベースにスイッチしてください。
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges
-----------+----------+----------+------------+------------+------------+-----------------+-----------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc |
quiz | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres +
| | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres +
| | | | | | | postgres=CTc/postgres
(4 rows)
postgres=# \c quiz
Password:
You are now connected to database "quiz" as user "postgres".
quiz=#
アプリ動作に必要な各種テーブルを作成してください。
create TABLE users_roles (
user_id integer NOT NULL,
role_id integer NOT NULL
);
create TABLE users (
userid SERIAL NOT NULL,
username varchar(255) NOT NULL UNIQUE,
password varchar(255) NOT NULL,
primary key (userid)
);
CREATE TABLE quiz (
quizid SERIAL NOT NULL,
userid integer NOT NULL,
quiz varchar(255),
category varchar(255),
option1 varchar(255),
option2 varchar(255),
option3 varchar(255),
option4 varchar(255),
answer integer,
explain varchar(1000),
status varchar(255),
PRIMARY KEY (quizid)
);
create TABLE roles (
roleid SERIAL NOT NULL,
rolename varchar(255) NOT NULL,
primary key (roleid)
);
postgres=#
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+----------
public | quiz | table | postgres
public | roles | table | postgres
public | users | table | postgres
public | users_roles | table | postgres
(4 rows)
quiz=#
サンプルデータをINSERTしておきます。
quiz=# delete from quiz;
select setval('quiz_quizid_seq', 1, false);
DO $$
BEGIN
FOR i IN 1..1000 LOOP
INSERT INTO quiz (quizid,userid,quiz,category,option1,option2,option3,option4,answer,explain,status) VALUES(default,i,'Linuxのシステムに関する一般的なログファイル名は?','Linux','/var/log/logs','/var/log/messages','/var/log/maillog','/var/log/spooler','1','/var/log/messagesは、UnixおよびUnix系オペレーティングシステム(例えばLinux)で使用される標準的なログファイルの一つです。このファイルはシステムやアプリケーションからの重要なメッセージや イベントを記録するために使用されます。','未完了');
INSERT INTO quiz (quizid,userid,quiz,category,option1,option2,option3,option4,answer,explain,status) VALUES(default,i,'ファイルの末尾から100 行を表示させるコマンドは?','Linux','head -n 100','head -l 100','tail -n 100','tail -l 100','3','tailコマンドは指定したファイルの末尾の内容を表示する ための Linux コマンドです。オプション-nで表示する行数を指定します。デフォルトでは最後の 10 行を表示します。','未完了');
INSERT INTO quiz (quizid,userid,quiz,category,option1,option2,option3,option4,answer,explain,status) VALUES(default,i,'新規作成するファイルのパーミッションが全て644になるようにする方法は?','Linux','umask 644','umask 022','chmod 644','chmod 022','2','umaskに022を指定するとデフォルトの権限は644となります。一方でディレクトリは755になりますので注意してください。','未完了');
END LOOP;
END;
$$;
select * from quiz;
DELETE 0
setval
--------
1
(1 row)
DO
quiz=#
publicユーザを登録しておきます。
quiz=# INSERT INTO users (username, password) VALUES('public', 'password');
INSERT 0 1
quiz=# select * from users;
userid | username | password
--------+----------+----------
1 | public | password
(1 row)
quiz=#
5. まとめ
DBコンテナ作成のハンズオンは以上となります。Persistent Volumeを利用することで、データベースをコンテナで動かす方法が理解できたかと思います。次のステップではAPコンテナの作成方法をご紹介しますので、引き続きトライしてみて下さい。
コメント