Назад | Перейти на главную страницу

Доступ к службам хоста из контейнеров systemd-nspawn

У меня есть набор контейнеров, которыми управляет systemd-nspawn. Контейнеры должны быть (полу) изолированы от внешней сети, но в то же время должны иметь возможность доступа к неконтейнерным сервисам, таким как СУБД, работающим на хосте (см. диаграмма). Сетью управляет systemd-networkd на обоих концах.

Я пробовал следующие наиболее распространенные режимы частной сети systemd-nspawn:

Виртуальный Ethernet

-n, --network-veth создает пару подключенных виртуальных адаптеров Ethernet для каждого контейнера, один на стороне хоста, другой внутри контейнера. Похоже, от этого мало толку, потому что неясно, какой адрес СУБД должна прослушивать и к какому адресу должны подключаться контейнеры.

Мост

--network-bridge= делает в основном то же самое, но добавляет виртуальные адаптеры к указанному мосту. Мост должен быть уже настроен и ему назначен IP:

# /etc/systemd/network/br0.netdev 
[NetDev]
Name=br0
Kind=bridge

 

# /etc/systemd/network/br0.network 
[Match]
Name=br0

[Network]
Address=169.254.1.1/16

Эта конфигурация доказала свою работоспособность, но требует дополнительной настройки моста и, как правило, проблематична, когда речь идет о внешнем сетевом доступе для контейнеров.

Зона

--network-zone= делает то же самое, но автоматически управляет интерфейсом моста. Вот что мы получаем по умолчанию для моста:

[root@host ~]# ip addr show vz-containers
26: vz-containers: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 169.254.120.107/16 brd 169.254.255.255 scope link vz-containers
       valid_lft forever preferred_lft forever
    inet 10.0.0.1/24 brd 10.0.0.255 scope global vz-containers
       valid_lft forever preferred_lft forever
    inet 10.0.1.1/24 brd 10.0.1.255 scope global vz-containers
       valid_lft forever preferred_lft forever

Похоже, ему назначен случайный адрес из 169.254.0.0/16, и два статических адреса 10.0.0.1 и 10.0.1.1. По этим двум адресам хост доступен из контейнеров. Но неясно, откуда берутся эти адреса, и я не уверен, что это не изменится в будущих версиях systemd. Чтобы убедиться, мы можем назначить дополнительный статический IP-адрес интерфейсу моста:

# /etc/systemd/network/80-container-vz.network - full override, systemd < 232 
[Match]
Name=vz-*
Driver=bridge

[Network]
# Default to using a /24 prefix, giving up to 253 addresses per virtual network.
Address=0.0.0.0/24
Address=169.254.1.1/24
# the rest is left as in the original /usr/lib/systemd/network/80-container-vz.network

 

# /etc/systemd/network/80-container-vz.network.d/override.conf - drop-in, systemd ≥ 232
[Network]
Address=169.254.1.1/24

Это работает хорошо, не создает проблем с подключением к внешней сети, но также требует дополнительной проверки конфигурации моста. Кроме того, оба метода (мост и зона) требуют настройки статического /etc/hosts запись, как systemd-resolved и друзья (mymachines, myhostname и resolve Модули NSS) здесь не очень полезны:

# /etc/hosts
169.254.1.1 host

К счастью, все контейнеры используют один и тот же базовый образ ОС, так что это не так сложно сделать.

Вопрос в том, можно ли все вышеперечисленное сделать проще? Или я должен подождать, пока systemd-nspawn получает какую-то волшебную опцию вроде "сделать хост доступным в контейнерах по имени хоста <foo>"?

Возникли те же сложности - мои ответы более или менее совпадают с ответами Кирали, но конфигурация полностью контролируется хостом.

Акция /lib/systemd/network/80-container-ve.network можно скопировать и изменить, чтобы установить адрес хоста на конкретный статический IP-адрес (вам также необходимо обновить [Match])

Затем - установите пул DHCP только с 1 адресом. Таким образом, это предсказуемо - и контейнер не нужно настраивать статически, он просто выбирает правильный адрес при загрузке.

Итак - что-то вроде этого

/etc/systemd/network/50-mycont.network

[Match]
# Hard match for the container interface name - no wildcards
Name=ve-mycont
Driver=veth

[Network]
# Static address for host
Address=10.0.60.49/28
LinkLocalAddressing=yes
DHCPServer=yes
IPMasquerade=yes
LLDP=yes
EmitLLDP=customer-bridge

[DHCPServer]
PoolOffset=2
PoolSize=1
# Little DHCP - container will have address 10.0.60.50

неясно, откуда эти адреса

Если вы используете systemd-networkd, то файлы конфигурации берутся из файлов конфигурации с расширением .network. Эти файлы находятся в /etc/systemd/network или /run/systemd/network или /usr/lib/systemd/network - последнее значение по умолчанию, если вы ничего не меняли в / etc. ... Документация для systemd-networkd есть Вот. В вашей сети может быть DHCP-сервер, и в зависимости от того, какой сетевой режим вы используете, IP-адреса могут быть назначены с этого DHCP-сервера.

Вопрос в том, можно ли все вышеперечисленное сделать проще?

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

сделать хост доступным в контейнерах по имени хоста

Поскольку вы контролируете свой IP-адрес на стороне хоста, вы можете ввести запись в /etc/hosts, как и вы. Я не знаю более простых решений или каких-либо внешних решений.