ry's Tech blog

Cloud Native技術などについて書いていきます。

Zalando ~ installation ~

Zalando

Zalandoとは、Kubernetes 上に HA 構成の PostgreSQL クラスタを構築するための Operatorです。 S3などを用いたバックアップなども可能になっています。

今回は簡単にインストールから実際に動くまでをご紹介させていただきます。

Zalando Operatorのデプロイ

まず、Gitレポジトリをクローンしてきます。

# git clone https://github.com/zalando/postgres-operator.git
# cd postgres-operator

それでは、Zalando Operatorをインストールしてきます。

Namespace

# kubectl create ns postgres
namespace/postgresql created

Configmap

# kubectl create -f manifests/configmap.yaml -n postgres
configmap/postgres-operator created

プライベートレジストリーからimageをpullする場合はdocker_image (1番下)を変更します。

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-operator
data:
  # additional_secret_mount: "some-secret-name"
  # additional_secret_mount_path: "/some/dir"
  api_port: "8080"
  aws_region: eu-central-1
  cluster_domain: cluster.local
  cluster_history_entries: "1000"
  cluster_labels: application:spilo
  cluster_name_label: cluster-name
  # custom_service_annotations: "keyx:valuez,keya:valuea"
  # custom_pod_annotations: "keya:valuea,keyb:valueb"
  db_hosted_zone: db.example.com
  debug_logging: "true"
  # default_cpu_limit: "1"
  # default_cpu_request: 100m
  # default_memory_limit: 500Mi
  # default_memory_request: 100Mi
  # docker_image: registry.opensource.zalan.do/acid/spilo-12:1.6-p2
  docker_image: harbor.pks.local/postgres/container:1.6-p2

RBAC設定

operator-service-account-rbac.yamlのnamespaceがdefaultになっているので書き換えます。

# vi operator-service-account-rbac.yaml
◯ 1か所目
apiVersion: v1
kind: ServiceAccount
metadata:
  name: postgres-operator
  namespace: postgres

◯ 2か所目
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: postgres-operator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: postgres-operator
subjects:
- kind: ServiceAccount
  name: postgres-operator
  namespace: postgres

それでは作成していきます。

# kubectl create -f manifests/operator-service-account-rbac.yaml
serviceaccount/postgres-operator created
clusterrole.rbac.authorization.k8s.io/postgres-operator created
clusterrolebinding.rbac.authorization.k8s.io/postgres-operator created
clusterrole.rbac.authorization.k8s.io/postgres-pod created

Operator

必要に応じて、imageをプライベートレジストリーに変えてください。

# kubectl create -f manifests/postgres-operator.yaml -n postgres
deployment.apps/postgres-operator created

$ kubectl create -f manifests/api-service.yaml -n postgres
service/postgres-operator created


# kubectl get all
NAME                                     READY   STATUS    RESTARTS   AGE
pod/postgres-operator-6fbd4d876c-bqvpg   1/1     Running   0          10m


NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/postgres-operator   ClusterIP   10.100.200.157   <none>        8080/TCP   10s


NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/postgres-operator   1/1     1            1           5h3m

NAME                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/postgres-operator-6fbd4d876c   1         1         1       5h3m

Zalando Operator UIのデプロイ

以下、3つのmanifestのNamespaceを変更して、適用していきます。

Service Account

# vi ui/manifests/ui-service-account-rbac.yaml
◯ 1か所目
apiVersion: v1
kind: ServiceAccount
metadata:
  name: postgres-operator-ui
  namespace: postgres


◯ 2か所目
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: postgres-operator-ui
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: postgres-operator-ui
subjects:
- kind: ServiceAccount
  name: postgres-operator-ui
  namespace: postgres


# kubectl apply -f ui/manifests/ui-service-account-rbac.yaml
serviceaccount/postgres-operator-ui created
clusterrole.rbac.authorization.k8s.io/postgres-operator-ui created
clusterrolebinding.rbac.authorization.k8s.io/postgres-operator-ui created

Deployment

Deployment の namespaceをpostgresに書き換えます。 ※必要に応じてimage をPrivate Repositoryのものに書き換えてください。

# kubectl apply -f ui/manifests/deployment.yaml
deployment.apps/postgres-operator-ui created

Service

以下の様に書き換えて、適用します。

apiVersion: "v1"
kind: "Service"
metadata:
  name: "postgres-operator-ui"
  namespace: "postgres"
  labels:
    application: "postgres-operator-ui"
spec:
  type: "LoadBalancer"
  selector:
    application: "postgres-operator-ui"
  ports:
    - port: 80
      protocol: "TCP"
      targetPort: 8081


# kubectl apply -f ui/manifests/service.yaml
service/postgres-operator-ui created

ここまでで、以下のようになっています。

# kubectl get all
NAME                                        READY   STATUS    RESTARTS   AGE
pod/postgres-operator-6fbd4d876c-bqvpg      1/1     Running   0          71m
pod/postgres-operator-ui-776899996c-ln9q5   1/1     Running   0          81s


NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
service/postgres-operator      ClusterIP      10.100.200.157   <none>          8080/TCP       61m
service/postgres-operator-ui   LoadBalancer   10.100.200.147   <External IP>   80:31474/TCP   7s


NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/postgres-operator      1/1     1            1           6h4m
deployment.apps/postgres-operator-ui   1/1     1            1           81s

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/postgres-operator-6fbd4d876c      1         1         1       6h4m
replicaset.apps/postgres-operator-ui-776899996c   1         1         1       81s

それではGUIにアクセスしていきます。

zalando
zalando

PostgreSQL Clusterの作成

GUIからの「Create cluster」では、Namaspaceがdefaultなので、 Cluster YAML definitionのmanifestをコピーし、CLIから作成していきます。

# vi postgres-manifest.yaml

kind: "postgresql"
apiVersion: "acid.zalan.do/v1"
metadata:
  name: "acid-my-cluster"
  namespace: postgres
  labels:
    team: acid
spec:
  teamId: "acid"
  postgresql:
    version: "13"
  numberOfInstances: 2
  enableMasterLoadBalancer: true
  volume:
    size: "30Gi"
  resources:
    requests:
      cpu: 100m
      memory: 100Mi
    limits:
      cpu: 500m
      memory: 500Mi


# kubectl apply -f postgres-manifest.yaml
postgresql.acid.zalan.do/acid-my-cluster created

#kubectl get pods,svc
NAME                                        READY   STATUS    RESTARTS   AGE
pod/acid-my-cluster-0                       1/1     Running   0          7m2s
pod/acid-my-cluster-1                       1/1     Running   0          6m9s
pod/postgres-operator-76b5fd66d-lf758       1/1     Running   0          27m
pod/postgres-operator-ui-5478dcfd7b-4cp6h   1/1     Running   0          21m

NAME                             TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)          AGE
service/acid-my-cluster          LoadBalancer   10.3.242.170   <External IP>     5432:30043/TCP   7m2s
service/acid-my-cluster-config   ClusterIP      None           <none>            <none>           6m6s
service/acid-my-cluster-repl     ClusterIP      10.3.241.48    <none>            5432/TCP         7m2s
service/postgres-operator        ClusterIP      10.3.255.23    <none>            8080/TCP         19m
service/postgres-operator-ui     LoadBalancer   10.3.243.36    <External IP>    80:32504/TCP     22m

では、アクセスしてみます。

# kubectl exec -it pod/acid-my-cluster-0 -- psql -U postgres
psql (13.1 (Ubuntu 13.1-1.pgdg18.04+1))
Type "help" for help.

postgres=# 

データの挿入

実際にデータを書き込んでみます。

postgres=# create database hatest;
CREATE DATABASE
postgres=# \c hatest
You are now connected to database "hatest" as user "postgres".
hatest=# 
hatest=# create table hatest (name text);
CREATE TABLE
hatest=# insert into hatest values ('test');
INSERT 0 1
hatest=# select * from hatest;
 name 
------
 test
(1 row)

Replica側から書き込みをしてみます。

# kubectl exec -it pod/acid-my-cluster-1 -- psql -U postgres 
psql (13.1 (Ubuntu 13.1-1.pgdg18.04+1))
Type "help" for help.

postgres=# 
postgres=# \c hatest
You are now connected to database "hatest" as user "postgres".
hatest=# 
hatest=# select * from hatest;
 name 
------
 test
(1 row)

hatest=# 
hatest=# insert into hatest values ('test2');
ERROR:  cannot execute INSERT in a read-only transaction

参照はできましたが、書き込みができないことを確認することができました。