云计算和容器化技术的演进改变了应用程序的开发、部署和管理方式。这种转变给网络格局带来了重大变化,为DevOps 和 SRE 工程师带来了新的挑战和机遇。然而,在这场变革之中,一个显著的知识差距出现了,特别是在理解物理网络和硬件环境下的网络复杂性方面。
对 API 驱动的基础设施配置的日益依赖,抽象化了许多底层网络复杂性,使工程师能够更有效地部署和管理应用程序。虽然这种抽象简化了部署过程,但也导致了对网络基础原理的熟悉度降低。因此,工程师经常发现自己在复杂、分布式环境中解决网络通信故障排除、优化和安全问题的挑战。
覆盖网络,特别是容器化技术(如 Docker 和 Kubernetes)的范围内,已经成为弥合这一知识差距的重要概念。通过在物理网络基础设施之上提供一个虚拟网络层,覆盖网络提供了强大的抽象,简化了网络任务,并支持可扩展、安全的配置。
容器网络的演进
为了充分理解覆盖网络的重要性,必须了解容器网络的历史发展过程。在 Docker 的早期阶段,网络主要集中在单主机连接,其中同一主机上的容器可以使用桥接网络相互通信。然而,随着容器化的普及以及对多主机网络的需求不断增加,Docker 引入了更复杂的网络解决方案。
随着 Docker Swarm(集群)的引入,多主机网络成为了现实,使运行在不同主机上的容器能够无缝通信。最初,这是通过链接和大使容器实现的,这些容器充当容器间通信的代理。然而,这些方法在可扩展性和灵活性方面存在局限性。
随着容器生态系统的不断发展,出现了更多动态和可扩展的网络解决方案,例如覆盖网络。覆盖网络提供了一种跨多个主机创建虚拟网络的方法,使容器能够像在同一个网络上一样进行通信,而无需考虑它们的物理位置。这为开发更复杂、分布式的容器化应用程序铺平了道路。
理解覆盖网络
覆盖网络是构建在现有网络基础设施(如物理网络或其他覆盖网络)之上的虚拟网络。它创建一个独立的逻辑网络拓扑,可以跨越多个物理网络或设备,提供简化网络任务并支持灵活、动态网络配置的抽象级别。
覆盖网络的概念并不新鲜,几十年来一直应用于各种网络环境中。然而,云计算和容器化技术将覆盖网络推到了前沿,因为它们提供了一种解决这些环境中网络挑战的方法。
覆盖网络的核心是一个逻辑结构,它封装网络流量并将其路由到底层网络基础设施。它使用各种封装和隧道协议,例如 VXLAN、NVGRE 和 IPsec,在节点之间创建虚拟链接,而不管其物理位置或底层网络拓扑结构。
覆盖网络的主要优势之一是它们能够实现节点之间的无缝通信,而不管它们的物理位置或底层网络架构如何。通过抽象化物理网络的复杂性,覆盖网络允许应用程序和服务相互通信,就像它们在同一个本地网络上一样,即使它们分布在多个数据中心或云提供商之间。
覆盖网络还在网络配置中提供了高度的灵活性和敏捷性。它们允许网络管理员以编程方式创建、修改和拆除虚拟网络,而无需进行物理网络更改。这支持网络资源的快速配置和扩展,以及根据不断变化的应用程序需求和流量模式动态调整网络的能力。
此外,覆盖网络提供了增强的安全性和隔离功能。通过封装流量并在不同应用程序或租户之间创建逻辑隔离,覆盖网络可以帮助防止未经授权的访问和数据泄漏。它们还支持实施细粒度的安全策略和访问控制,进一步增强网络的整体安全态势。
Docker 网络和覆盖网络
Docker 作为最广泛采用的容器化平台,原生支持各种网络模式,包括桥接网络、主机网络和覆盖网络。其中,覆盖网络已成为跨多个主机实现容器之间通信的强大解决方案,使其特别适合在容器化环境中部署分布式应用程序。
Docker 网络驱动程序
Docker 网络通过一组驱动程序来实现,这些驱动程序配置容器的网络接口,管理网络连接,并确保隔离和安全性。这些驱动程序在确定容器如何相互交互以及如何与外部网络交互方面发挥着至关重要的作用。
Docker 网络驱动程序图一些主要的 Docker 网络驱动程序包括
- 桥接:Docker 中的默认网络驱动程序,它在主机上创建虚拟桥接网络,并将容器连接到该网络。同一桥接网络上的容器可以使用它们的 IP 地址相互通信。
- 主机:此驱动程序消除了容器和主机之间的网络隔离,允许容器直接使用主机的网络栈。这可以提供更好的性能,但会牺牲容器化的安全性和隔离优势。
- 覆盖:覆盖驱动程序支持跨多个 Docker 主机创建分布式网络。它允许运行在不同主机上的容器像在同一个网络上一样相互通信,而无需在主机之间进行显式路由。
- Macvlan:此驱动程序为每个容器分配一个 MAC 地址,使其在网络上看起来像一个物理设备。这允许容器直接连接到物理网络,使它们能够接收可路由的 IP 地址。
- Ipvlan:与 Macvlan 驱动程序类似,Ipvlan 驱动程序为每个容器提供一个唯一的 IP 地址。但是,它不会分配 MAC 地址,而是使用与主机接口相同的 MAC 地址,减少了 MAC 地址管理的开销。
每个驱动程序都有自己的用例、优势和局限性。了解这些驱动程序的特点和行为对于根据应用程序的特定需求优化容器网络至关重要。
Docker 中的覆盖网络
Docker 的覆盖网络允许将多个 Docker 主机集群在一起并作为单个统一系统进行管理。当在 Docker 集群中创建覆盖网络时,它跨越集群中的所有节点,创建一个虚拟网络,使容器能够无缝相互通信,而不管它们运行在哪个节点上。连接到覆盖网络的每个容器都会收到一个唯一的 IP 地址,即使容器被重新调度或移动到不同的节点,该地址也会保持一致。
Docker 中的覆盖网络使用 VXLAN(虚拟可扩展局域网)协议来封装和隧道跨底层物理网络的容器之间的网络流量。VXLAN 是一种广泛采用的标准,通过将第 2 层以太网帧封装在 UDP 数据包中,支持创建大规模的多租户网络。
在 Docker 中使用覆盖网络带来了几个主要优势
- 多主机网络:覆盖网络使运行在不同主机上的容器能够无缝相互通信,就像它们在同一个本地网络上一样。这对于部署跨越多个节点的分布式应用程序至关重要,例如微服务架构或集群数据库。
- 服务发现:Docker 的覆盖网络与内置的服务发现机制集成,允许容器使用服务名称而不是 IP 地址来发现和连接彼此。这简化了复杂、多容器应用程序的配置和管理。
- 负载均衡:Docker 中的覆盖网络支持跨多个容器实例对传入流量进行负载均衡。这支持服务的水平扩展,并有助于确保高可用性和性能。
- 安全:覆盖网络默认情况下提供一定程度的隔离和安全性。连接到覆盖网络的容器只能与同一个网络上的其他容器通信,容器之间的流量使用 IPsec 进行加密,提供额外的安全层。
Kubernetes 网络和 CNI 插件
Kubernetes 作为领先的容器编排平台,拥有自己的网络模型,并依赖于 CNI(容器网络接口)插件来为容器提供网络连接和策略执行。CNI 是一个标准化接口,允许不同的网络提供商为 Kubernetes 实现他们自己的网络解决方案。
在 Kubernetes 中,每个 Pod(一组一个或多个容器)都获得一个唯一的 IP 地址,Pod 内的容器可以使用 localhost 相互通信。但是,为了支持跨集群中不同节点的 Pod 之间的通信,Kubernetes 依赖于 CNI 插件。
Kubernetes 中使用的一些流行 CNI 插件包括
- Flannel:Flannel 是一个简单且轻量级的 CNI 插件,为 Kubernetes 集群提供一个平面覆盖网络。它使用 VXLAN 或 host-gw(主机网关)作为后端来封装和路由 Pod 之间的流量。
- Calico:Calico 是一个高度可扩展且灵活的 CNI 插件,提供高级网络功能,例如网络策略,并支持覆盖和非覆盖模式。它使用 BGP(边界网关协议)进行路由,并使用 IPIP(IP 中 IP)或 VXLAN 进行封装。
- Weave 网络: Weave Net 是一个功能齐全的 CNI 插件,它使用 VXLAN 创建虚拟网络覆盖。它为 Kubernetes 提供了一个简单易用的网络解决方案,具有内置加密和对网络策略的支持。
这些 CNI 插件与底层网络组件(如 Open vSwitch (OVS) 或 iptables)交互,以配置 pod 的网络接口和路由。它们还实现网络策略,这些策略允许根据标签和选择器对 pod 之间的流量进行细粒度控制。
Kubernetes 中的网络策略提供了一种定义规则的方法,这些规则控制哪些 pod 可以相互通信。它们充当 pod 的防火墙,根据 pod 标签、命名空间或 IP 范围等因素指定允许或拒绝哪些流量。网络策略由 CNI 插件实现,并在内核级别使用 iptables 或其他机制进行强制执行。
通过利用 CNI 插件和网络策略,Kubernetes 为容器化应用程序提供了安全高效的网络,确保 pod 可以相互通信,同时保持所需的隔离级别和访问控制。
使用覆盖网络部署 MinIO
为了说明覆盖网络在容器化环境中的有效性,让我们探索一个现实世界的场景:使用覆盖网络部署 MinIO 高性能 S3 兼容对象存储解决方案。
MinIO 旨在成为云原生且容器友好的,使其成为在容器化环境中部署的理想选择。它提供了一个可扩展的分布式存储层,可以轻松地与各种应用程序和服务集成。
步骤 1:创建覆盖网络
创建一个将用于 MinIO 部署的覆盖网络。此网络将跨越 Docker 集群中的所有节点,使 MinIO 节点能够相互通信以及与客户端应用程序通信。
docker network create --driver=overlay --attachable minio-overlay-network
docker network create
步骤 2:定义 MinIO 服务
使用 Docker Compose 文件 (minio-compose.yml
) 定义 MinIO 服务
version: '3.8'
services:
minio:
image: minio/minio:latest
command: server /data
volumes:
- minio-data:/data
networks:
- minio-overlay-network
deploy:
mode: global
placement:
constraints:
- node.role == worker
volumes:
minio-data:
networks:
minio-overlay-network:
external: true
docker compose 示例
此 Compose 文件使用官方 MinIO Docker 镜像定义了 MinIO 服务,将其附加到 minio-overlay-network 覆盖网络,并指定了一种全局部署模式,以便在 docker 集群中的每个工作节点上运行一个服务实例。
步骤 3:部署 MinIO 堆栈
使用以下命令将 MinIO 堆栈部署到 Docker 集群
docker stack deploy --compose-file minio-compose.yml minio
docker stack deploy
Docker 集群将在集群中的工作节点之间分发 MinIO 服务,在每个节点上创建一个服务实例。覆盖网络将使 MinIO 实例之间的无缝通信成为可能。
此外,要使用 docker service create 在多主机环境中部署容器,将使用 --network minio-overlay-network 标志和值,如以下命令所示,以在覆盖网络中将 MinIO 部署为复制服务
docker service create --name minio_service --network minio-overlay-network --replicas 4 -e "MINIO_ROOT_USER=minioadmin" -e "MINIO_ROOT_PASSWORD=minioadmin" minio/minio server /data
docker service create
预期结果:
服务 'minio_service' 在 'minio-overlay' 网络中创建了 4 个副本。
步骤 4:检查 MinIO 覆盖网络
使用 Docker Swarm 和覆盖网络部署 MinIO 服务后,必须检查网络配置以确保连接正常并解决任何问题。Docker 提供了 docker network inspect
命令来检索有关网络的详细信息。
要检查 minio-overlay-network
,请运行以下命令
docker network inspect minio-overlay-network
docker network inspect
此外,您可以使用 docker network inspect 命令来检索有关网络的特定信息,使用过滤和格式选项。
此命令将显示有关覆盖网络的全面详细信息,包括其配置、已连接的容器和网络端点。
示例输出
[
{
"Name": "minio-overlay-network",
"Id": "nvk9xhel1f1qs1nuzf2trbiv1",
"Created": "2023-06-03T15:30:00.123456789Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.1.0/24",
"Gateway": "10.0.1.1"
}
]
},
"Containers": {
"0e1f2d3c4b5a": {
"Name": "minio_service.1.abc123def456",
"EndpointID": "1a2b3c4d5e6f",
"MacAddress": "02:42:0a:00:01:03",
"IPv4Address": "10.0.1.3/24",
"IPv6Address": ""
},
...
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": {},
"Peers": [
...
]
}
]
输出:docker network inspect
输出提供了有关 minio-overlay-network 的宝贵信息,包括
- 网络 ID 和名称
- 范围(例如,swarm)
- 驱动程序(例如,overlay)
- IP 地址管理 (IPAM) 配置
- 已连接的容器及其网络端点
- 网络选项和标签
通过检查覆盖网络,您可以验证 MinIO 服务容器是否已正确连接,并识别任何与网络相关的问题。
例如,要获取覆盖网络的子网
docker network inspect --format='{{range .IPAM.Config}}{{.Subnet}}{{end}}' minio-overlay-network
docker network inspect --format
此命令将输出 minio-overlay-network 的子网配置。
步骤 5:访问 MinIO 容器和服务
部署 MinIO 服务并验证覆盖网络后,您可以访问 MinIO 容器和服务以与您的对象存储进行交互。
访问 MinIO 容器:您可以直接在容器的环境中执行命令(如 docker exec)或附加到容器以执行交互式任务。这种方法用于直接与在容器中运行的 MinIO 的特定实例进行交互。
要访问在容器内运行的 MinIO 服务器,您可以使用 docker exec 命令在容器内打开 shell 或执行命令。
首先,检索 MinIO 服务副本的容器 ID
CONTAINER_ID=$(docker ps --filter "name=minio_service" --format "{{.ID}}" | head -n 1)
Bash 脚本以设置 CONTAINER_ID
然后,在 MinIO 容器内打开一个 shell
docker exec -it $CONTAINER_ID sh
在 CONTAINER_ID 上使用交互式终端执行 docker
进入容器后,您可以运行 MinIO CLI 命令或直接与 MinIO 服务器交互。
例如,要使用 MinIO CLI 列出存储桶中的对象
mc ls minio/my-bucket
minio 客户端 (mc) 在 minio/my-bucket 中列出对象
此命令将列出存储在 "my-bucket" 存储桶中的对象。
访问 MinIO 服务:这涉及到考虑 MinIO 部署作为一个整体的交互,尤其是在 Docker Swarm 环境中,在该环境中可能存在多个 MinIO 副本运行。诸如扩展服务、更新服务或通过服务的已发布端口访问 MinIO Web 控制台之类的操作属于此类。
要访问部署在 Docker Swarm 集群中的 MinIO 服务,您可以使用 docker service
命令。
列出正在运行的服务
docker service ls
docker list services
预期结果
ID NAME MODE REPLICAS IMAGE PORTS
abc123def456 minio_service replicated 4/4 minio/minio *:9000->9000/tcp
验证 MinIO 服务副本的状态
docker service ps minio_service
列出服务进程状态
预期结果
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
def456abc123 minio_service.1 minio/minio node1 Running Running 5 minutes ago
ghi789jkl012 minio_service.2 minio/minio node2 Running Running 5 minutes ago
jkl012mno345 minio_service.3 minio/minio node3 Running Running 5 minutes ago
mno345pqr678 minio_service.4 minio/minio node4 Running Running 5 minutes ago
输出显示了 MinIO 服务的每个副本的详细信息,表明它们在 Docker 集群中的不同节点上运行并处于活动状态。
访问 MinIO Web 控制台:要访问 MinIO Web 控制台,请打开 Web 浏览器并导航到 http://<swarm-manager-ip>:9000
。将 <swarm-manager-ip>
替换为 Docker 集群中任何节点的 IP 地址。
系统将提示您输入访问密钥和密钥。从 MinIO 服务器日志或服务创建期间设置的环境变量中获取这些凭据。
登录后,您可以使用 MinIO Web 控制台来管理存储桶、上传/下载对象以及执行各种对象存储操作。
通过访问 MinIO 容器、服务和 Web 控制台,您可以有效地与使用覆盖网络部署的分布式对象存储进行交互。这使您能够跨集群中的多个节点无缝管理您的数据。
更新或从服务中删除网络
要更新已运行的服务的网络,您可以使用 docker service update --network-add
命令
docker service update --network-add minio-overlay-network <service-id>
docker service update --network-add
预期结果
<service-id>
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
如果服务错误地附加到网络,您可以使用 --network-rm 命令将其从该网络中删除
docker service update --network-rm minio-overlay-network <service-id>
docker service update --network-rm
步骤 5:测试 MinIO 连接
使用 MinIO 客户端 (mc) 或任何 S3 兼容的 SDK 或工具测试 MinIO 部署的连接性和功能。
此概述演示了 Docker 中的覆盖网络如何简化分布式存储解决方案(如 MinIO)的部署和管理。通过利用覆盖网络,MinIO 实例可以在 Docker 集群中的多个节点之间无缝通信,为容器化应用程序提供可扩展且弹性的存储层。
结论
覆盖网络已成为弥合 DevOps 和 SRE 工程师 在现代网络领域面临的知识差距的重要概念。通过提供一个强大的抽象层来简化网络复杂性,覆盖网络使容器化环境中能够部署可扩展、灵活且安全的网络配置。
Docker 对覆盖网络的原生支持以及通过 CNI 插件 与 Kubernetes 的集成,使分布式应用程序的部署和管理方式现代化。这些技术极大地简化了与现代云原生架构相关的网络挑战,允许容器在多个主机之间无缝通信。
总之,覆盖网络与 Docker 和 Kubernetes 等容器化技术相结合,为解决现代网络的挑战提供了一个强大的工具集。通过了解和利用这些技术,工程师可以构建可扩展、灵活且安全的基础设施,以推动数字时代的创新和业务成功。随着容器化采用的不断增长,熟练掌握覆盖网络将成为 DevOps 和 SRE 专业人员的一项重要技能,使他们能够充满自信和专业地应对现代网络的复杂性。
如果您对覆盖网络或任何网络有任何疑问,请随时在 Slack 或 hello@min.io 上与我们联系。