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 的负载均衡模式,可选 dedicatedshared
  • ingress.cilium.io/service-type:指定专用 Ingress 的服务类型,可选 LoadBalancerNodePort
  • ingress.cilium.io/tls-passthrough:为此 Ingress 启用 TLS 透传模式,可选 enableddisabled

主机网络模式

从 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 流的源地址。

最后更新于 2024/09/16