笔记Day15:K8s网络工作原理【Pod 网络模型,CNI 网络插件,Calico 工作模式详解,BGP协议,路由反射器】)
一、K8s 网络要解决的四类通信问题Kubernetes 网络设计的核心目标是解决以下四类通信问题通信类型说明关键组件Pod 内通信同一个 Pod 内多个容器间的通信通过 localhost共享网络命名空间pause 容器Pod 间通信不同 Pod 之间的直接通信CNI 网络插件Calico/Flannel/CiliumPod 与 Service 通信Pod 如何通过稳定的 Service 域名访问彼此kube-proxyiptables/IPVS CoreDNS域名解析外部与 Service 通信集群外部如何访问集群内的服务ServiceNodePort/LoadBalancer Ingress三大核心组件K8s网络的实现依赖于几个关键的组件协同工作组件作用运行位置CNI 插件为 Pod 创建网络接口、分配 IP、设置路由每个节点上被 kubelet 调用kube-proxy实现 Service 的负载均衡维护 iptables/IPVS 规则每个节点上的 DaemonSetCoreDNS为 Service 提供域名解析服务集群内的 Deployment二、容器网络基础Docker 网络模型在学习 K8s 网络之前必须先理解 Docker 容器网络的工作原理因为 K8s 的网络模型正是建立在这之上的。2.1 Docker0 网桥与 veth 对安装 Docker 后宿主机上会自动创建一个名为docker0的网桥它充当虚拟交换机的角色。所有容器都连接到这个网桥上使得容器之间的通信就像在同一局域网中一样。关键概念解析vethVirtual Ethernetveth 是一个成对出现的虚拟网络设备就像一根虚拟的网线。它的一端连接在容器的网络命名空间中命名为eth0另一端连接在宿主机的docker0网桥上。数据流向当 Container1 发送数据包时数据从它的eth0出发通过 veth 对到达宿主机的docker0网桥再由网桥转发给 Container2 或外部网络。为什么要用 veth 对因为容器运行在自己的网络命名空间中拥有独立的网络栈无法直接使用宿主机的网络接口。veth 对就像一根虚拟网线连接了容器的网络命名空间和宿主机网络让容器能够“看见”外界。2.2 容器访问外部网络当容器需要访问外部网络如访问百度时数据包需要经过宿主机的网络转发。Docker 默认在宿主机上创建了如下 iptables 规则来实现-APOSTROUTING-s172.17.0.0/16!-odocker0-jMASQUERADE这条规则的含义-s 172.17.0.0/16匹配源 IP 为容器网段的流量! -o docker0排除目标是 docker0 网桥的流量即容器间通信不处理-j MASQUERADE进行源地址转换SNAT将容器的源 IP 替换为宿主机的 IP通俗理解当容器访问外网时它报出的是自己的私有 IP如 172.17.0.2外网不认识这个 IP无法回包。MASQUERADE 就是将这个私有 IP 替换为宿主机的公网 IP让外网能够把数据包回复给宿主机宿主机再转交给容器。2.3 外部访问容器端口映射容器的 IP 地址只在宿主机内部有效外部网络无法直接访问容器。因此Docker 提供了-p参数将宿主机端口映射到容器端口[roothd1 ~]# docker run -d --name web -p 8080:80 nginx访问宿主机IP:8080就能访问到容器的 80 端口。这个映射通过 iptables 规则实现-APREROUTING-tnat-ptcp--dport8080-jDNAT --to-destination172.17.0.2:80这条规则的含义当外部访问宿主机的 8080 端口时将目标地址转换为容器的 IP:80从而实现访问容器。三、Kubernetes Pod 网络模型3.1 Pod 网络配置流程在 Kubernetes 中Pod 的网络配置与 Docker 容器类似但更加标准化。整个网络配置流程由 kubelet 和 CNI 插件协同完成第一步kubelet 收到创建 Pod 的请求后首先调用容器运行时如 containerd创建pause 容器。第二步kubelet 调用 CNI 插件为 pause 容器配置网络。CNI 插件是位于/opt/cni/bin/目录下的可执行文件它们根据配置文件通常在/etc/cni/net.d/为 Pod 创建网络接口、分配 IP 地址、设置路由规则。第三步kubelet 调用容器运行时创建应用容器并将它们加入 pause 容器的网络命名空间中。这样同一 Pod 内的所有容器共享同一个网络栈可以通过localhost互相通信。第四步当 Pod 被删除时kubelet 通过 CNI 插件进行网络资源的清理和回收释放 IP、删除 veth 接口等。3.2 为什么需要 pause 容器pause 容器是一个极其轻量级的容器运行一个永远阻塞的进程它的核心作用是充当网络命名空间的“持有者”。同一 Pod 内的所有业务容器都加入 pause 容器的网络命名空间共享同一个 IP 地址和端口空间。这样做的好处简化网络管理Pod 内的所有容器共享同一个 IP对外表现为一个整体。生命周期管理pause 容器作为网络命名空间的“锚点”即使业务容器重启网络命名空间也不会销毁保证了 IP 地址的稳定性。资源隔离网络命名空间独立于容器生命周期由 pause 容器统一管理。四、跨节点 Pod 通信 —— CNI 网络插件在单节点上Pod 通过 docker0 网桥或类似的网桥就能通信。但 Kubernetes 集群通常包含多个节点Pod 可以被调度到任意节点上这就需要不同节点上的 Pod 之间也能够直接通信。这完全由 CNI 网络插件来实现。其核心问题是如何让不同节点上的 Pod IP 能够互相路由4.1 覆盖网络Overlay Network代表插件FlannelVXLAN 模式覆盖网络在现有物理网络之上构建一个虚拟的二层网络。跨节点通信时数据包会被封装在 UDP 包中常用 VXLAN 协议通过节点的物理 IP 进行路由到达目标节点后再解封装还原为原始 Pod IP 数据包。优点对底层网络无特殊要求只要节点之间 IP 可达即可。缺点封装和解封装带来性能开销。4.2 路由模式Routing Mode代表插件CalicoBGP 模式路由模式不使用封装而是将 Kubernetes 集群当作一个大型路由器来运作。每个节点都配置了到其他节点 Pod 子网的路由并通过BGP 协议边界网关协议将这些路由信息同步给集群路由器或让节点间相互学习路由。优点数据包直接根据 IP 路由转发性能更高没有封装开销。缺点需要底层网络支持路由配置节点通常需要在同一二层网络内。选择建议公有云环境如阿里云、AWS推荐 Flannel 的 host-gw 模式配置简单私有数据中心Calico 能覆盖更多场景提供更强的网络策略能力五、Calico 三种工作模式详解Calico 是目前最流行的 Kubernetes CNI 插件之一支持三种工作模式分别适用于不同的网络环境。5.1 IPIP 模式默认模式IPIP 模式是 Calico 的默认模式。当 Pod 跨节点通信时Calico 使用 IP-in-IP 隧道技术来封装原始 Pod IP 数据包确保数据包能够通过非本地网络传输。IPIP模式原始IP包进入tunl0设备就会被Linux内核的IPIP驱动劫持将这个IP包直接封装在一个宿主机网络的IP包中目的地址为Node2的IP通信流程node1的10.233.1.2和node2的10.233.2.2通信的过程请求从10.233.1.2出去此时src10.233.1.2dest10.233.2.2请求会进入tunl0tunl0会把这个请求封装在一个宿主机网络的IP包中目的地址为Node2的IP此时src: 192.168.1.1 dest192.168.2.2将src和dest都进行了封装拆包就能获得真实的src和dest。需要注意这里并不是DNAT和SNAT请求经过路由进入node2的tunl0进行解包获取真正的dest目标地址此时src10.233.1.2dest10.233.2.2这样请求就到达了目标pod。目标pod回复的过程与这个过程一致。tunl0IPIP驱动工作在内核态的三层IP层。它不关心数据内容只是机械地在外面套一个IP头。不需要用户态进程介入。工作原理Pod A 发出的原始 IP 包源 IP: Pod A IP目标 IP: Pod B IP进入tunl0隧道设备。Linux 内核的 IPIP 驱动将这个原始 IP 包直接封装在一个新的 IP 包中新 IP 包的源地址为 Node1 的 IP目标地址为 Node2 的 IP。Node2 收到封装包后解封装还原出原始 Pod IP 包转发给 Pod B。适用场景节点处于不同网段需要跨子网通信的环境。5.2 BGP 模式路由模式BGP 模式不使用任何隧道封装允许pod与pod直接通信节点上的路由表通过BGP协议动态路由协议直接获得。每个节点上的 Calico 组件通过 BGP 协议将本节点的 Pod 子网路由信息通告给其他节点数据包直接根据路由表进行转发。Calico BGP模式的作用就在于用BGP把“不同网段”的Node连成一个逻辑上的大二层使得Pod IP可以直接作为源目地址跨越物理网段通信且全程不拆包、不改地址。BGP 模式是所有场景下无论同网段还是跨网段性能最佳的选择因为它无隧道封装开销。唯一的限制是要求节点间三层路由可达能互相 Ping 通。只要物理网络能路由BGP 就能跑且性能远超 IPIP/VXLAN。适用场景追求最佳性能的数据中心环境。BGP 模式适用于对网络性能要求极高的场景无隧道损耗且底层物理网络基础设施支持三层路由无论是直连二层还是通过交换机/路由器做三层转发。在大型数据中心中BGP 模式常结合架顶交换机TOR使用以规避大二层广播域带来的风险。5.3 VXLAN 模式VXLANVirtual eXtensible Local Area Network虚拟可扩展局域网使用 VXLAN 封装技术在不同节点之间建立逻辑的二层网络。Pod 的 IP 数据包被封装在这个二层网络中并通过底层物理网络进行通信。关于 VXLAN 的层次定位这点容易混淆从功能视角看VXLAN 主要解决的是二层L2网络跨三层扩展的问题。它能让位于不同物理位置、甚至不同数据中心的虚拟机或容器感觉像在同一个二层网络中一样通信。从实现视角看VXLAN 是在三层 IP 网络之上建立虚拟二层网络的技术。它“呈现”给用户的是一个二层网络但“依赖”并“运行”在三层 IP 网络之上并使用四层 UDP 协议端口 4789进行封装传输。在 Calico 中的定位Calico 将 VXLAN 作为一种隧道模式来使用与 IPIP 模式并列用于解决跨三层网络的 Pod 通信问题。但它与 Calico 的 BGP 模式纯路由有本质区别。优势突破传统 VLAN 的 4096 个数量限制跨越三层网络边界没有广播风暴的限制。适用场景大规模云数据中心需要跨越多个网络区域的 Kubernetes 集群。5.4 安装calicoctl查看和切换 Calico 工作模式#下载对应版本的 calicoctl[roothd1 ~]# curl -L https://github.com/projectcalico/calico/releases/download/vX.Y.Z/calicoctl-linux-amd64 -o calicoctl#赋予执行权限并移动到 PATH 目录[roothd1 ~]# chmod x calicoctl-linux-amd64[roothd1 ~]# mv calicoctl-linux-amd64 /usr/local/bin/calicoctl# 查看 Calico 节点状态[roothd1 ~]# calicoctl node status---------------------------------------------------------------|PEER ADDRESS|PEER TYPE|STATE|SINCE|INFO|---------------------------------------------------------------|192.168.1.12|node-to-node mesh|up|22:23:49|Established||192.168.1.13|node-to-node mesh|up|22:23:45|Established|---------------------------------------------------------------# 查看 Calico 节点列表[roothd1 ~]# calicoctl get nodes --allow-version-mismatcNAME hd1 hd2 hd3# 查看 IP 池配置包含当前工作模式[roothd1 ~]# calicoctl get ippool -o wide --allow-version-mismatchNAME CIDR NAT IPIPMODE VXLANMODE SELECTOR default-ipv4-ippool10.244.0.0/16trueAlways Never all()# 字段说明# IPIPMODE Always → 启用 IPIP 模式默认# IPIPMODE Never → 禁用 IPIP 模式# VXLANMODE Never → 禁用 VXLAN 模式# VXLANMODE Always → 启用 VXLAN 模式修改为 BGP 模式注意这里的ipipMode: Never表示关闭 IPIP 隧道从而让 Calico 工作在以 BGP 路由为主的模式下[roothd1 ~]# kubectl edit ippool default-ipv4-ippool修改前apiVersion:projectcalico.org/v3kind:IPPoolmetadata:name:default-ipv4-ippoolspec:cidr:10.244.0.0/16ipipMode:AlwaysnatOutgoing:truenodeSelector:all()vxlanMode:Never修改后apiVersion:projectcalico.org/v3kind:IPPoolmetadata:name:default-ipv4-ippoolspec:cidr:10.244.0.0/16ipipMode:Never# ← 关闭 IPIP 隧道natOutgoing:truenodeSelector:all()vxlanMode:Never修改后查看路由表可以看到目标为其他节点 Pod 子网的流量直接走物理网卡ens33而非隧道设备tunl0当同时禁用ipip和vxlan的时候默认就是BGP模式# IPIP 模式下的路由表走 tunl0 隧道[roothd1 ~]# ip routedefault via192.168.100.2 dev ens33 proto static metric10010.244.59.128/26 via192.168.100.12 dev tunl0 proto bird onlink# BGP 模式下的路由表直接走物理网卡[roothd1 ~]# ip routedefault via192.168.100.2 dev ens33 proto static metric10010.244.59.128/26 via192.168.100.12 dev ens33 proto bird选择哪种模式取决于你的具体需求和网络环境。BGP 模式是所有场景下无论同网段还是跨网段性能最佳的选择。如果你的环境需要跨多个网络区域IP-in-IP 或 VXLAN 模式也是可考虑的。在选择模式时需要综合考虑性能、安全性和部署的复杂性。六、BGP 协议介绍6.1 什么是 BGPBGPBorder Gateway Protocol边界网关协议是一个 Linux 内核原生支持的、专门用在大规模数据中心里维护不同自治系统AS之间路由信息的、无中心的路由协议。BGP 的核心作用是让不同网络之间互相筛选并通告最佳路径。自治系统AS指一个组织管辖下的所有 IP 网络和路由器的全体。例如一个大型企业、一家云服务商或者整个 Kubernetes 集群都可以被视为一个自治系统。6.2 BGP 的工作原理BGP 的工作流程可以概括为三个步骤第一步建立可靠连接。BGP 使用 TCP 协议端口 179作为传输层协议确保路由信息交换的可靠性。第二步建立对等体关系。运行 BGP 的路由器被称为BGP 发言者Speaker它们之间通过手动配置建立对等体Peer关系来交换路由信息。第三步交换和选择路由。对等体之间互相通告各自知道的路由信息并根据策略选择最优路径加入到路由表中。6.3 BGP 在 Kubernetes 中的应用场景在 Calico 的 BGP 模式下每个节点都扮演着 BGP 发言者的角色每个节点将自己的 Pod 子网如 Node1 的10.244.1.0/24通过 BGP 通告给其他节点。其他节点收到通告后在本地路由表中添加对应的路由条目。当某个 Pod 访问另一个节点的 Pod 时数据包直接根据路由表转发无需任何封装。典型应用场景全球互联网骨干BGP 是连接全球成千上万个 AS 的基石承载着超过 90% 的跨国互联网流量。多线接入与优化云服务商通过 BGP 实现“单 IP 多线路”让不同运营商的用户都能高速访问。大型数据中心与云环境在 Kubernetes 中Calico 等 CNI 插件使用 BGP 来宣告 Pod 的路由实现高性能的跨节点 Pod 通信。七、路由反射器重点7.1 为什么需要路由反射器在 Calico 的默认配置中采用的是node-to-node mesh全互联模式。这意味着集群中的每个节点都需要与其他所有节点建立 BGP 连接以交换路由信息。全互联模式的问题当节点数量增加时连接数呈指数级增长组合数 C(n,2)。每个节点都需要维护大量的 BGP 连接消耗 CPU 和内存资源。网络开销巨大限制了集群的扩展能力。7.2 路由反射器机制为了解决全互联模式的可扩展性问题Calico 引入了路由反射器Route Reflector机制核心思路在集群中选择少数节点作为路由反射器中心节点其他普通节点只需要与这些路由反射器建立 BGP 连接。路由反射器负责收集所有节点的路由信息并将它们反射转发给其他节点。7.3 配置路由反射器步骤 1选择路由反射器节点并设置集群 ID选择节点hd1和hd2作为路由反射器为它们添加集群 ID 注解[roothd1 ~]# kubectl annotate node hd1 projectcalico.org/RouterReflectorclusterid224.0.0.1node/hd1 annotated[roothd1 ~]# kubectl annotate node hd2 projectcalico.org/RouterReflectorclusterid224.0.0.1node/hd2 annotated集群 ID 的作用集群 ID 用于标识路由反射器的“集群”。具有相同集群 ID 的反射器属于同一个反射器集群它们之间相互备份。如果多个集群 ID 存在每个反射器集群需要独立管理。步骤 2创建 BGP 对等体配置创建一个 BGPPeer 资源定义所有节点all()与带有route-reflector true标签的节点建立 BGP 对等关系[roothd1 ~]# cat bgppeer.yamlapiVersion: projectcalico.org/v3 kind: BGPPeer metadata: name: peer-with-route-reflectors spec: nodeSelector: all()# 所有节点都应用此配置peerSelector: route-reflectortrue# 仅与带有此标签的节点建立对等关系#实际生产环境中--allow-version-mismatch 忽略版本差异强制应用不建议加[roothd1 ~]# calicoctl apply -f bgppeer.yaml --allow-version-mismatch配置解析nodeSelector: all()表示所有节点都作为 BGP 客户端。peerSelector: route-reflector true表示这些 BGP 客户端仅与带有route-reflector true标签的节点建立对等关系。在生产环境中集群 ID 和节点名字要根据实际进行配置节点名字要换成你实际选的 Master 或专用节点名。步骤 3给路由反射器节点打标签[roothd1 ~]# kubectl label node hd1 route-reflectortruenode/hd1 labeled[roothd1 ~]# kubectl label node hd2 route-reflectortruenode/hd2 labeled这一步让步骤 2 中的peerSelector能够选中这些节点。步骤 4禁用BGP的全互联模式[roothd1 ~]# cat bgpconfig.yamlapiVersion: projectcalico.org/v3 kind: BGPConfiguration metadata: name: default spec: nodeToNodeMeshEnabled:false# 关闭全互联模式[roothd1 ~]# calicoctl apply -f bgpconfig.yaml --allow-version-mismatch关闭全互联模式后节点之间不再自动建立 BGP 连接而是按照 BGPPeer 资源的定义只与路由反射器建立连接。验证配置结果[roothd1 ~]# calicoctl node statusCalico process is running. IPv4 BGP status -----------------------------------------------------------|PEER ADDRESS|PEER TYPE|STATE|SINCE|INFO|-----------------------------------------------------------|192.168.1.12|nodespecific|up|08:27:50|Established||192.168.1.13|nodespecific|up|08:27:50|Established|-----------------------------------------------------------当PEER TYPE显示为node specific而非mesh或其他时说明路由反射器模式已成功启用。不难看到在私有部署环境里Calico 项目能够覆盖更多的场景Calico 的 IPIP/VXLAN 模式或者配合云厂商 ENI弹性网卡 的 CNI 插件是现在公有云上的主流方案八、K8s 网络优化建议优化建议适用场景原理节点在同一网段时使用 BGP 模式私有数据中心、节点二层可达避免隧道封装带来的性能开销直接路由转发BGP 模式中使用路由反射器集群节点超过 10 个减少 BGP 连接数从 O(n²) 降为 O(n)公有云环境使用 Flannel host-gw阿里云、AWS 等公有云公有云网络环境简单host-gw 模式性能好且配置方便使用 NetworkPolicy 实现网络隔离需要安全隔离的多租户环境Calico 原生支持 Kubernetes NetworkPolicyFlannel 不支持各插件的对比总结特性CalicoBGPCalicoIPIP/VXLANFlannelhost-gwFlannelVXLAN性能★★★★★★★★★★★★★★★封装开销无有无有网络策略✅ 支持✅ 支持❌ 不支持❌ 不支持跨子网通信❌ 需要 BGP 路由✅ 支持❌ 需要直连✅ 支持对底层网络要求高需 BGP 支持低中需二层可达低推荐场景私有数据中心混合网络环境公有云环境跨子网且无需网络策略核心知识速查卡关键词一句话总结docker0 网桥宿主机的虚拟交换机所有 Docker 容器通过它互联veth 对一根虚拟网线连接容器的网络命名空间和宿主机的网桥pause 容器Pod 内共享网络命名空间的“锚点容器”所有业务容器加入它的网络命名空间CNI 插件Kubernetes 网络配置的标准化接口负责为 Pod 分配 IP 和设置网络Calico IPIP使用 IP-in-IP 隧道封装跨子网流量适用于三层不相通的环境Calico BGP节点通过 BGP 协议互相通告 Pod 子网路由直接路由性能最优Calico VXLAN使用 VXLAN 构建虚拟二层网络允许跨越三层网络通信BGP 全互联所有节点两两建立 BGP 连接节点数增加时连接数指数级增长路由反射器解决 BGP 全互联扩展性问题的机制将 O(n²) 连接降为 O(n)BGP边界网关协议用于 AS 之间交换路由信息被 Calico 用于 Pod 路由通告