Informações básicas
Eu tenho um servidor com duas interfaces de rede executando o Docker. O Docker, como algumas ferramentas de virtualização, cria uma interface de ponte do Linux chamada docker0
. Essa interface é configurada por padrão com um IP 172.17.42.1
e todos os contêineres do Docker se comunicam com essa interface como gateway e recebem endereços IP no mesmo /16
intervalo. Pelo que entendi, todo o tráfego de rede de / para contêineres passa por um NAT, de maneira que parece ser de saída 172.17.42.1
e de entrada para o qual é enviado 172.17.42.1
.
Minha configuração é assim:
+------------+ /
| | |
+-------------+ Gateway 1 +-------
| | 10.1.1.1 | /
+------+-------+ +------------+ |
| eth0 | /
| 10.1.1.2 | |
| | |
| DOCKER HOST | |
| | | Internet
| docker0 | |
| (bridge) | |
| 172.17.42.1 | |
| | |
| eth1 | |
| 192.168.1.2 | \
+------+-------+ +------------+ |
| | | \
+-------------+ Gateway 2 +-------
| 192.168.1.1| |
+------------+
O problema
Desejo rotear todo o tráfego de / para qualquer contêiner do Docker da segunda eth1
192.168.1.2
interface para um gateway padrão 192.168.1.1
, enquanto todo o tráfego da / para a máquina host sai da eth0
10.1.1.2
interface para um gateway padrão de 10.1.1.1
. Eu tentei várias coisas até agora sem sucesso, mas a única coisa que acho que é a mais próxima de corrigir é usar o iproute2 da seguinte maneira:
# Create a new routing table just for docker
echo "1 docker" >> /etc/iproute2/rt_tables
# Add a rule stating any traffic from the docker0 bridge interface should use
# the newly added docker routing table
ip rule add from 172.17.42.1 table docker
# Add a route to the newly added docker routing table that dictates all traffic
# go out the 192.168.1.2 interface on eth1
ip route add default via 192.168.1.2 dev eth1 table docker
# Flush the route cache
ip route flush cache
# Restart the Docker daemon so it uses the correct network settings
# Note, I do this as I found Docker containers often won't be able
# to connect out if any changes to the network are made while it's
# running
/etc/init.d/docker restart
Quando trago um contêiner, não consigo sair dele depois de fazer isso. Não tenho certeza se as interfaces de ponte são tratadas da mesma maneira que as interfaces físicas são para esse tipo de roteamento, e só quero uma verificação de sanidade, além de dicas de como eu posso realizar essa tarefa aparentemente simples.
Respostas:
Você pode ter que procurar mais na configuração do iptables também. O Docker mascara todo o tráfego originado da sub-rede do contêiner, digamos 172.17.0.0/16, para 0.0.0.0. Se você executar
iptables -L -n -t nat
, poderá ver a cadeia POSTROUTING na tabela nat, que faz isso -Agora, você pode remover esta regra e substituí-la por uma regra que mascara todo o tráfego originado da sub-rede dos contêineres para o IP - 192.168.1.2 da sua segunda interface, pois é isso que você deseja. A regra de exclusão será, assumindo que seja a primeira regra na cadeia POSTROUTING -
Então você adiciona esta regra personalizada -
fonte
ip rule add from 172.17.0.0/16 table docker
ip route add default via 192.168.1.2 dev eth1 table docker
ip route flush cache
iptables -t nat -D POSTROUTING 1
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT --to-source 192.168.1.2
/etc/init.d/docker restart
. Tentei executar um ping e um traceroute de um contêiner e não consegui alcançar nada.Um amigo e eu encontramos esse problema exato em que queríamos que o docker suporte várias interfaces de rede para atender a solicitações. Estávamos trabalhando especificamente com o serviço AWS EC2, onde também estávamos conectando / configurando / trazendo as interfaces adicionais. Neste projeto , há mais do que você precisa, então tentarei incluir apenas o que você precisa aqui.
Primeiro, o que fizemos foi criar uma tabela de rotas separada para
eth1
:Em seguida, configuramos a tabela mangle para definir algumas marcas de conexão provenientes de
eth1
:Finalmente, adicionamos esta regra para todos os
fwmark
s usarem a nova tabela que criamos.O
iptables
comando abaixo restaurará a marca de conexão e permitirá que a regra de roteamento use a tabela de roteamento correta.Acredito que isso é tudo o que é necessário em nosso exemplo mais complexo, onde (como eu disse) nosso projeto foi anexar / configurar / exibir o
eth1
interface no momento da inicialização.Agora, este exemplo não impediria conexões de
eth0
atender solicitações até,docker0
mas acredito que você poderia adicionar uma regra de roteamento para impedir isso.fonte
O baile de máscaras não é de 172.17.42.1, mas sim
O que significa que esta regra não funcionará corretamente.
Experimente
fonte
ip rule add from 172.17.0.0/16 table docker
ip route add default via 192.168.1.2 dev eth1 table docker
ip route flush cache
/etc/init.d/docker restart
De dentro do recipiente Corri um traceroute e o primeiro salto foi 10.1.1.1, quando deveria ter sido 192.168.1.1