1.3. Быстрый запуск

Shardman состоит из следующих программных компонентов:

  • СУБД PostgreSQL 14 с набором изменений.

  • Расширение Shardman.

  • Инструменты и сервисы управления, включая встроенный менеджер stolon для обеспечения отказоустойчивости.

Конфигурации Postgres Pro Shardman и stolon хранятся в кластере etcd, поэтому можно использовать существующий или развернуть новый простой кластер etcd с одним узлом.

Демон shardmand контролирует конфигурацию кластера Shardman и управляет кластерами stolon, которые обеспечивают отказоустойчивость сегментов. Общая конфигурация Shardman (shardmand, stolon) хранится в кластере etcd.

В настоящее время пакеты Shardman доступны для следующих ОС:

  • Ubuntu 20.04/22.04

  • Debian 10/11/12

  • Red Hat Enterprise Linux 7/8/9

  • РЕД ОС 7.3/7.3.1/7.3.2

  • Альт 9/10

  • Astra Linux «Смоленск» 1.7

1.3.1. Конфигурация кластера

Предположим, есть три узла для развёртывания Postgres Pro Shardman: один будет использоваться для кластера etcd с одним узлом, а два других — для кластера Postgres Pro Shardman с двумя узлами.

Допустим, у нас есть следующие имена узлов и IP-адреса:

192.0.1.1 etcd  - кластер etcd с одним узлом
192.0.1.20 sdm01 - первый узел Shardman
192.0.1.21 sdm02 - второй узел Shardman

Характеристики каждого узла: 4Gb RAM, 20GB HDD, 2CPU и ОС Ubuntu 22.04.

1.3.2. Подготовка

1.3.2.1. Добавление имён узлов в /etc/hosts

Этот шаг следует выполнить на всех узлах.

sudo /bin/sh -c 'cat << EOF >> /etc/hosts
192.0.1.1 etcd
192.0.1.20 sdm01
192.0.1.21 sdm02
EOF'

1.3.2.2. Синхронизация по времени

Этот шаг следует выполнить на всех узлах.

Установите и запустите демон chrony на всех узлах.

sudo apt install -y chrony

По умолчанию chrony получает время с доступных серверов в Интернете или с локального сервера времени. Проверить доступные серверы времени можно следующим образом:

chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^? 192.0.1.100                   1   6     7     1    -98us[  -98us] +/-   11ms
^* time.cloudflare.com           3   6     7     1   +139us[ +163us] +/-   11ms
^+ tms04.deltatelesystems.ru     1   6     7     1   -381us[ -357us] +/-   17ms

Желательно синхронизировать время с вашим сервером или локальным сервером для кластера. Для этого внесите в конфигурацию chrony следующие изменения:

cat /etc/chrony/chrony.conf

server 192.0.1.100 iburst
keyfile /etc/chrony.keys
driftfile /var/lib/chrony/chrony.drift
log tracking measurements statistics
logdir /var/log/chrony

systemctl restart chrony

Проверьте, что демон chrony подключён к нужному серверу.

chronyc sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^? 192.0.1.100                   8   6    17    37    +14us[  +70us] +/-  161us
chronyc tracking
Reference ID    : 0A80000C (ntp.local)
Stratum         : 9
Ref time (UTC)  : Wed Nov 15 11:58:52 2023
System time     : 0.000000004 seconds slow of NTP time
Last offset     : -0.000056968 seconds
RMS offset      : 0.000056968 seconds
Frequency       : 10.252 ppm fast
Residual freq   : -2.401 ppm
Skew            : 364.419 ppm
Root delay      : 0.000455358 seconds
Root dispersion : 0.010503666 seconds
Update interval : 2.1 seconds
Leap status     : Normal

1.3.3. Развёртывание кластера etcd с одним узлом

Рекомендуем также ознакомиться с Развёртывание кластера etcd с несколькими узлами.

Установите следующие пакеты:

sudo apt install -y vim curl

Для подключения общедоступного репозитория Postgres Pro Shardman выполните следующие шаги:

  • Запустите указанные скрипты:

    curl -fsSL -u "<user>:<password>" https://repo.postgrespro.ru/sdm/sdm-14/keys/pgpro-repo-add.sh > pgpro-repo-add.sh
    chmod +x pgpro-repo-add.sh
  • Откройте файл pgpro-repo-add.sh и укажите пароль от репозитория в переменной PASSWORD.

  • Запустите sudo pgpro-repo-add.sh.

Установите пакеты etcd-sdm:

sudo apt install -y etcd-sdm

Укажите значения переменных окружения в соответствующем файле:

sudo vim /etc/default/etcd-sdm
ETCD_NAME=etcd
ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
ETCD_ADVERTISE_CLIENT_URLS=http://192.0.1.1:2379
ETCD_MAX_SNAPSHOTS=5
ETCD_MAX_WALS=5
ETCD_AUTO_COMPACTION_MODE=periodic
ETCD_AUTO_COMPACTION_RETENTION=5m
ETCD_QUOTA_BACKEND_BYTES=6442450944
ETCD_DATA_DIR=/var/lib/etcd-sdm/sdm-14

Этот файл будет загружен при запуске etcd.

Очистите каталог данных etcd:

sudo rm -rf /var/lib/etcd-sdm/sdm-14/*

Перезапустите службу etcd-sdm:

sudo systemctl restart etcd-sdm

Для локального пользователя добавьте путь /opt/pgpro/sdm-14/bin в переменную окружения PATH:

echo "export PATH=$PATH:/opt/pgpro/sdm-14/bin" >> .bashrc
source .bashrc

Проверьте правильность конфигурации etcd:

etcdctl endpoint --endpoints=http://192.0.0.1:2379 status health -w table
+------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------------------------------+
|        ENDPOINT        |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX |             ERRORS             |
+------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------------------------------+
| http://10.5.48.50:2379 | 9324a99282752a09 |   3.5.9 |  2.1 GB |      true |      false |        14 |   91459207 |           91459207 |  memberID:10602785869456026121 |
|                        |                  |         |         |           |            |           |            |                    |                 alarm:NOSPACE  |
+------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------------------------------+

Кластер etcd с одним узлом правильно сконфигурирован и готов обрабатывать запросы.

Чтобы предотвратить раздувание при интенсивном использовании etcd, добавьте команду дефрагментации в cron:

sudo sh -c '
{ crontab -l; echo "@hourly /opt/pgpro/sdm-14/bin/etcdctl defrag"; }
| crontab'

1.3.4. Развёртывание узлов Shardman

Добавьте общедоступный репозиторий Postgres Pro Shardman на каждом узле:

  sudo curl -fsSL https://repo.postgrespro.ru/sdm/sdm-14/keys/pgpro-repo-add.sh | bash

Установите пакеты (на каждом узле):

  sudo apt update
  sudo apt install -y postgrespro-sdm-14-server postgrespro-sdm-14-client postgrespro-sdm-14-contrib postgrespro-sdm-14-libs pg-probackup-sdm-14  shardman-services shardman-tools

Предположим, выбранное имя кластера — cluster0. Следующий шаг — поместить переменные окружения Shardman в каталог /etcd/shardman (на каждом узле):

  sudo sh -c 'cat << EOF > /etc/shardman/shardmand-cluster0.env
  SDM_CLUSTER_NAME=cluster0
  SDM_LOG_LEVEL=info
  SDM_STORE_ENDPOINTS=http://etcd:2379
  EOF'

Для локального пользователя добавьте путь /opt/pgpro/sdm-14/bin в переменную окружения PATH:

echo "export PATH=$PATH:/opt/pgpro/sdm-14/bin" >> .bashrc
source .bashrc

Сгенерируйте пример конфигурации с помощью утилит Shardman (только на одном узле).

  shardmanctl config generate > spec.json

На этом шаге можно внести некоторые изменения в спецификацию (конфигурацию) кластера, например изменить пароль или параметр PostgreSQL shared_buffers и так далее.

1.3.5. Инициализация кластера Shardman

Осталось несколько последних шагов. Сначала инициализируйте конфигурацию кластера в etcd (только на одном [любом] узле).

  shardmanctl init -f spec.json

Ожидается такой результат:

  2023-04-18T12:30:03.043Z	DEBUG	cmd/common.go:100	Waiting for metadata lock...
  2023-04-18T12:30:03.048Z	DEBUG	cluster/cluster.go:365	DataDir is not specified, setting to default /var/lib/pgpro/sdm-14/data

Включите и запустите службу shardmand (на каждом узле):

  sudo systemctl enable --now shardmand@cluster0
  sudo systemctl status shardmand@cluster0
  ● shardmand@cluster0.service - deployment daemon for shardman
       Loaded: loaded (/lib/systemd/system/shardmand@.service; enabled; vendor preset: enabled)
       Active: active (running) since Tue 2023-04-18 12:28:18 UTC; 2min 13s ago
         Docs: https://github.com/postgrespro/shardman
     Main PID: 618 (shardmand)
        Tasks: 10 (limit: 4571)
       Memory: 32.0M
          CPU: 422ms
       CGroup: /system.slice/system-shardmand.slice/shardmand@cluster0.service
               └─618 /opt/pgpro/sdm-14/bin/shardmand --cluster-name cluster0 --system-bus --user postgres

1.3.6. Добавление узлов в кластер Shardman

На этом шаге предполагается, что все предыдущие шаги выполнены успешно: кластер etcd работает нормально, время на всех узлах синхронизировано, и демон запущен на sdm01 и sdm02. На последнем шаге выполняется команда shardmanctl:

  shardmanctl nodes add -n sdm01,sdm02 \
             --cluster-name cluster0 \
             --log-level debug \
             --store-endpoints=http://etcd:2379 

Ожидается такой результат:

  2023-04-18T12:43:11.300Z	DEBUG	cmd/common.go:100	Waiting for metadata lock...
  2023-04-18T12:43:11.306Z	INFO	cluster/store.go:277	Checking if shardmand on all nodes have applied current cluster configuration
  ✓ Waiting for shardmand on node sdm01 to apply current configuration: success 0.000s
  ✓ Waiting for shardmand on node sdm02 to apply current configuration: success 0.000s
  2023-04-18T12:43:11.307Z	INFO	add/case.go:112	Initting Stolon instances...
  2023-04-18T12:43:11.312Z	INFO	add/case.go:170	Waiting for Stolon daemons to start... make sure shardmand daemons are running on the nodes
  ✓ Waiting for Stolon daemons of rg clover-1-sdm01: success 31.012s
  ✓ Waiting for Stolon daemons of rg clover-1-sdm02: success 0.012s
  2023-04-18T12:43:42.336Z	INFO	add/case.go:187	Adding repgroups...
  ✓ waiting rg 1 config apply: done 7.014s
  2023-04-18T12:43:49.444Z	DEBUG	broadcaster/worker.go:33	start broadcaster worker for repgroup id=1
  2023-04-18T12:43:49.453Z	DEBUG	broadcaster/worker.go:51	repgroup 1 connect established
  2023-04-18T12:43:49.453Z	DEBUG	commands/addrepgroup.go:575	waiting for extension lock...
  2023-04-18T12:43:49.453Z	DEBUG	commands/addrepgroup.go:137	Loading schema into replication group rg 1
  ...
  2023-04-18T12:44:25.665Z	DEBUG	rebalance/service.go:528	wait all tasks finish
  2023-04-18T12:44:25.666Z	DEBUG	broadcaster/worker.go:75	finish broadcaster worker for repgroup id=1
  2023-04-18T12:44:25.666Z	DEBUG	broadcaster/worker.go:75	finish broadcaster worker for repgroup id=2
  2023-04-18T12:44:25.666Z	INFO	add/case.go:221	Successfully added nodes sdm01, sdm02 to the cluster

Сообщение «Successfully added nodes sdm01, sdm02 to the cluster» (Узлы sdm01, sdm02 успешно добавлены в кластер) означает, что всё в порядке и узлы sdm01 и sdm02 работают нормально.

1.3.7. Проверка состояния кластера Shardman

Проверьте состояние узлов кластера:

  shardmanctl status
  ┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                                        == STORE STATUS ==                                        │
  ├───────────┬──────────────────────────────────────────┬─────────────────────┬─────────────────────┤
  │   STATUS  │                  MESSAGE                 │  REPLICATION GROUP  │         NODE        │
  ├───────────┼──────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │  Warning  │ Store has only one member, consider      │                     │                     │
  │           │ deploying store cluster                  │                     │                     │
  └───────────┴──────────────────────────────────────────┴─────────────────────┴─────────────────────┘
  ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                                      == TOPOLOGY STATUS ==                                      │
  ├───────────┬─────────────────────────────────────────┬─────────────────────┬─────────────────────┤
  │   STATUS  │                 MESSAGE                 │  REPLICATION GROUP  │         NODE        │
  ├───────────┼─────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │   CROSS   │ Topology placement policy is CROSS      │                     │                     │
  └───────────┴─────────────────────────────────────────┴─────────────────────┴─────────────────────┘
  ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                                      == METADATA STATUS ==                                      │
  ├───────────┬─────────────────────────────────────────┬─────────────────────┬─────────────────────┤
  │   STATUS  │                 MESSAGE                 │  REPLICATION GROUP  │         NODE        │
  ├───────────┼─────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ Metadata is OK                          │                     │                     │
  └───────────┴─────────────────────────────────────────┴─────────────────────┴─────────────────────┘
  ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                                      == SHARDMAND STATUS ==                                     │
  ├───────────┬─────────────────────────────────────────┬─────────────────────┬─────────────────────┤
  │   STATUS  │                 MESSAGE                 │  REPLICATION GROUP  │         NODE        │
  ├───────────┼─────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ shardmand on node sdm01 is OK           │                     │        sdm01        │
  ├───────────┼─────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ shardmand on node sdm02 is OK           │                     │        sdm02        │
  └───────────┴─────────────────────────────────────────┴─────────────────────┴─────────────────────┘
  ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                                  == REPLICATION GROUP STATUS ==                                 │
  ├───────────┬─────────────────────────────────────────┬─────────────────────┬─────────────────────┤
  │   STATUS  │                 MESSAGE                 │  REPLICATION GROUP  │         NODE        │
  ├───────────┼─────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ Replication group clover-1-sdm01 is OK  │    clover-1-sdm01   │                     │
  ├───────────┼─────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ Replication group clover-1-sdm02 is OK  │    clover-1-sdm02   │                     │
  └───────────┴─────────────────────────────────────────┴─────────────────────┴─────────────────────┘
  ┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                                        == MASTER STATUS ==                                       │
  ├───────────┬──────────────────────────────────────────┬─────────────────────┬─────────────────────┤
  │   STATUS  │                  MESSAGE                 │  REPLICATION GROUP  │         NODE        │
  ├───────────┼──────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ Replication group clover-1-sdm01 master  │    clover-1-sdm01   │      sdm01:5432     │
  │           │ is running on sdm01:5432                 │                     │                     │
  ├───────────┼──────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ Replication group clover-1-sdm02 master  │    clover-1-sdm02   │      sdm02:5432     │
  │           │ is running on sdm02:5432                 │                     │                     │
  └───────────┴──────────────────────────────────────────┴─────────────────────┴─────────────────────┘
  ┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                                      == DICTIONARY STATUS ==                                     │
  ├───────────┬──────────────────────────────────────────┬─────────────────────┬─────────────────────┤
  │   STATUS  │                  MESSAGE                 │  REPLICATION GROUP  │         NODE        │
  ├───────────┼──────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ Replication group clover-1-sdm01         │    clover-1-sdm01   │                     │
  │           │ dictionary is OK                         │                     │                     │
  ├───────────┼──────────────────────────────────────────┼─────────────────────┼─────────────────────┤
  │     OK    │ Replication group clover-1-sdm02         │    clover-1-sdm02   │                     │
  │           │ dictionary is OK                         │                     │                     │
  └───────────┴──────────────────────────────────────────┴─────────────────────┴─────────────────────┘

1.3.8. Подключение к кластеру Shardman

Для подключения к кластеру получите строку подключения на любом узле кластера (sdm01 или sdm02):

  shardmanctl getconnstr

  dbname=postgres host=sdm01,sdm02 password=!!!CHANGE_ME!!! port=5432,5432 user=postgres

Затем попробуйте подключиться:

  psql -d 'dbname=postgres host=sdm01,sdm02 password=!!!CHANGE_ME!!! port=5432,5432 user=postgres'

  psql (14.7)
  Type "help" for help.

  postgres=#

1.3.9. Создание сегментированных таблиц

Создайте сегментированную таблицу и проверьте, всё ли работает корректно.

  postgres=# create table x(id int primary key, t text) with (distributed_by='id',num_parts=2);
  CREATE TABLE

  postgres=# \d
                   List of relations
    Schema |  Name   |       Type        |  Owner
   --------+---------+-------------------+----------
    public | x       | partitioned table | postgres
    public | x_0     | table             | postgres
    public | x_1_fdw | foreign table     | postgres
   (3 rows)

  postgres=# \d x_0
    Table "public.x_0"
    Column |  Type   | Collation | Nullable | Default
   --------+---------+-----------+----------+---------
    id     | integer |           | not null |
    t      | text    |           |          |
   Partition of: x FOR VALUES WITH (modulus 2, remainder 0)
   Indexes:
       "x_0_pkey" PRIMARY KEY, btree (id)

  postgres=# \d x_1_fdw
                   Foreign table "public.x_1_fdw"
   Column |  Type   | Collation | Nullable | Default | FDW options
  --------+---------+-----------+----------+---------+-------------
   id     | integer |           | not null |         |
   t      | text    |           |          |         |
  Partition of: x FOR VALUES WITH (modulus 2, remainder 1)
  Server: shardman_rg_2
  FDW options: (table_name 'x_1')

  postgres=# insert into x values (1,'t'),(2,'t'),(3,'t');
  INSERT 0 3

  postgres=# select * from x_0;
   id | t
  ----+---
    1 | t
    2 | t
  (2 rows)

  postgres=# select * from x_1_fdw;
   id | t
  ----+---
    3 | t
  (1 row)

Всё работает так, как и ожидалось.

1.3.10. Пример: развёртывание кластера etcd с несколькими узлами

В примере используются следующие серверы:

192.0.1.1 etcd1
192.0.1.2 etcd2
192.0.1.3 etcd3

Установите необходимые пакеты на каждом сервере:

sudo apt install -y vim curl

Для подключения к репозиторию запустите на каждом сервере следующую команду:

sudo curl -fsSL https://repo.postgrespro.ru/sdm/sdm-14/keys/pgpro-repo-add.sh | bash

Установите пакеты etcd-sdm на каждом сервере:

sudo apt install -y etcd-sdm

Для каждого сервера отредактируйте файл со списком переменных окружения, заменив местозаполнители в угловых скобках конкретными значениями:

sudo vim /etc/default/etcd-sdm
ETCD_NAME=<hostname>
ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
ETCD_ADVERTISE_CLIENT_URLS=http://<host ip address>:2379
ETCD_INITIAL_ADVERTISE_PEER_URLS=http://<host ip address>:2380
ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-1
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_MAX_SNAPSHOTS=5
ETCD_MAX_WALS=5
ETCD_AUTO_COMPACTION_MODE=periodic
ETCD_AUTO_COMPACTION_RETENTION=5m
ETCD_QUOTA_BACKEND_BYTES=6442450944
ETCD_DATA_DIR=/var/lib/etcd-sdm/sdm-14
ETCD_INITIAL_CLUSTER=etcd1=http://<ip etcd1>:2380,etcd2=http://<ip etcd2>:2380,etcd3=http://<ip etcd3>:2380

Этот файл будет загружен при запуске etcd со своими собственными параметрами запуска на каждом сервере.

Очистите каталог данных etcd:

sudo rm -rf /var/lib/etcd-sdm/sdm-14/*

Перезапустите службы etcd-sdm на каждом сервере:

sudo systemctl restart etcd-sdm

Для локального пользователя добавьте путь /opt/pgpro/sdm-14/bin в переменную окружения PATH:

echo "export PATH=$PATH:/opt/pgpro/sdm-14/bin" >> .bashrc
source .bashrc

Проверьте правильность конфигурации etcd:

etcdctl member list -w table
+------------------+---------+-------+----------------------------+----------------------------+------------+
|        ID        | STATUS  | NAME  |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-------+----------------------------+----------------------------+------------+
|  318be6342e6d9ac | started | etcd1 | http://192.0.1.1:2380      | http://192.0.1.1:2379      |      false |
| 9e49480544aedb89 | started | etcd2 | http://192.0.1.2:2380      | http://192.0.1.2:2379      |      false |
| bb3772bfa22482d7 | started | etcd3 | http://192.0.1.3:2380      | http://192.0.1.3.4:2379    |      false |
+------------------+---------+-------+----------------------------+----------------------------+------------+
$ etcdctl --endpoints=http://192.0.1.1:2380,http://192.0.1.2:2380,http://192.0.1.3:2380 endpoint status health  -w table
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|          ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://192.0.1.1:2380      |  318be6342e6d9ac |   3.5.9 |  5.7 MB |      true |      false |        13 |     425686 |             425686 |        |
| http://192.0.1.2:2380      | 9e49480544aedb89 |   3.5.9 |  5.7 MB |     false |      false |        13 |     425686 |             425686 |        |
|  http://192.0.1.3:2380     | bb3772bfa22482d7 |   3.5.9 |  5.7 MB |     false |      false |        13 |     425686 |             425686 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
-------+

Кластер etcd правильно сконфигурирован и готов обрабатывать запросы.

Чтобы предотвратить раздувание при интенсивном использовании etcd, добавьте команду дефрагментации в cron:

sudo { crontab -l; echo "@hourly /opt/pgpro/sdm-14/bin/etcdctl defrag"; } | crontab

Последняя строка с границами кластера etcd:

etcd1=http://<ip etcd1>:2380,etcd2=http://<ip etcd2>:2380,etcd3=http://<ip etcd3>:2380
        

Её следует указать в файле конфигурации /etc/shardman и в качестве параметра --store-endpoints shardmanctl.