MyTetra Share
Делитесь знаниями!
Как в PostgreSQL прописать дополнительный IP-адрес и обеспечить правильный запуск сервиса?
Время создания: 11.04.2024 14:05
Текстовые метки: linux, astra, debian, postgres, sql, postgresql, сеть, IP-адрес, дополнительный, хост, порт, интерфейс, сетевой, сервис, самодельный, собственный, юнит, unit, запуск, старт, настройка, systemd
Раздел: Компьютер - Программирование - SQL - PostgreSQL
Запись: xintrea/mytetra_syncro/master/base/1712833553ixp8imlnvq/text.html на raw.github.com

Имеется компьютер, на котором запущен PostgreSQL, и у которого настроено несколько сетевых интерфейсов, смотрящих в разные подсети основной сети:



> ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

inet 127.0.0.1/8 scope host lo

valid_lft forever preferred_lft forever

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

link/ether 1c:6f:65:96:54:bc brd ff:ff:ff:ff:ff:ff

inet 192.168.1.95/24 brd 192.168.1.255 scope global eth0

valid_lft forever preferred_lft forever

...

inet 192.168.222.95/24 brd 192.168.222.255 scope global eth0:7

valid_lft forever preferred_lft forever



Вопрос: как правильно разрешить PostgreSQL обрабатывать запросы только на локальном порту и на порту, висящем на адресе 192.168.222.95 (закрепленным за виртуальным сетевым интерфейсом eth0:7)?


* * *


Порядок действий следующий (проверено на Astra Linux 1.6).


1. По умолчанию, PostgreSQL обслуживает локальный порт 5432, и его дополнительно настраивать не нужно. Чтобы PostgreSQL слушал порт подсети 222, требуется изменить опцию listen_addresses в файле /etc/postgresql/9.6/main/postgresql.conf, прописав следующее:



listen_addresses = 'localhost,192.168.222.95'


2. Кроме того, надо добавить строку в файл /etc/postgresql/9.6/main/pg_hba.conf:



host all all 192.168.222.0/24 md5



3. Казалось бы, теперь достаточно перезагрузить сервис postgres, и все заработает как надо. Да, именно так и произойдет. Но это не значит, что сервер PostgreSQL нормально запустится при перезапуске компьютера. Проблема может оказаться в том, что на момент старта сервиса postgres сеть уже заработала, а виртуальный интерфейс eth0:7 еще не поднялся. И тогда PostgreSQL будет работать только на локальном порту 5432, а на IP-адресе 192.168.222.95 порт 5432 не поднимется. Это можно узнать, выполнив команду:



# netstat -lnp | grep 5432

tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN -



Здесь видно, что работает только локальный порт. Кроме того, в лог-файле /var/log/postgresql/postgresql-9.6-main.log будут ошибки:



СООБЩЕНИЕ: не удалось привязаться к сокету IPv6: Невозможно назначить запрошенный адрес

ПОДСКАЗКА: Возможно порт 5432 занят другим процессом postmaster? Если нет, повторите попытку через несколько секунд.


СООБЩЕНИЕ: не удалось привязаться к сокету IPv4: Невозможно назначить запрошенный адрес

ПОДСКАЗКА: Возможно порт 5432 занят другим процессом postmaster? Если нет, повторите попытку через несколько секунд.


ПРЕДУПРЕЖДЕНИЕ: не удалось создать принимающий сокет для "192.168.222.95"

СООБЩЕНИЕ: передача вывода в протокол процессу сбора протоколов

ПОДСКАЗКА: В дальнейшем протоколы будут выводиться в каталог "pg_log".



Чтобы эту проблему решить, необходимо сделать дополнительные настройки сервису postgresql. Ниже приводится решение только для IPv4.


4. Необходимо создать каталог /etc/systemd/system/postgresql@.service.d , а в нем создать файл override.conf следующего содержания:



[Unit]

Requires=network-online.target


After=network-online.target

After=wait-additional-network-interfaces.service



Эта дополнительная настройка шаблонных юнитов postgresql заставит их запускаться после того как отработают юниты network-online.target и wait-additional-network-interfaces.service.


5. Далее надо создать файл самодельного юнита wait-additional-network-interfaces, который будет ожидать появления требуемого IP-адреса в нужной подсети (а значит, и появления виртуального сетевого интерфейса, ему соответствующего).


Для этого в каталоге /etc/systemd/system/ создается файл wait-additional-network-interfaces.service со следующим содержанием:



[Unit]

Description=Ожидание поднятия некоторых дополнительных сетевых интерфейсов (используется для правильного старта PostgreSQL)


Requires=network-online.target

After=network-online.target



[Service]

Type=simple


ExecStartPre=-/usr/bin/timeout 25 bash -c 'while ! /bin/ip -o -4 a | /bin/grep -q "192.168.222."; do /bin/sleep 0.2; done'

ExecStart=/bin/true


WorkingDirectory=/tmp



[Install]

Alias=wait-additional-network-interfaces.service



Данный юнит будет пытаться в течение 25 секунд проверить наличие подсети 192.168.222.xxx. Если подсеть появится, то юнит сразу завершит свою работу с нулевым кодом завершения. Если же в течении 25 секунд интерфейс в подсети 192.168.222.xxx не появился, то юнит завершится тоже с нулевым кодом завершения. Это произойдет потому, что опция ExecStart возвращает нулевой код завершения во всех случаях.


Таким образом, зависимый модуль postgresql запустится в любом случае. Если в течении 25 секунд после инициализации сети появится заданная подсеть, то PostgreSQL будет запущен и на локальном, и на заданном IP. Если же заданная подсеть не появится, то пройдет 25 секунд, и PostgreSQL запустится только на локальном IP, потому что на дополнительном IP порт не сможет создастся, так как этого IP еще нет.


6. Для проверки созданных зависимостей надо выполнить следующие команды. Вначале надо перечитать информацию о юнитах и их зависимостях:



systemctl daemon-reload



Затем надо посмотреть зависимости сервиса postgresql.service:



# systemctl list-dependencies --after postgresql.service

postgresql.service

● ├─postgresql@9.6-main.service

● ├─system.slice

● ├─systemd-journald.socket

● ├─basic.target

● │ ├─-.mount

● │ ├─systemd-ask-password-plymouth.path



Здесь видно, что сервис postgresql.service зависит от шаблонного сервиса postgresql@9.6-main.service. Поэтому надо посмотреть зависимости у шаблонного сервиса и проверить, зависит ли он от сервиса ожидания заданной сети:



# systemctl list-dependencies --after postgresql@9.6-main.service | grep wait

● ├─wait-additional-network-interfaces.service



Да, зависит, и это правильно.


7. Теперь можно перезагрузить машину и убедиться, что сервер PostgreSQL начинает обслуживать порт 5432, расположенный в обеих подсетях:



# netstat -lnp | grep 5432

tcp 0 0 192.168.222.95:5432 0.0.0.0:* LISTEN -

tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN -



Примечание: все это решение сделано для варианта, когда в системе не используется либо не настроен сетевой менеджер, например connman или systemd-networkd.


Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования