容器网络概述

简介: 本文讲的是容器网络概述【编者的话】本文介绍容器网络,对容器网络的实践。
本文讲的是容器网络概述【编者的话】本文介绍容器网络,对容器网络的实践。

我在博客中经常讨论关于容器的事情,是因为我在工作中一直在关注着它们。

对于这些新奇容器的东西,最难理解的实际是关于容器的网络问题。

虽然有很多不同的方式来解决容器网络互连问题,并且介绍这方面的文档也很多,但是有些用起来很糟糕。我对这些非常的困惑,因此我试图在这篇博客当中用非专业术语的方式来理清这个问题。
(我不喜欢夸夸其谈,但是我对于容器网络文档当前状态真的很沮丧。)

到底容器网络是什么呢?

当我们在容器中运行程序时,你将有两个主要的操作:
  • 在主机网络命名空间上运行该程序。这是正常的容器网络方式——如果你在8282端口上运行的程序,那么他将在本地计算机的8282端口上运行。这很正常。
  • 在容器自身的网络命名空间上运行该程序。

如果你将程序运行在其自身所在容器网络命名空间上(假如是在 9382 端口),那么在其他计算机上的其它程序将要通过网络连接来与此程序通信。

起初我想:“这能复杂到哪去,将两个程序连接在一起很简单,不是吗?”就像说这个问题只有一种解决方式吗?而事实上对于容器中的程序网络互联问题有着成百上千的解决办法。接下来让我们去看看都有哪些方式。

每个容器都有个IP

如果你经常关注容器,你应该听说过 Kubernetes  。Kubernetes 是一个可以使得你的容器可以自行决定其应该在哪一台机器上运行的系统(当然还有其它功能)。

Kubernetes 的核心需求之一(当你刚刚开始用它的时候)就是每个容器要分配IP地址,于是在集群当中的其它应用程序可以通过容器对应的IP地址与之通信。这也就意味着在一台计算机上,你可能会拥有成百上千的容器以及对应的成百上千个IP地址(而不是一个IP地址和一堆端口)。

当我第一次听到“每个容器都有一个IP地址”的概念,我很困惑和担心。这个怎么可能行得通?!我的计算机也仅仅只有一个IP地址!这个听起来像是难以理解的魔法一样。事实证明,幸运的是,与大多数计算机的东西类似,这是完全可以理解的。

“每一个容器具有一个IP地址“这个问题正是我写这篇博客想要说清楚的问题。虽然有很多解决容器网络的方法,但是从现在开始这里只解释上述的这一种方式。

而且我讲的是针对AWS来解决容器网络问题。如果你有自己的物理数据中心,那么将有更多的选择。

我们的目标

你有一台计算机(AWS instance),这个计算机有一个IP地址(比如172.9.9.9)。

你想要你的容器也有一个IP地址(比如10.4.4.4)。

我们将要学习在172.9.9.9这台计算机上如果将一个数据包发送给10.4.4.4。

在AWS上是非常容易实现的—AWS上具有这项功能叫做 “VPC Route Tables”,你可以直接的告诉它“请为10.4.4.*发送数据包到172.9.9.9”,这样AWS将为你完成这件事。但是这个规则的限制是最多只能有50个,如果你想要的容器集群数目超过50个实例,那么你需要回到对容器网络困惑的原点。

一些网络基础:IP地址、MAC地址、本地网络

为了更好的理解怎样在一台物理机上拥有成百个IP地址,我们需要懂得一些计算机网络的基本概念。

我将说一些你理所应当懂得的东西:
  • 在计算机网络当中,程序是通过发送数据包来进行互相交互通信的
  • 每一个数据包(大部分的)都有一个IP地址包含在内
  • 在Linux中,内核来完成大部分的网络协议工作
  • 一点有关子网概念:子网10.4.4.0/24指的是“从10.4.4.0到10.4.4.255的每一个IP”。我有的时候会写成10.4.4.*来代替。

接下来我会尽全力去解释。

网络数据包的组成

一个网络数据包有很多个部分组成(经常被称为“layers”)。网络数据包的种类也有很多种,但是让我们只谈最常见的HTTP请求(像 GET / )。组成部分有:
  1. 数据包将被发送到的MAC地址(“Layer 2”)
  2. 源IP地址和目标IP地址(“Layer 3”)
  3. 端口和其它的TCP/UDP信息(“Layer 4”)
  4. HTTP数据包的具体数据内容像GET / (“Layer 7”)

本地网络 VS 远端网络

当你直接将一个数据包发给一台计算机(在同一个本地网络当中),过程如下。

数据包被MAC地址标记,我的MAC地址是 3c:97:ae:44:b3:7f ;我通过运行 ifconfig 命令:
bork@kiwi~> ifconfig
enp0s25   Link encap:Ethernet  HWaddr 3c:97:ae:44:b3:7f 


如果发送一个数据包给我,任意的一台本地计算机都可以将  3c:97:ae:44:b3:7f 写在数据包上,然后将它发送到我这里。在AWS上,“本地网络”意味着“可用区域”。如果两个实例在同一个AWS的可用区域中,它们只需写上目标的MAC地址,然后数据包会被传送到止指定的目标计算机,无所谓数据包上写的哪个IP地址。

OK,那么如果我的计算机和目标计算机不在同一个本地网络/可用区域中呢?然后呢?然后中间路由器就会查看数据包上的IP地址,然后将它送达指定的地址。

路由器的工作原理还有很多内容,但是现在我们没有时间去探讨。幸运的是,在AWS上你通常没有办法去配置路由信息,因此也就无所谓它是如何工作的!发送一个数据包到可用区域外的实例,你需要将该实例所在的物理机的IP地址写在数据包上。否则数据包无法找到目标实例。

如果你管理自己的数据中心,你可以很轻松的去设置自己的路由信息。
因此,针对AWS我们可以学到的如下:
  • 如果你和目标主机在同一个可用区域里,你仅仅发送数据包携带随便任何IP地址都可以,只要MAC地址是正确的就可以。
  • 如果你和目标主机不不同的AZ里,那么发送数据包到那台计算机,你就必须要将目标实例所在的IP地址写在数据包上。

路由表

你可能想问:“Julia,但是我如何控制要发送到的MAC地址的数据包呢。我从来没有做过这个,这非常令人困惑”。

当你发送一个数据包到本地网络的一台计算机,地址为 172.23.2.1 ,你的操作系统(我们希望你的操作系统是Linux)通过它维护的一个表来查看该IP所对应的MAC地址(这个表叫做ARP table)。将这个MAC地址放在数据包上,然后发送出去。

那么,如果我有一个地址为 10.4.4.4 的容器的数据包,但是我想将它发送到 172.23.2.1 ?这个其实也是非常简单的。你仅仅是在另外一个表上插入一个条目而已。这些都是表能做的事情。

这是推荐你可以手动执行的命令:
sudo ip route add 10.4.4.0/24 via 172.23.1.1 dev eth0


ip route add 是你所在的计算机(IP:172.23.1.1)的路由表当中加一个条目。这个路由表表示:“Linux,当你看到从 10.4.4.* 来的数据包,就将它发送到MAC地址为 172.23.2.1 的目标主机,可以吗?”

我可以赋予容器IP地址

是时候来庆祝我们的第一波胜利!我们现在知道所有的基本工具以及一种主要的方式来路由容器IP地址。

步骤如下:
  1. 为你的每一个计算机选择一个不同的子网(比如10.4.4.0/24,也表示为10.4.4.*)。这个子网将会让你可以在一台机器上有256个容器。
  2. 在每一台计算机上,增加路由到其它的每一台计算机。于是你可以为10.4.1.0/2410.4.2.0/2410.4.3.0/24等等增加一个路由。
  3. 你已经完成了,数据包10.4.4.4现在将会路由到正确的计算机。这里还存在一个问题就是如果数据包到达目标计算机,它们将会做些什么呢,稍后我会介绍一下。

于是我们用来处理容器网络的第一个工具就是路由表。

如果两台计算机不在同一个可用区域呢?

我们早些时候说过路由表这个方式仅仅作用在计算机直连网络中。那么如果两台计算机在远端网络(在不同的本地网络)我们就需要做一些更加复杂的事情了。

我们想要发送数据包到一个容器,该容器IP地址为 10.4.4.4 ,该容器所在的计算机地址为 172.9.9.9 。因为目标计算机是远端网络,那么我们不得不将IP地址 172.9.9.9 写入该数据包。那么现在问题来了,我们应该在哪里放 10.4.4.4 这个地址呢?

封装

所有的数据包都不会丢失,我们可以做一个叫“封装”的东西。这就是你拿到一个网络数据包,然后将它放在另外一个网络数据包里面。

因此代替原有的数据包:
IP: 10.4.4.4
TCP stuff
HTTP stuff

我们将会发送如下数据包:
IP: 172.9.9.9
(extra wrapper stuff)
IP: 10.4.4.4
TCP stuff
HTTP stuff

这里至少有两种不同的方式来做封装:分别为“ ip-in-ip ”封装和 “ vxlan ”封装。

Vxlan  封装是将你的整个数据包(包含MAC地址) 外包已成 UDP 数据。就像这样:
MAC address: 11:11:11:11:11:11
IP: 172.9.9.9
UDP port 8472 (the "vxlan port")
MAC address: ab:cd:ef:12:34:56
IP: 10.4.4.4
TCP port 80
HTTP stuff

ip-in-ip  封装仅仅是在就的IP头上打上一个额外的IP头。这就意味着,你不需要将目标MAC地址保持在你想发给的数据包上,但是我不确定你是否会关心这一点。
MAC:  11:11:11:11:11:11
IP: 172.9.9.9
IP: 10.4.4.4
TCP stuff
HTTP stuff


如何设置封装

像之前那样,你可以会想“我如何通过我的内核去对我的数据包做这样一个奇怪的封装“?这个证实确实并没有那么困难。基本上你所需要做的就是设置一个新的 网络接口 来配置封装。

在我自己的电脑上,我可以这样做: 参考这里
sudo ip tunnel add mytun mode ipip remote 172.9.9.9 local 10.4.4.4 ttl 255
sudo ifconfig mytun 10.42.1.1


紧接着你要设置一个路由表,但是你要告诉Linux将你的数据包路由到你所配置的封装网络接口上。这里我们可以像这样做:
sudo route add -net 10.42.2.0/24 dev mytun
sudo route list 


我给你这些命令是因为我认为你可以使用 create / inspect 这些 tunnels( ip route list ip tunnel ifconfig )——我已经遇到过一些错误,但是这是关于它是如何工作的。

路由是如何分布的?

我们已经谈论了将路由添加到路由表的过程( 10.4.4.4 被添加到 172.9.9.9 ),但是我没有解释路由器具体如何从路由表当中获取信息的。理论上我们是希望他们能自动去识别。

每一个容器网络的东西都是通过在每一个box里面运行一个守护进程来负责添加路由信息到路由表。

这里有两种主要方式:
  1. 这些路由器在一个etcd集群当中,每一个程序通过etcd集群来确认配置哪一个路由
  2. 通过BGP路由协议来互相的通信,然后在每一个box里面用一个守护进程(BIRD)来监听BGP消息

当数据包到达的你的box时会发生什么?

在正在运行Docker中,一个数据包从IP地址为 10.4.4.4 的容器过来,那么这个数据包最终到达你的程序是终态是什么样的呢?

我现在来解释 桥接网络 。这个地方我有一点模糊,所以可能会出现错误。

我现在的理解是这样的:
  • 在你的计算机上的每一个数据包都是通过一个实际的接口传送出去的(比如eth0
  • Docker会为每一个单一的容器创建(虚拟)网络接口,这些接口具有IP地址类似10.4.4.4
  • 这些虚拟网络接口都被桥接到你的真实的物理网络接口上。这就是说这些数据包被复制(?)到这些网络接口所对应真实网卡上,然后在网络上被传送出去

这看起来非常重要,但是我还没有完全理解。

最终:这些容器的网络如何工作的

现在我们有已经介绍了容器网络的基本概念。

Flannel

Flannel支持几种不同方式的网络:
  • vxlan(封装所有的数据包)
  • host-gw(仅仅是设置路由表,没有封装)

这个守护进程通过etcd集群来设置路由信息。

Calico

Calico支持两种不同的网络方式:
  • ip-in-ip:封装
  • “普通“模式(仅仅是设置路由表,没有封装)

这里守护进程是通过使用使用其它主机的 BGP 信息来设置路由表。Calico具有etcd集群但它并不用于分发路由。

Calico最令人兴奋的是可以不使用封装。如果你观察的够仔细你会发现Flannel也有一个选择是不需要使用封装。如果你是在AWS上,这两种你看不出哪个更好,它们有共同的限制:他们都是工作在具有相同的可用区域的实例之间。

这些关于容器网络的问题大部分都是设置路由以及tunnels等等一些事情,但是我觉得弄明白这些场景中到底做了什么是非常重要的,这样你才可以在出问题的时候调试和解决问题。

这是软件定义网络吗?

我不知道什么是软件定义网络。这有助于你做与众不同的网络,而且它都是软件,也许这就是所谓的软件定义网络吧?

总结

我已经陈述完了。希望这些能对您有一定作用,这个证明了容器网络并不是很烂,而且我们花费了一些时间在 ip 命令。 ifconfig tcpdump ,这些可以帮助我们理解基本的Kubernetes部署。你不需要成为一个专家级的网络工程师。我的同事Doug帮助我理解了很多问题。

原文链接: A container networking overview(翻译:edge_dawn 审校: 田浩浩)

原文发布时间为:2017-02-12

本文作者:田浩浩

本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:容器网络概述

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
5月前
|
存储 Linux 容器
【Container App】在容器中抓取网络包的方法
本文介绍在Azure Container App中安装tcpdump抓取网络包,并通过Storage Account上传抓包文件的方法。内容包括使用curl和nc测试外部接口连通性、长Ping端口、安装tcpdump、抓取网络包、以及通过crul命令上传文件至Azure Storage。适用于需要分析网络请求和排查网络问题的场景。
202 1
|
6月前
|
Docker 容器
Docker网关冲突导致容器启动网络异常解决方案
当执行`docker-compose up`命令时,服务器网络可能因Docker创建新网桥导致IP段冲突而中断。原因是Docker默认的docker0网卡(172.17.0.1/16)与宿主机网络地址段重叠,引发路由异常。解决方法为修改docker0地址段,通过配置`/etc/docker/daemon.json`调整为非冲突段(如192.168.200.1/24),并重启服务。同时,在`docker-compose.yml`中指定网络模式为`bridge`,最后通过检查docker0地址、网络接口列表及测试容器启动验证修复效果。
1104 39
|
人工智能 弹性计算 运维
ACK Edge与IDC:高效容器网络通信新突破
本文介绍如何基于ACK Edge以及高效的容器网络插件管理IDC进行容器化。
|
7月前
|
网络协议 Docker 容器
使用网络--容器互联
使用网络--容器互联
173 18
|
7月前
|
Kubernetes Cloud Native 区块链
Arista cEOS 4.30.10M - 针对云原生环境设计的容器化网络操作系统
Arista cEOS 4.30.10M - 针对云原生环境设计的容器化网络操作系统
242 0
|
安全 网络安全 数据安全/隐私保护
利用Docker的网络安全功能来保护容器化应用
通过综合运用这些 Docker 网络安全功能和策略,可以有效地保护容器化应用,降低安全风险,确保应用在安全的环境中运行。同时,随着安全威胁的不断变化,还需要持续关注和研究新的网络安全技术和方法,不断完善和强化网络安全保护措施,以适应日益复杂的安全挑战。
395 61
|
机器学习/深度学习 运维 安全
图神经网络在欺诈检测与蛋白质功能预测中的应用概述
金融交易网络与蛋白质结构的共同特点是它们无法通过简单的欧几里得空间模型来准确描述,而是需要复杂的图结构来捕捉实体间的交互模式。传统深度学习方法在处理这类数据时效果不佳,图神经网络(GNNs)因此成为解决此类问题的关键技术。GNNs通过消息传递机制,能有效提取图结构中的深层特征,适用于欺诈检测和蛋白质功能预测等复杂网络建模任务。
497 2
图神经网络在欺诈检测与蛋白质功能预测中的应用概述
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
1150 7
|
SQL 存储 安全
网络安全与信息安全概述####
本文探讨了网络安全(Cybersecurity)和信息安全(Information Security)的基本概念及其差异,重点介绍了网络安全漏洞、加密技术及安全意识在信息保护中的重要性。本文旨在通过深入分析这些关键技术和策略,提升对信息安全整体性的理解,帮助读者在数字化时代更好地应对信息安全挑战。 ####
|
网络协议 Ubuntu 前端开发
好好的容器突然起不来,经定位是容器内无法访问外网了?测试又说没改网络配置,该如何定位网络问题
本文记录了一次解决前端应用集成到主应用后出现502错误的问题。通过与测试人员的沟通,最终发现是DNS配置问题导致的。文章详细描述了问题的背景、沟通过程、解决方案,并总结了相关知识点和经验教训,帮助读者学习如何分析和定位网络问题。
658 1