1.使用veth pair连接两个network namespace

1.1 基本使用

  1. # 查看linux上的network namespace
  2. sudo ip netns list
  3. # 删除network namespace
  4. sudo ip netns delete [name]
  5. # 创建network namespace
  6. sudo ip netns add test1
  7. # 查看namespace里的ip(可以看到只有环回口,并且是down的状态)
  8. sudo ip netns exec test1 ip a
  9. # 将状态设置为up(结果是UNKNOW,单个端口是没法up的,必须是一对)
  10. # sudo ip netns exec test1 ip link(这条也是查看)
  11. sudo ip netns exec test1 ip link set dev lo up

1.2 目标

# 将test1和test2连接起来(连接两个namespace)

docker网络与通信 - 图1

1.3 实现

1.查看本机link
ip link

2.添加veth pair
sudo ip link add veth-test1 type veth peer name veth-test2
# 再ip link发现出现了一对link,分别是veth-test1@veth-test2和veth-test2@veth-test1,均有mac地址,但没有ip,状态为down

3.将veth pair添加到namespace
sudo ip link set veth-test1 netns test1
sudo ip link set veth-test2 netns test2

4.查看namespace和本地的变化
#namespace
sudo ip netns exec test1 ip link
sudo ip netns exec test2 ip link

# 本地
# 发现本地ip link创建的一对veth pair已经消失了,不再有veth-test1@veth-test2和veth-test2@veth-test1了

5.给veth-test1和veth-test2分配ip地址
# 分配
sudo ip netns exec test1 ip addr add 192.168.118.1/24 dev veth-test1
sudo ip netns exec test2 ip addr add 192.168.118.2/24 dev veth-test2

# 启动
sudo ip netns exec test1 ip link set dev veth-test1 up
sudo ip netns exec test2 ip link set dev veth-test2 up

# 查看(发现已经正确有了ip地址)
sudo ip netns test1 ip a
sudo ip netns test2 ip a

6.两个namespace互ping(发现已经能够正确ping通)
sudo ip netns exec test1 ping 192.168.118.2
sudo ip netns exec test2 ping 192.168.118.1

2.docker网络

# 上面的示例是通过veth pair来实现的连接,那么docker呢
# docker创建一个容器,同时也会创建一个network namespace,怎么互通呢?

# 查看网络
docker network ls(bridge,host,none)

# 查看bridge网络上连接了哪些容器
docker network inspect [bridge的ID]

# 容器网络的连接
1.启动容器
docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"

2.查看veth pair对
# 运行ip -a发现多了一个15: vethxxxxxx@if14
# 运行docker exec test1 ip a发现多了一个14: eth0@if15
# 这两个其实就是一个veth pair对,他们将容器与docker0进行了连接,我们验证一下
sudo yum install bridge-utils

brctl show
bridge name  bridge id       STP enabled   intefaces
docker0      8000.0242301b1d5e no          vethxxxxx
# 其中这个vethxxxx就是本机ip -a时的那个虚拟eth

docker网络与通信 - 图2

# 访问外网

docker网络与通信 - 图3

3.容器间的link

# 我们已经有了一个容器busybox test1
# 现在创建test2,连接到test1
docker run -d --name test2 --link test1 busybox /bin/sh -c "while true; do sleep 3600; done"
# 这时候进入test2,ping test1的ip和test1这个名字均可以正常通
# 进入test1,ping test2的ip肯定是通的,但Ping test2的名字是不通的
# 但有一种例外,跟下面的创建network有关,如果两个容器都连接到了用户自定义的网络上.比如下面的my-bridge,而不是系统默认的docker0这个bridge,则默认情况下互相link好了,通过名字可以ping通
# 实际中--link这个参数很少使用

4.network的种类

1.bridge
sudo docker network create -d bridge my-bridge

# 新建容器指定网络为my-bridge
sudo docker run -d --name test3 --network my-bridge busybox /bin/sh -c "while true; do sleep 3600; done"

# 指定已经存在的容器到新的网络(原网络也还在,即test2即在my-bridge上,也在bridge上)
sudo docker network connect my-bridge test2

2.none
容器是孤立的(没有ip地址,mac地址,ip a里面除了回环地址也没别的,除了exec的方式可以进入容器,没有其他任何办法,用得非常少

3.host
也没有ip地址,mac地址,容器没有独立的namespace,与主机共享一套,ip a看到的信息与宿主机一致,容易造成端口冲突

5.docker多机通信

# 了解VXLAN
# 了解LVS(Linux Virtual Server)
# Overlay多机通信,依赖于etcd分布式kv存储,etcd能够保证ip地址不会冲突

docker网络与通信 - 图4
docker网络与通信 - 图5

6.routing mesh

Internal:
Container和Container之间的访问通过overlay网络(通过VIP虚拟IP)

Ingress:
如果服务有绑定接口,则此服务可以通过任意swarm节点的相应接口访问

# 查看本地创建的network namespcae
sudo ls /var/run/docker/netns
10de222a0ebc 1-heweupwlcu 1-obe9f2751s ingress_sbox

# 进入ingress_sbox
sudo nsenter --net=/var/run/docker/netns/ingress_sbox

docker网络与通信 - 图6