LINUX.ORG.RU
решено ФорумAdmin

Настройка Virtual Ethernet в systemd-networkd.

 , , ,


0

1

Пытаюсь настроить сеть для systemd-nspawn контейнеров с IPv4/IPv6 адресами, но работает оно не так, как хотелось бы.
В юните systemd-nspawn@.service используется флаг --network-veth.
Для него используется конфиг /usr/lib/systemd/network/80-container-ve.network со следующим содержимым:

[Match]
Name=ve-*
Driver=veth

[Network]
# Default to using a /28 prefix, giving up to 13 addresses per container.
Address=0.0.0.0/28
LinkLocalAddressing=yes
DHCPServer=yes
IPMasquerade=both
LLDP=yes
EmitLLDP=customer-bridge
IPv6SendRA=yes

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

# ip -4 address
8: ve-d0a47fadj0Iy@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link-netnsid 1
    altname ve-d0a47fad-260b-468d-a931-37e73de87a34
    inet 192.168.111.209/28 brd 192.168.111.223 scope global ve-d0a47fadj0Iy
       valid_lft forever preferred_lft forever
# ip -4 route
192.168.111.208/28 dev ve-d0a47fadj0Iy proto kernel scope link src 192.168.111.209 

И в целом всё работает. Но если я вместо Address=0.0.0.0/28 укажу к примеру Address=10.0.5.1/28, то результат будет таким:

# ip -4 address
9: ve-d0a47fadj0Iy@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link-netnsid 1
    altname ve-d0a47fad-260b-468d-a931-37e73de87a34
    inet 10.0.5.1/28 brd 10.0.5.15 scope global ve-d0a47fadj0Iy
       valid_lft forever preferred_lft forever
# ip -4 route
default dev wg scope link 
10.0.5.0/28 dev ve-d0a47fadj0Iy proto kernel scope link src 10.0.5.1 

В таком случае тоже работает, пока я не создам второй контейнер.
Вот результат после создания второго контейнера:

# ip -4 address
10: ve-d0a47fadj0Iy@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link-netnsid 1
    altname ve-d0a47fad-260b-468d-a931-37e73de87a34
    inet 10.0.5.0/28 brd 10.0.5.15 scope global ve-d0a47fadj0Iy
       valid_lft forever preferred_lft forever
11: ve-c9c8aa34cqwn@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link-netnsid 2
    altname ve-c9c8aa34-13da-45d0-adf1-44d900439ee1
    inet 10.0.5.0/28 brd 10.0.5.15 scope global ve-c9c8aa34cqwn
       valid_lft forever preferred_lft forever
# ip -4 route
10.0.5.0/28 dev ve-d0a47fadj0Iy proto kernel scope link src 10.0.5.0 
10.0.5.0/28 dev ve-c9c8aa34cqwn proto kernel scope link src 10.0.5.0 

И сеть работает только в одном контейнере.
Примерно тоже самое с IPv6. Если я в секцию [IPv6Prefix] добавлю Assign = true, то адрес из /64 префикса назначается нормально, но маршруты прописываются таким образом:

2a01:aaaa:bbbb:cccc::/64 dev ve-c9c8aa34cqwn proto kernel metric 256 pref medium
2a01:aaaa:bbbb:cccc::/64 dev ve-d0a47fadj0Iy proto kernel metric 256 pref medium
fe80::/64 dev ve-d0a47fadj0Iy proto kernel metric 256 pref medium
fe80::/64 dev ve-c9c8aa34cqwn proto kernel metric 256 pref medium

Т.е. опять дублирование маршрутов.
В общем можно ли как-то настроить Virtual Ethernet интерфейсы для systemd-nspawn таким образом, чтобы адреса и маршруты на хост машине не пересекались у контейнеров?
Спасибо.


Ну а как ты собрался выдавать двум разным интерфейсам один и тот же адрес и ожидать, что всё будет работать?

У тебя systemd-nspawn --network-veth создаёт новую пару veth на каждый новый контейнер. Конфиг networkd применяется ко всем таким интерфейсам одновременно. Он работает только потому, что Address=0.0.0.0 — это особый случай, который заставляет его выделять новую подсеть на каждый интерфейс (см. systemd.networkd(5)).

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

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 5)
Ответ на: комментарий от intelfx

Ну это вроде понятно, вопрос в том, можно ли добиться такого же поведения через systemd-networkd со своими префиксами/подсетями.
Или veth для этого не подходит и нужно делать это через bridge?

Sorcus
() автор топика
Ответ на: комментарий от Sorcus

Отвечая на единственный прямо поставленный вопрос:

В общем можно ли как-то настроить Virtual Ethernet интерфейсы для systemd-nspawn таким образом, чтобы адреса и маршруты на хост машине не пересекались у контейнеров?

Да, можно: для этого достаточно ничего не трогать.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Назначать автоматически адреса контейнерам systemd-nspawn из своих подсетей/префиксов.
Для IPv4 в принципе можно оставить Address = 0.0.0.0/28.
А вот для IPv6 хотелось бы назначать контейнерам адреса из префикса, который назначен хосту через Wireguard.
Т.е.

[Match]
Name = ve-*
Driver = veth

[Network]
IPv6SendRA=yes

[IPv6Prefix]
Prefix = 2a01:aaaa:bbbb:cccc::/64
Assign = yes

Оно в принципе назначает всё нормально, но маршруты прописываются в виде 2a01:aaaa:bbbb:cccc::/64 и это приводит к тому, что сеть работает только в одном из контейнеров.

Sorcus
() автор топика
Ответ на: комментарий от Sorcus

Назначать автоматически адреса контейнерам systemd-nspawn из своих подсетей/префиксов.

Понял.

Кажется, так нельзя. Автоназначение подсетей работает только из фиксированного пула (IPv4 private addresses или IPv6 ULA), либо через DHCP Prefix Delegation. Свои префиксы указать нет возможности ни в том, ни в другом случае.

[IPv6Prefix]
Prefix = 2a01:aaaa:bbbb:cccc::/64
Assign = yes

Эта секция совершенно не о том. Она про рассылку RA.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Ну в общем я решил воспользоваться старым добрым bridge.
Конфиги:

$ cat /etc/systemd/network/10-bridge.netdev
[NetDev]
Name = bridge
Kind = bridge
$ cat /etc/systemd/network/10-bridge.network
[Match]
Name = bridge

[Network]
Address = 10.0.5.1/28
IPMasquerade = ipv4
DHCPServer = true
IPv6SendRA = true

[IPv6Prefix]
Prefix = 2a01:7e01:e002:8fea::/64
Assign = true
$ cat /etc/systemd/nspawn/d0a47fad-260b-468d-a931-37e73de87a34.nspawn
[Network]
Bridge = bridge

Других изменений не вносил, опция --network-veth в systemd-nspawn@.service так и используется.
В целом полученный результат соответствует тому, что мне нужно было.

Sorcus
() автор топика
Ответ на: комментарий от intelfx

в одной подсети и видят друг друга вне зависимости от файрволла.

Ну файрвол можно то и поднять(фильтрующий мост в Linux - штука не новая), достаточно вот этих опций в sysctl:

net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

Но так-то да, конфигурация несколько другая получается.

Pinkbyte ★★★★★
()