想象一下,你是一家大型物流公司的仓库主管。仓库里有几百个货箱(容器),每个货箱里都装着自己的货物和工具(进程和文件)。货箱要互相发货,就必须有地址、有传送带、有分拣规则。如果每个货箱都直接连一根网线到别人那儿,仓库会乱成一团麻。于是,我们给仓库设计了一套“内部物流系统”:每个货箱有独立的操作间(网络命名空间),货箱之间用传送带(veth pair)连接,中间架一个分拣台(网桥),再贴上一套分拣规则(iptables)。这套系统,就是容器网络模型。 更进一步,当仓库大到需要统一管理时,你还需要“仓库管理协议”——Docker 用 CNM(Container Network Model),Kubernetes 用 CNI(Container Network Interface)。它们就像两套不同的物流调度章程,告诉你货箱怎么上架、怎么连传送带、怎么登记地址。而 Calico 和 Flannel 则是两家物流设备供应商,用不同的技术路线把这张网铺好。 这篇文章,我们就用这个“仓库物流”的比喻,把容器网络的底层原理一层层拆开:从命名空间讲到 veth,从网桥讲到 iptables,最后看 K8s 网络插件怎么选型。读完你会明白:容器网络不是黑魔法,而是一套可以拆解、可以排查、可以设计的工程系统。

岗位关联

掌握容器网络模型,是理解 Kubernetes 网络排障、插件选型和多集群架构设计的基石。无论你是开发、运维还是 AI 工程化从业者,这都是一项绕不开的核心技能。

目录
  1. 可视化演示
  2. 网络命名空间:仓库里的独立操作间
  3. 虚拟网络设备:连接操作间的传送带
  4. CNM 模型:Docker 的仓库管理章程
  5. CNI 规范:K8s 的插件式插座
  6. iptables 规则:仓库的安检与分拣系统
  7. 网络插件剖析:Flannel 的隧道与 Calico 的路由
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

动态演示容器网络模型的核心机制,通过输入/处理/存储/输出四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

容器网络模型:CNI与 CNI与CNM网络模型标准对比 网络命名空间与veth pai 核心机制可视化 容器网络模型整体架构与关键组件

网络命名空间:仓库里的独立操作间

我们回到那个物流仓库。假设每个货箱(容器)都是一个独立的小操作间,里面有自己的一套“电话分机系统”——自己的电话线(网卡)、自己的电话本(路由表)、自己的分机号码(IP 地址)。操作间之间如果不接线,谁也联系不上谁。这个“操作间”在 Linux 里就叫网络命名空间(Network Namespace)。

技术上讲,网络命名空间是 Linux 内核提供的一种隔离机制。每个命名空间拥有一套独立的网络协议栈,包括网卡、回环接口、路由表、iptables 规则和套接字等。容器就是利用了这点:每个容器默认都有自己的网络命名空间,所以容器里的进程看到的是“一台只有自己的机器”,端口不会互相冲突。

在 Docker 中,启动容器时如果不特别指定,Docker 会为容器创建一个全新的网络命名空间。这样,容器 A 的 80 端口和容器 B 的 80 端口可以同时存在而不冲突——就像两家快递公司都有“1 号柜”,互不干扰。如果想省掉隔离,可以用 --network=host,容器直接共享宿主机的命名空间,这时端口就会撞车。

1. 命名空间标识:每个网络命名空间在 /proc 下有唯一的 inode 标识

2. 协议栈隔离:网卡、路由表、iptables 各自独立

如果所有容器共享宿主机的网络命名空间,就失去了隔离性——好处是性能极佳,坏处是端口必须全局唯一。所以在生产环境里,我们通常让每个容器有自己的操作间,再用传送带把它们连起来。这个传送带,就是我们下一节要讲的 veth pair。

ns_inode=stat(/proc/self/ns/net).ino\text{ns\_inode} = \text{stat}(\text{/proc/self/ns/net}).\text{ino}
Namespace={netdev,route_table,iptables_rules}\text{Namespace} = \{ \text{netdev}, \text{route\_table}, \text{iptables\_rules} \}
text2 行
# 查看当前进程所属的网络命名空间ls -l /proc/self/ns/net

虚拟网络设备:连接操作间的传送带

两个独立操作间怎么互通?我们不可能真的在每个操作间之间拉一根物理网线。Linux 给了我们一种虚拟的“网线”——veth pair。它总是成对出现:想象一根管子,一头在容器 A 的操作间里(叫 veth0),另一头在宿主机或网桥上(叫 veth1)。数据从 veth0 塞进去,就会原封不动地从 veth1 冒出来,反之亦然。

这就是容器与外界通信的第一座桥。但光有传送带还不够,我们需要一个“集散中心”——宿主机上的 docker0 网桥。docker0 是一个虚拟交换机,所有容器的 veth1 端都插到这台交换机上,容器之间就能通过它互相转发数据包,就像包裹在分拣台上按地址投递到不同传送带。

那外部网络怎么访问容器?比如你的 Web 服务跑在容器里,外部用户要访问宿主机的 8080 端口,Docker 会自动设置一条 iptables 规则,把宿主机 8080 端口的流量转发到容器 IP 的 80 端口——这就是 端口映射(-p 8080:80)。这套机制本质上就是数据包的“地址重写”。

1. veth 成对创建:创建 veth0 时自动生成 veth1

2. 流量进出:一端收包,另一端发包,方向相反

当你把容器接入 docker0 网桥后,容器、网桥、宿主机就构成了一个小型二层网络。这个网络默认使用 172.17.0.0/16 网段,容器从网桥动态获取 IP。有了 IP,容器之间就能像同一个小区的邻居一样互相访问——不需要任何额外配置。

veth0↔veth1\text{veth0} \leftrightarrow \text{veth1}
ingress(veth0)⇒egress(veth1)\text{ingress}(\text{veth0}) \Rightarrow \text{egress}(\text{veth1})
text2 行
# 创建一对 veth 网线ip link add veth0 type veth peer name veth1

CNM 模型:Docker 的仓库管理章程

现在仓库大了,操作间多了,传送带也多了,谁来统一管理这些资源?Docker 提出了 CNM(Container Network Model,容器网络模型)——一套管理容器网络的“章程”。它不是具体代码,而是一份抽象规范,规定了管理网络需要哪几个零件。

CNM 的核心是三个抽象概念:沙箱(Sandbox)、端点(Endpoint) 和网络(Network)。沙箱是一个容器的网络命名空间,是隔离的操作间;网络是可以互通的一组端点集合,相当于一个分拣片区;端点则是沙箱接入网络的“插头”,通常就是一个 veth pair 的容器侧网卡。三者关系是:一个沙箱可以有多个端点,接入多个网络,每个端点属于一个网络。

Docker 发布了若干内置驱动来实现 CNM:bridge 驱动创建 docker0 网桥,让同主机的容器互通;overlay 驱动则用于跨主机的容器通信,它会在所有宿主机之上建立一个大二层网络,让不同机器的容器像在同一个局域网内。还有 host、macvlan 等驱动,分别对应不同的网络诉求。

1. 沙箱(Sandbox):容器网络栈的载体,即网络命名空间

2. 端点(Endpoint):连接沙箱与网络的桥梁

3. 网络(Network):端点的集合,定义了互通边界

CNM 这套章程只服务于 Docker 生态。但随着 Kubernetes 崛起,容器编排需要更开放、更标准的接口——于是 CNI 粉墨登场。CNM 更像是 Docker 的内部管理制度,而 CNI 则是行业的统一语言。

Sandbox≡Net_Namespace\text{Sandbox} \equiv \text{Net\_Namespace}
Endpoint=(Interface,IP,Gateway)\text{Endpoint} = (\text{Interface}, \text{IP}, \text{Gateway})
Network={Endpoint1,Endpoint2,…}\text{Network} = \{ \text{Endpoint}_1, \text{Endpoint}_2, \ldots \}
text2 行
# 查看 Docker 当前的网络docker network ls

CNI 规范:K8s 的插件式插座

如果说 CNM 是 Docker 自己定的“公司章程”,那么 CNI(Container Network Interface,容器网络接口)就是整个容器行业公认的“统一插座标准”。它由 CoreOS 发起,是一个标准化的接口协议。任何网络插件(Flannel、Calico、Weave 等)只要实现了 CNI 规定的接口,就能被 Kubernetes 直接使用。

CNI 规范极其简洁,只定义了两个核心操作:ADD(把容器加入网络)和 DEL(把容器从网络移除)。Kubelet 在启动 Pod 时,会调用 CNI 插件的 ADD 接口,传入容器 ID、网络命名空间等参数,插件负责创建 veth、分配 IP、配置路由,然后返回结果。删除 Pod 时,则调用 DEL 接口做清理。

这种插件化的好处是什么?想象你的仓库需要更换传送带供应商,只要新供应商的接口尺寸符合国家统一标准,你不需要改造整个仓库——拔下旧插头,插上新插头即可。Kubernetes 因此可以灵活选择 Flannel、Calico、Cilium 等任意网络方案,而无需修改核心代码。

1. ADD 操作:插件接收容器 ID 与命名空间,完成网络接入

2. DEL 操作:移除容器网络资源

CNI 的接口设计非常克制,它只关心“连通性”,不关心“网络策略”(那是 NetworkPolicy 的事)。这种克制让它迅速成为行业标准。K8s 的每个 Pod 默认共享一个网络命名空间(pause 容器),CNI 插件只需为 Pod 创建一个 veth,并把另一端接入宿主机网桥即可。

ADD(containerID,nsPath)→(IP,route)\text{ADD}(\text{containerID}, \text{nsPath}) \rightarrow (\text{IP}, \text{route})
DEL(containerID,nsPath)→∅\text{DEL}(\text{containerID}, \text{nsPath}) \rightarrow \varnothing
text2 行
# 查看节点上已安装的 CNI 插件ls /opt/cni/bin/

iptables 规则:仓库的安检与分拣系统

容器网络里,真正做“地址重写”和“流量控制”的,是 Linux 内核里的 iptables。它好比仓库的安检分拣系统:每个进出仓库的包裹都要经过若干检查点(规则链),每个检查点按规则表决定放行、丢弃还是改写地址。

iptables 中最常用的表是 NAT 表,它有两个关键链:PREROUTING(包裹进仓库时先检查)和 POSTROUTING(包裹出仓库时再检查)。Docker 做端口映射,就是在 PREROUTING 链上加了一条 DNAT 规则:把目标地址为宿主机 8080 端口的包,改写为容器 IP 的 80 端口。而容器访问外网时,POSTROUTING 链上的 MASQUERADE 规则会把包的源地址改写成宿主机的 IP,让外部以为请求来自宿主机。

我们用数据包的走向来理解:外部请求到达宿主机 → PREROUTING 链做 DNAT(目标地址改写为容器 IP)→ 数据包经 docker0 网桥转发 → 进入容器。响应包则走反向:容器发出 → POSTROUTING 链做 SNAT(源地址改写为宿主机 IP)→ 返回外部。整个过程中,容器完全不知道自己被“代理”了。

1. DNAT 改写:修改数据包的目标地址

2. SNAT 改写:修改数据包的源地址

iptables 的规则是顺序匹配的:数据包从第一条规则开始逐条比对,命中的先执行,没命中的继续往下走。这也是排查网络问题时最常见的坑——规则顺序错了,包就走了不该走的路。理解了 iptables,你就理解了“端口映射”和“容器上网”的真正幕后黑手。

DNAT:(dst_ip=hostIP,dst_port=8080)→(dst_ip=containerIP,dst_port=80)\text{DNAT}: (dst\_ip = \text{hostIP}, dst\_port = 8080) \rightarrow (dst\_ip = \text{containerIP}, dst\_port = 80)
SNAT:(src_ip=containerIP)→(src_ip=hostIP)\text{SNAT}: (src\_ip = \text{containerIP}) \rightarrow (src\_ip = \text{hostIP})
text2 行
# 查看 NAT 表规则iptables -t nat -L

网络插件剖析:Flannel 的隧道与 Calico 的路由

最后,我们把目光投向生产环境。Kubernetes 集群通常有几十台机器,Pod 散布在各机器上。Pod 之间要互通,就需要跨主机的容器网络。业界两大主流方案是 Flannel 和 Calico,它们实现 CNI 规范的方式截然不同。

Flannel 的核心思路是“隧道封包”。它给每台宿主机分配一个子网段,比如主机 A 是 10.244.1.0/24,主机 B 是 10.244.2.0/24。当主机 A 上的 Pod 要访问主机 B 上的 Pod 时,Flannel 会把原始数据包整个封装进一个新的 UDP 包(VXLAN 隧道),新包的目标地址是主机 B 的物理 IP。到达主机 B 后,再解封装还原原始包。这就像把一件小包裹塞进一个大集装箱,走铁路(物理网络)运过去,到了再拆箱。

Calico 则完全不同,它走的是“纯路由”路线。Calico 不使用隧道封包,而是把每个宿主机当作一台路由器,通过 BGP(边界网关协议) 在集群内广播路由信息。每台机器都知道“哪个 Pod IP 在哪台机器上”,数据包直接按路由表一跳一跳地送过去,没有额外的封装开销。Calico 还天然支持 NetworkPolicy,可以做细粒度的网络访问控制。

1. VXLAN 封装:原始数据包外套一个新数据包

2. BGP 路由:各节点通过 BGP 交换 Pod 网段路由

选型时怎么取舍?如果集群规模小(<50 节点)、对性能要求不高,Flannel 简单易用、够用就好;如果集群规模大、追求低延迟高吞吐,Calico 的纯路由模式性能更优,但要求底层网络支持 BGP(通常是物理路由器)。理解这两种路线的差异,你在面试和架构设计中就能言之有物。

OuterPkt=(ethsrc,ethdst,UDP,InnerPkt)\text{OuterPkt} = (\text{eth}_{src}, \text{eth}_{dst}, \text{UDP}, \text{InnerPkt})
routei=(PodCIDRi→NodeIPi)\text{route}_i = (\text{PodCIDR}_i \rightarrow \text{NodeIP}_i)
text2 行
# 查看 Flannel 分配的 Pod CIDRkubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}'

AI 应用场景

场景一:K8s 集群网络问题排查

阶段:模型训练/推理服务的网络保障

解决的问题:AI 模型训练通常涉及多机多卡分布式任务(如 PyTorch DDP),Pod 之间需要高吞吐、低延迟的网络通信。传统排查网络问题靠瞎猜,理解了容器网络模型后,你可以按“命名空间 → veth → 网桥 → iptables → CNI 插件”的路径逐层定位。

具体案例:某训练任务中,两个 Pod 跨节点通信时断时续。先用 ip netns exec 进入容器命名空间 ping 网关,发现丢包,再用 iptables -t nat -L 检查 NAT 规则,最后确认是 Flannel VXLAN 隧道 MTU 配置过大导致分片丢失。调整 MTU 后问题解决。

场景二:CNI 插件选型评估

阶段:AI 平台基础设施建设

解决的问题:部署 GPU 推理集群时,需要选择网络插件。传统选型只凭经验或文档,理解 Flannel 的 VXLAN 封装开销和 Calico 的 BGP 直连特性后,可以基于实际流量模型做量化评估。

具体案例:某公司 AI 平台有 200 个节点,推理服务 QPS 高、延迟敏感。评测发现 Flannel 的隧道封装带来约 10% 的吞吐损耗,而 Calico 的 IPIP 模式(或 BGP 直连)几乎没有额外开销。最终选择 Calico,并将网络策略与安全合规一并落地。

场景三:多租户网络隔离设计

阶段:AI 应用的多环境部署

解决的问题:多个业务团队共享一个 K8s 集群,需要网络隔离。传统做法是分配不同节点池,资源浪费大;理解了网络命名空间和 CNI 的 NetworkPolicy 机制后,可以在同一集群内用命名空间 + 网络策略实现租户隔离。

具体案例:数据团队和算法团队共用集群,通过 Calico NetworkPolicy 指定:数据团队的 Pod 只能访问特定数据库命名空间,算法团队之间可互相通信但不可跨租户。隔离规则精确到 Pod 级,无需拆分集群。

Python 演示

python52 行
"""解析 /proc 文件系统,展示容器网络命名空间与 veth 关系."""import osimport subprocess  def read_link(path):    """读取符号链接指向并返回名称."""    try:        return os.path.basename(os.readlink(path))    except OSError:        return None  def list_network_namespaces():    """列出当前进程可见的网络命名空间."""    hosts = {}    for item in os.listdir('/proc'):        if not item.isdigit():            continue        ns_path = f'/proc/{item}/ns/net'        if not os.path.exists(ns_path):            continue        ident = read_link(ns_path)        hosts.setdefault(ident, []).append(item)    for ident, pids in hosts.items():        print(f'网络命名空间 inode={ident}: PID {pids[:3]}')  def list_veth_interfaces():    """通过 ip 命令列出 veth 网卡."""    out = subprocess.run(        ['ip', '-o', 'link', 'show'],        capture_output=True, text=True    ).stdout    for line in out.splitlines():        if 'veth' in line:            print(line.strip())  def main():    print('=== 当前进程网络命名空间 ===')    print('ns/net ->', read_link('/proc/self/ns/net'))    print()    print('=== 系统中其他命名空间概览 ===')    list_network_namespaces()    print()    print('=== 主机的 veth 网卡 ===')    list_veth_interfaces()  if __name__ == '__main__':    main()
目的:通过解析 /proc 文件系统和 ip 命令,直观展示网络命名空间与 veth 网卡的存在形态,帮助你建立“命名空间是操作间、veth 是传送带”的直觉。
  1. os.readlink(os.path.join('/proc', item, 'ns', 'net'))读取进程网络命名空间的符号链接,得到 inode 标识,这就是“操作间编号”
  2. hosts.setdefault(ident, []).append(item)把共享同一命名空间的 PID 归组,直观看到哪些进程住在同一间操作间
  3. read_link('/proc/self/ns/net')当前 Python 进程自己的命名空间标识
  4. subprocess.run(['ip', '-o', 'link', 'show'], capture_output=True, text=True)调用 ip 命令获取所有网卡信息,过滤出 veth 字样
  5. line.strip()美化输出,每行显示一个网卡设备
  6. if __name__ == '__main__': main()程序入口,保证模块可复用

常见误区

误区我理解容器网络,就是每个容器都有自己的独立 IP 和网卡,Docker 默认就是这样。如果不用独立命名空间,容器就不安全。

正解Docker 确实默认创建独立命名空间,但 --network=host 就是共享宿主机的命名空间。此时容器直接使用宿主机 IP 和端口,性能最优,常用于高性能服务。还有 --network=none 完全不开网络,以及 --network=container:xxx 与另一个容器共享。不是“必须隔离”,而是“按需选择隔离级别”。

为何常见:多数教程只讲默认 bridge 模式,很少讲 host 模式,导致“容器必隔离”的错觉。

误区CNM 和 CNI 是同一个东西,只是叫法不同,都是 Kubernetes 的网络插件接口。

正解CNM 是 Docker 提出的容器网络模型,核心是沙箱、端点、网络三要素;CNI 是 CoreOS 发起的容器网络接口规范,核心是 ADD/DEL 两个操作。Kubernetes 用的是 CNI,Docker 默认用的是 CNM。虽然 Docker 也支持 CNI,但两者是不同体系、不同规范。

为何常见:两者缩写相似,且都用于容器网络管理,初学者极易混为一谈。

误区veth pair 就是一根虚拟网线,数据从一端进去,从另一端出来,所以它和物理网线行为完全一样,可以直接用它连接外部网络。

正解veth pair 的行为确实像一根线,但它只在命名空间之间做二层转发,不参与物理网卡的工作。要让容器访问外网,veth 通常要接在网桥(如 docker0)上,再由网桥通过 NAT 规则与物理网卡打通。veth 本身不路由、不封包。

为何常见:“像一根线”的比喻容易让人忘记它只是虚拟设备,实际是内核里的两个网络接口。

误区Docker 的端口映射是 Docker 自己的功能,和 Linux 内核的 iptables 没什么关系。

正解端口映射完全依赖 Linux 内核的 iptables NAT 表。Docker 只是帮你自动加了 DNAT 规则:把宿主机端口转发到容器 IP。手动删除 NAT 规则后,端口映射立即失效。理解 iptables 才能排查端口映射异常的问题。

为何常见:Docker 封装得太好,用户只看到 -p 8080:80 就完成了映射,看不到背后的 iptables 规则。

误区Flannel 用 VXLAN 隧道有性能损耗,Calico 用 BGP 直连更快,所以生产环境永远应该选 Calico。

正解Flannel 的 VXLAN 模式确实有额外封装开销,但它有更多模式可选(如 host-gw 模式不需要隧道),且配置极简、排障文档丰富。Calico 的 BGP 直连模式性能好,但对底层网络有要求(支持 BGP 或 IPIP),且运维复杂度更高。小集群、快速交付场景,Flannel 可能更合适。

为何常见:网络赛道喜欢“唯性能论”,忽略了运维成本、稳定性和团队技术栈。

面试题

Q1. 以下哪个术语描述了 Linux 内核为容器提供的独立网络协议栈?

单选题 · easy

  • A.网络命名空间← 正确答案
  • B.虚拟内存
  • C.进程调度器
  • D.文件描述符

答案:A。网络命名空间隔离了网卡、路由表、iptables 等网络资源,是容器获得独立 IP 和端口空间的基础。虚拟内存、进程调度器、文件描述符虽然是 Linux 的重要概念,但与“独立网络协议栈”无关。

Q2. CNM 模型中的三要素是什么?

单选题 · easy

  • A.沙箱、端点、网络← 正确答案
  • B.容器、镜像、仓库
  • C.节点、服务、端点
  • D.Pod、Service、Ingress

答案:A。CNM 是 Docker 提出的网络模型,三要素为沙箱(Sandbox)、端点(Endpoint)和网络(Network)。容器、镜像、仓库是 Docker 的整体概念;节点、服务、端点是 K8s 的抽象;Pod、Service、Ingress 是 K8s 的网络对象。

Q3. CNI 规范中最核心的两个操作是什么?

单选题 · easy

  • A.ADD 和 DEL← 正确答案
  • B.GET 和 POST
  • C.CREATE 和 DROP
  • D.OPEN 和 CLOSE

答案:A。CNI 规范只定义 ADD(把容器加入网络)和 DEL(移除容器网络)两个操作。GET/POST 是 HTTP 方法,CREATE/DROP 和 OPEN/CLOSE 是其他领域的接口命名。

Q4. 关于 veth pair 的描述,正确的是哪一项?

单选题 · mid

  • A.可以单独创建一个 veth 网卡
  • B.数据从一端进入,从另一端流出← 正确答案
  • C.veth 直接用于跨越物理网络
  • D.veth 会自行分配 IP 地址

答案:B。veth pair 成对创建、成对存在,数据从 veth0 进就从 veth1 出。它不能单独存在,不能穿越物理网络,也不会自动分配 IP——IP 是网桥或上层网络分配后配置上去的。

Q5. Docker 端口映射 -p 8080:80 的底层实现主要依赖哪个机制?

单选题 · mid

  • A.iptables 的 DNAT 规则← 正确答案
  • B.网桥的二层转发
  • C.容器内部的端口监听
  • D.DNS 解析记录

答案:A。Docker 通过 iptables NAT 表的 PREROUTING 链添加 DNAT 规则,把宿主机 8080 端口的流量转发到容器 IP 的 80 端口。二层转发是数据如何在网桥内流通,容器监听是应用层行为,DNS 解析则完全无关。

Q6. Flannel 的 VXLAN 模式与 Calico 的 BGP 模式本质区别是什么?

单选题 · mid

  • A.前者封包走隧道,后者直接按路由转发← 正确答案
  • B.前者只支持单机,后者支持跨机
  • C.前者使用 TCP,后者使用 UDP
  • D.前者不支持 IPv6,后者不支持 IPv4

答案:A。Flannel VXLAN 把原始数据包封装到 UDP 里走隧道,Calico 通过 BGP 广播路由、按路由表直接转发。两者都支持跨机通信;VXLAN 外层是 UDP 而非 TCP;两者都支持 IPv4 和 IPv6。

Q7. 容器网络命名空间的 inode 标识可以从哪个路径查看?

单选题 · mid

  • A./proc/self/ns/net← 正确答案
  • B./etc/hosts
  • C./sys/kernel/debug
  • D./var/run/docker.sock

答案:A。/proc/self/ns/net 是指向当前进程网络命名空间的符号链接,它的 inode 可唯一标识命名空间。/etc/hosts 是主机名映射,/sys/kernel/debug 是内核调试信息,/var/run/docker.sock 是 Docker 的通信 socket。

Q8. 关于网络命名空间,以下说法正确的有哪些?

多选题 · mid

  • A.每个容器默认拥有独立的网络命名空间← 正确答案
  • B.路由表是命名空间的隔离资源← 正确答案
  • C.使用 host 网络时容器拥有新命名空间
  • D.iptables 规则在命名空间内是独立的← 正确答案

答案:ABD。Docker 默认创建独立网络命名空间,路由表和 iptables 规则都在命名空间内隔离。使用 --network=host 时容器共享宿主机命名空间,所以描述 C 错误。独立命名空间是隔离和安全的基础。

Q9. 关于 CNI 与 CNM,说法正确的有哪些?

多选题 · mid

  • A.CNI 是 Kubernetes 采用的网络接口规范← 正确答案
  • B.CNM 是 Docker 提出的容器网络模型← 正确答案
  • C.CNI 和 CNM 是同一规范的不同名称
  • D.CNI 定义了 ADD/DEL 两个核心操作← 正确答案

答案:ABD。CNI 是 Kubernetes 采用的插件化网络接口规范,CNM 是 Docker 的容器网络模型,两者是不同的体系。CNI 核心操作是 ADD/DEL。选项 C 混淆了两者,是经典的初学者误区。

Q10. 在排查“容器无法访问外网”问题时,按容器网络模型的分析框架,应依次检查哪些内容?

多选题 · hard

  • A.容器网络命名空间的默认路由← 正确答案
  • B.veth pair 两端的 link 状态← 正确答案
  • C.宿主机 iptables NAT 表的 MASQUERADE 规则← 正确答案
  • D.Docker 镜像的构建缓存

答案:ABC。按照容器网络的层次,容器要访问外网需要四条路径:容器内有默认路由指向网桥(A),veth 链路正常连接(B),宿主机的 NAT 转发(POSTROUTING/MASQUERADE)让包能出去并回来(C)。镜像构建缓存只影响构建阶段,与运行时网络无关。