☰
kube-proxy、CNI与CoreDNS职责边界详解:K8s网络故障定位核心地图
2026/10/27 4:01:29 网站建设 项目流程

1. 这不是“选哪个”,而是“它们各自在替谁干活”——从真实排障现场说起

你有没有遇到过这样的情况:Pod明明跑起来了,kubectl get pods显示 Running,kubectl logs也能看到日志在刷,但一用curl http://service-name:8080就超时?或者更诡异的——在集群内curl service-name能通,但从节点宿主机上curl 10.96.0.100:8080却失败?又或者,刚部署完 CoreDNS,nslookup kubernetes.default.svc.cluster.local返回server can't find ...: NXDOMAIN,但dig @10.96.0.10 kubernetes.default.svc.cluster.local却能拿到正确 A 记录?

这些不是配置写错了,也不是 YAML 拼错了字母,而是你正在同时和三个不同层级、不同职责、不同生命周期的网络组件打交道:kube-proxy、CNI 插件、CoreDNS。它们名字里都带个“网”字,但干的活儿天差地别——就像一栋写字楼里的保安(kube-proxy)、电梯维保公司(CNI)、前台总机(CoreDNS),三者协作才能让访客(请求)准确抵达目标办公室(Pod)。把它们混为一谈,等于让保安去修电梯、让前台去查监控录像。

这个标题里的“区别”,绝不是教科书式的名词解释对比表。它是一张故障定位地图,是你在深夜收到告警后,能30秒内判断该先敲哪台机器、该看哪个日志、该改哪行配置的实战指南。我过去三年在某中型互联网公司的K8s平台组,处理了超过270起与服务访问异常相关的工单,其中73%的问题根源,都卡在对这三者的职责边界理解模糊上。比如有一次,开发同学坚持说“Service没生效”,我们花了两小时排查 kube-proxy 的 iptables 规则,最后发现是 CNI 插件的 Calico BGP 邻居没建立,导致 Pod 网络根本没连通;还有一次,运维同事反复重启 CoreDNS,却始终无法解析,直到我登录到一个 Pod 里执行cat /etc/resolv.conf,才发现 DNS 搜索域被错误覆盖成了default.svc.cluster.local,而实际应该包含svc.cluster.local和cluster.local—— 这完全是 kubelet 启动参数配置问题,和 CoreDNS 本身毫无关系。

所以,这篇文章不讲“什么是 kube-proxy”,而是讲“当你 curl 失败时,它到底有没有被调用”;不罗列 CNI 插件列表,而是讲“为什么 Flannel 的 vxlan 模式下,节点间流量必须走 8472 端口,而 Calico 的 bgp 模式下,这个端口压根不存在”;不背诵 DNS 解析流程,而是讲“当nslookup返回 SERVFAIL 时,你应该立刻检查 CoreDNS 的forward插件是否指向了上游 DNS,还是该去查 kubelet 的--cluster-dns参数是否指向了正确的 ClusterIP”。

核心关键词:kube-proxy、CNI、CoreDNS、服务发现、DNS域名解析、Kubernetes网络模型。如果你正被 Service 访问不通、Pod 间网络异常、域名解析失败等问题困扰,或者你刚学完 K8s 基础概念,正试图把零散的知识点串成一张可操作的网络地图,那么接下来的内容,就是你真正需要的“解剖刀”。

2. 三层网络职责解耦:谁管“连接”,谁管“通路”,谁管“地址簿”

Kubernetes 的网络设计哲学,是把一个复杂的分布式系统通信问题,拆解成三个正交、可独立演进、可自由组合的子问题。这种分层不是为了炫技,而是为了工程上的可维护性与可替换性。你可以把 kube-proxy 换成 IPVS 模式,不影响 CNI 插件;可以换掉 Calico 改用 Cilium,CoreDNS 依然照常工作;甚至可以把 CoreDNS 替换成自研的 DNS 服务,只要它遵循 Kubernetes 的 DNS 规范。这种解耦,正是理解“区别”的起点。

2.1 kube-proxy:集群内部的“智能负载均衡器”,只管 Service 层的流量转发

kube-proxy 的核心使命,是实现 Kubernetes Service 抽象的网络语义。它不关心 Pod 怎么启动、IP 怎么分配、数据包怎么跨节点传输。它只做一件事:确保当你访问一个 Service 的 ClusterIP(如10.96.0.100)时,请求能被可靠地、按策略(ClusterIP/NodePort/LoadBalancer)转发到后端某个健康的 Pod IP 上。

它的实现方式,本质上是在每个 Node 上,构建一个“虚拟服务入口”。这个入口不是物理设备,而是由 kube-proxy 动态维护的一套规则集合。目前主流有三种模式:

  • iptables 模式(默认,稳定可靠):kube-proxy 监听 Service 和 Endpoint 的变更事件,将每一条 Service 规则翻译成一组 iptables 链(如KUBE-SERVICES,KUBE-SEP-xxxx)。当数据包到达 Node 的 netfilter 框架时,会按顺序匹配这些链,最终通过 DNAT 将目标 IP 和端口修改为某个后端 Pod 的 IP 和端口。整个过程完全在内核态完成,性能极高。但规则数量随 Service 和 Pod 数量线性增长,当集群规模超过 5000 个 Service 时,iptables 规则链会变得极其庞大,更新延迟明显,且缺乏连接跟踪之外的高级功能(如会话保持、健康检查重试)。

  • IPVS 模式(高性能,推荐用于中大型集群):kube-proxy 利用 Linux 内核的 IP Virtual Server 模块,将 Service 映射为一个 IPVS virtual server,并将后端 Pod 注册为 real server。IPVS 基于哈希表查找,规则更新复杂度为 O(1),即使 Service 数量达到数万个,性能依然稳定。它原生支持多种负载均衡算法(rr, wrr, lc, dh, sh)、会话保持(--ipvs-scheduler=sh)、健康检查(--ipvs-exclude-cidrs)。但要求内核版本 >= 4.1,且需手动加载ip_vs,ip_vs_rr,ip_vs_wrr,ip_vs_sh等模块。我所在团队在将集群从 3000+ Service 扩容到 8000+ 时,将 kube-proxy 切换为 IPVS 模式后,Service 规则同步延迟从平均 12 秒降至 200 毫秒以内,效果立竿见影。

  • userspace 模式(已废弃,仅作历史了解):kube-proxy 自己监听 Service 端口,接收请求后再通过 socket 转发给后端 Pod。这种方式完全在用户态,灵活性高但性能极差,且存在单点故障风险,K8s 1.16 版本后已被彻底移除。

提示:kube-proxy 的工作范围严格限定在Node 的网络命名空间(netns)内。它只处理目标地址是本节点上某个 Service ClusterIP 或 NodePort 的入站流量。它不参与任何 Pod 之间的直接通信,也不负责 Pod IP 的可达性。一个 Pod 要访问另一个 Pod,流量路径是:PodA -> CNI 网络 -> PodB。只有当 PodA 访问的是 Service 名称或 ClusterIP 时,kube-proxy 的规则才会被触发。

2.2 CNI(Container Network Interface):容器网络的“基建承包商”,负责 Pod 网络的“物理层”与“数据链路层”

如果说 kube-proxy 是在“应用层”定义服务如何被访问,那么 CNI 就是在“底层”定义容器如何获得 IP、如何与其他容器通信、如何与外部世界连通。它是一个规范(spec),而不是一个具体软件。Kubernetes 本身不提供网络实现,它只在 Pod 创建和销毁时,调用 CNI 插件定义的二进制程序(如/opt/cni/bin/flannel),并传入标准的 JSON 配置(CNI_COMMAND=ADD/DEL,CNI_CONTAINERID,CNI_NETNS等环境变量),由插件来完成具体的网络配置工作。

一个典型的 CNI 插件链(chain)会依次完成以下任务:

  1. IP 地址分配(IPAM):从预定义的网段(如10.244.0.0/16)中为 Pod 分配一个唯一的 IPv4/IPv6 地址。这通常由一个专门的 IPAM 插件(如host-local,dhcp,static)完成。
  2. 网络接口创建与配置:在 Pod 的网络命名空间(netns)内,创建一对 veth 设备(如eth0和vethxxx),并将eth0配置为 Pod 的默认网卡,赋予其分配到的 IP 和路由。
  3. 主机侧网络连接:将 veth 设备的另一端(vethxxx)挂载到主机的 root netns,并连接到一个桥接设备(如cbr0,flannel.1,cali0)或直接配置为路由。
  4. 跨节点通信隧道/路由配置:这是 CNI 插件最核心的差异化能力。Flannel 通过 VXLAN 或 host-gw 模式,在节点间建立隧道或配置静态路由;Calico 使用 BGP 协议,让每个节点像一台路由器一样宣告自己的 Pod 网段;Cilium 则利用 eBPF,在内核中直接实现高性能的网络策略和负载均衡。

注意:CNI 插件的配置文件(通常是/etc/cni/net.d/10-flannel.conflist)决定了整个集群的网络拓扑。一旦集群初始化完成,随意修改 CNI 配置是极其危险的操作。我曾见过一个团队在生产环境尝试将 Flannel 从 vxlan 切换到 host-gw,结果因为所有节点的路由表未同步更新,导致一半 Pod 网络瞬间中断,恢复耗时 47 分钟。正确的做法是:在新集群上线前充分验证,或使用支持平滑迁移的 CNI(如 Cilium 的--enable-bpf-masquerade=false模式)。

2.3 CoreDNS:集群内部的“电话总机”,负责将服务名称翻译成 IP 地址

CoreDNS 是 Kubernetes 官方推荐的、可插件化的 DNS 服务器,它取代了早期的 kube-dns。它的唯一核心职责,就是响应集群内 Pod 发起的 DNS 查询请求,并根据 Kubernetes 的 DNS 命名规范,返回对应 Service 或 Pod 的 IP 地址。

Kubernetes 定义了一套严格的 DNS 命名约定:

  • Service 名称解析:<service-name>.<namespace>.svc.cluster.local→ 解析为该 Service 的 ClusterIP。
  • Headless Service 的 Pod 名称解析:<pod-ip-as-hyphenated>.<service-name>.<namespace>.svc.cluster.local→ 解析为该 Pod 的 IP。
  • Pod 名称解析(需开启--enable-pod-hostname-annotation):<pod-name>.<namespace>.pod.cluster.local→ 解析为该 Pod 的 IP。

CoreDNS 本身并不“知道”这些规则。它依靠一个名为kubernetes的专用插件来实现。这个插件会与 kube-apiserver 建立长连接,实时监听 Service、Endpoint、Namespace 等资源的变化,并将这些信息缓存到内存中。当收到一个 DNS 查询时,kubernetes插件会首先检查查询的域名是否符合上述约定,如果符合,则直接从本地缓存中返回结果,无需向 apiserver 发起额外请求,因此响应速度极快(通常 < 5ms)。

关键点:CoreDNS 是一个纯粹的应用层服务。它的正常运行,高度依赖于底层网络的通畅。如果 Pod 根本无法访问 CoreDNS 的 ClusterIP(10.96.0.10),那么无论 CoreDNS 配置多么完美,DNS 解析都会失败。这就是为什么排查 DNS 问题,永远要从“网络连通性”开始,而不是一上来就检查 CoreDNS 的 ConfigMap。

3. 实操场景深度拆解:一次完整的“服务访问失败”故障排查链

理论终归要落地。下面我以一个真实的、高频发生的故障场景为例,手把手带你走一遍,如何运用对 kube-proxy、CNI、CoreDNS 三者职责的理解,进行精准、高效的排查。这个过程,就是对“区别”最深刻的认知。

3.1 故障现象还原:一个看似简单的curl命令为何失败?

假设你有一个名为nginx的 Deployment,部署在default命名空间,暴露了一个名为nginx-service的 ClusterIP 类型 Service,端口为80。你在一个名为busybox的临时调试 Pod 中执行:

kubectl exec -it busybox -- sh / # nslookup nginx-service Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: nginx-service Address 1: 10.96.0.100 nginx-service.default.svc.cluster.local / # curl -v http://nginx-service * Trying 10.96.0.100:80... * connect to 10.96.0.100 port 80 failed: Connection refused * Failed to connect to nginx-service port 80 after 131173 ms: Connection refused

nslookup成功,说明 DNS 解析没问题,CoreDNS 工作正常。但curl却提示Connection refused,这明确指向了kube-proxy 的转发环节。因为nslookup只是查到了 IP,而curl是要真正建立 TCP 连接。

3.2 第一步:确认 kube-proxy 是否在工作——检查 iptables/IPVS 规则

登录到busyboxPod 所在的 Node(假设为node-01),执行:

# 查看 kube-proxy 的进程状态 ps aux | grep kube-proxy # 如果是 iptables 模式,检查 Service 规则是否存在 sudo iptables -t nat -nL KUBE-SERVICES | grep "10.96.0.100" # 如果是 IPVS 模式,检查 virtual server sudo ipvsadm -ln | grep "10.96.0.100"

预期输出应类似:

# iptables 模式 Chain KUBE-SERVICES (2 references) target prot opt source destination KUBE-SVC-XXXXXX tcp -- 0.0.0.0/0 10.96.0.100 /* default/nginx-service cluster IP */ tcp dpt:80 # IPVS 模式 TCP 10.96.0.100:80 rr -> 10.244.1.3:80 Masq 1 0 0 -> 10.244.1.4:80 Masq 1 0 0

如果这里没有找到对应的规则,说明 kube-proxy 没有成功同步该 Service 的配置。常见原因有:

  • kube-proxy 的--master参数指向了错误的 apiserver 地址。
  • kube-proxy 的 RBAC 权限不足,无法 list/watch Service 和 Endpoint。
  • kube-proxy 的配置文件中--proxy-mode设置错误,或未启用--bind-address。

实操心得:不要只看 kube-proxy 的 Pod 状态是 Running,就认为它工作正常。我曾在一个集群中,kube-proxy Pod 一直 Running,但日志里持续报错Failed to list *v1.Service: Get https://127.0.0.1:6443/api/v1/services?limit=500&resourceVersion=0: dial tcp 127.0.0.1:6443: connect: connection refused,原因是 kube-proxy 的启动参数里--master错误地写成了https://127.0.0.1:6443,而该节点上并没有运行 apiserver(apiserver 只在 master 节点上)。这是一个典型的“进程活着,但功能瘫痪”的案例。

3.3 第二步:确认后端 Pod 是否真实可达——绕过 kube-proxy 直连测试

如果 kube-proxy 规则存在,但curl仍失败,问题就出在后端 Pod 本身。此时,你需要绕过 Service 层,直接访问 Pod 的 IP。

在busyboxPod 中,先获取nginx的 Pod IP:

/ # kubectl get pods -o wide | grep nginx nginx-7c5f7d8b9-abcde 1/1 Running 0 5m 10.244.1.3 node-01 <none> <none>

然后直接curl:

/ # curl -v http://10.244.1.3 # 如果成功,说明 Pod 本身是健康的,问题一定在 kube-proxy 的 DNAT 或 SNAT 规则上。 # 如果失败,说明问题在 CNI 层或 Pod 应用层。

3.4 第三步:验证 CNI 网络连通性——Pod 到 Pod 的基础通信

如果直连 Pod IP 也失败,那就要怀疑 CNI 了。此时,你需要验证两个最基本的能力:

  • 同一节点内 Pod 间通信:busybox和nginx是否在同一节点?如果是,执行ping 10.244.1.3。如果 ping 不通,说明 CNI 在本节点的 veth 配置或桥接出了问题。
  • 跨节点 Pod 间通信:如果busybox在node-01,nginx在node-02,则需要从node-01上 pingnode-02的 Pod 网段网关(通常是10.244.2.1,即node-02上的cni0或flannel.1接口 IP)。如果 ping 不通,说明跨节点隧道或路由未建立。

一个快速验证 CNI 的命令是:

# 在 node-01 上,查看 flannel 的 vxlan 设备状态 ip -d link show flannel.1 # 查看 calico 的 BGP 邻居状态 calicoctl node status # 查看 cilium 的健康状态 cilium-health status

注意:CNI 的问题往往表现为“部分 Pod 无法通信”,而非全部。这是因为 CNI 插件的配置错误(如错误的网段、错误的 backend 类型)通常只影响特定节点或特定网段。排查时,务必记录下哪些 Pod 通、哪些不通,然后找出它们的共同点(如都在同一个节点、都属于同一个网段)。

3.5 第四步:终极验证——CoreDNS 的健康检查

虽然nslookup成功了,但这只是证明了 CoreDNS 的kubernetes插件能响应查询。你还需要验证 CoreDNS 作为一个整体服务是否健康。

登录到 CoreDNS 的 Pod(通常在kube-system命名空间):

kubectl exec -it -n kube-system coredns-xxxxx -- sh / # dig @127.0.0.1 kubernetes.default.svc.cluster.local / # cat /etc/coredns/Corefile

检查Corefile中的forward插件是否配置了正确的上游 DNS(如114.114.114.114或公司内网 DNS),以及kubernetes插件的pods insecure参数是否设置正确(对于非 headless Service,通常设为insecure)。

一个更直接的健康检查是:

# 在任意 Pod 中,向 CoreDNS 的 metrics 端口发起请求 curl http://10.96.0.10:9153/metrics | grep 'coredns_dns_request_count_total'

如果这个请求超时或返回 404,说明 CoreDNS 的监听端口或服务本身有问题。

4. 配置与参数详解:那些决定成败的关键开关

纸上得来终觉浅,绝知此事要躬行。光知道“是什么”和“怎么查”还不够,你必须亲手配置过、调整过、踩过坑,才能真正掌握这三者的精髓。下面,我将列出每个组件最核心、最易出错的配置项,并附上我的实操建议。

4.1 kube-proxy 关键配置参数

kube-proxy 的配置主要通过启动参数或KubeProxyConfigurationAPI 对象(推荐)来完成。以下是几个生死攸关的参数:

参数默认值说明我的建议
--proxy-modeiptables指定工作模式。iptables稳定,ipvs高性能。中大型集群(>1000 Pods)务必使用ipvs。切换前,确保内核模块已加载:modprobe ip_vs && modprobe ip_vs_rr && modprobe ip_vs_wrr && modprobe ip_vs_sh。
--cluster-cidr无必须显式指定!告诉 kube-proxy 哪些 IP 是集群内的 Pod IP,用于判断是否需要 SNAT。必须与 CNI 插件配置的 Pod 网段(如10.244.0.0/16)完全一致。如果填错,会导致访问外部网络时,Pod 的源 IP 被错误地 SNAT 成 Node IP,造成外部服务无法识别真实客户端。
--masquerade-allfalse是否对所有流量进行 SNAT。一般保持false。只有在--cluster-cidr无法精确指定,或需要强制隐藏所有 Pod 源 IP 时才设为true。滥用会导致网络追踪困难。
--metrics-bind-address127.0.0.1:10249Prometheus metrics 暴露地址。生产环境建议改为0.0.0.0:10249,并配合 NetworkPolicy 限制访问来源。

实操心得:--cluster-cidr是 kube-proxy 的“命门”。我曾在一个混合云集群中,因--cluster-cidr被错误地设置为10.0.0.0/8(一个巨大的网段),导致所有访问10.x.x.x网段的请求(包括公司内网的10.100.0.0/16)都被 kube-proxy 强制 SNAT,结果是业务系统无法访问内网数据库。修复方法很简单:将--cluster-cidr改为精确的10.244.0.0/16,然后滚动重启 kube-proxy DaemonSet。

4.2 CNI 插件核心配置要点(以 Flannel 为例)

CNI 插件的配置文件(/etc/cni/net.d/10-flannel.conflist)是集群网络的“宪法”。一个微小的错误,就会引发全局性故障。

{ "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": {"portMappings": true}, "snat": true } ] }
  • "hairpinMode": true:这是解决“Pod 访问自己 Service”的关键。当一个 Pod 通过 ClusterIP 访问自己所在的 Service 时,流量会先出 Pod,再经 kube-proxy DNAT 回到本 Pod。如果没有hairpinMode,这个回环流量会被丢弃。必须开启。
  • "isDefaultGateway": true:表示 Flannel 会将自己配置为 Pod 的默认网关。这决定了 Pod 的默认路由。如果为false,你需要手动在 Pod 的 netns 中添加路由,否则 Pod 无法访问集群外网络。
  • "snat": true(在 portmap 插件中):为 NodePort 类型的 Service 提供源地址转换,确保从集群外访问 NodePort 时,后端 Pod 看到的源 IP 是 Node 的 IP,而不是客户端的真实 IP。这是 NodePort 正常工作的前提。

注意:Flannel 的配置文件中,"name"字段(这里是"cbr0")必须与 kubelet 的--cni-bin-dir和--cni-conf-dir参数所指向的目录下的文件名相匹配。如果文件名是10-flannel.conflist,那么"name"可以是任意值,但必须保证整个集群所有节点的配置文件内容完全一致。我曾因一个节点的配置文件里多了一个空格,导致该节点上所有 Pod 的网络初始化失败。

4.3 CoreDNS 配置文件(Corefile)精讲

CoreDNS 的灵魂在于其Corefile。一个典型的、健壮的 Corefile 如下:

.:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . 114.114.114.114 8.8.8.8 { max_concurrent 1000 } cache 30 loop reload loadbalance }
  • errors:将错误日志输出到标准错误流,便于排查。
  • health&ready:提供/health和/readyzHTTP 接口,供 kubelet 健康检查。
  • kubernetes插件:pods insecure表示允许解析pod-name.namespace.pod.cluster.local形式的域名(不校验 Pod 是否真实存在)。fallthrough表示当kubernetes插件无法解析时,将请求传递给下一个插件(forward)。
  • forward插件:这是 CoreDNS 的“出口”。.表示转发所有不在cluster.local等域内的查询。max_concurrent 1000是防止上游 DNS 被打爆的关键参数,强烈建议设置。
  • cache 30:缓存 DNS 响应 30 秒,极大减轻上游 DNS 压力。
  • loop:检测并防止 DNS 循环查询(如 CoreDNS 自己又去查询自己),如果检测到循环,会自动退出并打印错误日志。必须保留。

实操心得:forward插件的上游 DNS 地址,绝对不能只配一个。我曾在一个集群中,forward只配置了公司内网 DNS10.100.1.1,结果该 DNS 服务器因硬件故障宕机 2 小时,导致整个集群的 DNS 解析全部失败,所有依赖外部 API 的服务全部中断。正确的做法是至少配置两个,形成 failover:forward . 10.100.1.1 114.114.114.114。

5. 常见问题速查表与独家避坑指南

纸上谈兵终觉浅,下面是我整理的、来自数百次真实排障的“血泪经验”,浓缩成一张速查表。当你再次遇到问题时,不必从头读起,直接对照症状,就能找到最快的解决方案。

问题现象最可能的原因排查命令/步骤我的独家避坑技巧
nslookup service-name返回NXDOMAIN1. CoreDNS 的kubernetes插件未启用pods insecure,且查询的是pod-name.namespace.pod.cluster.local。
2. Service 的clusterIP为None(headless),但查询的是service-name.namespace.svc.cluster.local。
kubectl get svc <service-name> -o wide
kubectl exec -it -n kube-system coredns-xxxxx -- cat /etc/coredns/Corefile
永远先用dig替代nslookup。nslookup有时会使用/etc/resolv.conf中的search域进行拼接,而dig更透明。执行dig @10.96.0.10 service-name.default.svc.cluster.local,看原始响应。
curl service-name超时(Timeout),但nslookup成功1. kube-proxy 的 iptables/IPVS 规则未生成或错误。
2. 后端 Pod 的 readinessProbe 未通过,kube-proxy 将其从 endpoints 列表中剔除。
kubectl get endpoints <service-name>
sudo iptables -t nat -nL KUBE-SERVICES | grep <service-clusterip>
不要只看kubectl get pods的 STATUS 是Running。一定要看READY列,如1/1。如果显示0/1,说明 readinessProbe 失败,该 Pod 不会被加入 endpoints。检查 Pod 日志和 probe 配置。
Pod 可以curl通其他 Pod 的 IP,但curl不通 Service 的 ClusterIP1. kube-proxy 的--cluster-cidr配置错误,导致 SNAT 失败。
2. CNI 插件的hairpinMode未开启。
kubectl get nodes -o wide
kubectl describe node <node-name>查看Allocatable和Conditions
在调试 Pod 中,用tcpdump抓包是最权威的证据。在busybox中执行tcpdump -i any host 10.96.0.100 and port 80,然后curl service-name。如果抓不到任何包,说明流量根本没到 kube-proxy;如果抓到了 SYN 包但没收到 SYN-ACK,说明 kube-proxy 规则有问题或后端不可达。
新建的 Pod 无法解析任何域名(nslookup google.com也失败)1. kubelet 的--cluster-dns参数未设置,或设置错误(如指向了不存在的 IP)。
2. Pod 的/etc/resolv.conf文件被错误覆盖。
kubectl exec -it <pod-name> -- cat /etc/resolv.conf
ps aux | grep kubelet | grep cluster-dns
/etc/resolv.conf的第一行nameserver必须是 CoreDNS 的 ClusterIP。如果看到nameserver 127.0.0.1或nameserver 10.0.0.1,说明 kubelet 配置错误。修复后,删除该 Pod,让其重建。
kubectl get nodes显示NotReady,且kubectl get pods -A显示corednsPod 为Pending1. CNI 插件未正确安装,导致 kubelet 无法为 Pod 创建网络命名空间。
2. 节点磁盘空间不足,无法拉取 CNI 镜像。
journalctl -u kubelet -n 100 --no-pager
df -h
kubelet的日志是黄金线索。搜索关键词cni、network、plugin not found。如果看到failed to load plugin "bridge",说明 CNI 二进制文件缺失。检查/opt/cni/bin/目录。

最后分享一个小技巧:为你的集群建立一个“网络健康检查清单”。每次集群升级、CNI 插件更新、或新增重要业务前,都执行一遍:

  1. kubectl run debug --image=busybox:1.35 --rm -it --restart=Never -- sh -c "nslookup kubernetes.default.svc.cluster.local && curl -I http://kubernetes.default.svc.cluster.local:443"
  2. kubectl get endpoints kubernetes
  3. kubectl get nodes -o wide这三行命令,能在 10 秒内告诉你集群最核心的网络功能是否完好。把它写成一个脚本,放在你的运维工具箱里,你会感谢过去的自己。

这个标题里的“区别”,从来就不是一个静态的知识点。它是一套动态的、可执行的、能救命的思维框架。当你下次再看到Connection refused,你脑子里浮现的,不再是模糊的“网络好像坏了”,而是清晰的决策树:先查 DNS,再查 Service 规则,再查 Pod 连通性,最后查底层网络。这,才是 Kubernetes 网络的真谛。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询