PostgreSQL: запуск в Kubernetes з PostgreSQL Operator та моніторинг з Prometheus

Автор |  21/09/2022
 

Отже, Друід ми запустили – див. Apache Druid: огляд, запуск в Kubernetes та моніторинг з Prometheus. Поки що в дефолтному вигляді, тобто в ролі сторейджа для метаданих використовується локальна база Apache Derby.

Далі будемо переключати Друід на PostgreSQL, ще згодом – прибирати звідти ZooKeeper.

Ну а для початку – запустимо кластер PostgreSQL в Kubernetes, додамо PostgreSQL Exporter для Promethues, та налаштємо збір метрік.

Запускати знову будемо в Minikube, для PostgreSQL використаємо Zalando Operator, а Експортер будемо запускати у вигляді sidecar container.

Глибоко копати в Оператор поки що не будемо, хоча він дуже цікавий, тож якось з ним побавимося. Наразі, нам треба лише його моніторинг.

Документація – Administrator Guide.

Запуск PostgreSQL оператора

Створюємо неймспейс:

[simterm]

$ kubectl create ns postgres-operator
namespace/postgres-operator created

[/simterm]

Додаємо Хельм-репозіторій:

[simterm]

$ helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator

[/simterm]

Встановлюємо сам оператор:

[simterm]

$ helm -n postgres-operator install postgres-operator postgres-operator-charts/postgres-operator

[/simterm]

За бажанням додаємо WebUI для оператора:

[simterm]

$ helm repo add postgres-operator-ui-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator-ui
$ helm -n postgres-operator install postgres-operator-ui postgres-operator-ui-charts/postgres-operator-ui

[/simterm]

Перевіряємо поди:

[simterm]

$ kubectl -n postgres-operator get pods
NAME                                    READY   STATUS    RESTARTS   AGE
postgres-operator-649799f4bd-dz5bl      1/1     Running   0          82s
postgres-operator-ui-5cfff55c65-v4bjj   1/1     Running   0          22s

[/simterm]

Вікриваємо собі доступ до Сервісу веб-морди Оператора:

[simterm]

$ kubectl port-forward svc/postgres-operator-ui 8081:80
Forwarding from 127.0.0.1:8081 -> 8081
Forwarding from [::1]:8081 -> 8081

[/simterm]

Перевіряємо:

Тут ми нічого робити не будемо – візьмемо готові приклади конфігу кластера.

Запуск PostgreSQL кластеру

Клонуємо репозіторій:

[simterm]

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

[/simterm]

В каталозі manifests є декілька прикладів, візьмемо собі manifests/minimal-master-replica-svcmonitor.yaml – він описує неймспейс, кластер-юзерів-бази, два Service та два ServiceMonitors + Sidecars с Prometheus Exporter.

Застосовуємо його:

[simterm]

$ kubectl apply -f manifests/minimal-master-replica-svcmonitor.yaml
namespace/test-pg created
postgresql.acid.zalan.do/acid-minimal-cluster created
service/acid-minimal-cluster-svc-metrics-master created
service/acid-minimal-cluster-svc-metrics-replica created
servicemonitor.monitoring.coreos.com/acid-minimal-cluster-svcm-master created
servicemonitor.monitoring.coreos.com/acid-minimal-cluster-svcm-replica created

[/simterm]

Перевіряєм кластер:

[simterm]

$ kk -n test-pg get postgresql
NAME                   TEAM   VERSION   PODS   VOLUME   CPU-REQUEST   MEMORY-REQUEST   AGE     STATUS
acid-minimal-cluster   acid   13        2      1Gi                                     2m21s   Running

[/simterm]

Та його поди:

[simterm]

$ kk -n test-pg get po
NAME                     READY   STATUS    RESTARTS   AGE
acid-minimal-cluster-0   2/2     Running   0          37s
acid-minimal-cluster-1   1/2     Running   0          24s

[/simterm]

У кожного є своя роль, яка задається в лейблах – spilo-role=master або spilo-role=replica.

PostgreSQL users

Див. доки тут>>> та тут>>>.

Юзери описуються в блоці – сюрпрайз – users:

[simterm]

$ kubectl -n test-pg get postgresql -o yaml
...
    users:
      foo_user: []
      zalando:
      - superuser
      - createdb
...

[/simterm]

І для кожного з них створюється окремий Kubernetes Secret:

[simterm]

$ kk -n test-pg get secret
NAME                                                                 TYPE     DATA   AGE
foo-user.acid-minimal-cluster.credentials.postgresql.acid.zalan.do   Opaque   2      38m
postgres.acid-minimal-cluster.credentials.postgresql.acid.zalan.do   Opaque   2      38m
standby.acid-minimal-cluster.credentials.postgresql.acid.zalan.do    Opaque   2      38m
zalando.acid-minimal-cluster.credentials.postgresql.acid.zalan.do    Opaque   2      38m

[/simterm]

Які потім мапляться в поди через змінні:

[simterm]

$ kubectl -n test-pg get statefulsets acid-minimal-cluster -o yaml
...
      - env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        - name: POSTGRES_USER
          value: postgres
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              key: password
              name: postgres.acid-minimal-cluster.credentials.postgresql.acid.zalan.do
...

[/simterm]

Ну і перевіримо.

Отримаємо пароль:

[simterm]

$ kubectl -n test-pg get secret postgres.acid-minimal-cluster.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d
CcWdAaqvPA8acxwIpVyM8UHkds2QG3opC3KD7rO1TxITQ1q31cwYLTswzfBeTVsN

[/simterm]

Відкриваємо порт:

[simterm]

$ kubectl -n test-pg port-forward acid-minimal-cluster-0 6432:5432

[/simterm]

Логінимося, та перевіряємо бази:

[simterm]

$ psql -U postgres -h localhost -p 6432
Password for user postgres: 
psql (14.5, server 13.7 (Ubuntu 13.7-1.pgdg18.04+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# \l
                                  List of databases
   Name    |   Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+-----------+----------+-------------+-------------+-----------------------
 bar       | bar_owner | UTF8     | en_US.utf-8 | en_US.utf-8 | 
 foo       | zalando   | UTF8     | en_US.utf-8 | en_US.utf-8 | 
 postgres  | postgres  | UTF8     | en_US.utf-8 | en_US.utf-8 | 
 template0 | postgres  | UTF8     | en_US.utf-8 | en_US.utf-8 | =c/postgres          +
           |           |          |             |             | postgres=CTc/postgres
 template1 | postgres  | UTF8     | en_US.utf-8 | en_US.utf-8 | =c/postgres          +
           |           |          |             |             | postgres=CTc/postgres
(5 rows)

postgres=#

[/simterm]

PostgreSQL Prometheus Exporter

Див. Sidecar definitions.

Сайдкар ми вже маємо – доданий із маніфесту, і в кожному поді наразі маємо два контейнери – самого PostgreSQL, та його Експортера:

[simterm]

$ kk -n test-pg get po acid-minimal-cluster-0 -o jsonpath='{.spec.containers[*].name}'
postgres exporter

[/simterm]

Глянемо чи є там метріки – відкриваємо порт:

[simterm]

$ kubectl -n test-pg port-forward svc/acid-minimal-cluster-svc-metrics-master 9187:9187
Forwarding from 127.0.0.1:9187 -> 9187
Forwarding from [::1]:9187 -> 9187

[/simterm]

І бачимо, що нічого не бачимо, а кластер взагалі “мертвий” – pg_up == 0:

[simterm]

$ curl -s localhost:9187/metrics | grep pg_ | grep -v '#'
pg_exporter_last_scrape_duration_seconds 1.00031302
pg_exporter_last_scrape_error 1
pg_exporter_scrapes_total 9
pg_up 0

[/simterm]

Чому – тому що експортер має мати дані доступу, тобто логін-пароль.

В конфізі сайдкару додаємо нові змінні, див. Environment Variables:

...
      env:
      - name: "DATA_SOURCE_URI"
        value: "$(POD_NAME)/postgres?sslmode=require"
      - name: "DATA_SOURCE_USER"
        value: "$(POSTGRES_USER)"
      - name: "DATA_SOURCE_PASS"
        value: "$(POSTGRES_PASSWORD)"
      - name: "PG_EXPORTER_AUTO_DISCOVER_DATABASES"
        value: "true"
...

Тобто, Оператор створює StatefulSet, в якому задає змінні POSTGRES_USER та POSTGRES_PASSWORD, які ми використовуємо для сайдкару, щоб задати його власні змінні.

Зберігаємо, оновлюємо:

[simterm]

$ kubectl apply -f manifests/minimal-master-replica-svcmonitor.yaml

[/simterm]

Перевіряємо змінні в самому поді:

[simterm]

$ kubectl -n test-pg get po acid-minimal-cluster-0 -o yaml
...
  - env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    - name: POD_NAMESPACE
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.namespace
    - name: POSTGRES_USER
      value: postgres
    - name: POSTGRES_PASSWORD
      valueFrom:
        secretKeyRef:
          key: password
          name: postgres.acid-minimal-cluster.credentials.postgresql.acid.zalan.do
    - name: DATA_SOURCE_URI
      value: $(POD_NAME)/postgres?sslmode=require
    - name: DATA_SOURCE_USER
      value: $(POSTGRES_USER)
    - name: DATA_SOURCE_PASS
      value: $(POSTGRES_PASSWORD)
    - name: PG_EXPORTER_AUTO_DISCOVER_DATABASES
      value: "true"
...

[/simterm]

Та знову перевіряємо мектріки в експортері:

[simterm]

$ curl -s localhost:9187/metrics | grep pg_ | grep -v '#' | tail -5
pg_stat_replication_pg_current_wal_lsn_bytes{application_name="acid-minimal-cluster-0",client_addr="172.17.0.17",server="acid-minimal-cluster-1:5432",slot_name="182",state="streaming"} 1.52655344e+08
pg_stat_replication_pg_wal_lsn_diff{application_name="acid-minimal-cluster-0",client_addr="172.17.0.17",server="acid-minimal-cluster-1:5432",slot_name="182",state="streaming"} 0
pg_stat_replication_reply_time{application_name="acid-minimal-cluster-0",client_addr="172.17.0.17",server="acid-minimal-cluster-1:5432",slot_name="182",state="streaming"} 1.663625745e+09
pg_static{server="acid-minimal-cluster-1:5432",short_version="13.7.0",version="PostgreSQL 13.7 (Ubuntu 13.7-1.pgdg18.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit"} 1
pg_up 1

[/simterm]

pg_up == 1 – йай! Іт воркс!

Prometehus ServiceMonitors

Відкриваємо порт для доступу до самого Prometheus:

[simterm]

$ kubectl -n monitoring port-forward svc/kube-prometheus-stack-prometheus 9090:9090
Forwarding from 127.0.0.1:9090 -> 9090
Forwarding from [::1]:9090 -> 9090

[/simterm]

Перевіряємо Status > Service Discovery – PostgreSQL тут не бачимо:

СервісМонітори також були створені із маніфесту:

[simterm]

$ kubectl -n test-pg get servicemonitor
NAME                                AGE
acid-minimal-cluster-svcm-master    65m
acid-minimal-cluster-svcm-replica   65m

[/simterm]

Повторюємо “грязний хак”, як робили для Друіда – додаємо в них label "release": "kube-prometheus-stack", чекаємо хвилину-дві, и перевіряємо ще раз:

Та маємо метріки в графіках:

Готово.