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

Заставить контейнер LXC использовать собственный IP-адрес

Извините, если этот вопрос уже задавали. Не нашел, у меня такая настройка:

+---------------------------------------------------------------------------------------------+
|HOST                                                                                         |
|                                                                                             |
| +-------------------------------------------------+                                         |
| | UBUNTU-VM                                       |                                         |
| |                                                 |                                         |
| | +-------------------+                           |                                         |
| | |UBUNTU-LXC         |                           |                   +------------------+  |
| | |       10.0.0.3/24 |  10.0.0.1/24              |                   |OTHER VM          |  |
| | |               eth0-----lxcbr0----------eth0-----------br0----------eth0              |  |
| | |                   |           192.168.100.2/24|  192.168.100.1/24 |192.168.100.3/24  |  |
| | +-------------------+                           |                   +------------------+  |
| +-------------------------------------------------+                                         |
+---------------------------------------------------------------------------------------------+

Когда я пингую 192.168.100.3 со своего UBUNTU-LXC, исходный IP-адрес автоматически изменяется на 192.168.100.2 с помощью UBUNTU-VM. Это похоже на NAT, в то время как я действительно хочу, чтобы мой UBUNTU-LXC разговаривал с собственным IP-адресом. Есть какой-либо способ сделать это ?

Изменить: эта информация может быть актуальной:

:

<interface type='bridge'>                                                    
  <mac address='52:54:00:cb:aa:74'/>                                         
  <source bridge='br0'/>                                                     
  <model type='e1000'/>                                                      
 <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</interface>                                                                 

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

Установка

+---------------------------------------------------------------------------------------------+
|HOST                                                                                         |
|                                                                                             |
| +-------------------------------------------------+                                         |
| | UBUNTU-VM                                       |                                         |
| |                                                 |                                         |
| | +-------------------+                           |                                         |
| | |UBUNTU-LXC         |                           |                   +------------------+  |
| | |       10.0.0.3/24 |  10.0.0.1/24              |                   |OTHER VM          |  |
| | |               eth0-----lxcbr0----------eth0-----------br0----------eth0              |  |
| | |                   |           192.168.100.2/24|  192.168.100.1/24 |192.168.100.3/24  |  |
| | +-------------------+                           |                   +------------------+  |
| +-------------------------------------------------+                                         |
+---------------------------------------------------------------------------------------------+

1. Удаление NAT на UBUNTU-VM

Причина, по которой мои пакеты исходят из UBUNTU-VM с 192.168.100.2 из-за дефолта iptables правило, которое создается, когда я запускаю свой контейнер:

root@UBUNTU-VM# iptables -nL -t nat     
Chain PREROUTING (policy ACCEPT)                    
target     prot opt source               destination

Chain INPUT (policy ACCEPT)                         
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)                        
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)                   
target     prot opt source               destination
MASQUERADE  all  --  10.0.3.0/24         !10.0.3.0/24 

В основном это правило гласит: «Если пакет из подсети 10.0.3.0/24 а пункт назначения находится в другой подсети, измените IP-адрес источника ". Поэтому, если я удалю это правило, я смогу выполнить эхо-запрос извне, используя IP-адрес моего контейнера. Давайте удалим это правило:

root@UBUNTU-VM# iptables -D POSTROUTING 1 -t nat

Теперь, если я пингую 192.168.100.1 из моего контейнера LXC (10.0.3.233) вот что происходит:

root@HOST# tcpdump -i br0 -n
12:51:56.174009 IP 10.0.3.233 > 192.168.100.1: ICMP echo request, id 498, seq 1, length 64
12:51:56.174072 ARP, Request who-has 10.0.3.233 tell 192.168.100.1, length 28

ICMP-запросы приходят с моего IP-адреса LXC :) Однако br0 кажется, не может ответить.

2. Добавление маршрута по умолчанию на HOST

root@HOST# ip route add 10.0.0.0/8 via 192.168.100.2

Теперь шлюз по умолчанию для 10.0.0.0/8 подсеть eth0 на УБУНТУ-ВМ. Попробуем пинг:

root@HOST# tcpdump -i br0 -n
14:14:33.885982 IP 10.0.3.233 > 192.168.100.1: ICMP echo request, id 660, seq 14, length 64
14:14:34.884054 ARP, Request who-has 10.0.3.233 tell 192.168.100.1, length 28

Это все еще не работает. К сожалению, у меня нет объяснения этому. И что хуже, почему br0 делать ARP-запрос для IP-адреса, которого нет даже в его подсети? По крайней мере, я ожидал, что запрос ICMP будет игнорироваться, но отвечать запросом ARP просто странно.

3. Настройка libvirt

3.1. Текущая конфигурация

br0 это мост, который я настроил на хосте вручную, используя netctl. В моем шаблоне UBUNTU-VM у меня есть это:

<interface type='bridge'>                                                    
   <mac address='52:54:00:cb:aa:74'/>                                         
   <source bridge='br0'/>                                                     
   <model type='e1000'/>                                                      
   <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</interface>     

Когда UBUNTU-VM создается, kvm (или libvirt ?) создает пару veth и прикрепляет их к мосту.

root@HOST# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.fe0000000001       no              vnet1
                                                        vnet2

По какой-то причине это не работает (изменения / комментарии приветствуются)

Решением было настроить routed network вместо просто bridged network.

3.2. Определить сеть

Создайте xml-шаблон для своей сети:

<network>                                                       
  <name>vms</name>                                              
  <uuid>f3e18be1-41fe-4f34-87b4-f279f4a02254</uuid>             
  <forward mode='route'/>                                       
  <bridge name='br0' stp='on' delay='0'/>                       
  <mac address='52:54:00:86:f3:04'/>                            
  <ip address='192.168.100.1' netmask='255.255.255.0'>          
  </ip>                                                         
  <route address='10.0.0.0' prefix='8' gateway='192.168.100.2'/>
</network>                                                      

Обратите внимание на раздел маршрута по умолчанию. Затем загрузите его и запустите

virsh # define vms.xml
virsh # net-start vms

3.3. Отредактируйте виртуальную машину

Теперь интерфейс должен выглядеть так:

<interface type='network'>                                                   
  <mac address='52:54:00:cb:aa:74'/>                                         
  <source network='vms'/>                                                    
  <model type='e1000'/>                                                      
  <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</interface>                                                                 

Финальный тест

После перезапуска виртуальной машины и контейнера я наконец могу пинговать br0 используя ip контейнера LXC:

root@HOST# tcpdump -i br0 -n
14:24:00.349856 IP 10.0.3.233 > 192.168.100.1: ICMP echo request, id 468, seq 16, length 64
14:24:00.349900 IP 192.168.100.1 > 10.0.3.233: ICMP echo reply, id 468, seq 16, length 64

Остающиеся вопросы

  • Почему этот ARP запрашивает в 2. ?
  • Почему моя установка не работает, если я не позволю libvirt обрабатывать мост и саму маршрутизацию? Моя ручная конфигурация (создание моста с помощью netctl и добавление маршрута по умолчанию с помощью ip route add) является очень похоже на то, что делает libvirt: мост с двумя подключенными к нему vnet-интерфейсами и маршрут по умолчанию ... делает ли libvirt здесь некую черную магию?
  • Смогу ли я масштабировать количество контейнеров с помощью этой настройки (это моя конечная цель).

Источники, которые помогли

  • сетевой документ libvirt
  • Я отредактирую и добавлю другие ссылки, когда у меня будет достаточно репутации (требуется 10 ...)

Измените описание сети для сети libvirt, чтобы она не выполняла nat.

С хоста виртуальной машины запустить virsh net-list.

затем virsh net-edit сеть, в которой живет виртуальная машина, чтобы убрать наттинг.