主题
网络通信与节点故障影响分析
集群: K3s v1.35.4+k3s1 | 3 Master (.38/.39/.40) + 1 Worker (.41) 最后更新: 2026-08-31 定位: 01-集群原理 的深度补充,回答三个问题: 节点内部怎么通信?节点之间怎么通信?etcd 怎么通信?以及——任意节点挂掉会发生什么?
目录
- 1. 集群通信全景图
- 2. 服务器内部网络访问(单节点内部)
- 3. 跨服务器网络访问(节点之间)
- 4. etcd 通信组件详解
- 5. 节点故障影响分析(1 个/多个节点宕机)
- 6. 网络链路故障场景(端口不通)
- 7. 单点清单与高可用加固建议
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 → 本机 etcd | 127.0.0.1:2379 | 所有集群状态的读写,最核心的内部链路 |
| scheduler / controller-manager → apiserver | 127.0.0.1:6443 | 进程内/回环调用,毫秒级 |
| kubelet → apiserver | 回环(本机)或 6443 | 上报节点状态、领取 Pod 任务 |
| apiserver → kubelet | 127.0.0.1:10250 | kubectl logs / exec 的实际执行通道 |
| kubelet → containerd | 本地 socket (CRI) | 创建/销毁容器 |
| kube-proxy (内置) | iptables/IPVS 规则 | Service 虚拟 IP → Pod 的转发 |
| flannel | flannel.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 iptables | Service 转发(含访问其他节点上的 CoreDNS/业务) |
| flannel.1 | Pod 跨节点通信 |
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 节点间通信矩阵(最重要的一张表)
| # | 源 | 目的 | 端口/协议 | 用途 | 断开的后果 |
|---|---|---|---|---|---|
| 1 | Worker / Master(agent) | Master apiserver | 6443/TCP (TLS) | 节点注册、心跳、领任务、上报状态 | 该节点 40 秒后被标记 NotReady;已运行 Pod 继续跑 |
| 2 | Master | Master 内嵌 etcd | 2380/TCP (TLS) | etcd 成员间数据复制与选举 | 断 1 条:无感;断到只剩 1 成员:失去多数派 |
| 3 | 任一节点 | 任一节点 | 8472/UDP | Flannel VXLAN,Pod 跨节点通信 | 跨节点 Pod 互访失败(同节点正常) |
| 4 | 任一节点 | 任一节点 | 30000-32767/TCP | NodePort 服务转发 | 该节点入口的对应服务不可达 |
| 5 | 任一节点 | 任一节点 | 80/443/TCP | Traefik Ingress / ServiceLB | 域名入口失效 |
| 6 | 任一节点 | Harbor .156 | 30000/TCP (HTTP) | 拉取镜像 | 新 Pod / 新镜像拉取失败 |
| 7 | 任一节点 | Rancher Prime | 443/TCP (wss) | cattle-agent 上报与受控 | 仅 UI 失联,集群本身无感 |
| 8 | Pod | CoreDNS 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)
发生什么:
- T+0:节点失联,kubelet 心跳停止;
- T+40s:节点被标记
NotReady(node-monitor-grace-period 默认 40 秒); - T+5min:该节点被打上
unreachable污点,上面的 Pod 被驱逐, Deployment/StatefulSet 控制器在其他节点重建副本; - 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 任一)
发生什么:
- T+0:若挂的恰是 etcd Leader,其余 2 成员约 1~3 秒选出新 Leader;
- agent 内嵌负载均衡自动切到剩余 2 台,Worker 无感;
- T+40s:该 Master 节点
NotReady;其上若跑着业务 Pod,同 5.1 被驱逐重建; - 客户端若固定连这台(无 VIP)会报连接失败,换一台/走 VIP 即好。
影响:集群整体可用——这是 3 Master 设计的目的。 唯一损失是冗余度从"容忍 1 台"降为"不容忍任何一台"。
处置:不紧急但不能拖——24 小时内修复或更换(运维手册 3.4), 期间避免对剩余 2 台做任何重启/升级操作。
5.3 场景三:挂 2 台 Master(失去多数派)
发生什么:
- etcd 只剩 1 个成员,< 法定人数 2 → 无法选举、无法写入;
- 最后一台 apiserver 上的写请求全部失败(报
etcd cluster is unavailable), 部分读请求可能从缓存返回,整体视为控制面不可用; - kubectl apply/delete、Rancher 操作、滚动更新全部失败;
- 已运行的 Pod、Service/NodePort 转发、Ingress 继续工作 (kubelet 与 iptables 规则不依赖实时控制面);
- 但:Pod 崩溃后无法自愈、新副本无法调度、证书到期无法轮换。
影响:业务"表面还活着,实际在裸奔"——任何一个后续故障都会放大。
处置(按顺序尝试):
- 优先复活原节点:多数派恢复,集群自动痊愈(首选!);
- 无法复活 → 按运维手册 6.3 场景 A:
--cluster-reset把幸存成员重置为 单节点 etcd,再让新节点重新加入; - 操作前:
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-3s | etcd 新 Leader 产生,写入恢复 |
| T+40s | kubelet 心跳超时,节点 NotReady |
| T+~40s | Service 端点摘除该节点上的 Pod |
| T+5min | unreachable 污点生效,Pod 被驱逐、异地重建 |
| T+5min+ | 副本回到期望数量,业务恢复(单副本业务除外) |
结论:对单点故障,约 5 分钟是 K8s 的自愈窗口。 对中断敏感的业务,应使用多副本 + Pod 反亲和(跨节点打散), 把影响从"5 分钟中断"压缩到"秒级、无感"。
6. 网络链路故障场景(端口不通)
节点都活着、但网络被防火墙/路由切断的场景,影响与宕机不同:
| 被切断的链路 | 现象 | 为什么 |
|---|---|---|
| Worker → Master 6443 | Worker 40s 后 NotReady;Pod 继续跑 | 心跳走 6443 |
| 某两台节点间 8472/UDP | 这两台之间的 Pod 互访超时,其余正常 | VXLAN 点对点隧道断 |
| 节点 → Harbor 30000 | 新 Pod ImagePullBackOff;老业务不受影响 | 只影响拉新镜像 |
| 节点 → Rancher 443 | UI 集群显示 Unavailable;集群自身正常 | 仅管理链路 |
| Master 之间 2380 | 取决于断几条:断 1 条无感;断 2 条则失多数派 | Raft 成员互联 |
| 客户端 → 6443 | kubectl/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 通用加固动作
- 副本:关键业务
replicas >= 2,并配置:yamlaffinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: { matchLabels: { app: <你的app> } } topologyKey: kubernetes.io/hostname # 副本尽量打散到不同节点 - 探针:所有业务配
livenessProbe+readinessProbe,让自愈真实生效; - 监控:装 Monitoring(运维手册第 9 节),对
节点 NotReady、etcd 无 Leader、Pod 重启配告警,别靠人肉发现; - 备份:
etcd-snapshot定时 + 异地副本(运维手册 6.1); - 演练:每季度在测试环境拔一台节点,验证 5 分钟自愈与快照恢复。
相关文档
| 文档 | 用途 |
|---|---|
| 01-零基础入门与集群原理 | 架构与建集群 |
| 03-日常运维手册 | 故障处置操作(第 6/10/12 节与本文配合使用) |
| ../../credentials.md | Harbor 凭据 |