Master-slave конфигурации PostgreSQL в Docker

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 22:26, 19 сентября 2018.
Master-Slave
Cau-hinh-postgresql-replication-master-slave.jpg
Разработчики: Python
Состояние разработки: Активное
Написана на: Python
Операционная система: Linux
Локализация: Английский язык
Веб-сайт master-slave

Описание Master-Slave

C английского Master&Slave переводится как «ведущий-ведомый». То есть в схеме один элемент является ведущим, а остальные, подключенные к главному элементы, – ведомыми.

В зависимости от количества устройств такая схема напоминает звезду или последовательное соединение, где сигналы slave-устройств направлены в одну точку master.

Эта схема подключения используется в таких сферах как IT, связь, электроника и автоматика.

Ведущее устройство(англ. Master — букв. «господин») — главное устройство в сети, которое может самостоятельно запрашивать данные у ведомых устройств, или рассылать широковещательные сообщения.

В сетях, работающих по принципу ведущий - ведомые (Master—Slave), только ведущее устройство может инициировать передачу данных и определяет порядок доступа к сети.[Источник 1] Встречаются термины «мастер-устройство», «устройство-мастер», «Master».

Master-slave

В одной сети может быть несколько ведущих устройств, тогда сеть называется многомастерной. Многомастерную технологию используют сети Profibus. Многомастерная система требует определения порядка доступа мастеров к сети. Например, в сетях Profibus используется метод передачи маркера (англ. token), по идее аналогичный применяемому в сетях Token ring, но зависящий не от топологического расположения мастеров в сети, а от сетевого адреса мастера. Одно ведомое устройство в сети с несколькими мастерами должно иметь только одного конкретного мастера.Ведущее устройство вместе с назначенными ему ведомыми составляют Мастер-систему. Конфигурация Мастер-системы обычно известна на стадии проектирования.

Master-slave

Технологию обмена Master-Slave поддерживают многие сетевые протоколы, в частности:
Profibus PA
Modbus
INTERBUS
PROFINET IO
SERCOS III

Технология Master-Slave может быть сопоставлена с технологией клиент-сервер, причём Master эквивалентен клиенту (активный партнёр), а Slave - серверу (пассивный партнёр), однако обратными являются количественные отношения в системе Master-Slave один активный партнёр и несколько пассивных. В системе "Клиент-сервер" обычно несколько активных партнёров приходится на один пассивный сервер.

PosgreSQL

PostgreSQL, или postgres – это популярная система управления базами данных (СУБД), предназначенная для систематизации и управления данными сайта или приложения. Репликация — это метод обеспечения высокой доступности и отказоустойчивости БД путём копирования информации из базы данных на вторую систему. [Источник 2]

Существует множество способов настройки репликации в PostgreSQL. Я приведу один из них

Для этого понадобится два виртуальных выделенных сервера Ubuntu 12.04. Один из них будет ведущим сервером (master), а второй – ведомым (slave), который и будет выполнять репликацию БД главного сервера.

Как работает docker

Создание образа

Сначала создаем docker image (или образ). Он создается при помощи скрипта, который для этого пишем. Образы наследуются и, для создания своего первого образа мы берём готовый образ и наследуем от него. В данном случае, образ в котором содержится та или иная версия linux.

Скрипт начинается так:
FROM ubuntu:16.04 

Далее при помощи директивы RUN мы можем исполнять любые команды, которые поддерживает этот линукс. Например

RUN apt-get install -y mc установит в наш образ midnight commander.

Кроме этого при помощи директивы COPY., мы можем копировать в наш образ любые локальные файлы Например:

 COPY mzoo.war /opt/tomcat/webapps/ROOT.war 
Докер поддерживает очень много различных директив. Например, директива USER roman указывает докеру, что все следующие директивы нужно выполнять из под пользователя roman. А директива
 ENTRYPOINT [“/opt/tomcat/catalina.sh”] 
задает исполняемый файл, который будет запускаться при старте.

То есть, создаём скрипт, называем его Dockerfile и запускаем команду docker build, docker выполняет скрипт и создает image.

Если есть ошибки, исправление скрипта происходит на этапе создания image. На этапе установки скрипт уже не используется. [Источник 3]

Создание контейнера

Когда у нас уже есть docker image можно создать из него контейнер на любом физическом сервере, где установлен докер. Если image – это тиражируемый образ некоторой «машины», то container это уже сама «машина», которую можно запускать и останавливать.

Создание контейнера

Важный момент — при создании контейнера из image, его можно параметризовать. Можго передавать докеру переменные окружения, которые он использует при создании контейнера из image. Так есть возможность создавать немного разные машины из одного образа. Например, передать образу web-сервера его доменное имя.

Есть возможность «упаковки» в один контейнер ровно одного постоянно работающего серверного процесса. Этот процесс работает на уровне физического сервера и честно регулируется установленной там операционной системой.

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

Vargant

Vagrant (с англ. — «бродяга») — свободное и открытое программное обеспечение для создания и конфигурирования виртуальной среды разработки. Является оболочкой для программного обеспечения виртуализации, например VirtualBox, и средств управления конфигурациями, такими как Chef, Salt и Puppet. [Источник 4]

Vagrant .configure ( ' 2 ' ) сделать | config |

  config.vm.box =  ' bento / ubuntu-16.04 '

  config.vm.network ' private_network ' , введите:  ' DHCP '

  % Вес (
    Докер-1
    Докер-2
    Докер-3
  ) .each do | host_name |
    config.vm.define host_name do | хост |

      host.vm.hostname = имя_хоста

      # install Docker
      host.vm.provision ' докер '

    конец

  конец
  
конец

Тест на идемпотентность

[vagrant@192.168.1.85] Executing task 'update'<br />
[vagrant@192.168.1.86] Executing task 'update'<br />
[vagrant@192.168.1.87] Executing task 'update'<br />
[vagrant@192.168.1.85] Found master: 192.168.1.85<br />
[vagrant@192.168.1.85] download: <file obj> <- /data/postgresql.conf<br />
[vagrant@192.168.1.85] /data/postgresql.conf not changed<br />
[vagrant@192.168.1.85] download: <file obj> <- /data/pg_hba.conf<br />
[vagrant@192.168.1.86] Waiting for master info (10 seconds)...<br />
[vagrant@192.168.1.85] /data/pg_hba.conf not changed<br />
[vagrant@192.168.1.85] run: docker inspect --type container postgres<br />
[vagrant@192.168.1.87] Waiting for master info (10 seconds)...<br />
[vagrant@192.168.1.85] run: docker inspect --type image postgres:9.6<br />
[vagrant@192.168.1.85] run: docker start postgres<br />
[vagrant@192.168.1.86] download: <file obj> <- /data/recovery.conf<br />
[vagrant@192.168.1.87] download: <file obj> <- /data/recovery.conf<br />
[vagrant@192.168.1.87] /data/recovery.conf not changed<br />
[vagrant@192.168.1.86] /data/recovery.conf not changed<br />
[vagrant@192.168.1.87] download: <file obj> <- /data/postgresql.conf<br />
[vagrant@192.168.1.86] download: <file obj> <- /data/postgresql.conf<br />
[vagrant@192.168.1.87] /data/postgresql.conf not changed<br />
[vagrant@192.168.1.86] /data/postgresql.conf not changed<br />
[vagrant@192.168.1.86] download: <file obj> <- /data/pg_hba.conf<br />
[vagrant@192.168.1.87] download: <file obj> <- /data/pg_hba.conf<br />
[vagrant@192.168.1.87] /data/pg_hba.conf not changed<br />
[vagrant@192.168.1.86] /data/pg_hba.conf not changed<br />
[vagrant@192.168.1.87] run: docker inspect --type container postgres<br />
[vagrant@192.168.1.86] run: docker inspect --type container postgres<br />
[vagrant@192.168.1.87] run: docker inspect --type image postgres:9.6<br />
[vagrant@192.168.1.86] run: docker inspect --type image postgres:9.6<br />
[vagrant@192.168.1.87] run: docker start postgres<br />
[vagrant@192.168.1.86] run: docker start postgres<br />
[vagrant@192.168.1.87] No changes detected, update skipped.<br />
[vagrant@192.168.1.85] No changes detected, update skipped.<br />
[vagrant@192.168.1.86] No changes detected, update skipped.<br />

Done.
Disconnecting from vagrant@127.0.0.1:2222... done.<br />
Disconnecting from vagrant@127.0.0.1:2200... done.<br />
Disconnecting from vagrant@127.0.0.1:2201... done.<br />

Fabricio

Fabricio — модуль, который расширяет стандартные возможности Fabric, добавляя в него функционал для работы с контейнерами Docker. Разработка Fabricio позволила нам перестать думать о сложности реализации автоматического деплоя и целиком сосредоточиться на решении поставленных бизнес-задач.

Fabricio: настройка развертывания master-slave-сервера PostgreSQL

Эта конфигурация основана на потоковой репликации PostgreSQL .

Требования

Fabricio 0.4.2 или выше
Vagrant
Один из списка поддерживаемых Vagrant провайдеров (этот пример был протестирован с VirtualBox )

файлы

fabfile.py , конфигурация Fabricio
pg_hba.conf , настройка проверки подлинности клиента PostgreSQL
postgresql.conf , основная конфигурация PostgreSQL
README.md , этот файл
recovery.conf , настройка восстановления PostgreSQL
Vagrantfile , Vagrant config

Создание виртуальных машин

Запустите vagrant up , и подождите, пока не будут созданы виртуальные машины.

Список доступных команд

 fab --list
развертывание
 --parallel

параметр должен быть указан во всех случаях. Этот режим используется для автоматического определения текущего местоположения ведущего устройства.

С нуля
 fab --parallel db

Этот случай будет использоваться в первый раз.

Ошибка мастера

Чтобы инициировать новое продвижение мастера, можно уничтожить VM с текущим мастером и снова запустить развертывание:

  1. vagrant destroy <name_of_the_VM_with_current_master>
  2. fab --parallel db<br />

Это приведет к новому продвижению мастера.

Добавление нового подчиненного

Добавьте новое определение виртуальной машины Vagrantfile и снова выполните развертывание:


 fab --parallel db 


от Фабрисио импорта задач

от fabricio.misc import Доступен VagrantHosts

db = tasks.DockerTasks (
    service = StreamingReplicatedPostgresqlContainer (
        name = ' postgres ' ,
        image = ' postgres: 10-alpine ' ,
        pg_data = ' / data ' ,
        pg_recovery_master_promotion_enabled = Верно ,
        sudo = Правда ,
        options = dict (
            volume = ' / data: / data ' ,
            env = ' PGDATA = / data ' ,
            опубликовано = ' 5432: 5432 ' ,
        ),
    ),
    hosts = AvailableVagrantHosts ( guest_network_interface = ' eth1 ' ),
    destroy_command = Правда ,
)

Начало работы

Пример конфигурации master-slave для PostgreSQL реализован на трех виртуальных машинах, в которых установлен Docker. Создание и первоначальная настройка этих виртуальных машин полностью автоматизированы при помощи Vagrant.

Настройка Master-Slave репликации в PostgreSQL

Репликация — это метод обеспечения высокой доступности и отказоустойчивости БД путём копирования информации из базы данных на вторую систему. Рассмотрим настройку Master-Slave репликацию для СУБД Postgresql.

Настройка будет проводиться на двух серверах с операционной системой Ubuntu16.04. Имена серверов Master - postgres-node1(10.25.128.172), Slave postgres-node2(10.25.128.109).

Настройка Master-сервера

Устанавливаем Postgresql

Добавим репозиторий postgresql, создадим файл /etc/apt/sources.list.d/pgdg.list и пропишем в него репозиторий

 deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main 

Добавляем ключ

 root@postgres-node1:~# wget --quiet -O - \  

https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -

Синхронизируем репозитории

root@postgres-node1:~# apt-get update

Ставим пакет postgresql-9.6

 root@postgres-node1:~# apt-get install postgresql-9.6 

Запускаем демона и добавляем в автозагрузку

 root@postgres-node1:~# systemctl start postgresql<br />

root@postgres-node1:~# systemctl enable postgresql 

На файерволе необходимо разрешить соединения на порту 5432 (порт по-умолчанию для postgresql)

 root@postgres-node1:~# iptables -A INPUT -p tcp --dport 5432 -j ACCEPT 

Настройка Postgresql

Правим основной конфигурационный файл /etc/postgresql/9.6/main/postgresql.conf

 root@postgres-node1:~# vim /etc/postgresql/9.6/main/postgresql.conf  
  1. Указываем ip-адреса, на которых postgresql будет принимать запросы
listen_addresses = "*"

port = 5432

# Добавляет информацию необходимую для запуска только 
#запросов на чтение на резервный сервер

wal_level = replica

#Использование локальной синхронизации

synchronous_commit = local

#Включение архивирования

archive_mode = on

#Команда для выполнения архива с указанием файла

archive_command = "cp %p /var/lib/postgresql/9.6/archive/%f"

#Число серверов, так как используем два, поэтому ставим значение 2

max_wal_senders = 2 

#Сколько хранить сегментов. Нужно надо выбрать столько,
#чтобы резервный сервер успевал все забирать и обрабатывать.

wal_keep_segments = 12

# Указываем имя сервера для репликации, оно будет использоваться на Slave-сервере
#в файле recovery.conf в директиве "application_name"

synchronous_standby_names = "postgresnode1"

Создаем директорию для архивов и подключаем пользвателю postgres на нее права:

root@postgres-node1:~# mkdir -p /var/lib/postgresql/9.6/archive
root@postgres-node1:~# chmod 700 /var/lib/postgresql/9.6/archive/
root@postgres-node1:~# chown -R postgres:postgres /var/lib/postgresql/9.6/archive/

Редактируем файл pg_hba.conf, который отвечает за аутентификацию

# Локальное подключение для пользователя replica_user
host replication replica_user   127.0.0.1/32                    md5

# Master-сервер ip-адрес
host replication replica_user   10.25.128.172/32                   md5
#Slave-сервер ip-адрес
host replication replica_user   10.25.128.109/32                md5

replication - это не имя базы, а специальное служебное значение для postgresql

Перезапускаем демона postgresql

 root@postgres-node1:~# systemctl restart postgresql 

Создаем пользователя, под именем которого будет работать репликация, заходим в консоль postgresql

root@postgres-node1:~# su postgres -c "psql"
postgres=# CREATE USER replica_user ENCRYPTED PASSWORD "1111" REPLICATION;
CREATE ROLE

Пароль нужно ставить надежный)

Настройка Slave-сервера

Так же устанавливаем демона postgresql по аналогии с Master хостом

Останавливаем демона postgresql

 root@postgres-node2:~# systemctl stop postgresql 

Удаляем директорию с данными postgresql, лучше на всякий случай ее сохранить где-нибудь

 root@postgres-node2:~# rm -rf /var/lib/postgresql/9.6/main/ 

Логинимся под пользователем postgres

root@postgres-node2:~# su postgres И копируем данные с Master-сервера

 postgres@postgres-node2:/root$ pg_basebackup -h 10.25.128.172 \ 
-U replica_user -D /var/lib/postgresql/9.6/main -P --xlog -p 5432
Password: 
38387/38387 kB (100%), 1/1 tablespace <.console>
Редактируем конфигурационный файл /etc/postgresql/9.6/main/postgresql.conf

<console> root@postgres-node2:~# vim /etc/postgresql/9.6/main/postgresql.conf 
  1. включаем hot_standby:

hot_standby = on

  1. Указываем ip-адреса, на которых демон будет ожидать подключения (все адреса)

listen_addresses = "*" </console>

Создаем recovery файл

 vim /var/lib/postgresql/9.6/main/recovery.conf 
 standby_mode = "on"
primary_conninfo = "host=10.25.128.172 port=5432 user=replica_user password=1111 \
application_name=postgresnode1"
trigger_file = "/tmp/postgresql.trigger.5432"

Вписываем только свои значения где host - ip-адрес Master

Запускаем демона postgresql

 root@postgres-node2:~# systemctl start postgresql 

Проверяем работу репликации, создадим на Master сервере таблицу и сделаем в ней записи

postgres=# CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR, age VARCHAR);
CREATE TABLE

Добавим несколько пользователей

postgres=# INSERT INTO users (name,owner...) VALUES ("postres", UTF8);
INSERT 0 1
postgres=# INSERT INTO users (name,owner...) VALUES ("template0", UTF8);
INSERT 0 1
postgres=# INSERT INTO users (name,owner...) VALUES ("template1", UTF8);
INSERT 0 1

Теперь проверяем их наличие на Slave

postgres=# SELECT * FROM users;
  name  | owner...
----+-------+-----
  | postgres | UTF8
  | template0 | UTF8
  | template1 | UTF8
(3 rows)

Записи появились, теперь попробуем вставить новую запись на Slave, должны получить ошибку

postgres=# INSERT INTO users (name,age) VALUES ("Ivan", 10);
ERROR:  cannot execute INSERT in a read-only transaction

Репликация работает

Рабочая репликация master-slave

В случае падения Master-сервера, Slave так и останется работать в режиме readonly.Если мы хотим сделать его Master-ом и разрешить запись на нем, нужен файл который указан в директории "trigger_file" файл recovery.conf. Но в этом случае когда мы вернем в работу основной Master, придется вручную перенести на него измененные записи и снова настраивать Slave для работы.

Удаление терминов master и slave из python от 12 сентября 2018 из соображений политкорректности

Бывший глава команды по разработке языка программирования Python Гвидо ван Россум вернулся из отставки ради одного сообщения — о том, что согласен с предложением одного из молодых разработчиков по отказу от терминов master и slave ради политкорректности. И хотя слово Россума было последним в дискуссии, подобное решение поняли далеко не все.

7 сентября специалист компании Red Hat и один из ведущих разработчиков языка программирования Python Виктор Стиннер опубликовал необычное предложение на сайте для поиска багов. Он предложил избавить документацию Python от двух терминов, обозначающих отношения между операциями, — master и slave. [Источник 5]

По мнению Стиннера, подобная терминология может вызывать ассоциации с рабством, упоминания которого в Соединённых Штатах (первоочередном рынке для множества IT-разработчиков) могут вызывать нежелательные коннотации. Разработчик привёл примеры компаний Drupal и Django, которые перешли на нейтральные термины в 2014 году.

Дословно эти термины можно перевести как «хозяин» и «раб». Однако у них есть ещё и переносные значения — «ведущий» и «ведомый», а также «основное устройство» и «вспомогательное устройство». Именно в таких значениях термины master и slave и используются в компьютерных науках.

В течение нескольких часов Стиннер вносил изменения в проекты документации Python, форматируя их под предложенные альтернативы для master и slave. Однако спустя некоторое время в обсуждении появились и другие разработчики, которые были удивлены решениями и поведением одного из ведущих специалистов проекта.

Я немного удивлён этим. Рабство не то чтобы было допустимым тогда, когда были придуманы эти термины, были введены в компьютерную науку, и они вышли из моды только совсем недавно. С другой стороны, в компьютерном программном обеспечении есть такие области, где master и slave выполняют роль точных технических терминов, и их избегание может привести к неразберихе.

— Ларри Гастингс, разработчик Python Ожесточённая дискуссия продлилась в течение двух дней, и к 11 сентября защитники терминов master и slave даже пришли к выводу, что в этих словах есть и положительные значения. В этот момент руководство команды Python не вытерпело и призвало в тред основателя проекта Гвидо ван Россума, который отошёл от управления проектом в июле.

Россум, вопреки возмущению и непониманию многих разработчиков, согласился с доводами Стиннера и удовлетворил три из четырёх предложений по замене терминов master и slave. Ещё одно предложение оказалось отклонено, потому что вызвало бы проблемы с совместимостью базовых механизмов UNIX-систем.

Несмотря на то что ещё одна из предложенных Стиннером замен осталась нерассмотренной после окончания дискуссии, большинство вариантов употребления терминов master и slave фактически были исключены из новой версии документации Python. Согласно сайту проекта, выход её финального варианта запланирован на конец октября.

Ссылки

Источники

  1. Wikipedia [Электронный ресурс] Master-Slave / Дата обращения: 17.08.2018. Режим доступа: https://en.wikipedia.org/wiki/Master/slave_(technology)
  2. postgresql [Электронный ресурс]: Дата обращения: 18.08.2018 /Режим доступа:https://www.postgresql.org/
  3. Docker [Электронный ресурс]: Дата обращения: 18.08.2018 /Режим доступа:https://www.docker.com/
  4. Vagrant [Электронный ресурс]: Дата обращения: 18.08.2018 /Режим доступа:https://www.vagrantup.com/
  5. medialeaks.ru [Электронный ресурс]: Дата обращения: 18.08.2018 /Режим доступа:http://social.medialeaks.ru/blog/43890953499/Avtoryi-yazyika-Python-ubrali-iz-nego-dva-izvestnyih-vsem-termin