k8s 网络基础解析
k8s 网络基础
k8s是为了解决大集群(Cluster)中容器部署、伸缩和管理的各种问题而出现的一种容器编排引擎。我们上次已经讲了k8s的基础架构,如果大家对基础架构不了解,那么建议先观看k8s的基础架构,那么今天我们来分析,k8s中的网络是怎么构成的。
Node之间的通信
Node IP 是节点在物理网络或云网络中的真实IP地址,可以是内网IP,也可以是公网IP。
构建集群时,必须保证所有节点可以通过Node IP互通,之后kubelet、kube-proxy 等组件通过 Node IP 连接到 API Server。
在 Kubernetes 集群中,节点(Node)之间的通信是通过Node IP来实现的,具体示例有:
通信类型 | 参与组件 | 协议 | 目的 |
---|---|---|---|
控制平面通信 | API Server ↔ kubelet | HTTPS | 节点状态上报、Pod 生命周期管理 |
控制平面通信 | API Server ↔ Scheduler | HTTP | 资源调度决策 |
控制平面通信 | API Server ↔ Controller Manager | HTTP | 集群状态维护(如 Deployment 扩缩容、Service 同步等) |
数据平面通信 | kube-proxy ↔ API Server | HTTPS | 同步 Service/Endpoint 信息 |
控制平面通信始终基于节点真实 IP,例如当新节点加入集群时,kubelet 使用 Node IP 访问 API Server,定期向API Server报告节点状态等。
pod中容器的通信
Pod 是 Kubernetes 的最小调度单元,同一 Pod 内的所有容器共享同一个网络命名空间,具体表现为:
- 共享同一 IP 地址
- 共享同一端口空间(需避免端口冲突)
- 共享同一网络设备(如虚拟网卡)
- 共享同一主机名(hostname)
此机制与 Docker 的 --network=container:<id>
模式原理一致。
Kubernetes 创建 Pod 时,首先启动一个 pause 容器(镜像为 k8s.gcr.io/pause),用来创建并持有网络命名空间(Network Namespace)。其作为其他容器的网络基础设施锚点且生命周期与 Pod 完全绑定(Pod 终止时才会销毁)。
其他业务容器通过 container 网络模式接入 pause 容器的网络命名空间。
由于pod中所有容器共享同一个IP地址,所以他们之间可以直接通过localhost
进行访问。注意,需要不同服务注册不同的端口号。此外,也可以通过共享内存或文件系统进行通讯。
在docker原生模式下,Pod 通过 docker0 网桥获得私有 IP(如 172.17.0.0/16),此时Pod IP 仅在宿主机内部可达,跨节点通信需通过 NodePort 或外部负载均衡。
此时 Pod 网络行为与传统 Docker 容器完全一致,要实现Pod IP 在全集群内可达,需要用到CNI网络插件。此时 Docker 仅作为容器运行时,网络由 CNI 插件接管。
集群中pod的相互通信
CNI介绍
Docker创建的IP只能在本地服务器上访问,怎么在才能在别的节点上访问这个 Pod IP,实现集群中所有pod的通信呢?
Kubernets网络模型中,有一个叫CNI的网络接口。
CNI(Container Network Interface,容器网络接口) 是 Kubernetes 中用于管理容器网络的标准接口规范,而 CNI 网络插件 是具体实现这一规范的组件,负责为容器(或 Pod)分配 IP 地址、配置网络设备、设置路由规则等,确保容器之间能够跨节点通信。
Kubernetes 本身不直接处理容器网络,而是通过 CNI 插件将网络管理能力解耦。
CNI可以为为每个 Pod 分配唯一的集群内 IP,并且可以确保Pod跨节点通信。
CNI原理
1、 pod创建时:
- Kubernetes 调用 CNI 插件,为 Pod 创建虚拟网络接口(如 eth0)。
- 分配 IP 地址,并配置路由规则(如 Pod 访问其他节点时的下一跳地址)。
2、跨节点通信:
- Overlay 模式(如 Flannel VXLAN):封装数据包,在物理网络之上构建虚拟网络。
- BGP 模式(如 Calico):通过路由协议将 Pod IP 通告到整个集群。
- Underlay 模式(如 Macvlan):直接使用物理网络设备分配 IP。
3、 pod销毁时
- CNI 插件释放 IP 地址并清理网络配置。
BGP 模式的实现
在 BGP(Border Gateway Protocol)模式下(如 Calico 的实现),Pod IP 是全局路由可达的,数据包 无需 NAT 即可跨节点直达目标 Pod。
每个节点 会通过 BGP 协议向集群 宣告本节点的 Pod 子网例。假如有两个节点,节点1和节点2:
节点 1 的 Pod CIDR 为 10.244.1.0/24
节点 2 的 Pod CIDR 为 10.244.2.0/24
之后,每个节点通过 BGP 学习到其他节点的路由信息,我们可以查看节点1的的路由信息。
# 节点 1 的路由表
$ ip route
10.244.2.0/24 via 192.168.0.2 dev eth0 # 目标 Pod IP 段下一跳为节点 2 的物理 IP
结果显示,10.244.2.0/24网段的下一跳地址,指向了PDD所在节点的物理IP 。
依据BGP协议跨节点通信的流程
下面我们观察跨节点通信流程,以
以 Pod A(10.244.1.2)→ Pod B(10.244.2.3)为例子。
1、源节点(节点 1):
- 根据 Pod B 的 IP
10.244.2.3
匹配路由规则10.244.2.0/24 via 192.168.0.2
- 直接通过物理网卡 eth0 将数据包发送到 节点 2 的物理 IP(
192.168.0.2
)
2、目标节点:
- 收到数据包后,根据本地路由规则 10.244.2.0/24 dev caliXXXX 转发到 Pod B 的虚拟网卡
- 全程无 NAT 转换,源 IP 保持 10.244.1.2,目标 IP 保持 10.244.2.3
3、BGP 对等体(Peer)配置
- BGP Speaker:每个节点运行 BGP 客户端(如 Calico 的 bird)
BGP模式的必要条件
1、 网络基础设施的支持
- 节点间物理网络需互通
- 物理交换机/路由器需支持 BGP 协议
2、 IP地址规划
- Pod CIDR 必须为 全局唯一且可路由 的 IP 段(如 10.244.0.0/16)
- 节点物理 IP 需在同一 Layer 3 网络
CNI的功能
下面我们总结CNI的功能。
-
节点上的 Pod 可以和其他任何节点上的 Pod 通信(称为扁平化网络),即节点间 Pod 的互相访问;
-
节点上的代理(比如:系统守护进程、kubelet)可以和节点上的所有 Pod 通信,即系统组件访问 Pod;
验证命令
我们给出是否成功配置k8s网络的验证命令(需提前安装calicoctl工具):
# 查看节点 BGP 邻居状态
calicoctl node status
# 检查节点路由表
ip route show | grep cali
# 测试跨节点 Pod 通信(tcpdump 抓包验证无 NAT)
kubectl exec -it pod-a -- curl http://10.244.2.3
tcpdump -i eth0 host 192.168.0.2 and port 80