Глава 2. Построение сети Docker взгляд вовнутрь
Данная глава подробно обсудит семантику и синтаксис построения сетей Docker, обнажая преимущества и недостатки текущей парадигмы сетевой среды Docker.
Она охватывает следующие темы:
-
Настройку стека IP для Docker
-
Поддержка IPv4
-
Проблемы управления адресами IPv4
-
Поддержка IPv6
-
-
Настройку DNS
-
Основы DNS
-
Групповой DNS
-
-
Настройку моста Docker
-
Оверлейные сетевые среды и подстилающие сетевые среды
-
Что это такое?
-
Как Docker применяет их?
-
В чём их некоторые преимущества?
-
Содержание
Для взаимодействия с внешним миром Docker применяет стек IP, используя TCP или UDP. Он поддерживает инфраструктуры адресации IPv4 и IPv6, которые объясняются в следующих подразделах.
По умолчанию Dockeer обеспечивает адресацию IPv4 каждому контейнеру, который подключён к мосту по умолчанию
docker0
. Диапазон адресов IP может быть определён при запуске демона Docker при помощи флага
--fixed-cidr
, как показано в следующем коде:
$ sudo docker –d --fixed-cidr=192.168.1.0/25
Более подробно мы обсудим это в разделе Настройка моста Docker.
Помимо сокета Unix, демон Docker может включаться в список терминала IPv4 TCP:
$ sudo docker -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock -d &
IPv4 и IPv6 могут работать совместно; это называется сдвоенным стеком
(dual stack). Такая поддержка сдвоенного стека делается возможной при выполнении демона Docker с флагом --ipv6
.
Docker установит мост docker0
с локальной связью IPv6 fe80::1
.
Все совместно используемые между контейнерами пакеты будут проходить через такой мост.
Для назначения маршрутизируемых адресов IPv6 адресов вашим контейнерам вы должны определить подсеть IPv6, откуда вы сможете выбирать нужные адреса.
Следующие команды при помощи параметра --fixed-cidr-v6
устанавливают подсеть IPv6 при запуске
демона Docker и кроме того добавляют новый маршрут в таблицу маршрутизации:
# docker –d --ipv6 --fixed-cidr-v6="1553:ba3:2::/64"
# docker run -t -i --name c0 ubuntu:latest /bin/bash
Следующий рисунок демонстрирует настроенный с диапазоном адресов IPv6 мост Docker:
Если внутри контейнера при помощи ifconfig
вы проверите диапазон адресов IP, вы отметите, что интерфейсу
eth0
была назначена соответствующая подсеть, что показывается в следующем коде:
#ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:01
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:1/64 Scope:Link
inet6 addr: 1553:ba3:2::242:ac11:1/64 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:7 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:738 (738.0 B) TX bytes:836 (836.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Весь обмен с подсетью 1553:ba3:2::/64
будет маршрутизироваться через интерфейс
docker0
.
Предыдущий контейнер назначался с применением fe80::42:acff:fe11:1/64
в качестве адреса
локальной связи и 1553:ba3:2::242:ac11:1/64
в качестве глабального адреса маршрутизации.
Docker предоставляет имя хоста и настройки DNS каждому контейнеру без нашего вмешательства в построение настраиваемого под пользователя образа.
Он совмещает (overlay) папку /etc
внутри данного контейнера виртуальными файлами, в которые он может
записывать новую информацию.
Это можно наблюдать выполнив команду mount
внутри этого контейнера. Контейнер получит то же самый
файл resolv.conf
, который имелся на машине хоста когда он первоначально создавался. Если файл хоста
resolv.conf
изменяется, это будет в файле контейнера /resolv.conf
только когда этот контейнер будет перезапущен.
В Docker вы можете установить параметры DNS двумя способами:
-
Воспользовавшись
run --dns=<ip-address>
-
Добавляя
DOCKER_OPTS="--dns ip-address"
в файл вашего демона Docker
Также вы можете определить поиск домена при помощи --dns-search=<DOMAIN>
.
Следующее изображение показывает настроенный в контейнере nameserver
с помощью установок DOCKER_OPTS
в файле вашего демона Docker:
Основными файлами DNS являются:
-
/etc/hostname
-
/etc/resolv.conf
-
/etc/hosts
Вот команда для добавления сервера DNS:
# docker run --dns=8.8.8.8 --net="bridge" -t -i ubuntu:latest /bin/bash
Имена хостов добавляются следующей командой:
#docker run --dns=8.8.8.8 --hostname=docker-vm1 -t -i ubuntu:latest /bin/bash
Обмен пакетами между контейнерами может осуществляться только если параметр ip-forward
установлен в значение 1
. Обычно вы просто оставляете сервер Docker в
состоянии настроек по умолчанию, --ip-forward=true
, а Docker установит
ip-forward
в значение 1
для вас
при старте этого сервера.
Для проверки текущих установок или включения пересылки IP вручную воспользуйтесь следующими командами:
# cat /proc/sys/net/ipv4/ip_forward
0#
echo 1 > /proc/sys/net/ipv4/ip_forward
# cat /proc/sys/net/ipv4/ip_forward
1
Разрешив ip-forward
, пользователи могут сделать возможным
взаимодействие между контейнерами и их внешним миром; это также будет необходимо для взаимодействия
между контейнерами в случае с установкой со множеством мостов. Следующий рисунок показывает как
--ip-forward=true
{Прим. пер.:
В оригинале опечатка: --ip-forward=false
.}
перенаправляет все пакеты к/от контейнера из/в внешней сетевой среды:
Docker не удаляет и не изменяет никакие правила в установленной цепочке фильтрации Docker. Это делает возможным пользователю создавать правила ограничения доступа к контейнеру.
Docker использует мост docker0
для потоков пакетов между всеми
имеющимися контейнерами на единичном хосте. Он добавляет правило для пересылки по цепочке используя
IPTables для организации перемещения пакетов между двумя контейнерами. Установка
--icc=false
отбрасывает все имеющиеся пакеты.
Когда демон Docker настроен и на --icc=false
, и на
--iptables=true
, а docker run
выполняется с параметром --link
, сервер Docker вставит пару правил
приёма из IPTables для новых контейнеров для соединения с портами, выставляемыми другими его контейнерами,
которые будут портами, которые упоминаются в строках выставления в своих Dockerfile. Следующий рисунок отображает
как ip_forward = false
отбрасывает все пакеты к/от контейнеру
из/в внешней сетевой среды:
По умолчанию правило Docker forward
разрешает все внешние IP.
Для открытия доступа только к определённым IP или сетевой среде, добавьте в верхней части цепочки
фильтрации Docker отвергающее правило.
Например, применяя следующую команду вы можете ограничить внешний доступ таким образом, что к
данному контейнеру может осуществлять доступ только обладатель IP источника
10.10.10.10
:
#iptables –I DOCKER –i ext_if ! –s 10.10.10.10 –j DROP
Ограничение доступа из одного контейнера к другому на SSH
Для ограничения SSH доступа от одного контейнера к другому следуйте таким шагам:
-
Создайте два контейнера,
c1
иc2
.Для
c1
воспользуйтесь следующей командой:# docker run -i -t --name c1 ubuntu:latest /bin/bash
Она породит следующий вывод:
root@7bc2b6cb1025:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:05 inet addr:172.17.0.5 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: 2001:db8:1::242:ac11:5/64 Scope:Global inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:7 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:738 (738.0 B) TX bytes:696 (696.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Для
c2
воспользуйтесь следующей командой:# docker run -i -t --name c2 ubuntu:latest /bin/bash
Она породит следующий вывод:
root@e58a9bf7120b:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:06 inet addr:172.17.0.6 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: 2001:db8:1::242:ac11:6/64 Scope:Global inet6 addr: fe80::42:acff:fe11:6/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:648 (648.0 B) TX bytes:696 (696.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Мы можем проверить наличие связи между контейнерами с использованием только что обнаруженных нами адресов. Давайте посмотри её сейчас применив инструмент
ping
:root@7bc2b6cb1025:/# ping 172.17.0.6 PING 172.17.0.6 (172.17.0.6) 56(84) bytes of data. 64 bytes from 172.17.0.6: icmp_seq=1 ttl=64 time=0.139 ms 64 bytes from 172.17.0.6: icmp_seq=2 ttl=64 time=0.110 ms ^C --- 172.17.0.6 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.110/0.124/0.139/0.018 ms root@7bc2b6cb1025:/# root@e58a9bf7120b:/# ping 172.17.0.5 PING 172.17.0.5 (172.17.0.5) 56(84) bytes of data. 64 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.270 ms 64 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.107 ms ^C --- 172.17.0.5 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.107/0.188/0.270/0.082 ms root@e58a9bf7120b:/#
-
Установите в обоих контейнерах сервер
openssh-server
#apt-get install openssh-server
-
Сделайте доступными iptables в вашей машине хоста:
-
Изначально вам будет доступен SSH из одного контейнера к другому.
-
Остановите службу Docker и добавьте
DOCKER_OPTS="--icc=false --iptables=true"
в Dockerfile по умолчанию вашей машины хоста. Этот параметр сделает доступным межсетевой экран iptables и отбросит все порты между контейнерами.По умолчанию,
iptables
не являются доступными на вашем хосте. Воспользуйтесь следующей командой для их доступности:root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination DOCKER all — 0.0.0.0/0 0.0.0.0/0 ACCEPT all — 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED ACCEPT all — 0.0.0.0/0 0.0.0.0/0 DOCKER all — 0.0.0.0/0 0.0.0.0/0 ACCEPT all — 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED ACCEPT all — 0.0.0.0/0 0.0.0.0/0 ACCEPT all — 0.0.0.0/0 0.0.0.0/0 ACCEPT all — 0.0.0.0/0 0.0.0.0/0 #service docker stop #vi /etc/default/docker
-
Docker Upstart и SysVinit файл установок. Настройте под себя местоположение своего исполняемого Docker (в особенности, при тестировании в процессе разработки):
#DOCKER="/usr/local/bin/docker"
-
Перезапустите службу Docker:
# service docker start
-
Проверьте iptables:
root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination DOCKER all — 0.0.0.0/0 0.0.0.0/0 ACCEPT all — 0.0.0.0/0 0.0.0.0/0 ctstate RELATED, ESTABLISHED ACCEPT all — 0.0.0.0/0 0.0.0.0/0 DOCKER all — 0.0.0.0/0 0.0.0.0/0 ACCEPT all — 0.0.0.0/0 0.0.0.0/0 ctstate RELATED, ESTABLISHED ACCEPT all — 0.0.0.0/0 0.0.0.0/0 ACCEPT all — 0.0.0.0/0 0.0.0.0/0 DROP all — 0.0.0.0/0 0.0.0.0/0
В
iptables
вашей машины хоста было добавлено правилоDROP
, которое отвергает соединение между контейнерами. Теперь вам будет недоступен SSH между контейнерами. -
[root@us-east-1 ~]# s3cmd ls s3://owncloud
-
-
Мы можем взаимодействовать или соединиться с контейнерами с применением параметра
--link
при помощи следующих шагов:-
Создайте первый контейнер, который будет выступать в роли вашего сервера,
sshserver
:root@ubuntu:~# docker run -i -t -p 2222:22 --name sshserver ubuntu bash root@9770be5acbab:/#
-
Выполните команду
iptables
и вы увидите добавленную цепочку правил Docker:#root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain DOCKER (0 references) target prot opt source destination ACCEPT tcp — 0.0.0.0/0 172.17.0.3 tcp dpt:22
-
Создайте второй контейнер, который выступает в роли клиента,
sshclient
:root@ubuntu:~# docker run -i -t --name sshclient --link sshserver:sshserver ubuntu bash root@979d46c5c6a5:/#
-
Мы можем видеть, что появились дополнительные правила в цепочке правил Docker:
root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain DOCKER (0 references) target prot opt source destination ACCEPT tcp — 0.0.0.0/0 172.17.0.3 tcp dpt:22 ACCEPT tcp — 172.17.0.4 172.17.0.3 tcp dpt:22 ACCEPT tcp — 172.17.0.3 172.17.0.4 tcp spt:22 root@ubuntu:~#
Следующий рисунок объясняет взаимодействие между контейнерами с применением флага
--link
:
-
-
Вы можете проинспектировать свой присоединённый контейнер при помощи команды
docker inspect
:root@ubuntu:~# docker inspect -f "{{ .HostConfig.Links }}" sshclient [/sshserver:/sshclient/sshserver]
теперь вы можете успешно осуществлять доступ ssh к
sshserver
по его IP адресу.#ssh root@172.17.0.3 –p 22
Применяя параметр --link
, Docker создаёт безопасный канал между
контейнерами который не требует делать видимыми вовне никакие порты ваших контейнеров.
Сервер Docker создаёт мост с именем docker0
по умолчанию внутри
ядра Linux, а он может передавать пакеты назад и далее между остальными физическими или виртуальными
интерфейсами так, как если бы они вели себя как отдельные сети Ethernet. Выполните следующую команду для
обнаружения списка интерфейсов в ВМ и те IP адреса, к которым они подключены:
root@ubuntu:~# ifconfig
docker0 Link encap:Ethernet HWaddr 56:84:7a:fe:97:99
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link
inet6 addr: fe80::1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11909 errors:0 dropped:0 overruns:0 frame:0
TX packets:14826 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:516868 (516.8 KB) TX bytes:46460483 (46.4 MB)
eth0 Link encap:Ethernet HWaddr 00:0c:29:0d:f4:2c
inet addr:192.168.186.129 Bcast:192.168.186.255
Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe0d:f42c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:108865 errors:0 dropped:0 overruns:0 frame:0
TX packets:31708 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:59902195 (59.9 MB) TX bytes:3916180 (3.9 MB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:336 (336.0 B) TX bytes:336 (336.0 B)
Когда у вас в наличии один или более запущенных и работающих контейнеров, вы можете подтвердить, что
Docker надлежащим образом соединил их с мостом docker0
выполнив
на своей машине хоста команду brctl
и промотрев его колонку
вывода interfaces
.
Перед настройкой моста docker0
установите утилиты моста:
# apt-get install bridge-utils
Вот хост с двумя различными присоединёнными контейнерами:
root@ubuntu:~# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.56847afe9799 no veth21b2e16
veth7092a45
Docker применяет настройки docker0
при каждом создании контейнера.
Он назначает новый IP адрес из доступного диапазона в мосте при каждом создании нового контейнера, как мы
можем увидеть здесь:
root@ubuntu:~# docker run -t -i --name container1 ubuntu:latest /bin/bash
root@e54e9312dc04:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:07
inet addr:172.17.0.7 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: 2001:db8:1::242:ac11:7/64 Scope:Global
inet6 addr: fe80::42:acff:fe11:7/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:7 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:738 (738.0 B) TX bytes:696 (696.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@e54e9312dc04:/# ip route
default via 172.17.42.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.7
По умолчанию Docker обеспечивает виртуальную сетевую среду с именем docker0
,
которая имеет IP адрес 172.17.42.1
. Контейнеры Docker имеют IP адреса
в диапазоне 172.17.0.0/16
.
Для изменения в Docker настроек умолчанию, отредактируйте его файл
/etc/default/docker
.
Изменения моста по умолчанию с docker0
на
br0
может быть сделано следующим образом:
# sudo service docker stop
# sudo ip link set dev docker0 down
# sudo brctl delbr docker0
# sudo iptables -t nat -F POSTROUTING
# echo 'DOCKER_OPTS="-b=br0"' >> /etc/default/docker
# sudo brctl addbr br0
# sudo ip addr add 192.168.10.1/24 dev br0
# sudo ip link set dev br0 up
# sudo service docker start
Следующая команда отображает новое имя моста и диапазон IP адресов службы Docker:
root@ubuntu:~# ifconfig
br0 Link encap:Ethernet HWaddr ae:b2:dc:ed:e6:af
inet addr:192.168.10.1 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::acb2:dcff:feed:e6af/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:738 (738.0 B)
eth0 Link encap:Ethernet HWaddr 00:0c:29:0d:f4:2c
inet addr:192.168.186.129 Bcast:192.168.186.255
Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe0d:f42c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:110823 errors:0 dropped:0 overruns:0 frame:0
TX packets:33148 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:60081009 (60.0 MB) TX bytes:4176982 (4.1 MB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:336 (336.0 B) TX bytes:336 (336.0 B)
Оверлейными (перекрывающими, overlay) являются виртуальные сетевые среды, которые стрятся поверх лежащих в основе сетевых инфраструктур (подстилающие, underlay). Их цель состоит в реализации сетевых служб, которые не доступны в физической сетевой среде.
Сетевые оверлеи драматически увеличивают число виртуальных подсетей которые могут быть созданы поверх физической сетевой среды, что в конечном итоге поддерживает множественную аренду и виртуализацию.
Каждому контейнеру в Docker назначается некий IP адрес, который применяется для взаимодействия с остальными контейнерами. Если контейнер должен взаимодействовать со своей внешней сетевой средой, вы настраиваете сетевую среду в системе хоста и выделяете или ставите в соответствие порт из контейнера в машину хоста. При таком подходе работающие внутри контейнера приложения не будут способны афишировать свои внешние IP и порты, поскольку данная информация им не доступна.
Решение в чём-то похоже назначению уникальных IP каждому контейнеру Docker по всем хостам и наличию некоторого сетевого продукта, который выполняет маршрутизацию обмена между хостами.
Для работы с сетевыми средами Docker существуют различные проекты, а именно:
-
Flannel
-
Weave
-
Open vSwitch
Flannel предоставляет решение, обеспечивая каждому контейнеру некий IP который может применяться для
взаимодействия контейнера- с- контейнером. Применяя инкапсуляцию пакета, он создаёт виртуальную оверлейную
сетевую среду поверх сетевой среды хоста. По умолчанию, Flannel обеспечивает хосту подсеть
/24
, из которой демон выделяет IP контейнерам. Следующий рисунок
показывает взаимодействие между контейнерами с применением Flannel:
На всех хостах flannel работает как агент, flanneld, и отвечает за выделение ареды подсети из предварительно настроенного пространства адресов. Для хранения настроек сетевой среды, выделения подсетей и вспомогательных данных (например, IP хоста) Flannel использует etcd.
Flannel применяет универсальное устройство TUN/TAP и создаёт оверлейную сетевую среду применяя UDP для инкапсуляции пакетов IP. Выделение подсети выполняется при помощи etcd, который устанавливает перекрывающее соответствие подсети-к-хосту.
Weave создаёт виртуальную сетевую среду, которая соединяет контейнеры Docker, развёртываемые в хостах/ ВМ и делает возможным их автоматическое обнаружение. Следующий рисунок отображает сетевую среду Weave:
Weave способен преодолевать межсетевые экраны и работать в частично соединённых сетевых средах. Обмен может быть опционально закодирован, что делает возможным хостам/ ВМ соединяться в сетевых средах с неподтверждённой безопасностью.
Weave расширяет существующие сетевые возможности Docker (для единичного хоста), такие как мост
docker0
, следовательно они могут продолжать применяться
контейнерами.
Open vSwitch является виртуальным коммутатором с OpenFlow- совместимым открытым исходным кодом, который обычно применяется с гипервизорами для интерконнекта виртуальных машин в пределах хоста, а также между различными хостами в сетевых средах. Перекрывающие сетевые среды требуют создания виртуальных путей данных с применением поддерживаемой инкапсуляции туннелирования, например, VXLAN и GRE.
Оверлейный путь данных предоставляется между терминалами туннеля расположенными в хосте Docker, что даёт возможность всем хостам в пределах данного сегмента поставщика напрямую соединяться друг с другом.
Как только контейнер становится работающим, в протоколе маршрутизации обновляется его префикс, объявляя его местоположение в качестве терминала туннеля. По мере получения обновлений прочими хостами Docker, правила перенаправления устанавливаются в OVS для терминала (endpoint) туннеля, который размежает данный хост. При свёртывании хоста происходит аналогичный процесс и терминал хостов Docker удаляет записи перенаправления для сворачиваемого контейнера. Следующий рисунок отображает взаимодействие между контейнерами работающими на множестве хостов через туннели VXLAN на основе OVS:
Рисунок 2.8. Взаимодействие контейнеров в сетевой среде с множеством хостов по туннелям VXLAN на основе OVS
В этой главе мы обсудили внутреннюю сетевую архитектуру Docker. Мы изучили настройки IPv4, IPv6 и DNS в Docker. Затем в этой главе мы рассмотрели мост Docker и взаимодействие между контейнерами в пределах одного хоста и множества хостов.
Также мы обсудили оверлейное туннелирование и различные методы которые реализуются в сетевых средах Docker, таких как OVS, Flannel и Weave.
В следующей главе мы изучим практическое построение сетей Docker, собираемых воедино при помощи различных инфраструктур.