Cilium 通过标准的 Kubernetes Ingress
资源定义提供服务,使用时将 ingressClassName
设置为 cilium
。这支持基于路径的路由和 TLS 终结。为了向后兼容,也支持 kubernetes.io/ingress.class
注解,值为 cilium
。
注意:Ingress 控制器会创建一个类型为 LoadBalancer 的服务,所以你的环境需要支持此类服务。
Cilium 允许你为 Ingress 资源指定负载均衡模式:
dedicated
:Ingress 控制器将为每个 Ingress 创建一个专用的负载均衡器。shared
:Ingress 控制器将使用一个共享的负载均衡器服务于所有 Ingress 资源。
每种负载均衡模式都有其优缺点。共享模式通过在集群中所有 Ingress 资源间共享单一的 LoadBalancer 配置节省资源,而专用模式可以帮助避免资源之间的潜在冲突(例如路径前缀)。
准备条件
- 安装 Cilium 时需要启用 NodePort,通过设置
nodePort.enabled=true
或启用kubeProxyReplacement=true
。 - Cilium 必须配置启用了 L7 代理,使用
l7Proxy=true
(默认启用)。 - 默认情况下,Ingress 控制器创建的是 LoadBalancer 类型的服务,你的环境需要支持此功能。或者,从 Cilium 1.16 开始,你可以直接在主机网络上暴露 Cilium L7 代理。
Ingress 路径类型和优先级
Ingress 规范支持三种类型的路径:
- Exact(精确):完全匹配给定的路径。
- Prefix(前缀):匹配 URL 路径的前缀,最后一个路径段必须完整匹配。
- ImplementationSpecific(实现特定):路径的解释取决于 IngressClass。在 Cilium 的案例中,我们定义实现特定为“Regex(正则表达式)”,因此 Cilium 会将任何给定路径视为正则表达式并相应地配置 Envoy。
支持的 Ingress 注解
ingress.cilium.io/loadbalancer-mode
:设置 Ingress 的负载均衡模式,可选dedicated
或shared
。ingress.cilium.io/service-type
:指定专用 Ingress 的服务类型,可选LoadBalancer
或NodePort
。ingress.cilium.io/tls-passthrough
:为此 Ingress 启用 TLS 透传模式,可选enabled
或disabled
。
主机网络模式
从 Cilium 1.16+ 开始支持。主机网络模式允许你直接在主机网络上暴露 Cilium Ingress 控制器(Envoy 监听器)。这在没有 LoadBalancer 服务的开发环境或其他环境中非常有用。
可以通过 Helm 启用主机网络模式,并通过注解为每个 Ingress
资源指定主机网络端口。
此外,云服务商特定的注解也受到支持,例如 cloud.google.com
等。
Cilium Ingress 和 Gateway API 与其他 Ingress 控制器的不同
Cilium 的 Ingress 和 Gateway API 与其他 Ingress 控制器最大的不同在于,它与 CNI 的结合更为紧密。对于 Cilium 来说,Ingress 和 Gateway API 是网络栈的一部分,因此与其他 Ingress 或 Gateway API 控制器(即使是在 Cilium 集群中运行的)的行为方式不同。
其他 Ingress 或 Gateway API 控制器通常作为 Deployment 或 Daemonset 在集群中安装,并通过 Loadbalancer 服务或类似方式暴露。Cilium 的 Ingress 和 Gateway API 配置可以通过 Loadbalancer 或 NodePort 服务暴露,或者可选地在主机网络上暴露。在所有这些情况下,当流量到达服务端口时,eBPF 代码会拦截流量并透明地转发到 Envoy(使用 TPROXY 内核功能)。
这影响了客户端 IP 可见性的工作方式,与其他 Ingress 控制器的支持不同。此外,Cilium 的网络策略引擎可以将 CiliumNetworkPolicy
应用于绑定到 Ingress 的流量和来自 Ingress 的流量。
Cilium 的 Ingress 配置和 CiliumNetworkPolicy
通过 Cilium 绑定到后端服务的 Ingress 和 Gateway API 流量会通过每个节点的 Envoy 代理。这个节点 Envoy 代理有特殊的代码,使其能够与 eBPF 策略引擎交互,并对流量进行策略查找。这使 Envoy 成为网络策略的执行点,不仅适用于 Ingress(和 Gateway API)流量,还适用于通过 GAMMA 或 L7 流量管理的东西流量。
对于 Ingress 配置,还有一个额外的步骤。到达 Envoy 的 Ingress 或 Gateway API 流量会在 Cilium 的策略引擎中被赋予特殊的ingress
身份。来自集群外部的流量通常被赋予 world
身份(除非集群中有 IP CIDR 策略)。这意味着在 Cilium Ingress 中实际上有两个逻辑策略执行点——在流量到达 ingress
身份之前和之后,即将离开每个节点的 Envoy 时。
源 IP 可见性
默认情况下,Cilium 的 Ingress 配置(无论是 Ingress 还是 Gateway API)应该在大多数安装中正常工作。Cilium 的 Envoy 实例默认配置为将来自 HTTP 连接的可见源地址附加到 X-Forwarded-For
头部,使用通常的规则。默认情况下,Cilium 将信任跳数设置为0
,表示 Envoy 应该使用连接打开的地址,而不是 X-Forwarded-For
列表中的值。
Loadbalancer 或 NodePort 服务的 externalTrafficPolicy
Cilium 的 Ingress 支持(无论是 Ingress 还是 Gateway API)经常使用 Loadbalancer 或 NodePort 服务来暴露 Envoy Daemonset。在这些情况下,服务对象中有一个与客户端 IP 可见性特别相关的字段——externalTrafficPolicy
字段。
这有两个相关的设置:
Local
:节点只会将流量路由到本地节点上运行的 Pod,并且不会隐藏源 IP。因此,在使用kube-proxy
的集群中,这是确保源 IP 可见性的唯一方式。Cluster
:节点将流量均匀地路由到集群中的所有端点。这意味着在许多情况下,使用Cluster
可能导致后端 pod 看不到源 IP。
TLS 透传和源 IP 可见性
Ingress 和 Gateway API 都支持 TLS 透传配置(通过 Ingress 的注解和 Gateway API 的 TLSRoute 资源)。这种配置允许多个 TLS 透传后端共享同一个负载均衡器上的 TLS 端口,Envoy 会检查 TLS 握手的服务器名称指示(SNI)字段,并使用该字段将 TLS 流转发到后端。
然而,这对源 IP 可见性构成了问题,因为 Envoy 正在对 TLS 流进行 TCP 代理。当进行 TLS 透传时,后端将看到 Envoy 的 IP 地址作为转发 TLS 流的源地址。