CCE LoadBalancer Service 外部流量策略(Local)最佳实践
概述
本文档介绍在百度智能云容器引擎 CCE 中,以节点作为负载均衡后端的 LoadBalancer Service 应如何选择并用好外部流量策略 spec.externalTrafficPolicy,并给出面向生产业务的推荐配置、常见问题规避与验证方法。
CCE 支持 Kubernetes 原生的 externalTrafficPolicy 配置,包含 Local 与 Cluster 两种模式。对于面向公网或 VPC 客户端提供服务的生产业务,建议优先使用 Local 模式:它可以避免 kube-proxy 跨节点转发引入的额外源地址转换、减少跨节点转发、并缩小节点故障对业务流量的影响范围。客户端源 IP 的最终获取方式还取决于负载均衡 BLB 监听协议与完整转发链路。
说明
导航路径:容器引擎 CCE->集群列表->目标集群->网络->服务。
CCE 控制台"创建服务"页的"外部流量策略"默认采用 Local,可在多数生产场景下保留客户端源 IP、减少跨节点转发并节省后端配额。
需要注意两个口径的区别:
- 通过控制台创建:控制台会在生成的 YAML 中显式写入
externalTrafficPolicy: Local,因此默认即 Local。- 手写 YAML 或调用 API 且不指定该字段:遵循 Kubernetes 原生默认值
Cluster。因此,若希望使用 Local,建议在 YAML 中显式声明,不要依赖默认值。
适用范围
本文推荐适用于未开启 Pod 直连、以 CCE 节点作为负载均衡后端的 LoadBalancer Service。
如果您的 LoadBalancer Service 已开启 Pod 直连模式(Annotation service.beta.kubernetes.io/cce-load-balancer-backend-type: "eni"),负载均衡会将流量直接转发到 Pod,其转发路径与客户端源 IP 的获取方式与本文介绍的节点后端场景不同,本文的推荐配置不适用于该场景。如需使用 Pod 直连模式,请参考使用直连 Pod 模式 LoadBalancer Service。
外部流量策略选择建议
- Local(推荐,默认):需要保留客户端源 IP、对时延敏感、希望节省 BLB 后端配额、希望缩小节点故障影响面的生产业务。前提是业务已多副本并跨节点部署。
- Cluster:业务副本少、Pod 暂时无法跨节点分布且更关注"任意入口节点到后端的可达性";或不需要源 IP、可接受跨节点转发与 SNAT;或存量业务依赖在集群内部用负载均衡 BLB 的访问地址(公网或内网 IP)互访、且短期无法改用 ClusterIP 替代。
- LB 直连 Pod:追求最短转发路径与最佳性能,集群为 VPC-ENI 网络模式(或已安装 ttm 模块的 VPC 路由模式),按使用直连 Pod 模式 LoadBalancer Service单独配置。
推荐配置
创建 LoadBalancer Service 时,建议显式指定外部流量策略:
1apiVersion: v1
2kind: Service
3metadata:
4 name: example-service
5spec:
6 type: LoadBalancer
7 externalTrafficPolicy: Local
8 selector:
9 app: example
10 ports:
11 - name: http
12 protocol: TCP
13 port: 80
14 targetPort: 8080
其中:
externalTrafficPolicy: Local:外部流量只转发到负载均衡后端节点上的本地 Pod。CCE LB Controller 根据 Service 对应的 Endpoints 筛选负载均衡后端节点。
本文适用于以节点作为负载均衡后端的场景,无需额外指定后端类型。如需迁移至 Pod 直连模式,应新建 LoadBalancer Service,验证通过后再切换业务流量;不支持通过修改已有 Service 的后端类型注解完成迁移。具体请参考使用直连 Pod 模式 LoadBalancer Service。
工作原理
Local 模式
Local 模式下,CCE 根据 Service 对应的 Endpoints 筛选节点,仅将存在关联 Endpoint 的节点加入负载均衡后端。流量到达节点后,由节点转发到本节点上的可用后端 Pod,不会再转发到其他节点。节点增删与 Endpoint 状态变化同步到 BLB 存在一定延迟。
1客户端
2 |
3 v
4负载均衡 BLB
5 |
6 +----> 节点 A ----> 节点 A 上的 Pod
7 |
8 +----> 节点 B ----> 节点 B 上的 Pod
Cluster 模式
Cluster 模式下,负载均衡后端通常包含集群内全部可用节点。流量到达节点后,可由 kube-proxy 转发到集群内任意节点上的后端 Pod。
1客户端
2 |
3 v
4负载均衡 BLB
5 |
6 +----> 节点 A ----> 本节点 Pod
7 | --> 节点 B 上的 Pod
8 |
9 +----> 未部署业务 Pod 的节点 C ----> 其他节点上的 Pod
两种模式的主要差异如下:
| 对比项 | Local 模式 | Cluster 模式 |
|---|---|---|
| 负载均衡后端 | 存在 Service 关联 Endpoint 的节点 | 通常为全部可用节点 |
| 节点内转发范围 | 仅本节点 Pod | 集群内任意 Pod |
| 客户端源 IP | 避免跨节点转发引入的额外 SNAT;实际获取方式取决于监听协议与转发链路 | 节点后端模式下,跨节点转发通常会执行 SNAT |
| 跨节点转发 | 无 | 可能存在 |
| 后端规模 | 随承载业务 Pod 的节点数变化 | 随集群节点数变化 |
| 流量均衡 | 需关注各节点上的 Pod 数量 | kube-proxy 可进行集群范围的二次分发 |
推荐使用 Local 模式的原因
避免跨节点转发引入额外 SNAT
Local 模式避免流量从入口节点再次转发到其他节点时发生额外的源地址转换。后端应用如何获取客户端源 IP,还取决于 BLB 监听协议与业务链路:
- 四层 TCP/UDP 监听:在 BLB 与后端网络支持客户端 IP 透传的场景下,应用可从连接或报文中获取客户端源 IP。
- 七层 HTTP/HTTPS 监听:BLB 会代理客户端连接,应用通常需从 BLB 写入的可信
X-Forwarded-For等请求头中获取客户端 IP。 - BLB 前还有 CDN、WAF 或其他代理:应根据完整代理链配置可信代理范围,并按对应产品文档解析客户端 IP,避免直接信任客户端自行构造的转发请求头。
客户端源 IP 常用于:按客户端 IP 记录访问日志与审计;配置安全策略、黑白名单与访问控制;进行限流、会话保持与地域分析。
减少跨节点转发
Local 模式下外部流量到达节点后直接转发到本节点 Pod,可减少一次跨节点转发,降低东西向网络带宽消耗与数据面处理开销。对于高并发、长连接或时延敏感业务,建议优先使用该模式。
缩小节点故障影响范围
Local 模式只允许存在后端 Pod 的节点承接流量。未部署业务 Pod 的节点不会作为流量中转节点,因此此类节点发生异常时,不会额外影响该 Service 的外部流量。Cluster 模式下所有可用节点都可能成为入口节点,即使节点上没有业务 Pod,该节点出现网络拥塞、kube-proxy 异常或节点故障时,仍可能影响分配到该节点的流量。
减少负载均衡后端数量,节省配额
CCE LB Controller 在 Local 模式下根据 Endpoints 过滤节点,只同步存在 Service 关联 Endpoint 的节点。该机制可减少无业务 Pod 节点占用的负载均衡后端配额,并缩小后端变更范围。Cluster 模式会把全部节点挂到后端,集群规模越大,消耗的 BLB 后端配额越多,同步变更范围也越大。
减少健康检查开销
负载均衡会对每个后端节点发送健康探测。Local 模式只挂载承载业务 Pod 的节点,探测请求随之减少;Cluster 模式下每个节点都会被每个 Service 探测,当节点数、Service 数较多时,单个节点收到的探测请求会成倍增长(N 个 Service 时,一个节点会收到 N 份探测)。
使用 Local 模式的前提条件
Local 模式不执行跨节点二次负载均衡,负载均衡按节点分配流量而非按 Pod 分配。因此业务需要合理分布 Pod,避免部分节点承载过多流量。建议满足以下条件:
- 生产业务至少部署 2 个副本,并分布到不同节点。
- 高可用业务将 Pod 分布到不同可用区,避免单个故障域承载全部后端。
- 配置
topologySpreadConstraints或 Pod 反亲和,控制各节点上的副本数量。 - 配置
readinessProbe,确保未就绪 Pod 不承接业务流量。 - 配置
preStop与足够的terminationGracePeriodSeconds,为负载均衡摘除后端与存量连接排空预留时间。 - 集群内应用优先通过 Service 的 ClusterIP 或服务发现域名访问服务,不建议依赖负载均衡 BLB 的访问地址进行集群内回流。
注意 如果 Service 只有一个副本,或所有 Pod 都集中在同一节点,Local 模式会使该节点承载全部外部流量;该节点故障时业务可能中断。请先完成多副本与跨节点部署,再用于生产流量。
典型问题与规避
下表汇总了 Local 模式下的常见问题与对应规避手段,建议在上线前逐项确认:
| 现象 | 根因 | 规避 / 处理 |
|---|---|---|
| 部分节点访问 BLB 地址不通、部分请求失败 | 被访问节点上没有该 Service 的后端 Pod | 多副本 + 拓扑分布,保证承流节点都有 Pod;集群内改用 ClusterIP 访问 |
kube-proxy 为 ipvs 时,Local 且本节点无 Pod,节点上访问 BLB 地址失败 |
kube-proxy 将 external-IP 加入本地转发规则,绕过了 BLB | 集群内统一走 ClusterIP 或服务发现域名(流量不再被当作 external-IP 由 kube-proxy 劫持,可避免此问题);Kubernetes 1.24+ 对部分 Pod 来源访问有改进,实际行为需结合 CCE 版本验证 |
| 各节点流量不均、出现热点 | 按节点分流,但各节点 Pod 数不同 | 用 topologySpreadConstraints 均匀分布;必要时开启 CCE 动态后端权重 |
| 扩容后新节点收不到流量 / 后端数超限 | BLB 后端数受最大后端数限制 | 设置 service.beta.kubernetes.io/cce-load-balancer-rs-max-num 不小于该 Service 的承载节点数(默认 200,最终以组件启动参数和目标版本为准) |
| 滚动升级 / 缩容期间连接中断 | 后端摘除与连接排空需要时间 | 配置 readinessProbe + preStop + 合理 terminationGracePeriodSeconds,见下文优雅下线 |
| 集群内访问 BLB 地址异常,但集群外正常 | 集群内回流路径绕过 BLB,受 Local 约束 | 集群内统一使用 ClusterIP 或服务发现域名 |
优化流量均衡
均匀分布 Pod
建议使用拓扑分布约束,将 Pod 均匀分布到不同节点,降低各节点承流差异:
1spec:
2 template:
3 spec:
4 topologySpreadConstraints:
5 - maxSkew: 1
6 topologyKey: kubernetes.io/hostname
7 whenUnsatisfiable: DoNotSchedule
8 labelSelector:
9 matchLabels:
10 app: example
按需开启 CCE 动态后端权重
如果不同节点上的后端 Pod 数量可能不一致,且当前负载均衡类型与 CCE LB Controller 版本支持动态后端权重,可为 Service 添加:
1metadata:
2 annotations:
3 service.beta.kubernetes.io/cce-dynamic-backend-server-weight: "true"
添加后,在 externalTrafficPolicy 为 Local、使用节点后端且当前负载均衡实现支持该能力时,CCE 会根据各节点上处于就绪状态的后端 Pod 数量设置 BLB 后端服务器权重(上限 100),使承载更多就绪 Pod 的节点获得相应比例的流量。该注解的完整说明参见LoadBalancer Service Annotation 说明。
说明 动态后端权重是可选优化项,不是使用 Local 模式的必需配置。配置前请通过 CCE 产品文档或技术支持确认目标负载均衡类型、集群组件版本及区域是否支持。该能力用于缓解节点间 Pod 数量不一致导致的流量偏斜,不能替代合理的多副本与跨故障域部署。
配置优雅下线
Pod 终止或滚动升级时,Endpoint 状态变更、CCE 同步负载均衡后端、BLB 停止向原后端分发新连接都需要时间,应用需为后端摘除与存量连接排空预留足够的优雅终止时间。Pod 删除时 Kubernetes 的优雅终止流程为:执行 preStop Hook 的同时,控制面将终止中的 Pod 标记为非就绪 Endpoint;preStop 完成后,kubelet 才向主进程发送 SIGTERM。建议:
- 配置能真实反映服务状态的
readinessProbe,确保异常或未就绪 Pod 不承接新流量。 - 在
preStopHook 中预留摘流等待时间,使 Pod 在 Endpoint 进入终止状态后继续运行,等待转发规则更新、停止向退出的 Pod 分配新连接;若退出的是本节点上该 Service 最后一个可用 Pod,还需考虑 BLB 健康检查与节点后端摘除的延迟。 - 应用收到
SIGTERM后停止接收新请求,并排空存量连接与正在处理的请求。 - 将
terminationGracePeriodSeconds设置为大于"preStop摘流等待时间 + 应用连接排空时间",避免 kubelet 在优雅退出完成前强制终止容器。
CCE LB Controller 的后端删除存在延迟(当前默认值约 60 秒,实际随组件版本与部署参数变化),加上 BLB 健康检查、后端同步与应用连接排空耗时,请先在目标环境分别测量以下两种情况的最长耗时:① Pod 摘流:转发规则更新、停止向退出的 Pod 分发新连接;② 节点摘流:退出的 Pod 为本节点最后一个可用 Pod 时,BLB 健康检查失败与节点后端摘除。再据此配置摘流等待时间,并为控制面或网络抖动预留余量。
以下 YAML 仅展示结构,请将 <摘流等待秒数> 与 <总优雅终止秒数> 替换为目标环境验证后的整数(总优雅终止时间应大于摘流等待时间与应用最大连接排空时间之和):
1spec:
2 template:
3 spec:
4 terminationGracePeriodSeconds: <总优雅终止秒数>
5 containers:
6 - name: example
7 lifecycle:
8 preStop:
9 exec:
10 command: ["/bin/sh", "-c", "sleep <摘流等待秒数>"]
11 readinessProbe:
12 httpGet:
13 path: /ready
14 port: 8080
15 periodSeconds: 5
16 failureThreshold: 2
验证建议
配置完成后,建议在测试环境完成以下验证,再切换生产流量:
- 从集群外访问负载均衡 BLB 的访问地址,确认业务可正常访问。
- 在应用日志中确认获取到的客户端源 IP 符合预期。
- 检查 BLB 后端列表,确认稳定状态下仅包含存在 Service 关联 Endpoint 的节点;变更期间应考虑 CCE 后端同步延迟。
- 多次访问服务,检查各节点与 Pod 的连接数、QPS、时延、CPU 与网络带宽,确认无明显热点。
- 执行滚动升级与 Pod 缩容,确认新连接可正常摘流、存量连接不会异常中断。
- 模拟单个 Pod 或节点故障,确认负载均衡可将流量转发到其他健康节点。
- 如业务需从集群内访问负载均衡 BLB 的访问地址,单独验证回流路径;若访问异常,改用 ClusterIP 或服务发现域名。
Cluster 模式适用场景
Cluster 是 Kubernetes Service 的默认外部流量策略,具有较好的 Pod 可达性:任意入口节点都可把请求转发到任意健康 Pod。但在以节点作为负载均衡后端的场景中,它会引入额外一跳转发、跨节点 SNAT 导致源 IP 丢失、无业务 Pod 节点仍中转流量、后端数随集群规模增长等影响。因此不建议将其作为节点后端生产业务的常规配置。以下场景可按实际情况选用 Cluster:
- 副本少且暂时无法跨节点分布:此时 Local 会把流量集中在少数节点,且没有 Pod 的节点不可达;改用 Cluster 可借助任意节点转发到健康 Pod,优先保证可达性。
- 业务不需要客户端源 IP:可以接受跨节点转发与源地址转换(SNAT)。
- 存量业务在集群内部用 BLB 地址互访、且短期无法改造:这类访问在 Local 下容易不通,在改用 ClusterIP 或服务发现域名之前,可继续使用 Cluster。
- 已使用会改变转发路径的特定网络插件或后端类型(例如 Pod 直连 eni 模式):请以对应产品文档说明为准。
对于上述场景,建议通过压测与故障演练评估 Cluster 模式的时延、带宽与节点故障影响。
常见问题(FAQ)
Q1:控制台默认是 Local,我手写 YAML 不写这个字段也是 Local 吗?
不是。控制台会在生成的 YAML 中显式写入 externalTrafficPolicy: Local;而手写 YAML 或调用 API 不指定该字段时,遵循 Kubernetes 原生默认值 Cluster。建议始终显式声明。
Q2:用了 Local 一定能拿到客户端真实源 IP 吗?
不一定。Local 只是避免了跨节点转发引入的额外 SNAT,最终能否拿到源 IP 还取决于 BLB 监听协议(四层透传 / 七层 X-Forwarded-For)与是否经过 CDN、WAF 等代理。详见"推荐使用 Local 模式的原因"第一条。
Q3:为什么有些节点访问 BLB 地址通、有些不通? 典型为 Local 模式下被访问节点上没有后端 Pod。请保证多副本并跨节点分布;集群内访问统一走 ClusterIP。若 kube-proxy 为 ipvs,该现象还与集群及 CCE 版本相关,集群内访问建议统一走 ClusterIP 或服务发现域名。
Q4:Local 下如何避免节点间流量不均?
优先用 topologySpreadConstraints 均匀分布 Pod;节点间 Pod 数仍可能不一致时,在确认产品与组件支持后开启 cce-dynamic-backend-server-weight。
Q5:节点很多时后端挂不全怎么办?
检查并调大 service.beta.kubernetes.io/cce-load-balancer-rs-max-num,使其不小于该 Service 的承载节点数(默认 200,最终以组件启动参数和目标版本为准)。
总结
对于未开启 Pod 直连、使用节点作为负载均衡后端的生产 LoadBalancer Service,建议优先配置 externalTrafficPolicy: Local,并配合多副本、跨节点部署与优雅下线;节点间 Pod 数量不一致时,可在确认产品与组件支持后按需启用动态后端权重。
Cluster 模式保留了集群范围的二次转发能力,但会增加跨节点网络路径、可能导致客户端源 IP 丢失、并扩大节点异常的影响范围。因此不建议将其作为节点后端生产业务的常规配置;存在明确例外场景时,应完成专项验证后使用。
相关文档
评价此篇文章
