Skip to content

网络通信与节点故障影响分析

集群: K3s v1.35.4+k3s1 | 3 Master (.38/.39/.40) + 1 Worker (.41) 最后更新: 2026-08-31 定位: 01-集群原理 的深度补充,回答三个问题: 节点内部怎么通信?节点之间怎么通信?etcd 怎么通信?以及——任意节点挂掉会发生什么?


目录


1. 集群通信全景图

                        Rancher Prime (wss 443, agent 主动外连)


  kubectl / 客户端 ──► VIP .43:6443 ─┐

 ┌──────────────────────────────────┼────────────────────────────────────────┐
 │ .38 Master                        │           .39 / .40 Master (同构)      │
 │ ┌────────────────────────────┐   │                                        │
 │ │ k3s 进程                    │   │                                        │
 │ │  kube-apiserver :6443 ◄────┼───┘  客户端/agent 入口                      │
 │ │  scheduler / ctrl-mgr ──► apiserver(本机回环)                            │
 │ │  内嵌 etcd  ◄──2379── apiserver(本机)                                    │
 │ │     │                                                   │                │
 │ │     └──────2380 (TLS, 成员互连)─────► .39/.40 的 etcd   │                │
 │ │  kubelet :10250 ◄── apiserver (exec/logs)                              │
 │ │  kube-proxy: iptables 规则 (Service 10.43.0.0/16)                       │
 │ └────────────────────────────┘                                            │
 │ containerd ◄── kubelet (CRI)                                             │
 │ flannel.1 (VXLAN) ◄──UDP 8472──► 其他 3 台节点 (Pod 10.42.x.x 互通)        │
 │ containerd ──► Harbor .156:30000 (拉镜像, HTTP)                            │
 └──────────────────────────────────────────────────────────────────────────┘
        ▲ 6443 (agent 内嵌负载均衡, 自动故障切换)
 ┌──────┴───────────────────────────────┐
 │ .41 Worker (k3s-agent)               │
 │  kubelet + containerd + kube-proxy   │
 │  业务 Pod (10.42.3.0/24)              │
 └──────────────────────────────────────┘

要点记忆:控制面走 6443 与 2379/2380,数据面走 UDP 8472,镜像拉取走 30000, 管理面走 443 外连。 四条链路互相独立,这也是"某条链路断了、集群只是部分受损"的原因。


2. 服务器内部网络访问(单节点内部)

2.1 Master 节点内部的组件通信

K3s 把控制面全部塞进一个 k3s 进程,组件之间主要走本机回环 (127.0.0.1), 不依赖外部网络——这是 Master 抗网络抖动能力强的根本原因:

通信路径地址/端口说明
apiserver → 本机 etcd127.0.0.1:2379所有集群状态的读写,最核心的内部链路
scheduler / controller-manager → apiserver127.0.0.1:6443进程内/回环调用,毫秒级
kubelet → apiserver回环(本机)或 6443上报节点状态、领取 Pod 任务
apiserver → kubelet127.0.0.1:10250kubectl logs / exec 的实际执行通道
kubelet → containerd本地 socket (CRI)创建/销毁容器
kube-proxy (内置)iptables/IPVS 规则Service 虚拟 IP → Pod 的转发
flannelflannel.1 网卡本机 Pod 流量的 VXLAN 封装/解封装

💡 K3s Server 节点默认同时运行 agent 组件(kubelet + containerd), 所以 Master 也能跑业务 Pod(除非打了污点)。这也是本集群只有 1 台 Worker 时,业务实际可能分布在 4 台机器上的原因。

2.2 Worker 节点内部

Worker 上没有 apiserver/etcd,内部链路更简单:

通信路径说明
kubelet → containerd (CRI socket)容器生命周期管理
kubelet → (远端 apiserver)唯一必须的对外控制链路,见第 3 节
kube-proxy iptablesService 转发(含访问其他节点上的 CoreDNS/业务)
flannel.1Pod 跨节点通信

2.3 一次访问在节点内部的路径

外部请求打到节点上的业务(以 NodePort 30180 为例):

网卡 :30180 → iptables (kube-proxy 规则)
           → 选中某个 Pod IP (10.42.x.x)
           ├─ Pod 在本节点: 直接走 veth/网桥送达
           └─ Pod 在其他节点: 交给 flannel.1 → VXLAN 封装 → UDP 8472 发出

推论:iptables 规则是节点本地持久的,即使控制面完全失联, 已建立的 Service/NodePort 转发依然有效(见第 5 节故障分析)。

3. 跨服务器网络访问(节点之间)

3.1 节点间通信矩阵(最重要的一张表)

#目的端口/协议用途断开的后果
1Worker / Master(agent)Master apiserver6443/TCP (TLS)节点注册、心跳、领任务、上报状态该节点 40 秒后被标记 NotReady;已运行 Pod 继续跑
2MasterMaster 内嵌 etcd2380/TCP (TLS)etcd 成员间数据复制与选举断 1 条:无感;断到只剩 1 成员:失去多数派
3任一节点任一节点8472/UDPFlannel VXLAN,Pod 跨节点通信跨节点 Pod 互访失败(同节点正常)
4任一节点任一节点30000-32767/TCPNodePort 服务转发该节点入口的对应服务不可达
5任一节点任一节点80/443/TCPTraefik Ingress / ServiceLB域名入口失效
6任一节点Harbor .15630000/TCP (HTTP)拉取镜像新 Pod / 新镜像拉取失败
7任一节点Rancher Prime443/TCP (wss)cattle-agent 上报与受控仅 UI 失联,集群本身无感
8PodCoreDNS Pod 所在节点53/UDP,TCP集群内域名解析新连接解析失败(走 IP 的不受影响)

3.2 几个容易误解的机制

① agent 连的不是"一台" Master,而是"所有" Master K3s agent 内部自带一个负载均衡器,会同时维护到 3 台 Master 6443 的连接, 某台 Master 宕机时自动切换到其余节点,不需要人工干预。 这就是为什么"挂 1 台 Master"对 Worker 几乎无感。

② Pod 跨节点通信不经过任何中心设备 Flannel 给每个节点分一个 /24 子网(本集群:.38→10.42.0.0/24、.39→10.42.1.0/24、 .40→10.42.2.0/24、.41→10.42.3.0/24),跨节点流量由节点之间点对点的 VXLAN 隧道直接承载,没有中心交换/网关单点。

③ Service 转发是分布式的 每个节点本地都有一份完整的 iptables 规则,客户端访问 10.43.x.x任一节点:NodePort 时,由收到包的那台节点本地完成转发。 所以 Service 不依赖"某台 Master 活着"。


4. etcd 通信组件详解

4.1 成员拓扑

   .38 Master                 .39 Master                 .40 Master
 ┌─────────────┐           ┌─────────────┐           ┌─────────────┐
 │ etcd 成员 A  │◄─────────►│ etcd 成员 B  │◄─────────►│ etcd 成员 C  │
 │ :2379 客户端 │   2380    │ :2379 客户端 │   2380    │ :2379 客户端 │
 │ :2380 对等   │◄─────────►│ :2380 对等   │◄─────────►│ :2380 对等   │
 └──────▲──────┘           └─────────────┘           └─────────────┘
        │ 2379 (127.0.0.1)
   本机 kube-apiserver
  • 每台 Master 内嵌一个 etcd 成员(编译在 k3s 二进制里,非独立进程);
  • 3 个成员两两通过 2380 全互联;
  • 每台 apiserver 只连本机 etcd(127.0.0.1:2379),读到的数据三处一致。

4.2 端口与证书

端口作用加密
2379客户端接口(apiserver、etcdctl、备份)TLS(etcd/client.crt)
2380成员对等接口(复制 + 选举)TLS(etcd/peer 证书)
2381本机 metrics(http://127.0.0.1:2381/metrics,可选监控)

证书位于 /var/lib/rancher/k3s/server/tls/etcd/(server-ca / client / peer 三组), 随 K3s 证书体系 1 年轮换(见运维手册第 8 节)。

4.3 Raft 协议如何工作(理解故障影响的关键)

  • 3 成员中选出 1 个 Leader,所有写请求只由 Leader 处理;
  • Leader 每 100ms 发一次心跳;成员超过 1000ms(选举超时)收不到心跳 就发起重新选举,通常 1~3 秒选出新 Leader;
  • 写入必须被多数派(3 中的 2 个)确认才算成功——这就是"法定人数";
  • 因此:能容忍任意 1 个成员失联;2 个成员失联则集群不可写

4.4 一次写入的路径

kubectl apply → 某台 apiserver → 本机 etcd 成员
   → 该成员恰好是 Leader?
        是: 直接写 → 复制给另 2 个成员 → 2/3 确认 → 提交成功
        否: 转发给 Leader → 同上

4.5 etcd 健康自检命令(任一 Master)

bash
ETCD=/var/lib/rancher/k3s/data/current/bin/etcdctl
TLS=/var/lib/rancher/k3s/server/tls/etcd
C="--cacert=$TLS/server-ca.crt --cert=$TLS/client.crt --key=$TLS/client.key"

# 三成员状态: 关注 LEADER 一列 (哪个成员是 Leader) 与 RAFT TERM
ETCDCTL_API=3 $ETCD --endpoints=https://127.0.0.1:2379 $C endpoint status -w table --cluster

# 健康检查
ETCDCTL_API=3 $ETCD --endpoints=https://127.0.0.1:2379 $C endpoint health --cluster

# Leader 切换/选举观察
ETCDCTL_API=3 $ETCD --endpoints=https://127.0.0.1:2379 $C member list -w table

巡检时若发现 endpoint status 有成员 IS LEARNER/离线,或集群只有 2 个成员在线, 按运维手册 3.4 / 6.3 处理,不要在未明确多数派前重启第 3 台。


5. 节点故障影响分析(1 个/多个节点宕机)

5.0 总览矩阵(先背这张表)

宕机场景etcd控制面 (API)已运行业务新部署/自愈紧急度
挂 1 台 Worker (.41)✅ 正常✅ 正常⚠️ 该节点上的 Pod 丢失✅ 正常P2
挂 1 台 Master✅ 2/3 多数派✅ 其余 2 台可用✅ 正常✅ 正常P3(尽快恢复冗余)
挂 2 台 Master❌ 失多数派❌ 不可写✅ 已运行的继续跑❌ 停止P1
挂 3 台 Master(全 Master)❌ 完全瘫痪⚠️ Worker 上存量 Pod 短期存活P1 灾难
挂 1 Master + 1 Worker✅ 2/3⚠️ Worker 上 Pod 丢失P2→P1 视恢复速度
挂全部 4 台❌ 全断P1 灾难,走灾备

5.1 场景一:挂 1 台 Worker(.41)

发生什么

  1. T+0:节点失联,kubelet 心跳停止;
  2. T+40s:节点被标记 NotReady(node-monitor-grace-period 默认 40 秒);
  3. T+5min:该节点被打上 unreachable 污点,上面的 Pod 被驱逐, Deployment/StatefulSet 控制器在其他节点重建副本;
  4. Service 端点自动摘除失联 Pod,流量不再进来。

影响

  • 控制面、etcd、其他节点完全正常;
  • 只运行在 .41 且副本数=1 的业务会中断约 5 分钟(驱逐窗口);
  • 多副本业务:部分流量短暂受损,自愈后恢复。

恢复:修好机器开机即可,k3s-agent 自动重连、节点自动回 Ready。 若机器报废:kubectl delete node szb122041 清理,按运维手册 3.2 补新节点。

⚠️ 本集群结构提醒:只有 1 台 Worker,若业务用 nodeSelector 钉死在 Worker 上,则挂 1 台 Worker = 全部该类业务中断。缓解方案见第 7 节。


5.2 场景二:挂 1 台 Master(.38/.39/.40 任一)

发生什么

  1. T+0:若挂的恰是 etcd Leader,其余 2 成员约 1~3 秒选出新 Leader;
  2. agent 内嵌负载均衡自动切到剩余 2 台,Worker 无感;
  3. T+40s:该 Master 节点 NotReady;其上若跑着业务 Pod,同 5.1 被驱逐重建;
  4. 客户端若固定连这台(无 VIP)会报连接失败,换一台/走 VIP 即好。

影响集群整体可用——这是 3 Master 设计的目的。 唯一损失是冗余度从"容忍 1 台"降为"不容忍任何一台"。

处置:不紧急但不能拖——24 小时内修复或更换(运维手册 3.4), 期间避免对剩余 2 台做任何重启/升级操作。


5.3 场景三:挂 2 台 Master(失去多数派)

发生什么

  1. etcd 只剩 1 个成员,< 法定人数 2 → 无法选举无法写入
  2. 最后一台 apiserver 上的写请求全部失败(报 etcd cluster is unavailable), 部分读请求可能从缓存返回,整体视为控制面不可用;
  3. kubectl apply/delete、Rancher 操作、滚动更新全部失败;
  4. 已运行的 Pod、Service/NodePort 转发、Ingress 继续工作 (kubelet 与 iptables 规则不依赖实时控制面);
  5. 但:Pod 崩溃后无法自愈、新副本无法调度、证书到期无法轮换。

影响:业务"表面还活着,实际在裸奔"——任何一个后续故障都会放大。

处置(按顺序尝试)

  1. 优先复活原节点:多数派恢复,集群自动痊愈(首选!);
  2. 无法复活 → 按运维手册 6.3 场景 A:--cluster-reset 把幸存成员重置为 单节点 etcd,再让新节点重新加入;
  3. 操作前:k3s etcd-snapshot save 留一份当前状态。

5.4 场景四:3 台 Master 全挂,Worker 存活

发生什么

  • 控制面完全消失:无 apiserver、无 etcd、无调度;
  • Worker 的 kubelet 失联,但按本地缓存继续维持已运行的容器 (崩溃的容器仍会按 restartPolicy 被 kubelet 本地拉起);
  • 已有 Service/Ingress/DNS 对存量 Pod 仍可短期工作。

影响:存量业务进入"惯性运行"状态——撑得住,但经不起任何变动; 节点一旦重启,本地没有 apiserver 下发清单,Pod 将无法恢复。

处置:这是灾难场景,按运维手册第 12 节流程: 修复任意一台 Master 优先;全损则用异地 etcd 快照在新节点重建并恢复。

5.5 场景五:1 台 Master + 1 台 Worker 同时挂

= 5.1 与 5.2 的叠加:

  • etcd 仍有 2/3 多数派,控制面可用;
  • Worker 上的 Pod 丢失,会在剩余 3 台 Master 上被重建 (前提是没打"只去 Worker"的 nodeSelector/污点,否则 Pod 一直 Pending);
  • 若恰好用了 nodeSelector 钉死 Worker:业务中断直到 Worker 恢复, 临时解法是改 Deployment 去掉 nodeSelector 或给某台 Master 打对应标签。

5.6 场景六:4 台全挂

全量灾难。业务全断,按运维手册 12.3 灾难恢复流程执行: 新机器重建集群 → 异地快照恢复 → 验证 → 重新对接 Rancher。 这也是为什么 etcd 快照必须有集群外的副本。

5.7 宕机事件时间线(通用)

时间点事件
T+0节点宕机/失联
T+~1s(若为 etcd Leader)其余成员发起选举
T+~1-3setcd 新 Leader 产生,写入恢复
T+40skubelet 心跳超时,节点 NotReady
T+~40sService 端点摘除该节点上的 Pod
T+5minunreachable 污点生效,Pod 被驱逐、异地重建
T+5min+副本回到期望数量,业务恢复(单副本业务除外)

结论:对单点故障,约 5 分钟是 K8s 的自愈窗口。 对中断敏感的业务,应使用多副本 + Pod 反亲和(跨节点打散), 把影响从"5 分钟中断"压缩到"秒级、无感"。


6. 网络链路故障场景(端口不通)

节点都活着、但网络被防火墙/路由切断的场景,影响与宕机不同:

被切断的链路现象为什么
Worker → Master 6443Worker 40s 后 NotReady;Pod 继续跑心跳走 6443
某两台节点间 8472/UDP这两台之间的 Pod 互访超时,其余正常VXLAN 点对点隧道断
节点 → Harbor 30000新 Pod ImagePullBackOff;老业务不受影响只影响拉新镜像
节点 → Rancher 443UI 集群显示 Unavailable;集群自身正常仅管理链路
Master 之间 2380取决于断几条:断 1 条无感;断 2 条则失多数派Raft 成员互联
客户端 → 6443kubectl/Rancher 无法操作;业务正常仅操作入口

排查思路:ping(ICMP 可能被禁,不作准)→ telnet/nc <ip> <port> 验证端口 → journalctl -u k3s(-agent) 看具体报错(connection refused = 端口不通, timeout = 防火墙/路由丢包,TLS/x509 = 证书或 --tls-san 问题)。


7. 单点清单与高可用加固建议

7.1 本集群当前的单点(按风险排序)

单点挂掉的影响加固建议
唯一 Worker (.41)钉在 Worker 的业务全断加 1~2 台 Worker;或接受业务跑在 Master
Harbor (.156)新镜像拉取失败Harbor 备份/双实例;关键镜像节点预热
etcd 快照仅在本机整机盘损 = 备份同损快照定时同步到集群外备份机
CoreDNS 单副本DNS 解析抖动扩容至 2 副本 + 反亲和
无 VIP 时的注册/访问地址.38 挂后客户端连不上部署 VIP(.43)指向健康 Master
Rancher 管理面UI 不可用(业务无感)管理集群多副本 + 备份

7.2 通用加固动作

  1. 副本:关键业务 replicas >= 2,并配置:
    yaml
    affinity:
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          podAffinityTerm:
            labelSelector: { matchLabels: { app: <你的app> } }
            topologyKey: kubernetes.io/hostname   # 副本尽量打散到不同节点
  2. 探针:所有业务配 livenessProbe + readinessProbe,让自愈真实生效;
  3. 监控:装 Monitoring(运维手册第 9 节),对 节点 NotReadyetcd 无 LeaderPod 重启 配告警,别靠人肉发现;
  4. 备份etcd-snapshot 定时 + 异地副本(运维手册 6.1);
  5. 演练:每季度在测试环境拔一台节点,验证 5 分钟自愈与快照恢复。

相关文档

文档用途
01-零基础入门与集群原理架构与建集群
03-日常运维手册故障处置操作(第 6/10/12 节与本文配合使用)
../../credentials.mdHarbor 凭据