
Итак, Друид мы запустили. 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", ждем минуту-две, и перепроверяем:
И пошли метрики в графиках:
Готово.









