docker高阶部分学习(三)---docker网络

560 阅读8分钟

docker网络(容器互联)

理解docker0

docker和ubuntu的通信

  • ip addr 查看网络的配置
    • GetImage (43).png
  • 查看启动的容器的网络配置
docker exec -it tomcat01 ip addr
  • 查看容器的内部网络地址,ip addr,发现容器启动的时候会得到一个96: eth0@if97的ip地址,docker自动分配的
    • GetImage (44).png

    • 思考:linux 能不能ping 通我们的容器内部?

      • 可以
      • GetImage (45).png
    • 原理

      • 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0,桥接模式,使用的技术就是evth-pair技术。
      • GetImage (46).png
    • 在启动一个容器,我们发现又多了一对网卡

    • 我们发现这个容器带来的网卡,都是一对对的

      • evth-pair 就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一端连着彼此
      • GetImage (47).png
      • 正是因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的

容器之间通信

  • 我们来测试下两个容器之间是不是能ping通

    • GetImage (48).png
    • 终极原理:docker0的路由转发
      • 我们感觉好像是容器之间的通信是直接联通的,其实并不是,而是我们的docker0充当了路由器的功能,首先tomcat01发送一条信息通过evth-pair技术传到docker0,然后docker0通过路由配置/广播机制,将我们的信息在通过evth-pair技术传送到tomcat02中
      • GetImage (49).png
    • 所有的容器在不指定网络的情况下,都是docker0进行路由的,docker都会给我们的容器分配一个默认的可用的ip
      • docker中所有的网络接口都是虚拟的,虚拟的转发效率高!
      • 当我们删除了这个容器的时候,evth-pair也是直接就消失了,docker自动管理
      • GetImage (50).png

通过名字来进行网络通信(不推荐)

  • 通过名字来进行网络通信

    • 问题

      • 我们每次重新启动容器,docker都是重新自动的分配evth-pair的地址,这样就会产生一个问题,假设我们写了一个服务,我们在服务中访问mysql,我们的MySQL是通过容器开启的,项目代码中写的是mysql的容器地址,mysql突然崩了,在重启ip就发生了变化,我们服务访问不到mysql,这样服务就会出现问题
    • 解决办法

      • 通过容器名称进行访问,访问到的是容器的ip地址,容器的名称不会变,ip即使变了,我们指向名字依旧可以找到ip

      • 技术 --link

        • docker run -d -P --name tomcat03 --link tomcat02 tomcat
          
        • GetImage (51).png

      • 反过来使用tomcat02去ping 容器tomcat03,是否能ping通?

        • 不能
        • GetImage (52).png
      • --link的单项连接(使用局限太大,不推荐)

        • 原因
          • GetImage (53).png
          • GetImage (54).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": {} 
            } 
        ] 
        
      • 查看所有网络

        • 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 
            
          • 网络模式

            • Bridge:桥接 docker(默认,自己创建也是使用的是桥接的模式)
            • none:不配置网络
            • Host: 和宿主机共享网络
            • Container:容器网络联通(不推荐)

自定义网络(常见)

  • 自定义网络

    • 默认命令的完整版
    docker run -d -P --name tomcat01 --net bridge tomcat 
    
    • 我们直接使用的run命令 --net bridge 而这个是我们的docker0

    • 创建自定义网络

    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 网关路由
    • GetImage (55).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的测试

      • GetImage (56).png
      • 我们自定义网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
      • 好处:
        • 可以将不同的集群间建立不同的子网进行隔离,互不干扰
  • 网络联通

    • 实际上是我们的自定义网络中两个不同的自网络之间的打通

    • 测试下面的例程

      • GetImage (57).png
    • 解决方法:

      • GetImage (58).png

      • GetImage (59).png

      • Docker network conmect mynet tomcat01 
        
        • GetImage (60).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的问题
      • 测试结果

        • GetImage (61).png

实战Redis集群

  • 搭建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
        
    • 测试搭建结果

      • GetImage (62).png