Docker高级学习(四) docker网络(容器互联)

1,597 阅读8分钟

压缩包

  • Save
    • image.png
  • Load
    • image.png

docker网络(容器互联)

理解docker0

  • 理解docker0
    • ip addr 查看网络的配置
    • image.png

查看启动的容器的网络配置

docker  exec -it tomcat01 ip addr
  • 查看启动的容器的网络配置
    • 查看容器的内部网络地址,ip addr,发现容器启动的时候会得到一个96: eth0@if97的ip地址,docker自动分配的
    • image.png
    • 思考:linux 能不能ping 通我们的容器内部?
      • 可以
      • image.png

原理

  • 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0,桥接模式,使用的技术就是evth-pair技术。
    • image.png
    • 在启动一个容器,我们发现又多了一对网卡
    • 我们发现这个容器带来的网卡,都是一对对的
      • evth-pair 就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一端连着彼此
      • image.png
      • 正是因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的
  • 我们来测试下两个容器之间是不是能ping通
    • image.png
    • 终极原理:docker0的路由转发
      • 我们感觉好像是容器之间的通信是直接联通的,其实并不是,而是我们的docker0充当了路由器的功能,首先tomcat01发送一条信息通过evth-pair技术传到docker0,然后docker0通过路由配置/广播机制,将我们的信息在通过evth-pair技术传送到tomcat02中
      • image.png
    • 所有的容器在不指定网络的情况下,都是docker0进行路由的,docker都会给我们的容器分配一个默认的可用的ip
      • docker中所有的网络接口都是虚拟的,虚拟的转发效率高!
      • 当我们删除了这个容器的时候,evth-pair也是直接就消失了,docker自动管理
      • image.png

通过名字来进行网络通信

  • 通过名字来进行网络通信
    • 问题
      • 我们每次重新启动容器,docker都是重新自动的分配evth-pair的地址,这样就会产生一个问题,假设我们写了一个服务,我们在服务中访问mysql,我们的MySQL是通过容器开启的,项目代码中写的是mysql的容器地址,mysql突然崩了,在重启ip就发生了变化,我们服务访问不到mysql,这样服务就会出现问题
    • 解决办法
      • 通过容器名称进行访问,访问到的是容器的ip地址,容器的名称不会变,ip即使变了,我们指向名字依旧可以找到ip
      • 技术 --link
        docker run -d -P --name tomcat03 --link tomcat02 tomcat
        
        image.png
      • 反过来使用tomcat02去ping 容器tomcat03,是否能ping通?
        • 不能
        • image.png
      • --link的单项连接(使用局限太大,不推荐)
        • 原因
          • image.png
          • image.png
        • 本质
          • 实际上就是我们在hosts文件中增加了一个172.17.0.3 tomcat02 容器id
    • 查看网络详情
      docker network inspect bridge
      
      root@iZbp12kyfwxfku3288sr59Z:~# docker network inspect bridge
      [
      {
          "Name": "bridge",
          "Id": "d80554cf321bff3d2821acfe37abdff08809fa1ee0f4a8d37693bb949e529476",
          "Created": "2020-10-02T13:30:57.993132975+08:00",
          "Scope": "local",
          "Driver": "bridge",
          "EnableIPv6": false,
          "IPAM": {
              "Driver": "default",
              "Options": null,
              "Config": [
                  {
                      "Subnet": "172.17.0.0/16",
                      "Gateway": "172.17.0.1"                                       # docker0
                  }
              ]
          },
          "Internal": false,
          "Attachable": false,
          "Ingress": false,
          "ConfigFrom": {
              "Network": ""
          },
          "ConfigOnly": false,
          "Containers": {                                                                               # 容器的网络
              "6fcc850bb9dda8098daae0129af2995a823330a79d6fc74a536e4f53b5bc093a": {
                  "Name": "tomcat02",
                  "EndpointID": "e54399c3dd68ca240379dfff6251652a888e61fa880b90334ac8cff872794521",
                  "MacAddress": "02:42:ac:11:00:03",
                  "IPv4Address": "172.17.0.3/16",                          # tomcat02的网络
                  "IPv6Address": ""
              },
              "8d2b39b543083ba0028212ccf2fc986eeb9b7591662c28b0171321c7dcaf93d5": {
                  "Name": "tomcat01",
                  "EndpointID": "453f09d79583b22ce429d2054eb720b0666d2cfb0c5978379b6a7dd89aa2907f",
                  "MacAddress": "02:42:ac:11:00:02",
                  "IPv4Address": "172.17.0.2/16",                          # tomcat01的网络
                  "IPv6Address": ""
              },
              "acf6df2a5d4e36e23b32aad793f1d28b9f91dfc1a53ecac569ec1c64f812ed3e": {
                  "Name": "tomcat03",
                  "EndpointID": "60eeb95e2e97d91070378771d2a4bd384e55e2285603232e067dd6cb25ebd622",
                  "MacAddress": "02:42:ac:11:00:04",
                  "IPv4Address": "172.17.0.4/16",                         # tomcat03的网络
                  "IPv6Address": ""
              }
          },
          "Options": {
              "com.docker.network.bridge.default_bridge": "true",
              "com.docker.network.bridge.enable_icc": "true",
              "com.docker.network.bridge.enable_ip_masquerade": "true",
              "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
              "com.docker.network.bridge.name": "docker0",
              "com.docker.network.driver.mtu": "1500"
          },
          "Labels": {}
      }
      ]
      
    • 查看所有网络
      • 网络模式
        • Bridge:桥接 docker(默认,自己创建也是使用的是桥接的模式)
        • none:不配置网络
        • Host: 和宿主机共享网络
        • Container:容器网络联通(不推荐)
      docker network ls
      root@iZbp12kyfwxfku3288sr59Z:~# docker network ls
      NETWORK ID          NAME                DRIVER              SCOPE
      d80554cf321b        bridge              bridge              local
      0985e4179804        host                host                local
      d95b28d99da4        none                null                local
      

自定义网络

  • 默认命令的完整版
    • 我们直接使用的run命令 --net bridge 而这个是我们的docker0
docker run -d -P --name tomcat01 --net bridge tomcat
  • 创建自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
  • 参数
    • --driver bridge 网络模式
    • --subnet 192.168.0.0/16 定义网段和主机数目 255*255
    • --gateway 192.168.0.0 网关路由
    • image.png
    • 自定义网络mynet的详细信息
      root@iZbp12kyfwxfku3288sr59Z:~# docker network inspect mynet 
      [
          {
              "Name": "mynet",
              "Id": "11690a7560b3c847045e9216a2fb3e91d90b0c8c8c5c3711ac57ce834ed0991b",
              "Created": "2020-10-04T20:50:40.991733452+08:00",
              "Scope": "local",
              "Driver": "bridge",                                            # 网络模式
              "EnableIPv6": false,
              "IPAM": {
                  "Driver": "default",
                  "Options": {},
                  "Config": [
                      {
                          "Subnet": "192.168.0.0/16",                # 子网掩码
                          "Gateway": "192.168.0.1"                    # 网关
                      }
                  ]
              },
              "Internal": false,
              "Attachable": false,
              "Ingress": false,
              "ConfigFrom": {
                  "Network": ""
              },
              "ConfigOnly": false,
              "Containers": {},
              "Options": {},
              "Labels": {}
          }
      ]
      
    • 创建三个自定义网络下的容器
      root@iZbp12kyfwxfku3288sr59Z:~# docker network inspect mynet 
      [
          {
              "Name": "mynet",
              "Id": "11690a7560b3c847045e9216a2fb3e91d90b0c8c8c5c3711ac57ce834ed0991b",
              "Created": "2020-10-04T20:50:40.991733452+08:00",
              "Scope": "local",
              "Driver": "bridge",
              "EnableIPv6": false,
              "IPAM": {
                  "Driver": "default",
                  "Options": {},
                  "Config": [
                      {
                          "Subnet": "192.168.0.0/16",
                          "Gateway": "192.168.0.1"
                      }
                  ]
              },
              "Internal": false,
              "Attachable": false,
              "Ingress": false,
              "ConfigFrom": {
                  "Network": ""
              },
              "ConfigOnly": false,
              "Containers": {                                                    # 在这个部分的容器选项中,包含了三个容器
                  "5ef9b87d364aafd27a509422bb24cdfbd249c2bcf74b2297b47bbfae1601b1e8": {
                      "Name": "tomcat-net-01",
                      "EndpointID": "e83f9febc5939b18d3e6c459c8564c12389c10cc2346678060327235437c23c3",
                      "MacAddress": "02:42:c0:a8:00:02",
                      "IPv4Address": "192.168.0.2/16",   
                      "IPv6Address": ""
                  },
                  "99c0df5990a5ec9d78fc392eb0ee698d00f320e387b5a66d05782ea2013ac3a1": {
                      "Name": "tomcat-net-03",
                      "EndpointID": "41c4e5a4f2f5712a3a070e5337aa80021e8c13844cac1243aa1d8b371cb1679e",
                      "MacAddress": "02:42:c0:a8:00:04",
                      "IPv4Address": "192.168.0.4/16",
                      "IPv6Address": ""
                  },
                  "cb12e21c37b83c38d894cca0a3b55816aebca90ba8b3b083289f28608d70a566": {
                      "Name": "tomcat-net-02",
                      "EndpointID": "ba491227f9a347145718fd051ff461aa1bd7200c66cacf3397a5a915a86e52a3",
                      "MacAddress": "02:42:c0:a8:00:03",
                      "IPv4Address": "192.168.0.3/16",
                      "IPv6Address": ""
                  }
              },
              "Options": {},
              "Labels": {}
          }
      ]
      
    • 通过ip和容器名称进行ping的测试
      • image.png
      • 我们自定义网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
      • 好处:
        • 可以将不同的集群间建立不同的子网进行隔离,互不干扰

网络联通

  • 实际上是我们的自定义网络中两个不同的自网络之间的打通
  • 测试下面的例程
    • image.png
  • 解决方法:
    • image.png
    • image.png
    Docker network conmect mynet tomcat01
    
    • image.png
      • 通过上图我们发现 tomcat01有两个ip 在docker0下的ip是172.17.0.1,在mynet下的IP是192.168.0.5,这个和阿里云的网络很像,在公网中121.199.122.222(公网ip),而172.186.11.1(就是私网ip),解释了一个容器两个IP的问题
    • 测试结果
      • image.png

实战

  • 搭建redis的集群
    • 第一步:创建子网
      docker network create redis --subnet 172.38.0.0/16
      
    • 第二步:使用shell脚本构建redis的节点
      for port in $(seq 1 6);\
      do \
      mkdir -p /mydata/redis/node-${port}/conf
      touch /mydata/redis/node-${port}/conf/redis.conf
      cat << EOF >> /mydata/redis/node-${port}/conf/redis.conf
      port 6379
      bind 0.0.0.0
      cluster-enabled yes
      cluster-config-file nodes.conf
      cluster-node-timeout 5000
      cluster-announce-ip 172.38.0.1${port}
      cluster-announce-port 6379
      cluster-announce-bus-port 16379
      appendonly yes
      EOF
      done
      
    • 第三步:设置容器(自定义网络、卷映射、端口等)
      # 将下面的红色数字替换成相应的1~6的序号就行
      docker run -p 6376:6379 -p 16676:16379 --name redis-6 -v /mydata/redis/node-6/data:/data -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
      
    • 第四步:进入redis的某一台机器
      docker exec -it redis-1 /bin/sh #redis默认没有bash
      
    • 第五步:创建集群,构建节点
      redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379  --cluster-replicas 1
      
    • 测试搭建结果
      • image.png