需求导向的K8S网络原理分析:Kube-proxy、Flannel、Calico的地位和作用

最近发现自己似乎从来没学明白过Kubernetes网络通信方案,特开一贴复习总结一下。

在k8s中,每个 Pod 都拥有一个独立的 IP 地址,而且假定所有 Pod 都在一个可以直接连通的、扁平的网络空间中。所以不管它们是否允许在同一个 Node(宿主机)中,都要求它可以直接通过对方的 IP 进行访问。用户不需要额外考虑如何建立 Pod 之间的连接,也不需要考虑将容器端口映射到主机端口等问题。同时,外界的

省流,K8s网络的目标是为了实现:

  1. pod之间的互联互通
  2. 对外提供服务

为了实现上述功能,需要为每一个pod都维护完整的网络协议栈,同时,维护pod之间的网络路由。

CNI容器网络接口

首先,当你起了一个裸的、没有网络的pod之后,这个pod是没有任何基于TCP/IP手段和外界进行通信的。你可能只能通过crictl的客户端看到自己起了这么一个pod。

为了建立pod和外界的(基于TCP/IP的)通信,并且将不同pod的网络隔离开,需要为每一个pod构建一个网络命名空间。网络命名空间(Network Namespace)是一种内核级别的隔离机制,用于将不同进程组(比如一个pod就是一个被隔离的进程组)的网络环境隔离开来。每个网络命名空间拥有独立的网络栈,实现网络资源的完全隔离。

具体一点,网络命名空间的核心功能及特性是:

  1. 网络隔离
    不同网络命名空间的进程无法直接通信,需通过跨命名空间的网络设备(如 veth 对、网桥)或物理设备连接。例如,pod A 在命名空间ns1,pod B 在命名空间ns2,它们的(虚拟)物理层、数据链路层、网络层、传输层、应用层都实现了相互独立。
  2. 独立网络栈
    每个命名空间可独立配置 IP 地址、子网、网关、DNS 服务器等。
  3. 轻量级隔离
    相比虚拟机,网络命名空间的资源开销极小,适合容器场景。

我们首先实现同一台物理机内pod之间的相互通信。

为了实现不同网络命名空间之间的通信,需要把若干的pod从物理层到网络层连起来。

我们首先实现(虚拟)物理层和数据链路层的相互连接,这基于veth设备对。

你可以把它想象为一根带有两个水晶头的网线,两端(veth1和veth2)分别插在两个pod上。如下图所示:

在这里插入图片描述

在有多个pod的情况下,一般会新建一个公用的虚拟交换机(如图所示的bridge),然后所有的pod都接到这个交换机上,也能通过这个交换机实现pod之间的通信。如下图所示:

在这里插入图片描述

图里面这个bridge是一个虚拟网络设备,所以具有网络设备的特征,可以配置IP、MAC地址等;其次,bridge是一个虚拟交换机,和物理交换机有类似的功能。
对于普通的网络设备来说,只有两端,从一端进来的数据会从另一端出去,如物理网卡从外面网络中收到的数据会转发给内核协议栈,而从协议栈过来的数据会转发到外面的物理网络中。
而bridge不同,bridge有多个端口,数据可以从任何端口进来,进来之后从哪个口出去和物理交换机的原理差不多,要看数据包指向的终端MAC地址。

进一步地,我们给pod、网桥都配上IP地址,于是我们实现了同一台物理机内pod之间的相互通信。

在这里插入图片描述
进一步地,我们需要实现跨不同主机pod之间的通信。

一种简单的想法是,建一个跨多个主机的bridge不就得了?

在这里插入图片描述
这种在已有的网络上通过软件构建一个扩展版虚拟网络的方法,被称为:Overlay Network(覆盖网络)。从实现效果来看,就是把若干个节点上的小bridge整合成了一个大bridge。

Calico和Flannel是overlay network的两种实现方案。

Calico和Flannel

为了实现跨节点之间的数据通信,这就需要calico和flannel出场了。

跨节点数据包路由,主要就是两种情形:

  1. 节点和节点之间能够通过IP直连(三层可达)
  2. 节点和节点之间连接复杂(三层不可达)

解决方案也很简单,对于三层可达的网络,可以直接配置节点的路由表进行转发。对于三层不可达的网络,搭一个隧道实现网络穿透就可以了。

从这个视角看,Calico和Flannel两个插件虽然名字不太一样,但是实现的功能大同小异。

calico中,主要提供两种跨node包路由的模式:

  • BGP 模式:在三层可达的时候,Calico 在每个节点上运行 BGP 客户端,将 Pod 的 IP 路由信息通过 BGP 协议通告给其他节点。pod间流量直接通过路由规则进行转发。
  • IPIP 模式:当两个节点不在同一子网(三层不可达)时,Calico 将Pod间数据包的外边再包一层IP 头,通过隧道实现传输。

IPIP模式的示意图

flannel中,也提供两种跨节点包路由的方式:

  • VXLAN模式:VXLAN 是 Linux 内核原生支持的网络虚拟化技术,通过在 IP 包内封装二层以太网帧,实现跨节点的虚拟二层网络。原理和Calico的IPIP模式类似。
  • Host-gateway模式:直接利用节点的物理网络进行路由,无需隧道封装,通过将 Pod 子网的路由直接指向目标节点的物理 IP,实现跨节点通信。
    flannel架构图

Kube-proxy

在前文中,我们已经通过calico / flannel等技术实现了同一个集群内pod的互联互通。但是仍然有一些比较关键的需求需要解决。

在实际使用集群的过程中,pod启动时的IP是随机分配的,这意味着访问集群内部pod必不能用硬编码方式实现。此外, Pod 实例会动态变化,需要设计动态服务发现和动态负载均衡方案。要在pod不断的变化的IP中追求不变,并且抓住这个不变实现集群内部pod的访问。

K8S的解决方案是service+DNS。Service里记录了pod的标签和端口映射规则(只是一个配置文件)。在用户向集群提交service的配置后,集群会创建和service同名的endpoint对象,用于根据service记录的标签去匹配对应的某些pod。用户在访问某些特定pod的时候,只需要访问service/endpoint的IP即可,由endpoint实现流量的路由和负载均衡。

由于endpoint的IP也在变,所以集群内引入了DNS机制,为每一个service都赋予了一个域名,通过service域名访问对应的pod。

为了实现上述功能,需要不断地监控pod的状态,进而实现路由转发。Kube-proxy提供了这样的解决方案。

kube - proxy 会持续监控 API Server,当 Service 或 Endpoint 资源发生变更时,kube - proxy 会通过list-watch手段获取这些信息。
kube - proxy 根据这些信息更新本地的iptables/ipvs规则,这些规则决定了如何将流量从 Service 的 IP 和端口转发到后端的 Pod。

references

https://segmentfault.com/a/1190000009491002
https://learn.lianglianglee.com
https://zhuanlan.zhihu.com/p/439920165
https://blog.csdn.net/weixin_42587823/article/details/144938902

<think>好的,我现在需要解决用户提出的关于Kubernetes中未找到pod 'kube-proxy-8vb8k'的问题。首先,我得理解这个问题的背景。用户遇到了一个NotFound错误,说明他们尝试访问或操作这个特定的kube-proxy Pod时,系统无法找到它。 首先,我应该回忆一下kube-proxyKubernetes中的角色。根据引用[3][5],kube-proxy是负责服务发现负载均衡的关键组件,通常以DaemonSet的形式部署在每个节点上。这意味着每个节点都应该有一个kube-proxy Pod在运行。如果用户找不到特定的Pod(比如kube-proxy-8vb8k),可能的原因有几个: 1. **DaemonSet未正确部署**:可能kube-proxy的DaemonSet没有被正确创建或配置,导致某些节点上没有运行Pod。 2. **节点选择器问题**:DaemonSet的节点选择器可能排除了某些节点,导致Pod没有被调度到目标节点上。 3. **Pod被删除或未启动**:可能该Pod被意外删除,或者由于资源不足、镜像拉取失败等原因无法启动。 4. **命名空间问题**:用户可能没有在正确的命名空间(比如kube-system)中查找Pod。 5. **集群状态异常**:节点可能处于NotReady状态,导致Pod无法运行。 接下来,我需要按照步骤来诊断解决这个问题。首先,用户应该检查kube-proxy的DaemonSet状态,确保它存在于集群中,并且所有节点都有预期的Pod数量。使用命令`kubectl get daemonset -n kube-system`可以查看DaemonSet的状态,确认DesiredAvailable的数量是否一致。 然后,检查Pod的具体情况。用户可能使用了错误的命名空间,kube-proxy通常部署在kube-system命名空间下,所以正确的命令是`kubectl get pods -n kube-system -l k8s-app=kube-proxy`。如果Pod列表中没有kube-proxy-8vb8k,可能该Pod已经被终止或从未创建。 接下来,查看节点状态。如果节点处于NotReady状态,kube-proxy Pod可能无法在该节点上运行。使用`kubectl get nodes`检查所有节点的状态,并确保目标节点是Ready的。 如果节点状态正常,需要进一步检查Pod的事件日志。使用`kubectl describe daemonset kube-proxy -n kube-system`可以查看DaemonSet的事件,了解是否有调度或启动错误。此外,查看特定节点的Pod日志,如果有Pod存在但处于CrashLoopBackOff状态,可以使用`kubectl logs <pod-name> -n kube-system`来获取日志信息,帮助诊断启动失败的原因。 另一个可能性是镜像拉取问题。kube-proxy的镜像可能配置错误,或者私有仓库的凭证问题导致无法拉取镜像。检查DaemonSet的镜像配置是否正确,以及节点是否有权限访问所需的镜像仓库。 如果以上步骤无法解决问题,可能需要重新生成DaemonSet。删除现有的kube-proxy DaemonSet(谨慎操作,需确认集群支持自动重建),Kubernetes可能会自动重新创建它。但需要注意,直接删除DaemonSet可能会导致服务中断,尤其是在生产环境中,需谨慎处理。 最后,如果问题依旧存在,考虑检查Kubernetes组件的整体健康状况,包括kubelet是否正常运行,以及是否有网络策略或安全策略阻止了Pod的创建运行。 总结起来,解决步骤应包括检查DaemonSet状态、确认命名空间、节点状态、Pod事件日志,验证镜像配置,必要时重建DaemonSet,并确保集群组件正常运行。如果用户按照这些步骤排查,应该能够定位并解决问题。</think>### Kubernetes中未找到Pod 'kube-proxy-8vb8k'的解决方法 #### 1. **确认kube-proxy的部署模式** Kube-proxy默认以DaemonSet形式部署在**所有节点**上[^3],执行以下命令检查DaemonSet状态: ```bash kubectl get daemonset -n kube-system | grep kube-proxy ``` - **预期结果**:`DESIRED``AVAILABLE`值应等于集群节点数。 - **异常处理**:若值为0,说明DaemonSet未正确部署,需检查集群初始化配置或重新部署kube-proxy组件。 --- #### 2. **检查Pod所在的命名空间** kube-proxy组件默认位于`kube-system`命名空间,确认查询命令是否包含命名空间过滤: ```bash kubectl get pods -n kube-system -l k8s-app=kube-proxy ``` - **常见错误**:未指定`-n kube-system`导致无法列出Pod。 --- #### 3. **排查节点状态问题** 如果节点处于`NotReady`状态,kube-proxy Pod将无法启动: ```bash kubectl get nodes ``` - **处理步骤**: 1. 检查节点状态:`kubectl describe node <节点名称>` 2. 修复节点网络或资源问题(如磁盘空间、内存不足)。 --- #### 4. **检查Pod事件日志** 若Pod存在但状态异常(如`CrashLoopBackOff`): ```bash # 查看Pod事件 kubectl describe pod kube-proxy-8vb8k -n kube-system # 查看Pod日志(若Pod曾短暂运行) kubectl logs kube-proxy-8vb8k -n kube-system ``` - **典型问题**: - **镜像拉取失败**:检查`kube-proxy`镜像配置(例如`k8s.gcr.io/kube-proxy:v1.23.0`)。 - **权限问题**:确认ServiceAccount权限RBAC配置[^4]。 --- #### 5. **验证kube-proxy配置模式** kube-proxy支持`iptables`/`ipvs`/`userspace`模式,配置错误可能导致Pod无法启动: ```bash # 查看kube-proxy的ConfigMap配置 kubectl get configmap -n kube-system kube-proxy -o yaml ``` - **关键参数**: ```yaml mode: "ipvs" # 推荐使用ipvs模式 ``` --- #### 6. **强制重建kube-proxy DaemonSet** 若确认配置无误,可尝试删除DaemonSet触发重建: ```bash kubectl delete daemonset kube-proxy -n kube-system ``` - **注意**:Kubernetes控制平面会自动重建DaemonSet(需确认集群处于健康状态)。 --- #### 7. **检查底层网络插件兼容性** 某些网络插件(如CalicoFlannel)可能与kube-proxy模式冲突: - **排查方法**:临时切换为`iptables`模式测试是否恢复正常。 --- ### 总结流程图 ```mermaid graph TD A[报错NotFound] --> B{检查DaemonSet状态} B -->|正常| C[检查命名空间标签] B -->|异常| D[重新部署kube-proxy] C -->|存在Pod| E[查看Pod事件/日志] C -->|无Pod| F[检查节点状态] E --> G[修复镜像/权限问题] F --> H[修复节点问题] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PenguinLeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值