cilium LB L2 vs L3

69 阅读10分钟

先说结论:

L3: BGP + ECMP 最稳定,最成熟,最适合大集群

L2: 目前还是 Beta 阶段:也难怪会有一些方案用 metallb 配合提供公网 IP 的维护

主题:Cilium LB IPAM 的功能定位、协同关系、启用机制及 IP Pool 配置与管理、Service 配置与 IP 分配等方面的详细介绍,包括关键问题及答案

1. 一段话总结

LB IPAM 是 Cilium 为 LoadBalancer 类型 Service 分配 IP 地址的功能,通常用于私有云环境(弥补公有云相关设施缺失),需与 Cilium BGP Control PlaneL2 Announcements/L2 Aware LB(Beta) 等功能协同:

  • Cilium BGP Control Plane 负责 IP 分配
  • L2 Announcements/L2 Aware LB(Beta) 后者负责负载均衡与 IP 宣告

LB IPAM 默认启用但休眠,添加首个 IP Pool 后激活该功能:

  • 支持通过 IP Pool 定义可用 IP 范围(CIDR 或起止 IP)

  • 服务选择器匹配特定 Service、IPv4/IPv6 单栈/双栈模式

  • 还可配置 IP 共享、禁用 Pool 等

  • 同时会检测 Pool 冲突

  • 通过状态反馈 IP 使用情况


2. 思维导图(mindmap)

image.png


3. 详细总结

一、LB IPAM 核心概述

  1. 功能定位:Cilium 提供的 LoadBalancer 类型 Service IP 分配功能,主要用于私有云环境(公有云通常由云厂商提供该能力,私有云常缺失)。

  2. 协同关系:仅负责 IP 分配,负载均衡与 IP 宣告需依赖其他功能,具体对应关系如下:

协同功能负责事项
Cilium BGP Control Plane通过 BGP 协议宣告 LB IPAM 分配的 IP
L2 Announcements/L2 Aware LB(Beta)在本地网络宣告 LB IPAM 分配的 IP
  1. 启用机制:默认启用但处于休眠状态,当集群中添加首个 IP Pool 后,控制器被激活并开始工作。

二、IP Pool 配置与管理

IP Pool 是管理员定义的可用 IP 范围集合,是 LB IPAM 分配 IP 的基础,核心配置与管理能力如下:

1. 基础配置(IP 块与特殊设置)

  • IP 块格式:支持两种方式定义可用 IP 范围,可在同一 Pool 中混合使用:

    • CIDR notation:如 cidr: "10.0.10.0/24"(IPv4)、cidr: "2004::0/112"(IPv6)
    • 起止 IP 范围:如 start: "20.0.20.100" + stop: "20.0.20.200"
  • CIDR 首尾 IP 保留

    • 默认行为:使用 CIDR 中的所有 IP(包括网络地址、广播地址,部分设备可能不兼容)

    • 保留配置:设置 .spec.allowFirstLastIPs: No,可保留 CIDR 首尾 IP

    • 例外情况:/32//31 IPv4 CIDR、/128//127 IPv6 CIDR(仅 1 或 2 个 IP),此设置无效;且该设置仅对 CIDR 格式 IP 块生效,对起止 IP 格式无效。

2. 服务选择器(Service Selector)

  • 作用:限制当前 IP Pool 只能为匹配条件的 Service 分配 IP,无选择器则对所有 Service 开放。

  • 匹配方式

    • matchExpressions:复杂匹配,如 {key: color, operator: In, values: [blue, cyan]}(匹配 label 中 color 为 blue 或 cyan 的 Service)
    • matchLabels:精确匹配,如 color: red(匹配 label 中 color 为 red 的 Service)
  • 特殊选择器:不匹配 Service 标签,而是匹配元数据,对应关系如下:

选择器键匹配的 Service 元数据字段
io.kubernetes.service.namespace.meta.namespace(Service 所在命名空间)
io.kubernetes.service.name.meta.name(Service 名称)

3. 冲突处理

  • 冲突规则:IP Pool 不允许存在重叠 CIDR,若管理员创建重叠 Pool,会触发“软错误”。

  • 冲突表现:后添加的 Pool 会被标记为 Conflicting,且不再从该 Pool 分配 IP。

  • 查看冲突

    • 命令 1(jsonpath 查看消息):kubectl get ippools/[Pool名] -o jsonpath='{.status.conditions[?(@.type=="cilium.io/PoolConflict")].message}'

    • 命令 2(describe 查看详情):kubectl describe ippools/[Pool名],在 Status.Conditions 中查看冲突原因(如“CIDR 20.0.10.0/24 与 blue-pool 的 CIDR 重叠”)。

4. 禁用 Pool

  • 配置方式:在 Pool 定义中设置 .spec.disabled: true

  • 效果:停止从该 Pool 分配新 IP,但保留已分配的 IP(适用于逐步排空 Pool 或预留 Pool 供未来使用)。

  • 状态查看kubectl get ippools 中,该 Pool 的 DISABLED 列显示为 true

5. 状态监控

Pool 状态包含 IP 使用关键数据,支持机器解析与人类可读两种查看方式:

  • 机器解析(jsonpath + jq)kubectl get ippools -o jsonpath='{.items[*].status.conditions[?(@.type!="cilium.io/PoolConflict")]}' | jq,可获取以下类型数据:

    • cilium.io/IPsTotal:Pool 总 IP 数
    • cilium.io/IPsAvailable:Pool 可用 IP 数
    • cilium.io/IPsUsed:Pool 已用 IP 数
  • 人类可读(describe)kubectl describe ippools/[Pool名],在 Status.Conditions 中查看上述三类数据的具体数值(如 Message: 254 表示对应 IP 数量)。

三、Service 配置与 IP 分配

LB IPAM 为 LoadBalancer 类型 Service 分配 IP,需满足匹配规则,且支持多种 IP 配置策略:

1. 基础分配条件与状态反馈

  • 分配条件:Service 需满足 spec.type=LoadBalancer,且匹配某 IP Pool 的服务选择器(否则 ExternalIP 显示为 <pending>)。

  • 状态反馈:当 LB IPAM 无法分配 IP 时,会更新 Service 状态条件,可通过命令查看:kubectl -n [命名空间] get svc/[Service名] -o jsonpath='{.status.conditions}' | jq,例如“无启用且匹配的 Pool”时,条件 io.cilium/lb-ipam-request-satisfied 状态为 False,原因是 no_pool;分配成功后,该条件状态变为 True,原因是 satisfied

2. IPv4/IPv6 家族与策略

LB IPAM 支持 IPv4、IPv6 的单栈(SingleStack)或双栈(DualStack)模式,由 Service 的 .spec.ipFamilyPolicy 控制,具体规则如下:

IP 家族策略行为说明满足条件
SingleStack(默认)若双栈启用,优先分配 IPv4;仅单栈启用则分配对应 IP分配到一种 IP 即满足
PreferDualStack尝试分配 IPv4 + IPv6;仅一种启用时仍正常分配分配到一种或两种 IP 均满足
RequireDualStack必须同时分配 IPv4 + IPv6需同时分配两种 IP 才满足,缺一种则不满足
  • 补充:.spec.ipFamilies 的顺序不影响 LB IPAM 分配,但会影响集群 IP 分配(集群 IP 不由 LB IPAM 处理)。

3. LoadBalancerClass(K8s ≥v1.24)

  • 功能作用:K8s 1.24+ 支持集群中存在多个负载均衡器,通过 .spec.loadBalancerClass 选择具体负载均衡器。

  • LB IPAM 处理规则

    • 默认:处理 loadBalancerClass 配置 的 Service。

    • 支持的 Cilium 类:需选择 Cilium 相关类才能使用 LB IPAM 分配 IP,对应关系如下:

loadBalancerClass关联 Cilium 功能
io.cilium/bgp-control-planeCilium BGP Control Plane
io.cilium/l2-announcerL2 Announcements/L2 Aware LB(Beta)
  • 忽略规则:若 loadBalancerClass 设为非 Cilium 处理的类,LB IPAM 会完全忽略该 Service,不分配 IP 也不更新状态条件。

  • 自定义配置:默认 LB IPAM 处理无类 Service,若需仅处理有认可类的 Service,可通过以下方式配置:

    • Helm:helm upgrade cilium cilium/cilium --version 1.18.3 --namespace kube-system --reuse-values --set defaultLBServiceIPAM=none

    • ConfigMap:设置 default-lb-service-ipam: none

4. 手动请求特定 IP

Service 可指定需分配的 IP,支持两种方式:

  • Legacy 方式(弃用) :通过 .spec.loadBalancerIP 指定单个 IP,K8s v1.24 已弃用,但暂支持。

  • 新方式(推荐) :通过 Annotation lbipam.cilium.io/ips 指定,格式为逗号分隔的多 IP(如 "20.0.10.100,20.0.10.200")。

  • 限制:请求的 IP 需属于某 IP Pool,且 Service 需匹配该 Pool 的服务选择器;不建议请求 CIDR 的首尾 IP(通常为网络/广播地址,不可用)。

5. IP 共享

多个 Service 可共享同一 IP 或 IP 集合,核心配置与规则如下:

  • 基础配置:在 Service 中添加 Annotation lbipam.cilium.io/sharing-key: [自定义字符串],相同 sharing-key 的 Service 会共享 IP。

  • 共享规则

    • 无端口冲突:多个 Service 共享同一 IP。
    • 有端口冲突:为冲突的 Service 分配不同 IP,但这些 IP 仍属于该 sharing-key 的共享组。
    • 结合手动请求 IP:若 Service 有 sharing-key 且手动请求 IP,该 IP 会被分配给 Service 并加入共享组。
  • 跨命名空间共享

    • 默认:不允许跨命名空间共享 IP。

    • 启用方式:两个 Service 均需添加 Annotation lbipam.cilium.io/sharing-cross-namespace: [命名空间列表],值为逗号分隔的允许命名空间(如 "tenant-a,tenant-b"),或用 * 表示允许所有命名空间。


4. 关键问题

问题 1:在 Cilium LB IPAM 中,IP Pool 出现 CIDR 重叠时会有什么后果?如何查看具体的冲突原因?

答案

  • 后果:IP Pool 不允许存在 CIDR 重叠,若管理员创建了重叠的 Pool,后添加的 Pool 会被标记为 Conflicting,且 LB IPAM 会停止从该冲突 Pool 中分配任何 IP;已存在的非冲突 Pool 不受影响,正常提供 IP 分配服务。

  • 查看冲突原因:有两种常用方式:

    • 使用 jsonpath 提取冲突消息:kubectl get ippools/[冲突 Pool 名称] -o jsonpath='{.status.conditions[?(@.type=="cilium.io/PoolConflict")].message}',例如输出“Pool conflicts since CIDR '20.0.10.0/24' overlaps CIDR '20.0.10.0/24' from IP Pool 'blue-pool'”。

    • 通过 describe 查看详情:kubectl describe ippools/[冲突 Pool 名称],在 Status.Conditions 段落中,找到类型为 cilium.io/PoolConflict 的条件,其 Message 字段会明确说明冲突原因(如 CIDR 重叠来源)。

问题 2:Cilium LB IPAM 支持 IPv4 和 IPv6 双栈模式,Service 的 .spec.ipFamilyPolicy 不同取值对应什么分配行为?若设置为 RequireDualStack 但集群仅启用了 IPv4,会有什么结果?

答案

  • .spec.ipFamilyPolicy 不同取值的分配行为

    • SingleStack(默认) :若集群同时启用 IPv4 和 IPv6,LB IPAM 优先为 Service 分配 IPv4 地址;若仅启用一种 IP 家族(仅 IPv4 或仅 IPv6),则分配对应家族的 IP。
    • PreferDualStack:LB IPAM 会尝试为 Service 同时分配 IPv4 和 IPv6 地址;若集群仅启用一种 IP 家族,仍会分配该家族的 IP,Service 状态视为“满足”(io.cilium/lb-ipam-request-satisfied 为 True)。
    • RequireDualStack:LB IPAM 必须为 Service 同时分配 IPv4 和 IPv6 地址才视为“满足”;若集群仅启用一种 IP 家族(如仅 IPv4),无法分配另一种 IP,Service 状态视为“不满足”(io.cilium/lb-ipam-request-satisfied 为 False),且 ExternalIP 可能处于 pending 状态。
  • RequireDualStack 且仅启用 IPv4 的结果:Service 无法同时获取 IPv4 和 IPv6 地址,LB IPAM 不会完成 IP 分配,Service 的 ExternalIP 可能显示为 <pending>,且通过 kubectl get svc/[Service名] -o jsonpath='{.status.conditions}' | jq 查看时,io.cilium/lb-ipam-request-satisfied 条件状态为 False,提示无法满足双栈 IP 需求。

问题 3:在 Cilium LB IPAM 中,如何配置多个 Service 共享同一 IP?跨命名空间共享 IP 需要额外做什么设置?

答案

  • 同命名空间下多个 Service 共享 IP 的配置

    • 为需要共享 IP 的所有 Service 添加相同的 Annotation:lbipam.cilium.io/sharing-key: [自定义共享密钥](如 "sharing-key: "app-common"")。
    • 确保这些 Service 无端口冲突(如均使用 80 端口则存在冲突):无端口冲突时,LB IPAM 会为它们分配同一 IP;有端口冲突时,会分配不同 IP,但这些 IP 仍属于该共享密钥对应的 IP 集合。
    • (可选)若某 Service 需指定共享的 IP,可额外添加 Annotation lbipam.cilium.io/ips: [指定 IP],该 IP 会被分配给该 Service 并加入共享组,供其他同共享密钥的 Service 使用(需确保指定 IP 属于匹配的 IP Pool)。
  • 跨命名空间共享 IP 的额外设置

默认情况下,LB IPAM 不允许跨命名空间共享 IP,需在两个共享 IP 的 Service 上均添加以下 Annotationlbipam.cilium.io/sharing-cross-namespace: [允许的命名空间列表],具体格式:

  1. 允许特定命名空间:值为逗号分隔的命名空间名称(如 "tenant-a,tenant-b"),表示当前 Service 仅允许与 tenant-a、tenant-b 命名空间中同共享密钥的 Service 共享 IP。
  2. 允许所有命名空间:值设为 *(如 "*"),表示当前 Service 允许与所有命名空间中同共享密钥的 Service 共享 IP。
  3. 注意:两个跨命名空间共享的 Service 必须同时配置该 Annotation,且允许的命名空间范围需包含对方所在的命名空间(如 Service A 在 ns1,Service B 在 ns2,Service A 的 Annotation 需包含 ns2,Service B 的需包含 ns1,或均设为 *)。

参考:

  1. docs.cilium.io/en/stable/n…