Я в основном следовал этому руководству: Контейнеры 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 ответа
Я воспроизвел вашу среду на виртуальных машинах, чтобы взглянуть на проблему. Вы можете найти полную конфигурацию здесь.
В этой конфигурации у меня есть следующие три узла:
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.
Салар