K8s-kube-proxy服务代理流程
kube-proxy 服务代理通信流程
目标
这篇文档只回答一个核心问题:kube-proxy 如何实现 Service 的负载均衡和网络代理?
重点放在 kube-proxy 与 API Server 的交互、规则同步机制以及 iptables/IPVS 模式的差异。
一句话摘要
kube-proxy 通过 watch API Server 中的 Service 和 EndpointSlice 对象,在本地维护 iptables/IPVS 规则,将到达 Service ClusterIP 的流量转发到后端 Pod。
1. 流程总览
从通信视角看,这条链路可以拆成 3 个阶段:
- 配置获取阶段:kube-proxy watch Service 和 EndpointSlice 对象。
- 规则计算阶段:根据 Service 类型计算需要生成的代理规则。
- 规则同步阶段:将规则写入 iptables/IPVS,实现流量转发。
架构总览图
flowchart TB
subgraph 控制面["控制面"]
API[kube-apiserver]
SVC[Service 对象]
EPS[EndpointSlice 对象]
end
subgraph KubeProxy["kube-proxy"]
direction TB
INFORMER[Informer<br/>watch Service/EndpointSlice]
HANDLER[EventHandler<br/>处理变更]
PROXIER[Proxier<br/>规则计算]
SYNC[SyncRunner<br/>规则同步]
end
subgraph 规则引擎["规则引擎"]
direction LR
IPT[iptables 模式]
IPVS[ipvs 模式]
NFPROXY[nftables 模式<br/>Alpha]
end
subgraph 数据面["数据面"]
direction TB
CLIP[ClusterIP<br/>服务虚拟IP]
NODEIP[NodePort<br/>节点端口]
EXTIP[ExternalIP<br/>外部IP]
end
API --> INFORMER
SVC --> API
EPS --> API
INFORMER --> HANDLER
HANDLER --> PROXIER
PROXIER --> SYNC
SYNC --> IPT
SYNC --> IPVS
SYNC --> NFPROXY
CLIP --> IPT
NODEIP --> IPT
EXTIP --> IPT
kube-proxy 内部架构图
flowchart TB
subgraph 输入层["配置输入"]
direction LR
S1[Service Informer]
S2[EndpointSlice Informer]
S3[Node Informer]
end
subgraph 处理层["事件处理"]
direction TB
QUEUE[Event Queue<br/>变更队列]
HANDLE[HandleServiceUpdate<br/>HandleEndpointSliceUpdate]
end
subgraph 计算层["规则计算"]
direction TB
BUILD[buildServiceMap<br/>buildEndpointMap]
DIFF[computeDiff<br/>计算差异]
PLAN[planning<br/>规则规划]
end
subgraph 执行层["规则执行"]
direction TB
SYNC[SyncRules<br/>同步规则]
IPT[iptables interface]
IPVS[ipvs interface]
NFT[nftables interface]
end
S1 --> QUEUE
S2 --> QUEUE
S3 --> QUEUE
QUEUE --> HANDLE
HANDLE --> BUILD
BUILD --> DIFF
DIFF --> PLAN
PLAN --> SYNC
SYNC --> IPT
SYNC --> IPVS
SYNC --> NFT
这张图想表达什么
- kube-proxy 是纯观察者,不主动创建 Service。
- 规则同步是定期执行的,不是每次变更都立即同步。
- 支持多种后端模式,iptables 是默认模式。
2. 分阶段通信流程
阶段一:配置获取
这个阶段的本质是:kube-proxy 通过 Informer 机制获取 Service 和 EndpointSlice 的变更。
步骤 1.1:启动 Informer
kube-proxy 启动时,会创建三个 Informer:
- Service Informer:watch Service 对象
- EndpointSlice Informer:watch EndpointSlice 对象
- Node Informer:watch Node 对象(用于检测本节点网络变化)
通信方向:kube-proxy → API Server(通过 informer/watch)
步骤 1.2:收到 Service 变更事件
当 Service 被创建、更新或删除时,Informer 会收到事件,并触发 EventHandler。
通信方向:API Server → kube-proxy(watch 推送)
步骤 1.3:收到 EndpointSlice 变更事件
当后端 Pod 发生变化时,EndpointSlice Controller 会更新 EndpointSlice,kube-proxy 的 Informer 会收到事件。
通信方向:EndpointSlice Controller → API Server → kube-proxy(watch 推送)
步骤 1.4:事件入队
EventHandler 不会立即处理变更,而是将变更信息放入队列,等待 SyncRunner 定期处理。
通信方向:EventHandler → Queue(内部队列)
阶段二:规则计算
这个阶段的本质是:根据 Service 配置计算需要生成的 iptables/IPVS 规则。
步骤 2.1:构建服务映射
Proxier 会构建两个核心数据结构:
serviceMap:Service UID → ServiceInfo(ClusterIP、Port、Protocol 等)endpointsMap:Service UID → []Endpoint(Pod IP、Port、Ready 状态等)
通信方向:Proxier 内部计算
步骤 2.2:计算规则差异
Proxier 会对比当前规则和期望规则,计算需要:
- 添加哪些规则
- 修改哪些规则
- 删除哪些规则
通信方向:Proxier 内部 diff 计算
步骤 3.3:生成规则指令
对于每个 Service,Proxier 会生成对应的规则指令,包括:
- ClusterIP 规则(KUBE-SERVICES 链)
- NodePort 规则(KUBE-NODEPORTS 链)
- 外部 IP 规则
- 负载均衡规则(KUBE-SVC-xxx 链)
- 会话亲和规则(KUBE-SEP-xxx 链)
通信方向:Proxier 内部规划
阶段三:规则同步
这个阶段的本质是:将计算好的规则写入内核网络栈。
步骤 3.1:执行 Sync 规则
SyncRunner 定期(默认 1 分钟)或在收到变更时触发 Sync() 方法。
通信方向:SyncRunner → Proxier.Sync()
步骤 3.2:调用 iptables/ipvs 命令
Proxier 调用 iptables 或 ipvs 命令,将规则写入内核:
- iptables 模式:调用
iptables-restore批量更新 - ipvs 模式:调用
ipvsadm配置虚拟服务器
通信方向:kube-proxy → Linux 内核(通过系统调用)
步骤 3.3:清理过期规则
同步完成后,Proxier 会清理不再需要的规则,避免规则堆积。
通信方向:kube-proxy → Linux 内核
3. iptables 模式详解
iptables 规则链结构
flowchart TB
subgraph nat表["iptables nat 表"]
PREROUTING[PREROUTING 链]
OUTPUT[OUTPUT 链]
POSTROUTING[POSTROUTING 链]
KS[KUBE-SERVICES 链<br/>所有 Service 入口]
KN[KUBE-NODEPORTS 链<br/>NodePort 规则]
KEXT[KUBE-EXTERNAL-SERVICES 链<br/>ExternalIP 规则]
KSVC[KUBE-SVC-xxx 链<br/>Service 负载均衡]
KSEP[KUBE-SEP-xxx 链<br/>后端端点]
KMARK[KUBE-MARK-MASQ 链<br/>标记需要 SNAT]
end
PREROUTING --> KS
OUTPUT --> KS
KS --> KN
KS --> KEXT
KS --> KSVC
KSVC --> KSEP
KSVC --> KMARK
KSEP --> KMARK
POSTROUTING --> KMARK
ClusterIP 流量路径
sequenceDiagram
autonumber
participant Client as 客户端 Pod
participant IPT as iptables/nat
participant EP as 后端 Pod
participant RESP as 响应路径
Client->>IPT: 发送到 ClusterIP:Port
Note over IPT: PREROUTING → KUBE-SERVICES
IPT->>IPT: 匹配 KUBE-SVC-xxx 链
Note over IPT: 概率选择后端
IPT->>IPT: 进入 KUBE-SEP-xxx 链
Note over IPT: DNAT: ClusterIP → PodIP
IPT->>EP: 转发到 PodIP:Port
EP->>RESP: 处理请求
RESP->>Client: 响应 (源 IP: PodIP)
Note over RESP: conntrack 反向 NAT
NodePort 流量路径
sequenceDiagram
autonumber
participant Ext as 外部客户端
participant NODE as 节点网络栈
participant IPT as iptables/nat
participant EP as 后端 Pod
Ext->>NODE: 发送到 NodeIP:NodePort
Note over NODE: 监听在所有接口
NODE->>IPT: 进入 PREROUTING
IPT->>IPT: KUBE-SERVICES → KUBE-NODEPORTS
IPT->>IPT: 匹配 NodePort 规则
Note over IPT: DNAT: NodePort → ClusterIP
IPT->>IPT: KUBE-SVC-xxx 负载均衡
IPT->>IPT: KUBE-SEP-xxx 选择后端
IPT->>EP: 转发到 PodIP:Port
EP-->>Ext: 响应
Note over Ext,EP: SNAT: 源 IP 可能被改写
4. IPVS 模式详解
IPVS vs iptables 对比
| 特性 | iptables 模式 | IPVS 模式 |
|---|---|---|
| 规则更新 | 全量更新 (iptables-restore) | 增量更新 (netlink) |
| 负载均衡算法 | 随机 (概率规则) | 多种算法 (rr/lc/dh/sh/sed/nq等) |
| 性能 | O(n) 规则匹配 | O(1) 哈希查找 |
| 规则数量 | 随 Service 数量线性增长 | 与 Service 数量无关 |
| 健康检查 | 无内置支持 | 支持后端健康检查 |
| 内核依赖 | 所有 Linux 内核 | 需要加载 ip_vs 模块 |
IPVS 规则结构
flowchart TB
subgraph IPVS["IPVS 虚拟服务"]
VS1[Virtual Service<br/>ClusterIP:Port]
RS1[Real Server 1<br/>PodIP1:Port]
RS2[Real Server 2<br/>PodIP2:Port]
RS3[Real Server 3<br/>PodIP3:Port]
end
subgraph iptables["iptables (辅助)"]
MASQ[KUBE-MARK-MASQ<br/>SNAT 标记]
CLUSTER[KUBE-CLUSTER-IP<br/>ClusterIP 跳转]
end
VS1 --> RS1
VS1 --> RS2
VS1 --> RS3
CLUSTER --> VS1
RS1 --> MASQ
RS2 --> MASQ
RS3 --> MASQ
IPVS 负载均衡算法
| 算法 | 代码 | 说明 |
|---|---|---|
| 轮询 | rr | Round Robin,依次分发 |
| 加权轮询 | wrr | Weighted Round Robin,按权重分发 |
| 最少连接 | lc | Least Connections,选连接数最少的 |
| 加权最少连接 | wlc | Weighted Least Connections |
| 源地址哈希 | sh | Source Hashing,相同源 IP 到同一后端 |
| 目标地址哈希 | dh | Destination Hashing |
| 短期期望延迟 | sed | Shortest Expected Delay |
| 最少队列 | nq | Never Queue |
5. 详细时序图
5.1 Service 创建完整时序图
sequenceDiagram
autonumber
participant User as 用户
participant API as kube-apiserver
participant EP as EndpointSlice Controller
participant KP as kube-proxy
participant IPT as iptables/ipvs
participant KERNEL as Linux 内核
User->>API: kubectl apply -f service.yaml
API->>API: 创建 Service 对象
Note over API,KP: Informer watch 触发
API-->>KP: watch Service ADDED
KP->>KP: ServiceHandler.OnServiceAdd()
KP->>KP: 入队 serviceUpdate
Note over API,EP: EndpointSlice 创建
EP->>EP: watch Service 创建
EP->>EP: 匹配 Pod labels
EP->>API: 创建 EndpointSlice
API-->>KP: watch EndpointSlice ADDED
KP->>KP: EndpointSliceHandler.OnAdd()
KP->>KP: 入队 endpointUpdate
Note over KP: SyncRunner 触发
KP->>KP: Sync()
KP->>KP: buildServiceMap()
KP->>KP: buildEndpointsMap()
KP->>KP: computeDifferences()
KP->>KP: generateRules()
KP->>IPT: iptables-restore / ipvsadm
IPT->>KERNEL: 写入网络规则
KERNEL-->>IPT: 确认
IPT-->>KP: 成功
Note over KP: Service 现在可达
5.2 后端 Pod 变更时序图
sequenceDiagram
autonumber
participant KL as Kubelet
participant API as kube-apiserver
participant EP as EndpointSlice Controller
participant KP as kube-proxy
participant IPT as iptables/ipvs
Note over KL: Pod Ready 状态变化
KL->>API: 更新 Pod status
API-->>EP: watch Pod UPDATE
EP->>EP: 检查 Pod 是否匹配 Service
EP->>EP: 更新 EndpointSlice
alt Pod 变为 Ready
EP->>API: 添加 Endpoint 到 EndpointSlice
else Pod 变为 NotReady
EP->>API: 从 EndpointSlice 移除 Endpoint
end
API-->>KP: watch EndpointSlice UPDATE
KP->>KP: EndpointSliceHandler.OnUpdate()
KP->>KP: 入队更新
Note over KP: 等待 SyncRunner
KP->>KP: Sync()
KP->>KP: 重新计算 endpointsMap
KP->>KP: 计算规则差异
KP->>IPT: 更新 iptables/ipvs 规则
IPT-->>KP: 成功
Note over KP: 流量现在路由到新后端
5.3 规则同步失败重试时序图
sequenceDiagram
autonumber
participant KP as kube-proxy
participant IPT as iptables/ipvs
participant KERNEL as Linux 内核
KP->>KP: SyncRunner 触发
KP->>KP: generateRules()
KP->>IPT: iptables-restore < rules
IPT->>KERNEL: 写入规则
alt 规则写入失败
KERNEL-->>IPT: Error (如资源不足)
IPT-->>KP: 失败
KP->>KP: 记录错误
KP->>KP: 保留旧规则
Note over KP: 等待下次 Sync
KP->>KP: SyncRunner 再次触发
KP->>IPT: 重试 iptables-restore
IPT->>KERNEL: 写入规则
KERNEL-->>IPT: 成功
IPT-->>KP: 成功
else 规则写入成功
KERNEL-->>IPT: 成功
IPT-->>KP: 成功
end
6. 故障排查指南
6.1 常见问题与诊断方法
问题 1:Service ClusterIP 无法访问
症状:通过 Service ClusterIP 访问服务超时或拒绝连接
排查流程图:
flowchart TD
A[ClusterIP 不可达] --> B{检查 Service 是否存在}
B -->|不存在| B1[创建 Service]
B -->|存在| C{检查 EndpointSlice}
C -->|无后端| C1[检查 Pod labels]
C1 --> C2[检查 Pod Ready 状态]
C2 --> C3[检查 selector 匹配]
C -->|有后端| D{检查 iptables 规则}
D -->|无规则| D1[检查 kube-proxy 日志]
D1 --> D2[重启 kube-proxy]
D -->|有规则| E{检查 conntrack}
E --> E1[conntrack -L]
E --> E2[检查连接状态]
A --> F{检查网络策略}
F --> F1[检查 NetworkPolicy]
F --> F2[检查 CNI 配置]
诊断命令:
1 | # 检查 Service |
问题 2:NodePort 外部无法访问
症状:从集群外部无法通过 NodeIP:NodePort 访问服务
排查流程图:
flowchart TD
A[NodePort 不可达] --> B{检查防火墙}
B --> B1[检查节点防火墙规则]
B1 --> B2[iptables -L INPUT]
B1 --> B3[firewalld/ufw 状态]
B --> C{检查 NodePort 范围}
C --> C1[kubectl get svc]
C1 --> C2[NodePort 是否在 30000-32767]
A --> D{检查 kube-proxy}
D --> D1[检查 KUBE-NODEPORTS 链]
D --> D2[检查 IPVS 虚拟服务]
A --> E{检查网络连通性}
E --> E1[从节点内测试 curl localhost:NodePort]
E --> E2[从节点外测试 curl NodeIP:NodePort]
A --> F{检查 local 部流量策略}
F --> F1[externalTrafficPolicy]
F1 --> F2[Local 模式只转发到本节点 Pod]
诊断命令:
1 | # 检查 NodePort 范围 |
问题 3:Session Affinity 不生效
症状:相同客户端请求被分发到不同后端
排查流程图:
flowchart TD
A[Session Affinity 失效] --> B{检查 Service 配置}
B --> B1[检查 sessionAffinity]
B --> B2[检查 sessionAffinityConfig.timeoutSeconds]
A --> C{检查负载均衡模式}
C --> C1[iptables 模式: 检查概率规则]
C --> C2[IPVS 模式: 检查调度算法]
A --> D{检查 conntrack}
D --> D1[conntrack 状态]
D --> D2[连接超时时间]
A --> E{检查客户端 IP}
E --> E1[是否经过 SNAT]
E --> E2[externalTrafficPolicy 设置]
诊断命令:
1 | # 检查 Session Affinity 配置 |
6.2 关键日志关键词
| 场景 | 日志关键词 | 含义 |
|---|---|---|
| 规则同步 | Sync rules |
开始同步规则 |
| 规则更新 | Setting iptables |
更新 iptables |
| Service 变更 | Adding new service |
新增 Service |
| Endpoint 变更 | Updating endpoints |
更新后端 |
| 同步失败 | Failed to execute |
规则执行失败 |
| IPVS 模式 | Using ipvs Proxier |
IPVS 模式启动 |
6.3 配置参数参考
| 参数 | 默认值 | 说明 |
|---|---|---|
--proxy-mode |
iptables | 代理模式 (iptables/ipvs/userspace) |
--cluster-cidr |
无 | Pod 网段,用于 masquerade |
--ipvs-sync-period |
1m | IPVS 规则同步周期 |
--iptables-sync-period |
1m | iptables 规则同步周期 |
--masquerade-all |
false | 是否对所有流量 SNAT |
--nodeport-addresses |
所有 | NodePort 监听地址 |
6.4 一键诊断命令
1 | # kube-proxy 问题诊断脚本 |
7. 版本差异说明
1.27 → 1.28 变化
| 变化点 | 说明 |
|---|---|
| nftables 模式 (Alpha) | 新增 nftables 后端,未来将替代 iptables |
| Dual-stack Service 改进 | IPv4/IPv6 双栈支持更完善 |
1.28 → 1.29 变化
| 变化点 | 说明 |
|---|---|
| Service 内部流量策略 | internalTrafficPolicy: Local 支持 |
| nftables 模式 (Beta) | nftables 模式更稳定 |
8. 代码入口(精简版)
如果读者想从流程跳回实现,可从下面几个入口开始:
- kube-proxy 主入口:
cmd/kube-proxy/proxy.go - Proxier 接口:
pkg/proxy/proxy.go - iptables Proxier:
pkg/proxy/iptables/proxier.go - IPVS Proxier:
pkg/proxy/ipvs/proxier.go - EndpointSlice 缓存:
pkg/proxy/endpointslicecache.go
9. 面试题与详细解答
问题 1:kube-proxy 的三种模式(userspace/iptables/IPVS)有什么区别?生产环境如何选择?
回答要点:
三种模式对比:
| 特性 | userspace | iptables | IPVS |
|---|---|---|---|
| 性能 | 最差(用户态转发) | 中等(内核态 O(n)) | 最好(内核态 O(1)) |
| 规则更新 | 立即生效 | 全量更新 | 增量更新 |
| 负载均衡 | 随机 | 概率规则 | 多种算法 |
| 可靠性 | 高 | 高 | 需加载 ip_vs 模块 |
选择建议:
生产环境推荐 IPVS:
- 大规模集群(Service > 1000)必须使用
- 需要高级负载均衡算法(如最少连接)
- 规则更新频繁场景
中小规模可用 iptables:
- 默认模式,无需额外配置
- 所有 Linux 内核都支持
- 规则数量可控时性能足够
避免使用 userspace:
- 仅用于兼容旧系统
- 性能瓶颈明显
代码位置:
- iptables Proxier:
pkg/proxy/iptables/proxier.go - IPVS Proxier:
pkg/proxy/ipvs/proxier.go
问题 2:kube-proxy 如何保证 Service 后端 Pod 变更后规则及时更新?更新延迟是多少?
回答要点:
更新机制:
Informer Watch 机制:
- kube-proxy watch API Server 的 EndpointSlice 对象
- 变更事件实时推送到 kube-proxy
事件处理流程:
1
EndpointSlice 变更 → Informer 收到事件 → EventHandler 入队 → SyncRunner 定期处理 → 规则计算 → 规则同步
同步周期(默认配置):
--iptables-sync-period:1 分钟(定期全量同步)--ipvs-sync-period:1 分钟- 但变更事件会立即触发增量更新
延迟分析:
| 阶段 | 延迟 |
|---|---|
| EndpointSlice 更新 | 1-2 秒(kubelet 上报 Pod Ready) |
| Informer Watch 延迟 | < 1 秒 |
| 队列等待 | 0 - sync-period |
| 规则写入 | < 1 秒 |
| 总延迟 | 通常 < 5 秒 |
代码位置:
- EndpointSlice 缓存:
pkg/proxy/endpointslicecache.go - SyncRunner:
pkg/proxy/sync_runner.go
问题 3:iptables 模式下的 ClusterIP 流量转发完整流程是什么?为什么需要 SNAT?
回答要点:
流量转发流程:
1 | 1. Pod 发送请求到 ClusterIP:Port |
iptables 链关系:
1 | PREROUTING → KUBE-SERVICES → KUBE-SVC-xxx → KUBE-SEP-xxx |
SNAT 的必要性:
- 场景:Pod 访问自身 Service(hairpin 模式)
- 问题:如果不 SNAT,响应包直接返回给客户端 Pod,源 IP 是后端 Pod IP,客户端无法识别
- 解决:
KUBE-MARK-MASQ链标记需要 SNAT 的流量- POSTROUTING 链执行 MASQUERADE
关键规则示例:
1 | # KUBE-SVC-xxx 链(概率负载均衡) |
问题 4:Service 的 SessionAffinity 是如何实现的?为什么有时候不生效?
回答要点:
实现原理:
iptables 模式:
- 使用
recent模块记录源 IP - 后续请求优先匹配已建立连接的后端
1
2
3# 示例规则
-A KUBE-SEP-xxx -m recent --set --name KUBE-SEP-xxx
-A KUBE-SEP-xxx -m recent --rcheck --seconds 10800 --name KUBE-SEP-xxx -j DNAT
- 使用
IPVS 模式:
- 使用 IPVS 的持久化连接(persistent connection)
ipvsadm -p参数设置持久化时间- 支持 source hashing 调度算法
不生效的常见原因:
客户端 IP 变化:
- 经过 SNAT 后,源 IP 被改写
- 解决:设置
externalTrafficPolicy: Local
超时时间过期:
- 默认 3 小时,可在
sessionAffinityConfig调整1
2
3
4sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
- 默认 3 小时,可在
负载均衡算法:
- IPVS 模式需要使用
sh(source hashing)算法 - 配置:
--ipvs-scheduler=sh
- IPVS 模式需要使用
后端 Pod 数量变化:
- Pod 增减导致哈希重新计算
- 解决:使用一致性哈希或减少 Pod 变化频率
调试命令:
1 | # 检查 SessionAffinity 配置 |
问题 5:NodePort 服务的外部流量策略(externalTrafficPolicy)有什么作用?Local 和 Cluster 模式的区别?
回答要点:
两种模式对比:
| 特性 | Cluster(默认) | Local |
|---|---|---|
| 流量转发 | 可转发到任意节点 Pod | 只转发到本节点 Pod |
| 源 IP 保留 | 否(SNAT) | 是(保留真实客户端 IP) |
| 负载均衡 | 集群级别均匀 | 取决于外部负载均衡 |
| 可用性 | 高(所有节点都可用) | 低(只有 Pod 所在节点可用) |
Cluster 模式流程:
1 | 外部请求 → NodeIP:NodePort → KUBE-NODEPORTS → KUBE-SVC-xxx |
Local 模式流程:
1 | 外部请求 → NodeIP:NodePort → KUBE-XLB-xxx → 仅本节点 Pod(保留源 IP) |
使用场景:
Cluster 模式:
- 对源 IP 无要求
- 需要高可用性
- 后端 Pod 分布不均匀
Local 模式:
- 需要保留源 IP(如安全策略、日志分析)
- 配合外部负载均衡使用
- 后端 Pod 在每个节点都有部署
配置示例:
1 | apiVersion: v1 |
注意事项:
- Local 模式下,如果本节点没有 Pod,请求会被拒绝
- 建议配合 DaemonSet 使用 Local 模式
问题 6:kube-proxy 如何处理 Service 的 headless 类型?DNS 解析与普通 Service 有什么区别?
回答要点:
Headless Service 特点:
- 定义:
spec.clusterIP: None - kube-proxy 行为:不创建任何 iptables/IPVS 规则
- 负载均衡:完全依赖 DNS 轮询或客户端实现
DNS 解析区别:
| 类型 | DNS 返回 | 示例 |
|---|---|---|
| ClusterIP Service | 单个 ClusterIP | 10.96.0.1 |
| Headless Service | 所有 Ready Pod IP | 10.244.1.2, 10.244.1.3, ... |
Headless Service DNS 查询结果:
1 | # 普通 Service |
使用场景:
- StatefulSet:每个 Pod 有稳定网络标识
- 自定义负载均衡:客户端自行选择后端
- 服务发现:获取所有后端 IP 列表
- 数据库集群:需要区分主从节点
实现原理:
EndpointSlice Controller:
- 仍然创建 EndpointSlice 对象
- 包含所有 Ready Pod 的 IP
CoreDNS:
- 读取 EndpointSlice
- 为每个 IP 返回 A 记录
- 支持 SRV 记录(带端口)
代码位置:
- EndpointSlice Controller:
pkg/controller/endpointslice/controller.go
问题 7:如何排查 Service 无法访问的问题?请给出完整的排查思路和命令。
回答要点:
排查流程图:
1 | Service 无法访问 |
详细排查步骤:
步骤 1:检查 Service 配置
1 | # 查看 Service |
步骤 2:检查 EndpointSlice
1 | # 查看后端 Pod |
步骤 3:检查 iptables 规则(在节点上)
1 | # 查看 KUBE-SERVICES 链 |
步骤 4:检查 IPVS 规则(在节点上)
1 | # 查看所有虚拟服务 |
步骤 5:检查 conntrack 状态
1 | # 查看连接追踪 |
步骤 6:网络连通性测试
1 | # 从 Pod 内测试 |
常见问题及解决:
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 无 ClusterIP | Service 配置错误 | 检查 yaml 配置 |
| 无后端 Pod | selector 不匹配 | 修正 labels |
| 后端 NotReady | Pod 未就绪 | 检查 Pod 状态 |
| 无 iptables 规则 | kube-proxy 故障 | 重启 kube-proxy |
| conntrack 满了 | 连接数超限 | 增大 conntrack 表 |
一键诊断脚本:
1 |
|

