PostgreSQL в Azure. Часть 1

Этой статьей мы начинаем цикл заметок об использовании PostgreSQL в Microsoft Azure.

Первая статья будет об установке и настройке кластера PostgreSQL:


  • Знакомство с ресурсами Azure
  • Управление через azure cli
  • Выбор подходящего хранилища
  • Сборка классической связки ведущий-ведомый в одной группе доступности

Задача этой части — реализовать схему, включающую следующие компоненты, ресурсы Azure:
Принципиальная схема

Делать мы будем это при помощи azure cli. Вы можете не устанавливать azure-cli и сделать все через веб-интерфейс portal.azure.com, но управление и создание через cli мне показалось более наглядным.

Утилита azure cli кроссплатформенная и работает везде, где можно работает nodejs. Установить ее под linux можно так:

# dnf install npm || apt-get install npm
NPM_CONFIG_PREFIX=~/.npm-global npm install -g 'git://github.com/Azure/azure-xplat-cli.git#v0.9.20-April2016'
echo 'NPM_PACKAGES="$HOME/.npm-global"' >> ~/.bash_profile
echo 'export PATH="$PATH:$NPM_PACKAGES/bin"' >> ~/.bash_profile

Ознакомиться с основными командами azure cli можно здесь. Все последующие команды azure cli запускаются с вашего рабочего компьютера. Начнем с того, что нам необходимо представиться системе и получить токен:

azure login

Подробнее про способы авторизации можно прочитать здесь.

Создаем группу ресурсов (контейнер ресурсов) в Северной Европе:

azure group create --name pg-resource-group --location northeurope

Создаем виртуальную локальную сеть 10.0.0.0/8 и подсеть 10.0.0.0/24:

azure network vnet create -g pg-resource-group -l northeurope --address-prefixes 10.0.0.0/8 --name pg-vnet
azure network vnet subnet create -g pg-resource-group --vnet-name pg-vnet --address-prefix 10.0.0.0/24 --name pg-vnet-subnet

Так как управлять мы собираемся через ssh по внешнему ip-адресу, создаем правила сетевого экрана и разрешаем подключения извне только к 22 порту:

azure network nsg create -g pg-resource-group -l northeurope --name pg-nsg
azure network nsg rule create -g pg-resource-group --nsg-name pg-nsg --name AllowSSH --protocol Tcp --access Allow --destination-port-range 22 --priority 200 --direction Inbound

Настраиваем внешний ip-адрес (public-ip), сетевой адаптер с приватной сетью и подсеть для ведущего:

azure network public-ip create -g pg-resource-group -l northeurope --allocation-method Static --name pg-public-1
azure network nic create -g pg-resource-group -l northeurope --subnet-name pg-vnet-subnet --subnet-vnet-name pg-vnet --private-ip-address 10.0.0.101 --network-security-group-name pg-nsg --name pg-nic-1

Создаем группу доступности. Вкратце это кластер машин, разделенный на группы (домены), которые не могут быть недоступны одновременно:

azure availset create -g pg-resource-group -l northeurope --name pg-availability-set

Подробнее про группы доступности можно прочитать здесь.

Настало время настройки виртуальной машины. Доступные типы виртуальных машин и их ограничения можно узнать через команду:

azure vm sizes -l northeurope

В списке будет более 50 типов машин, с ценами можно ознакомиться здесь. К более дешевым можно подключить меньшее количество дисков (общее количество дисков может быть от 1 до 40). Для тестирования мастера выбран Standard_DS4_v2: 8 CPU, 28GB RAM, к которому можно подключить до 16 дисков premium storage.

Команда создания виртуальной машины, которая подразумевает пользователя pg с sudo-правами и разрешеным входом по ssh с применением ssh-ключа:

azure vm create -g pg-resource-group -l northeurope --nic-name pg-nic-1 --os-type Linux --image-urn OpenLogic:CentOS:7.2:latest --admin-username pg --ssh-publickey-file ~/.ssh/id_rsa.pub --vm-size Standard_DS4_v2 --public-ip-name pg-public-1 --availset-name pg-availability-set --name pg-1

Посмотреть параметры созданной машины, а также внешние ip, можно через команду:

azure vm show -g pg-resource-group --name pg-1

Теперь мы имеем виртуальную машину с установленной CentOS 7.2, запущенной в приватной виртуальной сети pg-vnet с ip-адресом 10.0.0.101 и публичным pg-public-1, по которому мы можем попасть на ssh извне. Необходимо создать диск, на котором будут расположены данные нашего PostgreSQL. Про различные типы хранилищ можно почитать тут. Для начала представим результаты нашего тестирования хранилища:

Производительность различных типов хранилищ

Создадим аккаунт хранилища Premium LRS с именем pgplrs (оно должно быть уникальным в пределах azure):

azure storage account create -g pg-resource-group -l northeurope --type PLRS pgplrs

Создадим диск и подключим его к виртуальной машине:

azure vm disk attach-new -g pg-resource-group -l northeurope --vm-name pg-1 --lun 1 --size-in-gb 512 --vhd-name pgdata-1 --host-caching ReadOnly --storage-account-name pgplrs

Создадим и запустим виртуальную машину pg-2:

azure network public-ip create -g pg-resource-group -l northeurope --allocation-method Static --name pg-public-2
azure network nic create -g pg-resource-group -l northeurope --subnet-name pg-vnet-subnet --subnet-vnet-name pg-vnet --private-ip-address 10.0.0.102 --network-security-group-name pg-nsg --name pg-nic-2
azure vm create -g pg-resource-group -l northeurope --nic-name pg-nic-2 --os-type Linux --image-urn OpenLogic:CentOS:7.2:latest --admin-username pg --ssh-publickey-file ~/.ssh/id_rsa.pub --vm-size Standard_DS4_v2 --public-ip-name pg-public-1 --availset-name pg-availability-set --name pg-2
azure vm disk attach-new -g pg-resource-group -l northeurope --vm-name pg-2 --lun 1 --size-in-gb 512 --vhd-name pgdata-2  --host-caching ReadOnly --storage-account-name pgplrs
azure vm start -g pg-resource-group pg-2

Теперь мы можем подключиться по ssh к pg-1 под пользователем pg:

ssh pg-public-1 -l pg -i ~/.ssh/id_rsa

Все дальнейшие действия мы будем выполнять на машине pg-1. Сразу после подключения диска нужно его сопоставить с физическим блочным устройством, доступным на виртуальной машине. Для этого запускаем команду:

[root@pg-1 ~] $ dmesg | tail -n 10
[  488.417024] Adjusting hyperv_clocksource more than 11% (1945964553 vs 1862270976)
[  525.969741] scsi 5:0:0:0: Direct-Access     Msft     Virtual Disk     1.0  PQ: 0 ANSI: 4
[  526.001471] sd 5:0:0:0: Attached scsi generic sg3 type 0
[  526.018792] sd 5:0:0:0: [sdc] 1073741824 512-byte logical blocks: (549 GB/512 GiB)
[  526.039690] sd 5:0:0:0: [sdc] 4096-byte physical blocks
[  526.053643] sd 5:0:0:0: [sdc] Write Protect is off
[  526.065818] sd 5:0:0:0: [sdc] Mode Sense: 0f 00 10 00
[  526.065985] sd 5:0:0:0: [sdc] Write cache: enabled, read cache: enabled, supports DPO and FUA
[  526.091754]  sdc: unknown partition table
[  526.105263] sd 5:0:0:0: [sdc] Attached SCSI disk

Из этих сообщений можно понять, что имя блочного устройства, назначенного подключенному диску: /dev/sdc. Создаем на нем файловую систему:

[root@pg-1 ~] $ mkfs.ext4 /dev/sdc
mke2fs 1.42.9 (28-Dec-2013)
/dev/sdc is entire device, not just one partition!
Proceed anyway? (y,n) y

Теперь мы должны создать запись в fstab. Получаем UUID устройства:

[root@pg-1 ~] $ blkid /dev/sdc
/dev/sdc: UUID="8cb25a32-175b-4c78-b557-8153327d48ba" TYPE="ext4"

И монтируем диск, предварительно создав точку монтирования и добавив запись в fstab:

[root@pg-1 ~] $ mkdir -p /var/lib/pgsql
[root@pg-1 ~] $ echo 'UUID=8cb25a32-175b-4c78-b557-8153327d48ba /var/lib/pgsql  ext4  defaults  0 0' >> /etc/fstab
[root@pg-1 ~] $ mount -a

Пришло время установки софта, подключаем репозиторий:

[root@pg-1 ~] $ rpm -ivh http://repo.postgrespro.ru/pgpro-9.5/keys/postgrespro-9.5.centos95.noarch.rpm

Устанавливаем софт:

[root@pg-1 ~] $ yum install postgrespro95-server postgrespro95-contrib

Включаем сервис и инициализируем экземпляр СУБД:

[root@pg-1 ~] $ chkconfig postgresql-9.5 on
[root@pg-1 ~] $ service postgresql-9.5 initdb
[root@pg-1 ~] $ service postgresql-9.5 start

Дальнейшие команды мы будем выполнять под пользователем postgres:

[root@pg-1 ~] $ su -l postgres

Разрешаем подключение к серверу в pg_hba с ip 10.0.0.101–102 для репликации:

[postgres@pg-1 ~] $ echo 'host  replication  replication  10.0.0.101/30  md5'  >> /var/lib/pgsql/9.5/data/pg_hba.conf

Создаем пользователя для репликации:

[postgres@pg-1 ~] $ /usr/pgsql-9.5/bin/psql -U postgres postgres

postgres=$ CREATE ROLE replication WITH REPLICATION PASSWORD 'password' LOGIN;
CREATE ROLE

Выставляем параметры, позволяющие использовать эту машинку как ведущий сервер для репликации:

[postgres@pg-1 ~] $ /usr/pgsql-9.5/bin/psql -U postgres postgres

postgres=$ alter system set listen_addresses to '*';
ALTER SYSTEM
postgres=$ alter system set wal_level to hot_standby;
ALTER SYSTEM
postgres=$ alter system set max_wal_senders to 3;
ALTER SYSTEM
postgres=$ alter system set wal_keep_segments to 128;
ALTER SYSTEM

Проверяем, применены ли параметры:

postgres=$ select * from pg_file_settings where not applied;
                  sourcefile                  | sourceline | seqno |       name       |   setting   | applied
----------------------------------------------+------------+-------+------------------+-------------+---------
 /var/lib/pgsql/9.5/data/postgresql.auto.conf |          3 |    20 | wal_level        | hot_standby | f
 /var/lib/pgsql/9.5/data/postgresql.auto.conf |          4 |    21 | max_wal_senders  | 3           | f
 /var/lib/pgsql/9.5/data/postgresql.auto.conf |          6 |    23 | listen_addresses | *           | f
(3 rows)

Перезапускаем службу:

[postgres@pg-1 ~] $ /usr/pgsql-9.5/bin/pg_ctl restart -D /var/lib/pgsql/9.5/data -w

Теперь мы можем подключиться по ssh к pg-2 под пользователем pg:

ssh pg-public-2 -l pg -i ~/.ssh/id_rsa

Все дальнейшие команды мы выполняем на машине pg-2. Пришло время заняться репликой: аналогично подключаем диск и устанавливаем postgrespro. И выполняем вход на pg-2 под пользователем postgres:

[root@pg-2 ~] $ su -l postgres

После этого подготавливаем реплику одной командой:

[postgres@pg-2 ~] $ /usr/pgsql-9.5/bin/pg_basebackup -U replication -D /var/lib/pgsql/9.5/data -R -x -P -c spread -h 10.0.0.101 -W
Password:
38895/38895 kB (100%), 1/1 tablespace

Теперь у нас есть полная копия в /var/lib/pgsql/9.5/data и прописанный файл recovery.conf, в который рекомендую добавить информацию о файле-триггере, при создании которого этот экземпляр СУБД из ведомого превратится в полноценный ведущий сервер. Таким образом, содержимое файла будет такое:

[postgres@pg-2 ~] $ cat /var/lib/pgsql/9.5/data/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=replication password=password host=10.0.0.101 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres'
trigger_file = '/var/lib/pgsql/stop_replication_trigger'

Запускаем экземпляр с репликой:

[postgres@pg-2 ~] $ /usr/pgsql-9.5/bin/pg_ctl start -w -D /var/lib/pgsql/9.5/data

И проверяем, запущен ли приёмник WAL (процесс wal receiver):

[postgres@pg-2 ~] $ ps axufwwww
postgres 29423  0.1  0.2 372920 16564 ?        S    09:07   0:00 /usr/pgsql-9.5/bin/postmaster -D /var/lib/pgsql/9.5/data
postgres 29425  0.0  0.0 225568  1608 ?        Ss   09:07   0:00  \_ postgres: logger process
postgres 29426  0.1  0.0 372960  2464 ?        Ss   09:07   0:00  \_ postgres: startup process   recovering 0000010000000000000003
postgres 29427  0.0  0.0 372920  1964 ?        Ss   09:07   0:00  \_ postgres: checkpointer process
postgres 29428  0.0  0.0 372920  1976 ?        Ss   09:07   0:00  \_ postgres: writer process
postgres 29429  0.2  0.0 379640  3360 ?        Ss   09:07   0:00  \_ postgres: wal receiver process   streaming 0/3000060

Итого мы имеем две виртуальные машины, между которыми настроена потоковая асинхронная репликация, работающая в одной группе доступности. В следующей части статьи мы обсудим резервные копии и балансировку клиентов.

Ждите продолжения!

© Habrahabr.ru