LoginSignup
1
1

More than 3 years have passed since last update.

Rook + Ceph & Postgres Operator でクラスタ内 PostgresQLを実現する

Posted at

この記事は、
softdeviceのみんなでゆるく記事を書く。 Advent Calendar 2020
の12/2分の記事として公開しています。

はじめに

kubernetes を使用してHA クラスタを組み始めると、その他の HA ではない部分 が気になってきます。
僕のケースでは、メインデータベースの PostgresQL がクラスタの外部にあり、いくら kubernetes が HA 構成になっていても、データベースが単一障害点に成り得る状況でした。

この状況を回避するため、Rook + Ceph でクラスタストレージを構成し、その上に Postgres OperatorPostgresQL データベースを構築する事を目指します。

kubernetes の HA クラスタを作る方法は、以前書いた記事がありますので、構築方法をお探しの方は見て見てみてください。

1. Rook + Ceph

まずは、土台である Rook + Ceph を設定していきます。
そもそも Rook + Ceph とは、ざっくりと(雑に)言うと、S3とかGCSみたいな分散型ストレージをオンプレミス環境で使う事が出来るOSS といったところでしょうか。
もちろん使い方は S3GCS とは全く違うのですが、データをクラスタの中に分散させて保管しておく事で冗長性の高いストレージを実現できます。

前準備

インストールの前に、以下に記載されている要件を満たす必要があります。

https://rook.io/docs/rook/v1.5/ceph-prerequisites.html
https://rook.io/docs/rook/v1.5/k8s-pre-reqs.html

色々な環境があると思いますが、僕は以下の点だけ対応しました。

ディスクを追加

Cephディスクの要件として、

  • 生のディバイス (パーティション無し、未フォーマット)
  • 生のパーティション (未フォーマット)
  • ブロックモードのストレージクラスから利用可能な PersistentVolume

を要求されます。
今回使用するクラスタは ESXi で動いているので、さくっと新規ドライブを追加しました。

インストール

公式の手順通りに進めていきますが、とても簡単です。
https://rook.io/docs/rook/v1.4/ceph-quickstart.html

gitからrookをcloneします。
https://github.com/rook/rook/releases

git clone --single-branch --branch release-1.4 https://github.com/rook/rook.git

examples に入っている以下の2つの yaml を適用します。

cd rook/cluster/examples/kubernetes/ceph
kubectl create -f common.yaml
kubectl create -f operator.yaml

ここまで実行したら、rook-ceph-operatorREADY になるまで待ちます。

kubectl -n rook-ceph get pod

NAME                                  READY   STATUS    RESTARTS   AGE
rook-ceph-operator-5668d7cd54-8q788   1/1     Running   0          36s
rook-discover-m8jzz                   1/1     Running   0          34s
rook-discover-sxkm8                   1/1     Running   0          34s
rook-discover-ttdwk                   1/1     Running   0          34s

READY になったら、最後の以下のコマンドを実行します。

kubectl create -f cluster.yaml

実際の使用は次の Postgres Operator の項目で行うとして、基本的な設定はこれで完了です!

ダッシュボード

cephにはダッシュボードがついているのですが、クラスタの中からしか見れません。
これを外向けにするには、以下のようなyamlを使用します。

dashboard-external-https.yaml
apiVersion: v1
kind: Service
metadata:
  name: rook-ceph-mgr-dashboard-external-https
  namespace: rook-ceph
  labels:
    app: rook-ceph-mgr
    rook_cluster: rook-ceph
spec:
  ports:
  - name: dashboard
    port: 8443
    protocol: TCP
    targetPort: 8443
    nodePort: 31443
  selector:
    app: rook-ceph-mgr
    rook_cluster: rook-ceph
  sessionAffinity: None
  type: NodePort
kubectl apply -f  dashboard-external-https.yaml

ページにアクセスすると認証を求められますが、パスワードは以下で取得できます。

kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo

ユーザー名は admin です。

(削除)

もし何らかの理由でクラスタを削除したい場合、ただ単に namespace を削除したりするだけではだめで、以下の手順に従う必要があります。

一番重要なのは、クラスタで使用したディスクを初期化する必要がある、というところですね。
VMを使用している場合は、仮想ディスクを削除してもう一度追加したら良いのですが、そうでない場合は以下のコマンドでディスクをクリアします。

#!/usr/bin/env bash
DISK="/dev/sdb"
# Zap the disk to a fresh, usable state (zap-all is important, b/c MBR has to be clean)
# You will have to run this step for all disks.
sgdisk --zap-all $DISK
# Clean hdds with dd
dd if=/dev/zero of="$DISK" bs=1M count=100 oflag=direct,dsync
# Clean disks such as ssd with blkdiscard instead of dd
blkdiscard $DISK

# These steps only have to be run once on each node
# If rook sets up osds using ceph-volume, teardown leaves some devices mapped that lock the disks.
ls /dev/mapper/ceph-* | xargs -I% -- dmsetup remove %
# ceph-volume setup can leave ceph-<UUID> directories in /dev (unnecessary clutter)
rm -rf /dev/ceph-*

2. Postgres Operator

Rook + Ceph の設定が終わったら、その上に Postgres Operator を設定していきます。

インストール

こちらも公式の手順に従ってやっていきます。
https://access.crunchydata.com/documentation/postgres-operator/4.4.1/quickstart/

インストーラーマニフェストをDLしてきます。

curl https://raw.githubusercontent.com/CrunchyData/postgres-operator/v4.4.1/installers/kubectl/postgres-operator.yml > postgres-operator.yml

今回は Rook を使用して構成するので、DLしてきた設定ファイル内の以下の項目を rook に設定します。

   backrest_storage: "rook"
   backup_storage: "rook"
   primary_storage: "rook"
   replica_storage: "rook"

設定ファイルを適用します。
名前空間 pgo が必要になるので、併せて作成します。

kubectl create namespace pgo
kubectl apply -f postgres-operator.yml

これで kubernetes 内の準備は出来ましたが、この中に PostgresQL のクラスタを作るには専用のコマンドが必要になります。
このインストーラも提供されているので、DLしてきて権限を付与し、実行します。

curl https://raw.githubusercontent.com/CrunchyData/postgres-operator/v4.4.1/installers/kubectl/client-setup.sh > client-setup.sh
chmod +x client-setup.sh
./client-setup.sh

このコマンドは、~/.pgo ディレクトリを作ってその中に必要なデータをインストールするので、パスを通しておきます。また、その他必要な環境変数を登録しておきます。

cat <<EOF >> ~/.bashrc
export PATH=${HOME?}:$PATH
export PGOUSER="${HOME?}/.pgo/pgo/pgouser"
export PGO_CA_CERT="${HOME?}/.pgo/pgo/client.crt"
export PGO_CLIENT_CERT="${HOME?}/.pgo/pgo/client.crt"
export PGO_CLIENT_KEY="${HOME?}/.pgo/pgo/client.key"
export PGO_APISERVER_URL='https://127.0.0.1:9443'
export PGO_NAMESPACE=pgo
EOF

source ~/.bashrc

クイックスタートでは PGO_APISERVER_URL の箇所でポートが 8443 となっていますが、僕の環境ではそのポートは kubernetes で使用していたので、変更しました。

基本的にインストール作業はここで完了ですが、クイックスタートの通りインストールの確認をしてみます。

kubectl -n pgo get deployments

NAME                READY   UP-TO-DATE   AVAILABLE   AGE
postgres-operator   1/1     1            1           61d
kubectl -n pgo get pods

NAME                                 READY   STATUS    RESTARTS   AGE
postgres-operator-5fbcccf9b5-svrpz   4/4     Running   0          3h51m

Postgres クラスタ作成

確認が終わったら、実際にクラスタを作っていきますが、その前に Rook を使ったストレージクラスを作ります。

storageclass-pgo.yaml
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
  name: postgres-replicapool
  namespace: rook-ceph
spec:
  failureDomain: host
  replicated:
    size: 3
    requireSafeReplicaSize: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: postgres-rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
    clusterID: rook-ceph
    pool: postgres-replicapool
    imageFormat: "2"
    imageFeatures: layering
    csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
    csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
    csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
    csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
    csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
    csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
    csi.storage.k8s.io/fstype: ext4
allowVolumeExpansion: true
reclaimPolicy: Retain
kubectl apply -f storageclass-pgo.yaml

ストレージクラスを作成した後 pgo コマンドを使用するのですが、そのためにはポートフォワーディングが必要になります。以下のコマンドでフォワーディングしますが、このコマンドはフォアグラウンドで実行されるので別ウィンドウで実行する必要があります。

kubectl -n pgo port-forward svc/postgres-operator 9443:8443

ポートフォワーディングされている間 pgo コマンドが使えます。早速 test という名前のクラスタを作ってみます。
~/.bashrcPGO_NAMESPACE を定義しているので、名前空間を省略するとそこで設定した値が使用されます。

pgo create cluster test

created cluster: test
workflow id: ca0bd585-c37e-4595-8f4f-8614e993905b
database name: test
users:
        username: testuser password: r+[pN>@+AU=}xOD{h4Ee)G/f

若干時間がかかりますが、以下のコマンドで状況を確認できます。Services も Instances も UP になったら完了です。

pgo test test

cluster : test
        Services
                primary (10.102.60.6:5432): UP
        Instances
                primary (test-76989b6696-vrb59): UP

このままだとクラスタ外から接続できないので、サービスの設定を変更します。

kubectl edit svc test -n pgo

(省略)
spec:
  clusterIP: 10.102.60.6
  ports:
  - name: sshd
    port: 2022
    protocol: TCP
    targetPort: 2022
  - name: postgres
    nodePort: 30001 # <- 追加
    port: 5432
    protocol: TCP
    targetPort: 5432
  selector:
    pg-cluster: test
    role: master
  sessionAffinity: None
  type: NodePort # <- ClusterIP から変更

NodePortは、30000~32767である必要があります。
これで保存すると、外部から接続できるようになります。以下のコマンドで接続できます。パスワードは、Postgresクラスタを作成した時に表示されるものを使用してください。

docker run --rm -it postgres psql postgres -h <ノードのip> -U testuser --password -p 30001

psql (13.1 (Debian 13.1-1.pgdg100+1), server 12.4)
Type "help" for help.

postgres=>

これで、クラスタ内に PostgresQL を構築する事が出来ました。

おわりに

分散ストレージやHA構成のDBは kubernetes よりももっと前からあった技術ですが、学習コストが高く、それぞれをHA化しようと思うと相当な学習が必要になります。
今回の方法であれば、 kubernetes をある程度学習するとその知識の範囲で構成する事が出来るため、それぞれを別々の技術として学ぶよりも学習コストが低いと思われます。また、 kubernetes が動く環境であればどこでも動くというのもメリットです。

僕もただ動かしているだけでそこまで深い理解には至っていないですが、この記事が他の同じような課題を抱えている人の一助になれば幸いです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1