この記事は PostgreSQL Advent Calendar 2021 12日目のエントリです。
はじめに
クラウドネイティブなストレージが注目を集める中、PostgreSQLなどのデータベースでも安定かつ高性能で利用できるストレージとしてローカルストレージ
が注目されています。
今回は分散ストレージとしても盤石な地位を築いているOpenEBS
のローカルストレージを利用して、データベースのワークロードでのベンチマーク(pgbench)をしてみたいと思います。
分散ストレージとローカルストレージの違い
今回は詳しい説明を割愛しますが、分散ストレージとローカルストレージのアーキテクチャの違いは、OpenEBSアーキテクチャのドキュメントでざっくり理解できると思います。
分散ストレージはローカルストレージと比べて、可用性の面で圧倒的に有利なのですが、データ同期のための遅延など、性能面のデメリットを抱えています。PostgreSQLのレプリケーションなど、ソフトウェアの層で分散する場合には、ローカルストレージを選択肢として取ることができます。
動作環境
k8sのノードが手元にある前提になります。筆者は以下の環境で構築しています。
- Windows11
- k8s on VM(Hyper-V)
- OS(VM): RHEL7
- k8s : v1.22.3
- OpenEBS : 3.0.0
- PostgreSQL : v14(pgbench)
インストール
公式マニュアルにある通りの手順でインストールしていきます。
ローカルストレージの中にも、hostPath, LVM, ZFS, blockdevice, rawfile
など複数の選択肢がありますが、今回は導入が簡易なhostPath
を使っていきたいと思います。
OpenEBSのインストール
OpenEBSのインストール自体は、以下のyamlをapply
するだけです。
kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml
STATUSがRunning
になるまで待ちます。
[root@k8s-master ~]# kubectl get pods -n openebs -l openebs.io/component-name=openebs-localpv-provisioner
NAME READY STATUS RESTARTS AGE
openebs-localpv-provisioner-6756f57d65-572r9 1/1 Running 0 2m2s
StorageClassが作成されていることの確認
local-hostpath
とopenebs-hostpath
が表示されます。
[root@k8s-master ~]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
openebs-device openebs.io/local Delete WaitForFirstConsumer false 2m16s
openebs-hostpath openebs.io/local Delete WaitForFirstConsumer false 2m16s
デフォルトストレージクラスの変更
デフォルトのストレージクラス
を変更しておきます。
[root@k8s-master ~]# kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
動作確認用Pod(Container)の作成
さて、上記PVCを使用するPostgreSQLコンテナを作成するのですが、色々方法があります。
- 任意のコンテナにPostgreSQLをインストール
- PostgreSQLのdockerイメージを使用する
- PostgreSQL Operatorを使用する
今回は3つめの方法で、StackGresのPostgreSQL Operator
を使って、PostgreSQLコンテナを作成します。
公式マニュアルのチュートリアルに従って、数ステップで構築します。(一部今回向けに変えてます)
PVCは後述するDBクラスタの作成
で、Operatorが作成してくれます。
Operatorインストール
Operatorをインストール
kubectl apply -f https://stackgres.io/downloads/stackgres-k8s/stackgres/1.0.0/stackgres-operator-demo.yml
STATUSがRunning
になるまで待ちます。
[root@k8s-master ~]# kubectl get pods -n stackgres -l group=stackgres.io
NAME READY STATUS RESTARTS AGE
stackgres-operator-658b86c697-wlmxd 1/1 Running 0 3m15s
stackgres-restapi-85b5fdf794-h44zt 2/2 Running 0 3m14s
インスタンスプロファイル作成
デフォルトのインスタンスプロファイル
はCPU:1、メモリ:2GBで小さすぎるので、インスタンスプロファイル
を別途作成します。
cat << 'EOF' | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGInstanceProfile
metadata:
name: size-l
spec:
cpu: "4"
memory: 6Gi
EOF
DBクラスタ作成
DBクラスタを作成する。今回はシングル構成とするため、instances: 1
とします。
[root@k8s-master ~]# cat << 'EOF' | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: simple
spec:
instances: 1
postgres:
version: 'latest'
pods:
persistentVolume:
size: '30Gi'
sgInstanceProfile: 'size-l'
EOF
STATUSがRunning
になるまで待ちます。
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
stackgres-operator-658b86c697-wlmxd 1/1 Running 0 3m15s
stackgres-restapi-85b5fdf794-h44zt 2/2 Running 0 3m14s
PVCも作成される。
[root@k8s-master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
simple-data-simple-0 Bound pvc-d3c500ce-a8b2-40f2-a3e1-7c822de479a3 30Gi RWO openebs-hostpath 8m18s
pgbenchの実行
コンテナに入って、pgbench
を実行します。
pgbench -i
の-s scalefactor
は1500(25GB程度)と大きめに設定し、VMに割り当てているメモリ8GBに対して、アクセスがメモリだけに留まらないよう設定しました。
[root@k8s-master ~]# kubectl exec simple-0 -it -- bash
bash-4.4$ createdb testdb
bash-4.4$ pgbench -i testdb -s 1500
一応shared_buffers
だけ変更しておきました。
bash-4.4$ psql testdb
testdb=# show shared_buffers;
shared_buffers
----------------
2GB
(1 row)
pgbenchを実行
bash-4.4$ pgbench -c 10 -t 1000 testdb
pgbench (14.0 OnGres Inc.)
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1500
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
latency average = 3.688 ms
initial connection time = 20.249 ms
tps = 2711.554095 (without initial connection time)
結果の比較
比較用にVM直下にpgbench
を導入してベンチマークしてみました。
微妙にPostgreSQLのバージョンが違いますがご容赦ください。
一応どちらの環境でも、OS再起動したり、pgbenchを複数回実行してみましたが、結果(latency average, tps)は殆ど変化ありませんでした。
VM直下でのベンチマーク
[user01@k8s-master ~]$ /usr/pgsql-14/bin/pgbench -c 10 -t 1000 testdb
pgbench (14.1)
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1500
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
latency average = 3.467 ms
initial connection time = 20.968 ms
tps = 2884.292288 (without initial connection time)
#まとめ
簡易な検証ですが、OpenEBSのローカルストレージの性能検証を行ってみました。
手元の環境では、VM直下で動作するpgbenchとの性能差異はあまり見受けられませんでした。
(負荷のかけ方が正しくないのかもしれないですが、、、)
今後は分散ストレージとどの程度、性能差が生じるのか確認してみようと思います。