docker-网络

483 阅读4分钟

一、Docker网络模型与跨主机的容器间通信原理与过程展示和分析

docker网络-host模式

优点:

  • 每个容器没有独立的net namespace,而是直接使用宿主机网卡通信
  • 服务器的端口只能被一个容器监听,其它容器再监听会出现端口冲突
  • 网络吞吐性能强(不需要iptables做目标地址和源地址转换)
  • 适用于在多台主机联合部署集群服务(redis cluster、elasticsearch cluster等)

缺点:

  • 单台主机运行较多容器的时候端口分配不好记录
  • 单台主机运行相同服务的时候端口的冲突问题

docker网络-bridge模式(网桥)

image.png

安装docker后 默认会创建 docker0 的网桥 image.png

优点

  • 基于net namespace为每个容器实现独立的网络空间(每一个容器一个独立的IP)
  • 同一个服务器的不同容器不会出现容器中的服务监听地址冲突
  • 同一个服务器的不同容器不会出现容器中的服务监听端口冲突
  • 适用于在单台主机运行多容器的场景(Harbor、LNMP以及基于docker-compsoe部署的由多容器组成的单机项目)

缺点

  • 需要维护每个服务的通信端口
  • 高并发的场景会有单节点瓶颈
  • 横向扩容需要在每台节点部署相同的服务
  • 进出宿主机的报文通过iptables进行转发,高并发的项目会有瓶颈 经验值: k8s相对 单机docker compose 网络损耗打8折

实验-创建测试容器

# 创建A
docker run -it -d -p 80:80 nginx:1.20.2-alpine 

# 创建B 
docker run -it -d -p 8080:8080 tomcat:7.0.93-alpine

iptables -vnL 可以看到添加了2个容器的IP的放行 image.png

多了2个veth设备 image.png

可以看到网桥上 多了2个接口 image.png

可以看到 会有两条DNAT的转换 image.png

containerA --> containerB 的网络走向(同一个宿主机)

  • step1 containerA 向对端发起网络请求 到vethA
  • step2 hostA 的docker0网桥
  • step3 containerB的 vethB

containerA --> containerB 的网络走向(跨宿主机)?

containerA 向对端发起网络请求(请求对端的hostB:hostB:DNAT_PORT)

  • step1 containerA 的vethA

  • step2 hostA 的docker0网桥

  • step3 hostA 的物理网卡

  • step4 hostB 的物理网卡

  • step5 hostB 的docker0网桥

  • step6 containerB 的vethB

抓包方法

tcpdump -nn -vvv -i vethbd9b771 -vvv -nn ! port 22 and ! arp and ! port 53 

同宿主机总结:

  • 1、同宿主机的容器通信,在docker0实现报文转发,不需要经过宿主机的eth0。

跨宿主机通信

  • 1、源容器产生请求报文发给网关docker0
  • 2、docker0检查报文的目的IP,如何是本机就直接转发,如果不是本机就转发给宿主机。
  • 3、目的宿主机收到报文后检查路由表,将源地址替换为本机IP并发送报文。
  • 4、目的主机收到请求报文,检查目的IP后将报文转发给docker0。
  • 5、docker0检查目的IP后匹配MAC地址表,将报文发送给目的MAC的容器。

创建测试容器

修改docker的默认IP地址范围

修改docker的默认IP地址范围:  
root@docker-server1:~# vim /lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=10.10.0.1/24 

root@docker-server1:~# systemctl daemon-reload && systemctl restart docker

root@docker-server2:~# vim /lib/systemd/system/docker.service  
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=10.20.0.1/24

root@docker-server2:~# systemctl daemon-reload && systemctl restart docker

注意 net.ipv4.ip_forward = 0 可能会导致网络转发有问题

容器的跨主机通信

在宿主机添加静态路由,将去往的目的容器网关(下一跳)指向目的容器所在的宿主机eth0网卡:

## 宿主机 172.31.6.202
root@docker-server1:~# route add -net 10.20.0.0/24 gw 172.31.6.202(宿主机的网卡地址) #去往10.20.0.0/24的下一跳是172.31.6.202
root@docker-server1:~# iptables -A FORWARD -s 172.31.0.0/21 -j ACCEPT #允许响应报文的转发

## 宿主机 172.31.6.201
root@docker-server2:~# route add -net 10.10.0.0/24 gw 172.31.6.201(宿主机的网卡地址)
root@docker-server2:~# iptables -A FORWARD -s 172.31.0.0/21 -j ACCEPT

创建自定义网络 创建新的网桥设备(默认安装时创建的是docker0)

root@docker-server2:~# docker network create -d bridge --subnet 10.200.0.0/24 --gateway 10.200.0.1 magedu-net

root@docker-server2:~# docker run -it -p 8080:8080 --name magedu-net-test --net=magedu-net alpine:3.16.2 sh