докер-контейнеры с «общедоступными» IP-адресами, мостовая сеть

Я в основном следовал этому руководству: Контейнеры Docker с общедоступными IP-адресами

У нас уже есть аналогичная установка, работающая в другом месте, но я не могу заставить ее работать в новой среде. К сожалению, мой предшественник ничего не задокументировал, поэтому я пытаюсь перепроектировать установку.

Хост докера:
10.10.60.41/24

с мостовой сетью докеров:
docker network create --subnet=10.60.0.0/16 --opt "com.docker.network.bridge.name"="br-ext" ext

маршруты на хосте докеров:

#  ip r
default via 10.10.60.1 dev br0 proto static 
10.10.60.0/24 dev br0 proto kernel scope link src 10.10.60.41 
10.60.0.0/16 dev br-ext proto kernel scope link src 10.60.0.1 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdow

запустить докер-контейнер:
docker run --network=ext -itd --name=web nginx

Этот док-контейнер получает IP 10.60.0.2 назначенный.

ping 10.60.0.2 или же curl 10.80.0.2 с хоста докера работает нормально… как и ожидалось.

Но докер-контейнер недоступен из сети. Сетевой маршрут для 10.60.0.0/16 на основной IP хоста докера 10.10.60.41 установлен.

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (2 references)
target     prot opt source               destination         

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere
# iptables -t nat -L -n -v
Chain PREROUTING (policy ACCEPT 35363 packets, 2140K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 140K 8413K DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 24828 packets, 1495K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 286 packets, 19813 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    6   504 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 10799 packets, 659K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    6   504 MASQUERADE  all  --  *      !br-ext  10.60.0.0/16         0.0.0.0/0           
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    2   168 RETURN     all  --  br-ext *       0.0.0.0/0            0.0.0.0/0           
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

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

Заранее спасибо и хорошего дня!

=====

РЕДАКТИРОВАТЬ — ответ на larsks

да пакеты могут достигать хоста/контейнера: 10.10.60.6 > 10.60.1.25

# tcpdump -n -i any icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
15:34:52.257656 IP 10.10.60.6 > 10.60.1.25: ICMP echo request, id 879, seq 1, length 64
15:34:52.257731 IP 10.10.60.6 > 10.60.1.25: ICMP echo request, id 879, seq 1, length 64
15:34:52.257741 IP 10.10.60.6 > 10.60.1.25: ICMP echo request, id 879, seq 1, length 64
15:34:52.257799 IP 10.60.1.25 > 10.10.60.6: ICMP echo reply, id 879, seq 1, length 64
15:34:52.257799 IP 10.60.1.25 > 10.10.60.6: ICMP echo reply, id 879, seq 1, length 64
15:34:52.257826 IP 10.60.1.25 > 10.10.60.6: ICMP echo reply, id 879, seq 1, length 64

даже ответ ICMP отправляется

на хосте 10.10.60.6 отправка запросов ICMP, нет ответов

# tcpdump -i any icmp and host 10.60.1.25
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
15:36:52.042690 IP vpnconnect > 10.60.1.25: ICMP echo request, id 879, seq 118, length 64
15:36:53.066672 IP vpnconnect > 10.60.1.25: ICMP echo request, id 879, seq 119, length 64
15:36:54.090729 IP vpnconnect > 10.60.1.25: ICMP echo request, id 879, seq 120, length 64
15:36:55.114713 IP vpnconnect > 10.60.1.25: ICMP echo request, id 879, seq 121, length 6

дополнительная информация: при отправке запроса ICMP из одного из док-контейнеров в 10.10.60.6это работает

$ ping 10.10.60.6
PING 10.10.60.6 (10.10.60.6): 56 data bytes
64 bytes from 10.10.60.6: seq=0 ttl=42 time=1.051 ms
64 bytes from 10.10.60.6: seq=1 ttl=42 time=0.738 ms

на 10.10.60.6 это выглядит так:

# tcpdump -i any icmp and host 10.10.60.41
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
15:40:57.489752 IP 10.10.60.41 > host: ICMP echo request, id 42, seq 38, length 64
15:40:57.489771 IP host > 10.10.60.41: ICMP echo reply, id 42, seq 38, length 64

запросы и ответы хосту Docker(?)

сеть iptables докер-мост

маб

2 ответа
2

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


В этой конфигурации у меня есть следующие три узла:

  • node1 это хост докера @ 10.10.60.41.
  • node2 находится ли маршрутизатор в 10.10.60.1
  • node3 является случайным другим хостом в сети по адресу 10.10.60.20.

Я создал сеть докеров, как в вашем примере, так что на node1хост-контейнер, у меня мост br-ext настроено так:

node# ip addr show br-ext
5: br-ext: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:83:d4:10:54 brd ff:ff:ff:ff:ff:ff
    inet 10.60.0.1/16 brd 10.60.255.255 scope global br-ext
       valid_lft forever preferred_lft forever
    inet6 fe80::42:83ff:fed4:1054/64 scope link
       valid_lft forever preferred_lft forever

И следующая таблица маршрутизации (маршруты к 192.168.121.0/24; это артефакт того, как vagrant обрабатывает конфигурацию):

default via 10.10.60.1 dev eth1
10.10.60.0/24 dev eth1 proto kernel scope link src 10.10.60.41 metric 101
10.60.0.0/16 dev br-ext proto kernel scope link src 10.60.0.1
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.121.0/24 dev eth0 proto kernel scope link src 192.168.121.12 metric 100

И дальше node2сетевой роутер, у меня есть:

default via 192.168.121.1 dev eth0 proto dhcp metric 100
10.10.60.0/24 dev eth1 proto kernel scope link src 10.10.60.1 metric 101
10.60.0.0/16 via 10.10.60.41 dev eth1 proto static metric 101
192.168.121.0/24 dev eth0 proto kernel scope link src 192.168.121.181 metric 100

На node3У меня есть:

default via 10.10.60.1 dev eth1
10.10.60.0/24 dev eth1 proto kernel scope link src 10.10.60.20 metric 101
192.168.121.0/24 dev eth0 proto kernel scope link src 192.168.121.184 metric 100

С приведенной выше конфигурацией, если я запускаю node1:

node1# tcpdump -n -i any icmp

И дальше node3 Я бегу:

node3# ping 10.60.0.2

я вижу в выводе tcpdump:

14:12:25.777825 eth1  In  IP 10.10.60.1 > 10.60.0.2: ICMP echo request, id 2, seq 1, length 64
14:12:26.836689 eth1  In  IP 10.10.60.1 > 10.60.0.2: ICMP echo request, id 2, seq 2, length 64
14:12:27.860833 eth1  In  IP 10.10.60.1 > 10.60.0.2: ICMP echo request, id 2, seq 3, length 64

Итак, эхо-запросы ICMP отображаются на node1что означает, что наша сетевая маршрутизация верна (node3 отправляет запросы через node2сетевой маршрутизатор, который корректно передает их на node1)… но мы не видим ответов. Что может быть причиной?

Одним из механизмов, который мы можем использовать для диагностики, является включение трассировки пакетов в нашей конфигурации сетевого фильтра на node1:

node1# iptables -t raw -A PREROUTING -s 10.10.60.20 -j TRACE

Теперь, когда мы пытаемся ping из node3 к node1мы видим следующие логи ядра:

Aug 15 14:19:05 node1 kernel: TRACE: raw:PREROUTING:policy:2 IN=eth1 OUT= MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: nat:PREROUTING:policy:2 IN=eth1 OUT= MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: filter:FORWARD:rule:1 IN=eth1 OUT=br-ext MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: filter:DOCKER-USER:return:1 IN=eth1 OUT=br-ext MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: filter:FORWARD:rule:2 IN=eth1 OUT=br-ext MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: filter:DOCKER-ISOLATION-STAGE-1:return:3 IN=eth1 OUT=br-ext MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: filter:FORWARD:rule:4 IN=eth1 OUT=br-ext MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: filter:DOCKER:return:1 IN=eth1 OUT=br-ext MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1
Aug 15 14:19:05 node1 kernel: TRACE: filter:FORWARD:policy:11 IN=eth1 OUT=br-ext MAC=52:54:00:95:12:24:52:54:00:f4:d3:e4:08:00 SRC=10.10.60.20 DST=10.60.0.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=20048 DF PROTO=ICMP TYPE=8 CODE=0 ID=3 SEQ=1

(Не забудьте отключить трассировку на этом этапе: iptables -t raw -F PREROUTING.)

Глядя на приведенные выше логи, мы видим, что наш пакет в итоге попал в FORWARD цепочка, где она не соответствовала ни одному терминальному правилу и в конечном итоге упала на дно, где она обрабатывается политикой по умолчанию:

Aug 15 14:19:05 node1 kernel: TRACE: filter:FORWARD:policy:11 ...

Который был установлен на DROP при установке Docker:

node1# iptables -S FORWARD
-P FORWARD DROP
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o br-ext -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-ext -j DOCKER
-A FORWARD -i br-ext ! -o br-ext -j ACCEPT
-A FORWARD -i br-ext -o br-ext -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT

Решение здесь состоит в том, чтобы добавить новое правило, явно разрешающее трафик из хост-сети в контейнерную сеть. На node1:

node1# iptables -A FORWARD -s 10.10.60.0/24 -d 10.60.0.0/16 -j ACCEPT

С этим правилом я теперь могу успешно пинговать из node3 к nginx контейнер на node1:

node3# ping -c2 10.60.0.2
PING 10.60.0.2 (10.60.0.2) 56(84) bytes of data.
64 bytes from 10.60.0.2: icmp_seq=1 ttl=63 time=0.417 ms
64 bytes from 10.60.0.2: icmp_seq=2 ttl=63 time=0.328 ms

--- 10.60.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1047ms
rtt min/avg/max/mdev = 0.328/0.372/0.417/0.044 ms

Я также могу успешно получить доступ к экземпляру Nginx, работающему в web контейнер:

node3# curl 10.60.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
.
.
.

Связь в обратном направлении тоже работает; на node1:

node1# docker exec -it apt-get update
node1# docker exec -it apt-get -y install iputils-ping
node1# docker exec -it web ping -c2 10.10.60.20
PING 10.10.60.20 (10.10.60.20) 56(84) bytes of data.
64 bytes from 10.10.60.20: icmp_seq=1 ttl=63 time=0.304 ms
64 bytes from 10.10.60.20: icmp_seq=2 ttl=63 time=0.378 ms

--- 10.10.60.20 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1024ms
rtt min/avg/max/mdev = 0.304/0.341/0.378/0.037 ms

Это может не совсем соответствовать вашей конфигурации: например, в вашем выводе ваш FORWARD цепочка имеет политику по умолчанию ACCEPTкоторый предполагает, что, возможно, происходит что-то еще… но, надеюсь, он предлагает несколько способов устранения проблемы.

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

По умолчанию вы не можете пинговать контейнер Docker с внешнего хоста.
По умолчанию любая служба, работающая внутри контейнера Docker, не является «опубликованной» (терминология Docker) и недоступна извне. Вы должны явно определить/разрешить службы, которые вы хотите опубликовать, при запуске контейнера.
В вашем случае я не вижу в вашей команде запуска docker какой-либо публикации порта, и вы используете nginx, поэтому я думаю, вам следует опубликовать как минимум 80.

Салар

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *