umnのtechブログかも

なんか書くかも

k8s上にクラスタリングされたPostgreSQLをデプロイする

この記事はFJCT アドベントカレンダー 2019の6日目の記事です。

明日は @tunakyonnさんの m3dbの知見をまとめてみた となります。

最近k8sを触り始めて、postgres-operatorを使ってみたので簡単な導入方法と使い方をまとめました。

postgres operatorを使う

今回使うのはCrunchyDataのpostgres-operatorです
Operatorそのものについては、こちらの記事などが参考になるかなと思います。
今回取り上げるもの以外にもpostgresのoperatorはいくつかあり、OperatorHubで調べるといくつか出てきます。

環境情報

  • Ubuntu18.04
  • kubernetes v1.16.0
  • pgo client version 4.1.1
  • pgo-apiserver version 4.1.1

Install

postgres-operator本体とpgo clientの2つをインストールする

postgres-operator installについて

  • 公式ドキュメントを見たい方はこちら
    • 上記の公式ドキュメントにまとまっているが、修正点などをも含めてここにも書く
  • 今回はbashのほうでやったがAnsible版もある

postgres-operator install手順

プロジェクトのクローン

$ go get  https://github.com/CrunchyData/postgres-operator.git
$ cd postgres-operator
$ git checkout v4.1.1

環境変数の設定

export PGOROOT=$GOPATH/src/github.com/CrunchyData/postgres-operator.git

pgoという名前でオペレーターのnamespaceを作成

$ export PGO_OPERATOR_NAMESPACE=pgo
$ make setupnamespaces

権限まわりの設定をする

$ make installrbac

ストレージを設定する

  • 必要なstorage classやらpersistent volumeといったリソースは事前に作成する
  • $GOPATH/src/github.com/crunchydata/postgres-operator/conf/postgres-operator/pgo.yamlのStorage内に利用するStorageの定義を書く。
PrimaryStorage: ncnas
BackupStorage: ncnas
ReplicaStorage: ncnas
BackrestStorage: ncnas
Storage:
  ncnas:
    AccessMode:  ReadWriteOnce
    Size: 5G
    StorageType:  dynamic
    StorageClass: nfs
    Fsgroup:  26

manifestファイルが最新のk8sに追従できていないため、以下のように修正する

  • deployment.jsonAPIバージョンをextensions/v1beta1からapps/v1
  • deployment.jsonspec配下にselectorの追加が必要。deploy/service.jsonServiceと同じ名前を設定する
{
    "apiVersion": "apps/v1",
    "kind": "Deployment",
    "metadata": {
        "name": "postgres-operator"
    },
    "spec": {
        "replicas": 1,
        "selector": {
            "matchLabels": {
                "name": "postgres-operator"
            }
        },
        "template": {
            "metadata": {
                "labels": {
                    "name": "postgres-operator"
                }
            },
            "spec": {

オペレーターのデプロイ

make deployoperator

確認:以下のリソースが作成されてればOK

$ kubectl get all -n pgo
NAME                                     READY   STATUS    RESTARTS   AGE
pod/postgres-operator-7c8489cf7f-t4srj   4/4     Running   0          12m

NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/postgres-operator   ClusterIP   10.98.238.169   <none>        8443/TCP,4171/TCP,4150/TCP   12m

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/postgres-operator   1/1     1            1           12m

NAME                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/postgres-operator-7c8489cf7f   1         1         1       12m

pgo CLI install手順

postgres-operatorの各種操作はpgo CLIを通して行うのが一般的とのこと
postgres-operatorとpgo CLIは同じバージョンにする必要がある

CLIが認証に使うpgouserファイル作成

  • kubectl get secrets -n pgo pgouser-pgoadmin -o yamlbase64 エンコードされたパスワードが格納されているのでdecodeすることで確認可能
echo pgoadmin:examplepassword  >  $HOME/.pgouser

APIサーバのURLを環境変数に追加

$ kubectl get service postgres-operator -n pgo
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
postgres-operator   ClusterIP   10.98.238.169   <none>        8443/TCP,4171/TCP,4150/TCP   1h

$ export PGO_APISERVER_URL=https://{Cluster-IP}:8443
$ export PGO_CLIENT_CERT=$GOPATH/src/github.com/crunchydata/postgres-operator/conf/postgres-operator/server.crt
$ export PGO_CLIENT_KEY=$GOPATH/src/github.com/crunchydata/postgres-operator/conf/postgres-operator/server.key

Releaseページから目的のCLIをインストール

wget https://github.com/CrunchyData/postgres-operator/releases/download/v4.1.1/pgo -P /usr/local/bin

port-forwardしてAPIへアクセスできるようにする

kubectl port-forward -n pgo srv/postgres-operator 8443

APIと疎通できるか確認

$ pgo version
pgo client version 4.1.1
pgo-apiserver version 4.1.1

使ってみる

pgo create namespace pgouser

とりあえずclusterの構築

  • デフォルトだとprimaryuser,testusertestdbが作成されている
pgo create cluster testcluster -n pgouser 

確認

$ kubectl get pod -n pgouser
NAME                                                READY   STATUS      RESTARTS   AGE
testcluster-6c9d87d968-lj6cw                        1/1     Running     0          3m43s
testcluster-backrest-shared-repo-7b55b46cb4-xjxzq   1/1     Running     0          3m43s
testcluster-stanza-create-zdnxp                     0/1     Completed   0          2m55s

psqlに入ってみる

$ kubectl -n pgouser get secrets testcluster-primaryuser-secret -oyaml
apiVersion: v1
data:
  password: xxxxxx  <- 実際はbase64でエンコードされた値が入っている
  username: yyyyyy

$ echo xxxxxx== | base64 --decode  
$ echo yyyyyy== | base64 --decode
$ kubectl -n pgouser get service
NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                AGE
testcluster                        ClusterIP   10.99.241.170   <none>        5432/TCP,10000/TCP,2022/TCP,9187/TCP   25m

$ psql -h {CLUSTER-IP} -U testuser -d userdb
psql (10.10 (Ubuntu 10.10-0ubuntu0.18.04.1), server 12.1)
Type "help" for help.

userdb=>

オプション付きで構築

レプリカを追加して、フェイルオーバーをTrueにする

pgo create cluster testcluster --autofail=true --replica-count=2 -n pgouser

1リソース確認

$ kubectl get pod -n pgouser
NAME                                                READY   STATUS      RESTARTS   AGE
testcluster-65455c8bd5-qjdbz                        1/1     Running     0          32m  <- primary
testcluster-backrest-shared-repo-7b55b46cb4-fkzd6   1/1     Running     0          32m
testcluster-ewwu-8f5845f6f-d29qv                    1/1     Running     0          32m  <- replica
testcluster-stanza-create-qswbv                     0/1     Completed   0          32m
testcluster-vzdp-75544c9689-w2dwl                   1/1     Running     0          32m  <- replica

レプリカの追加

$ pgo scale testcluster -n pgouser

pgpool作成

$ pgo create pgpool testcluster -n pgouser

クラスタ情報の確認

$ pgo show cluster testcluster  -n pgouser
cluster : testcluster (crunchy-postgres:centos7-12.1-4.1.1)
        pod : testcluster-65455c8bd5-qjdbz (Running) on kubenode002 (1/1) (primary)
        pvc : testcluster
        pod : testcluster-ewwu-8f5845f6f-d29qv (Running) on kubenode002 (1/1) (replica)
        pvc : testcluster-ewwu
        pod : testcluster-pgpool-fff889dd-v665z (Running) on kubenode002 (1/1) (pgpool)
        pod : testcluster-qbes-86c845b74d-d59qp (Running) on kubenode002 (1/1) (replica)
        pvc : testcluster-qbes
        pod : testcluster-vzdp-75544c9689-w2dwl (Running) on kubenode002 (1/1) (replica)
        pvc : testcluster-vzdp
        resources : CPU Limit= Memory Limit=, CPU Request= Memory Request=
        storage : Primary=5G Replica=5G
        deployment : testcluster
        deployment : testcluster-backrest-shared-repo
        deployment : testcluster-ewwu
        deployment : testcluster-pgpool
        deployment : testcluster-qbes
        deployment : testcluster-vzdp
        service : testcluster - ClusterIP (10.99.241.170)
        service : testcluster-pgpool - ClusterIP (10.107.152.16)
        service : testcluster-replica - ClusterIP (10.108.233.42)
        replica : testcluster-ewwu
        replica : testcluster-qbes
        replica : testcluster-vzdp
        labels : autofail=true crunchy-pgbadger=false crunchy_collect=false pgouser=pgoadmin workflow-id=0cd5f497-da08-46bb-bd63-15db3fafdc12 pgo-backrest=true pgo-version=4.1.1 archive-timeout=60 current-primary=testcluster deployment-name=testcluster name=testcluster pg-cluster=testcluster

使ってみて

  • 負荷分散のために使いたかったpgpoolとかバックアップとリストアをするpgBackRestとか含めて楽に構築できて便利だった
    • なんとなく--autofail=trueでRepilicaがPrimaryに昇格するのかインスタンス落として確認したけどちゃんと動いてたし(当たり前だけど)
  • api versionが古かったりするのが気になる
  • cluster作成時に読み込まれているconfigのこともちゃんとわかってない所あるのでもうちょい調べる必要がある