Docker 与 K8S学习笔记(八)—— 自定义容器网络

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 我们在上一篇中介绍了Docker中三种网络,none、host和bridge,除了这三种网络,Docker还允许我们创建自定义网络,当我们要创建自定义网络时,Docker提供了三种网络驱动供我们选择:bridge、macvlan和overlay,其中macvlan和ovelay都是用于创建跨主机网络

Docker 与 K8S学习笔记(八)—— 自定义容器网络


我们在上一篇中介绍了Docker中三种网络,none、host和bridge,除了这三种网络,Docker还允许我们创建自定义网络,当我们要创建自定义网络时,Docker提供了三种网络驱动供我们选择:bridge、macvlan和overlay,其中macvlan和ovelay都是用于创建跨主机网络,我们后面在研究,本篇我们主要使用bridge驱动。


一、创建自定义网络


我们通过docker network create命令创建test_net1网络:


$ sudo docker network create --driver bridge test_net1
c7c20444a940135c92958f4434ca2b7428ba17f70a2a8a954a6cf160a011b513
$ sudo docker network ls
NETWORK ID     NAME        DRIVER    SCOPE
6f0087fd32cd   bridge      bridge    local
464b3d11003c   host        host      local
faa8eb8310b4   none        null      local
c7c20444a940   test_net1   bridge    local
$ brctl show
bridge name  bridge id    STP enabled  interfaces
br-c7c20444a940    8000.024200e01cd2  no
docker0    8000.0242cef1fc32  no


我们可以看到,此时系统中新增了一个网桥br-c7c20444a940,其中c7c20444a940就是我们刚刚创建的桥接网络的ID。我们可以看下test_net1的详细配置信息:


$ sudo docker network inspect test_net1
[
    {
        "Name": "test_net1",
        "Id": "c7c20444a940135c92958f4434ca2b7428ba17f70a2a8a954a6cf160a011b513",
        "Created": "2021-10-23T07:07:47.870947684Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]


如果我们在创建网络时,不指定--subnet和--gateway参数时,Docker会自动为其分配网段和网关,我们接着再创建一个网络并指定其网段和网关:


$ sudo docker network create --driver bridge --subnet 173.20.0.0/16 --gateway 173.20.0.1  test_net2
47542e86dc4474779a3b105f1d22f005fc39a529b1f19aa7af2c68297c1c0a41
$ sudo docker network inspect test_net2
[
    {
        "Name": "test_net2",
        "Id": "47542e86dc4474779a3b105f1d22f005fc39a529b1f19aa7af2c68297c1c0a41",
        "Created": "2021-10-23T07:21:47.684305897Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "173.20.0.0/16",
                    "Gateway": "173.20.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
$ brctl show
bridge name  bridge id    STP enabled  interfaces
br-47542e86dc44    8000.024273a34080  no
br-c7c20444a940    8000.024200e01cd2  no
docker0    8000.0242cef1fc32  no
$ ifconfig br-47542e86dc44
br-47542e86dc44: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 173.20.0.1  netmask 255.255.0.0  broadcast 173.20.255.255
        ether 02:42:73:a3:40:80  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


二、自定义网络的使用


容易要使用自定义的网络,同样需在启动时通过--network参数指定即可:


$ sudo docker run -it --network=test_net2 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ad:14:00:02 brd ff:ff:ff:ff:ff:ff
    inet 173.20.0.2/16 brd 173.20.255.255 scope global eth0
       valid_lft forever preferred_lft forever


我们可以看到Docker会根据容易所使用的网络的网段自动为容器分配IP,当然,容器IP也是可以指定的,即通过--ip参数,但是要注意两点:


  • 只有使用--subnet参数指定网段创建的网络才能指定IP


  • 所指定的IP一定要在所使用的网络的网段中

下图所示的错误就是容器使用的网络并没有通过--subnet指定网段:


$ sudo docker run -it --network=test_net1 --ip 172.19.0.5  busybox
docker: Error response from daemon: user specified IP address is supported only when connecting to networks with user configured subnets.

下图所示的错误是容器所指定IP不在其网络的指定网段内:


$ sudo docker run -it --network=test_net2 --ip 172.20.0.2  busybox
ERRO[0000] error waiting for container: context canceled
docker: Error response from daemon: Invalid address 172.20.0.2: It does not belong to any of this network's subnets.

以下是正确的指定容器IP的例子:


$ sudo docker run -it --network=test_net2 --ip 173.20.0.4  busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
54: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ad:14:00:04 brd ff:ff:ff:ff:ff:ff
    inet 173.20.0.4/16 brd 173.20.255.255 scope global eth0
       valid_lft forever preferred_lft forever


三、Docker网络隔离及原理


到目前位置我们创建使用test_net2网络创建了两个容器,那么这两个容器网络应该是互通的,我们来验证一下:


$ sudo docker run -it --network=test_net2 --ip 173.20.0.4  busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
54: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ad:14:00:04 brd ff:ff:ff:ff:ff:ff
    inet 173.20.0.4/16 brd 173.20.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 173.20.0.2
PING 173.20.0.2 (173.20.0.2): 56 data bytes
64 bytes from 173.20.0.2: seq=0 ttl=64 time=1.319 ms
64 bytes from 173.20.0.2: seq=1 ttl=64 time=0.106 ms
64 bytes from 173.20.0.2: seq=2 ttl=64 time=0.107 ms
^C
--- 173.20.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.106/0.510/1.319 ms


所以,我们得出结论,使用同一网络创建的容器是能够互通的。相反,如果是不同网络创建的容器应该是无法通信,我们使用test_net1创建一个容器验证一下:


$ sudo docker run -it --network=test_net1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
58: eth0@if59: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 173.20.0.2
PING 173.20.0.2 (173.20.0.2): 56 data bytes
^C
--- 173.20.0.2 ping statistics ---
146 packets transmitted, 0 packets received, 100% packet loss


从结果来看确实无法通信,但是如果我们开启系统的ip forwarding,把当前主机当作路由,那么不同网络应该是能通信的,我们首先来看下系统的配置:


$ ip r
default via 172.16.194.2 dev ens33 proto dhcp src 172.16.194.135 metric 100
172.16.194.0/24 dev ens33 proto kernel scope link src 172.16.194.135
172.16.194.2 dev ens33 proto dhcp scope link src 172.16.194.135 metric 100
172.19.0.0/16 dev br-c7c20444a940 proto kernel scope link src 172.19.0.1
173.20.0.0/16 dev br-47542e86dc44 proto kernel scope link src 173.20.0.1
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1


看来我们的主机已经开启了ip forwarding并且172.19.0.0/16和173.20.0.0/16的路由也定义好了,那为什么网络还是不通呢?我们看看iptables:


$ sudo iptables-save
# Generated by iptables-save v1.6.1 on Sat Oct 23 08:19:03 2021
*filter
...
# 如果数据包是从br-47542e86dc44流入但不从br-47542e86dc44流出则跳转到DOCKER-ISOLATION-STAGE-2处理
-A DOCKER-ISOLATION-STAGE-1 -i br-47542e86dc44 ! -o br-47542e86dc44 -j DOCKER-ISOLATION-STAGE-2
# 如果数据包是从br-c7c20444a940流入但不从br-c7c20444a940流出则跳转到DOCKER-ISOLATION-STAGE-2处理
-A DOCKER-ISOLATION-STAGE-1 -i br-c7c20444a940 ! -o br-c7c20444a940 -j DOCKER-ISOLATION-STAGE-2
# 如果数据包是从docker0流入但不从docker0流出则跳转到DOCKER-ISOLATION-STAGE-2处理
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
# 如果非以上三种情况则返回上一层处理
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
# 如果数据包流出到br-47542e86dc44则drop
-A DOCKER-ISOLATION-STAGE-2 -o br-47542e86dc44 -j DROP
# 如果数据包流出到br-c7c20444a940则drop
-A DOCKER-ISOLATION-STAGE-2 -o br-c7c20444a940 -j DROP
# 如果数据包流出到docker0则drop
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
# 如果非以上三种情况则返回上一层处理
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
...


看来原因就在这里了,我们发现Docker创建了一系列网络隔离策略,当数据包流入的网络与流出的网络相同则不作处理,不同则弃数据包,我们通过一个流程图来说明

DOCKER-ISOLATION-STAGE-1和DOCKER-ISOLATION-STAGE-2规则的逻辑:


 

如果我一定要两个使用不同网络的容器通信,该怎么处理呢?也很简单,我们只需要给容器添加对应的网络的的网卡即可,我们通过docker network connect命令可以实现:


# 0da5e260a4b6容器使用的是test_net1,另外两个使用的是test_net2,
# 如果大家在这一步不确定的话可以使用docker inspect 容器id进行确定 
$ sudo docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED       STATUS       PORTS     NAMES
0da5e260a4b6   busybox   "sh"      2 hours ago   Up 2 hours             objective_blackburn
c6871db3efbb   busybox   "sh"      2 hours ago   Up 2 hours             goofy_swartz
c683eacc4eae   busybox   "sh"      2 hours ago   Up 2 hours             modest_swartz
yangye@ayato:~$ sudo docker network connect test_net2 0da5e260a4b6


我们在容器0da5e260a4b6中先ping下173.20.0.2发现网络是通的,我们再看看其网络配置,发现容器中添加了my_net2网络的网卡eth1:


/ # ping 173.20.0.2
PING 173.20.0.2 (173.20.0.2): 56 data bytes
64 bytes from 173.20.0.2: seq=0 ttl=64 time=0.291 ms
64 bytes from 173.20.0.2: seq=1 ttl=64 time=0.100 ms
64 bytes from 173.20.0.2: seq=2 ttl=64 time=0.097 ms
64 bytes from 173.20.0.2: seq=3 ttl=64 time=0.100 ms
64 bytes from 173.20.0.2: seq=4 ttl=64 time=0.147 ms
^C
--- 173.20.0.2 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.097/0.147/0.291 ms
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:13:00:02
          inet addr:172.19.0.2  Bcast:172.19.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:25 errors:0 dropped:0 overruns:0 frame:0
          TX packets:150 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1830 (1.7 KiB)  TX bytes:14476 (14.1 KiB)
eth1      Link encap:Ethernet  HWaddr 02:42:AD:14:00:03
          inet addr:173.20.0.3  Bcast:173.20.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:18 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1440 (1.4 KiB)  TX bytes:574 (574.0 B)
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


好的,以上就是本篇的内容,下一篇我们再看看容器间通信方式。

 

分类: 容器技术

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
8天前
|
NoSQL 关系型数据库 MySQL
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
101 56
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
|
15天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
152 77
|
23天前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
|
2天前
|
Unix Linux Docker
CentOS停更沉寂,RHEL巨变限制源代:Docker容器化技术的兴起助力操作系统新格局
操作系统是计算机系统的核心软件,管理和控制硬件与软件资源,为用户和应用程序提供高效、安全的运行环境。Linux作为开源、跨平台的操作系统,具有高度可定制性、稳定性和安全性,广泛应用于服务器、云计算、物联网等领域。其发展得益于庞大的社区支持,多种发行版如Ubuntu、Debian、Fedora等满足不同需求。
15 4
|
17天前
|
数据建模 应用服务中间件 nginx
docker替换宿主与容器的映射端口和文件路径
通过正确配置 Docker 的端口和文件路径映射,可以有效地管理容器化应用程序,确保其高效运行和数据持久性。在生产环境中,动态替换映射配置有助于灵活应对各种需求变化。以上方法和步骤提供了一种可靠且易于操作的方案,帮助您轻松管理 Docker 容器的端口和路径映射。
59 3
|
20天前
|
安全 Docker 容器
docker的默认网络模式有哪些
Docker 默认网络模式包括:1) bridge:默认模式,各容器分配独立IP,可通过名称或IP通信;2) host:容器与宿主机共享网络命名空间,性能最优但有安全风险;3) none:容器隔离无网络配置,适用于仅需本地通信的场景。
34 6
|
24天前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
58 7
|
24天前
|
存储 Prometheus 监控
Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行
本文深入探讨了在Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行。
30 5
|
24天前
|
负载均衡 网络协议 算法
Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式
本文探讨了Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式,以及软件负载均衡器、云服务负载均衡、容器编排工具等实现手段,强调两者结合的重要性及面临挑战的应对措施。
53 3
|
24天前
|
存储 安全 数据安全/隐私保护
Docker 容器化应用管理更加高效,但数据安全和业务连续性成为关键。
在数字化时代,Docker 容器化应用管理更加高效,但数据安全和业务连续性成为关键。本文探讨了 Docker 应用的备份与恢复策略,涵盖备份的重要性、内容、方法及常见工具,制定备份策略,恢复流程及注意事项,并通过案例分析和未来趋势展望,强调备份与恢复在保障应用安全中的重要性。
29 2

相关产品

  • 容器服务Kubernetes版