覆盖网络在大多数云原生微服务应用程序中处于核心位置。在本章中,我们将让您了解Docker上的覆盖网络。
Windows上的Docker覆盖网络与Linux具有功能平等性。这意味着本章中使用的示例在Linux和Windows上都可以工作。
我们将本章分为通常的三个部分:
- 简要说明
- 深入探讨
- 命令
让我们进行一些网络魔法。
Docker叠加网络 - 简而言之
在现实世界中,容器必须能够在不同主机上、不同网络中可靠且安全地进行通信。这就是叠加网络发挥作用的地方。它们创建了一个横跨多个主机的平面、安全的第二层网络。不同主机上的容器可以连接到同一叠加网络并直接进行通信。
Docker提供了本地叠加网络,配置简单且默认情况下安全。
在幕后,它是建立在libnetwork和本地叠加驱动程序之上的。Libnetwork是容器网络模型(CNM)的官方实现,而叠加驱动程序则实现了所有的网络机制。
Docker叠加网络 - 深入
在2015年3月,Docker, Inc.收购了一家名为Socket Plane的容器网络初创公司。收购背后的两个原因是为Docker引入真正的网络功能,以及使容器网络足够简单,即使开发人员也能轻松使用它。
他们在这两方面都取得了超越预期的成就,叠加网络仍然是2023年以及可预见的未来容器网络的核心。
然而,在一些简单的网络命令背后隐藏着许多复杂性。这是在进行生产部署和尝试解决问题之前需要理解的内容。
本节的其余部分将分为两个部分:
- 构建和测试Docker叠加网络
- 解释叠加网络
构建和测试Docker叠加网络
以下示例将使用两个配置为集群的Docker节点。这两个节点位于由路由器连接的两个不同网络上。
如果您在跟随操作,节点是否在由路由器连接的两个不同网络上并不重要,但它们可以这样配置。唯一需要的是两个节点都运行Docker,具有网络连通性,并可以配置成一个集群。这意味着您可以在Play with Docker上跟随操作,也可以在本地机器上的几个Multipass虚拟机上跟随操作,或者在公共云中进行操作。
虽然在Docker Desktop上跟随操作是可能的,但您将无法获得完整的体验,因为您只能访问一个节点。
初始配置如图12.1所示。如果您的节点在同一网络上,一切都将正常工作,只是您的底层网络会更简单。我们稍后将解释底层网络。
搭建一个Swarm集群
首先要做的是将这两个节点配置为一个Swarm集群。这是因为Swarm模式是Docker Overlay网络的先决条件。
我们将在node1上运行docker swarm init
命令以使其成为管理节点,然后在node2上运行docker swarm join
命令以使其成为工作节点。这不是一个生产级别的设置,但对于学习实验来说足够了。鼓励您测试更多的管理节点和工作节点,并扩展示例。
如果您在自己的实验室中跟着进行操作,需要用您环境中正确的值替代IP地址和名称。您还需要确保没有任何防火墙阻止这两个节点之间的以下端口通信:
- 2377/tcp 用于管理平面通信
- 7946/tcp 和 7946/udp 用于控制平面通信(基于SWIM的通信)
- 4789/udp 用于VXLAN数据平面
在node1上运行以下命令。
$ docker swarm init
--advertise-addr=172.31.1.5
--listen-addr=172.31.1.5:2377
Swarm initialized: current node (1ex3...o3px) is now a manager.
复制输出中包含的docker swarm join
命令,并将其粘贴到node2上的终端中。
$ docker swarm join
--token SWMTKN-1-0hz2ec...2vye
172.31.1.5:2377
This node joined a swarm as a worker.
现在我们有一个包含两个节点的Swarm,其中node1是管理节点,node2是工作节点。
创建一个新的覆盖网络
从node1(管理节点)运行以下命令来创建一个名为uber-net的新覆盖网络。
$ docker network create -d overlay uber-net
c740ydi1lm89khn5kd52skrd9
就这样。您刚刚创建了一个全新的覆盖网络,可供群集中的所有主机使用,并且其控制平面使用TLS进行加密(使用自动每12小时旋转密钥的AES GCM模式)。如果要加密数据平面,只需在命令中添加 -o encrypted 标志。但是,默认情况下不启用数据平面加密,因为会导致性能开销。在生产环境中启用数据平面加密之前,请务必测试性能。但是,如果启用了数据平面加密,它将由相同的AES GCM模式和密钥轮换保护。
如果您对诸如控制平面和数据平面之类的术语不太了解...控制平面流量是集群管理流量,而数据平面流量是应用程序流量。默认情况下,Docker覆盖网络加密集群管理流量,但不加密应用程序流量。您必须明确启用应用程序流量的加密。
您可以使用 docker network ls 命令列出每个节点上的所有网络。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
ddac4ff813b7 bridge bridge local
389a7e7e8607 docker_gwbridge bridge local
a09f7e6b2ac6 host host local
ehw16ycy980s ingress overlay swarm
2b26c11d3469 none null local
c740ydi1lm89 uber-net overlay swarm
新创建的网络位于列表底部,名为 uber-net。其他网络是在安装Docker和初始化群集时自动创建的。
如果您在node2上运行 docker network ls 命令,您会注意到它不会显示 uber-net 网络。这是因为只有当工作节点被分配运行网络上的容器任务时,才会将新的覆盖网络扩展到工作节点。这种惰性扩展覆盖网络的方法通过减少网络八卦的数量来提高可伸缩性。
将服务连接到覆盖网络
现在我们有了一个覆盖网络,让我们将一个新的Docker服务连接到它。这个示例将创建一个包含两个副本的服务,以便一个运行在node1上,另一个运行在node2上。这将自动将uber-net覆盖扩展到node2。
从node1运行以下命令。
$ docker service create --name test
--network uber-net
--replicas 2
ubuntu sleep infinity
该命令创建了一个名为test的新服务,并将两个副本都附加到uber-net覆盖网络。因为我们在一个两节点的Swarm上运行两个副本,所以一个副本将被调度到每个节点上。
使用docker service ps命令来验证操作。
$ docker service ps test
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE
77q...rkx test.1 ubuntu node1 Running Running
97v...pa5 test.2 ubuntu node2 Running Running
在node2上运行docker network ls,以验证它现在可以看到这个网络。
独立的容器,即不属于Swarm服务的容器,除非网络是使用attachable=true属性创建的,否则不能连接到覆盖网络。可以使用以下命令创建一个可附加的覆盖网络,独立容器可以连接到该网络。
$ docker network create -d overlay --attachable uber-net
恭喜你。你已经创建了一个覆盖网络,跨越了两个位于不同物理底层网络上的节点。你还将两个容器连接到了这个网络。这有多简单!
当你在理论部分的时候,当你意识到背后发生的事情有多么复杂时,你将完全欣赏到你所做的简单性!
测试覆盖网络
让我们使用ping命令来测试覆盖网络。
如图12.2所示,我们有两个位于不同网络上的Docker主机,以及一个跨越两者的覆盖网络。我们还有一个连接到每个节点上的覆盖网络的容器。让我们看看它们是否可以相互ping通。
您可以通过名称对远程容器执行测试。不过,示例将使用IP地址,因为这给了我们一个学习如何查找容器IP地址的机会。
运行docker inspect
来查看分配给覆盖网络的子网以及分配给两个测试服务副本的IP地址。
$ docker inspect uber-net
[
{
"Name": "uber-net",
"Id": "c740ydi1lm89khn5kd52skrd9",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",