Networking entre KVM VM e Docker container no mesmo host

Em um host Debian-Stretch (conectado a physical LAN) eu tenho uma nova instalação do docker (v18.09) com um contêiner de banco de dados (porta mapeada para o host) e eu executo KVM/libvirt com alguns VMs Debian-Stretch. Posso acessar o contêiner docker e as VMs da LAN (dependendo da configuração através do túnel SSH ou direto), mas estou lutando para acessar o contêiner docker das VMs.

enter image description here

# brctl showbridge name         bridge id           STP enabled interfacesbr-f9f3ccd64037     8000.0242b3ebe3a0   no      docker0             8000.024241f39b89   no      veth35454acvirbr0              8000.525400566522   yes     virbr0-nic

Depois de ler por dias, encontrei uma solução muito atraente neste post Docker e KVM com uma ponte (original) que eu não comecei a trabalhar. A solução sugere iniciar o docker com um daemon de configuração de uma linha.código json para usar a ponte "padrão" KVM. Que bom seria isso! Há alguma esperança?

Tentei duas configurações diferentes para rede entre as VMs KVM. Em ambos os casos, a comunicação entre as VMs e a nuvem LAN + router + é impecável, mas eu simplesmente não sei como superar a cerca - para a grama mais verde... :)

Conf 1-KVM ponte padrão com NAT: posso ssh para o host Debian e acessar a porta do contêiner docker, mas há uma configuração com uma rota direta?

Conf 2-adaptador macvtap no modo Bridge para a LAN: não consigo fazer ping no ip da LAN host da VM, embora ambos estejam conectados ao mesmo roteador. A resposta da própria VM é Destination Host Unreachable. Algum pensamento por quê?

Seria melhor executar o daemon docker em uma VM separada em vez de diretamente no host Debian? Dessa forma, o contêiner e a VM podem acessar a ponte padrão KVM. Mas achei meio estranho executar o docker em uma VM em um host KVM.

Qualquer orientação clara seria apreciada!

Btw, a ponte br-f9f3ccd64037 é uma ponte definida pelo usuário que criei com o docker para futura comunicação entre contêineres. Não é usado.

Actualizacao:

Acabei de perceber que, com a primeira configuração, posso simplesmente me conectar ao contêiner docker por seu endereço IP (172.17.0.2) dos convidados da VM.

Minha configuração inicial foi a segunda configuração porque eu queria RDP nas VMs, o que é mais fácil, pois o driver macvtap conecta as VMs diretamente à LAN e nenhum link SSH é necessário. Foi quando eu não consegui chegar ao contêiner.

A solução foi tão simples quanto indicado no artigo vinculado. Não tenho certeza por que minha configuração não mudou na primeira vez que reiniciei o daemon do docker.

Depois que encontrei evidências no Documentação do Docker daemon para o argumento bridge no daemon.json, eu dei Outra Chance e o daemon do docker pegou a ponte padrão KVM na inicialização.

Primeiro eu criei o arquivo de configuração /etc/docker/daemon.json conforme sugerido na documentação com o seguinte conteúdo (a linha iptables pode nem ser necessária):

{"bridge": "virbr0","iptables": false}

tudo o que era necessário era:

docker stop mysqlsystemctl stop dockersystemctl start dockerdocker start mysql

E o contêiner docker existente estava funcionando na ponte KVM. O endereço IP do contêiner pode ser verificado com:

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mysql192.168.122.2

Não tenho certeza se posso remover a ponte docker0 agora, mas o contêiner está listado em virbr0 junto com as três VMs.

brctl showbridge name bridge id           STP enabled interfacesdocker0     8000.024241f39b89   no      virbr0      8000.068ff2a4a56e   yes         veth2abcff1                                            virbr0-nic                                            vnet0                                            vnet1                                            vnet2

Estou acostumado a implementar isso usando a seguinte configuração :

  • Eu crio um br0 ponte com o NIC físico dentro

  • as máquinas kvm estão conectadas na ponte usando o trecho de configuração qemu xml abaixo

    <interface type='bridge'>      <mac address='52:54:00:a9:28:0a'/>      <source bridge='br0'/>      <model type='virtio'/>      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>    </interface>
  • as pilhas do docker estão todas funcionando da mesma forma : reservo um IP roteável público para cada pilha. Eu conecto este IP público à ponte br0 usando o snippet de configuração do serviço opensvc abaixo.

    • o [ip#0] seção diz que queremos o ip 1.2.3.4 configurado no contêiner com ID de recurso container#0 que é um docker google / pause e conectado ao bridge br0

    • todos os outros dockers na configuração de rede do stack herit de container#0 devido à configuração netns = container#0 na declaração docker

    • quando o serviço opensvc é iniciado, a configuração de rede é feita pelo agente, produzindo todos os comandos relatados nos logs abaixo

configuração do serviço opensvc

[DEFAULT]docker_daemon_args = --log-opt max-size=1m --storage-driver=zfs --iptables=falsedocker_data_dir = /{env.base_dir}/dockerenv = PRDnodes = srv1.acme.com srv2.acme.comorchestrate = startid = 4958b24d-4d0f-4c30-71d2-bb820e043a5d[fs#1]dev = {env.pool}/{namespace}-{svcname}mnt = {env.base_dir}mnt_opt = rw,xattr,acltype = zfs[fs#2]dev = {env.pool}/{namespace}-{svcname}/dockermnt = {env.base_dir}/dockermnt_opt = rw,xattr,acltype = zfs[fs#3]dev = {env.pool}/{namespace}-{svcname}/datamnt = {env.base_dir}/datamnt_opt = rw,xattr,acltype = zfs[ip#0]netns = container#0ipdev = br0ipname = 1.2.3.4netmask = 255.255.255.224gateway = 1.2.3.1type = netns[container#0]hostname = {svcname}image = google/pauserm = truerun_command = /bin/shtype = docker[container#mysvc]image = mysvc/mysvc:4.1.3netns = container#0run_args = -v /etc/localtime:/etc/localtime:ro    -v {env.base_dir}/data/mysvc:/home/mysvc/server/datatype = docker[env]base_dir = /srv/{namespace}-{svcname}pool = data

log de inicialização

2019-01-04 11:27:14,617 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - checking 1.2.3.4 availability2019-01-04 11:27:18,565 - srv1.acme.com.appprd.mysvc.fs#1 - INFO - mount -t zfs -o rw,xattr,acl data/appprd-mysvc /srv/appprd-mysvc2019-01-04 11:27:18,877 - srv1.acme.com.appprd.mysvc.fs#2 - INFO - mount -t zfs -o rw,xattr,acl data/appprd-mysvc/docker /srv/appprd-mysvc/docker2019-01-04 11:27:19,106 - srv1.acme.com.appprd.mysvc.fs#3 - INFO - mount -t zfs -o rw,xattr,acl data/appprd-mysvc/data /srv/appprd-mysvc/data2019-01-04 11:27:19,643 - srv1.acme.com.appprd.mysvc - INFO - starting docker daemon2019-01-04 11:27:19,644 - srv1.acme.com.appprd.mysvc - INFO - dockerd -H unix:///var/lib/opensvc/namespaces/appprd/services/mysvc/docker.sock --data-root //srv/appprd-mysvc/docker -p /var/lib/opensvc/namespaces/appprd/services/mysvc/docker.pid --exec-root /var/lib/opensvc/namespaces/appprd/services/mysvc/docker_exec --log-opt max-size=1m --storage-driver=zfs --iptables=false --exec-opt native.cgroupdriver=cgroupfs2019-01-04 11:27:24,669 - srv1.acme.com.appprd.mysvc.container#0 - INFO - docker -H unix:///var/lib/opensvc/namespaces/appprd/services/mysvc/docker.sock run --name=appprd..mysvc.container.0 --detach --hostname mysvc --net=none --cgroup-parent /opensvc.slice/appprd.slice/mysvc.slice/container.slice/container.0.slice google/pause /bin/sh2019-01-04 11:27:30,965 - srv1.acme.com.appprd.mysvc.container#0 - INFO - output:2019-01-04 11:27:30,965 - srv1.acme.com.appprd.mysvc.container#0 - INFO - f790e192b5313d7c3450cb257d075620f40c2bad3d69d52c8794eccfe954f2502019-01-04 11:27:30,987 - srv1.acme.com.appprd.mysvc.container#0 - INFO - wait for up status2019-01-04 11:27:31,031 - srv1.acme.com.appprd.mysvc.container#0 - INFO - wait for container operational2019-01-04 11:27:31,186 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - bridge mode2019-01-04 11:27:31,268 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /sbin/ip link add name veth0pl20321 mtu 1500 type veth peer name veth0pg20321 mtu 15002019-01-04 11:27:31,273 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /sbin/ip link set veth0pl20321 master br02019-01-04 11:27:31,277 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /sbin/ip link set veth0pl20321 up2019-01-04 11:27:31,281 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /sbin/ip link set veth0pg20321 netns 203212019-01-04 11:27:31,320 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /usr/bin/nsenter --net=/var/lib/opensvc/namespaces/appprd/services/mysvc/docker_exec/netns/fc2fa9b2eaa4 ip link set veth0pg20321 name eth02019-01-04 11:27:31,356 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /usr/bin/nsenter --net=/var/lib/opensvc/namespaces/appprd/services/mysvc/docker_exec/netns/fc2fa9b2eaa4 ip addr add 1.2.3.4/27 dev eth02019-01-04 11:27:31,362 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /usr/bin/nsenter --net=/var/lib/opensvc/namespaces/appprd/services/mysvc/docker_exec/netns/fc2fa9b2eaa4 ip link set eth0 up2019-01-04 11:27:31,372 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /usr/bin/nsenter --net=/var/lib/opensvc/namespaces/appprd/services/mysvc/docker_exec/netns/fc2fa9b2eaa4 ip route replace default via 1.2.3.12019-01-04 11:27:31,375 - srv1.acme.com.appprd.mysvc.ip#0 - INFO - /usr/bin/nsenter --net=/var/lib/opensvc/namespaces/appprd/services/mysvc/docker_exec/netns/fc2fa9b2eaa4 /usr/bin/python3 /usr/share/opensvc/lib/arp.py eth0 1.2.3.42019-01-04 11:27:32,534 - srv1.acme.com.appprd.mysvc.container#mysvc - INFO - docker -H unix:///var/lib/opensvc/namespaces/appprd/services/mysvc/docker.sock run --name=appprd..mysvc.container.mysvc -v /etc/localtime:/etc/localtime:ro -v /srv/appprd-mysvc/data/mysvc:/home/mysvc/server/data --detach --net=container:appprd..mysvc.container.0 --cgroup-parent /opensvc.slice/appprd.slice/mysvc.slice/container.slice/container.mysvc.slice mysvc/mysvc:4.1.32019-01-04 11:27:37,776 - srv1.acme.com.appprd.mysvc.container#mysvc - INFO - output:2019-01-04 11:27:37,777 - srv1.acme.com.appprd.mysvc.container#mysvc - INFO - 1616cade9257d0616346841c3e9f0d639a9306e1af6fd750fe70e17903a110112019-01-04 11:27:37,797 - srv1.acme.com.appprd.mysvc.container#mysvc - INFO - wait for up status2019-01-04 11:27:37,833 - srv1.acme.com.appprd.mysvc.container#mysvc - INFO - wait for container operational

Quando eu li a pergunta, eu estava olhando para ver se havia uma maneira de se conectar virbr0 para uma rede Docker. A imagem abaixo é a minha modificação do que eu acho que estava sendo perguntado:

enter image description here

Se for esse o caso, a resposta é usar um macvlan rede, que permite anexar uma rede docker diretamente a um dispositivo host. Então, algo como o seguinte iria te dar o que você quer:

docker network create --driver=macvlan --subnet=192.168.0.0/16 -o parent=virbr0 mynet