在Kubernetes的网络体系中,Ingress扮演着”海关大门”的角色——负责检查每个进入集群的HTTP请求,根据Host头部(域名)来决定把请求转发到哪个内部服务。这与K8s原生Service有着本质区别:Service只能在网络模型的第四层(L4)做到IP到IP的转发,而Ingress Controller则是第七层(L7)的反向代理,能够根据HTTP的内容(如Host头部中的域名)进行智能路由。
本文将从一个简化的Ingress Controller实现出发,深入剖析七层流量治理的核心机制。
南北向流量指的是从集群外部流向内部的流量。Ingress通常部署在集群的最边缘,是一个真实的Pod(运行Nginx、Traefik或Envoy)。其工作流程如下:
这种模式下,Ingress就像一个巨大的”单点”守门人,所有外部请求都必须经过它的检查和分发。
东西向流量指集群内部服务之间的相互访问,例如服务A访问服务B。对于这类流量,有两种处理方式:
低效方案:服务A将消息发送给边缘的Ingress,再由Ingress转发给服务B。这种方法效率极低,因为流量需要绕行到集群边缘再返回。
高效方案:通过kube-proxy编写的iptables规则,服务A直接将流量转发给服务B。但这种方式是L4协议的IP:端口转发,无法理解HTTP Header的内容,因此无法实现基于HTTP内容的智能路由。
这就引出了一个关键问题:如何在L7层面实现集群内部的智能流量治理?答案就是Service Mesh。
Service Mesh的核心思想是将Ingress的能力缩小、打包到每一个业务Pod中,形成Sidecar(边车)模式。此时它已经不再是传统意义上的Ingress,而是嵌入到每个服务旁边的代理。
工作流程:
在没有Service Mesh的时代,业务代码必须自行处理大量复杂的网络逻辑:
1. 重试与超时
服务A调用服务B失败时,A需要自己实现超时和重试逻辑,这增加了业务代码的复杂度。
2. 熔断与限流
当服务C宕机,服务B仍在等待C的响应,导致B的资源耗尽;紧接着等待B的服务A也会宕机,引发连锁反应的”雪崩效应”。传统解法是引入各种复杂的中间件来处理这些熔断规则。
3. 链路追踪
在服务调用链A→B→C中,如果某个环节出现问题,需要在每个服务中手动打印日志、传递Trace ID,排查问题极其困难。
4. 灰度发布
原生K8s Ingress只能根据域名进行流量分发,无法实现更细粒度的流量控制,如根据请求头、请求参数等进行灰度发布。
Service Mesh将上述所有网络处理能力统一抽象为以下四个核心功能,实现了业务处理与网络处理的完全解耦:
1. L7层路由能力
可以根据HTTP Header的内容进行智能路由,不再局限于域名级别的分发。
2. 统一的流量管理
重试、超时、熔断、限流等功能全部由Service Mesh接管,业务代码只需发送请求,无需担心网络抖动等问题。
3. 零侵入的可观测性
Sidecar自动为流量打上Trace-ID,开发者可以在控制台直观地看到流量拓扑图和调用链路。
4. 安全控制
即使在内网环境中也能实现加密传输,同时支持认证和授权机制。
让我们从一个简化的Ingress Controller实现来理解其核心工作机制。
Ingress Controller本质上是一个七层反向代理,其核心数据结构包含:
1 | proxy := &httputil.ReverseProxy{ |
这段代码揭示了Ingress Controller的三个关键步骤:
第一步:拆包检查
读取HTTP请求的Host头部,这是L7代理区别于L4转发的核心特征。L4转发只关心目标IP和端口,而L7代理会深入解析HTTP协议的内容。
第二步:路由决策
根据Host头部的值进行条件判断,决定将请求转发到哪个后端服务。在实际生产中,这一过程会更加复杂,可能涉及:
第三步:请求重写
修改原始请求的目标URL,将其指向正确的后端服务地址,然后由ReverseProxy自动完成后续的转发工作。
Ingress Controller启动后,会监听一个统一的对外端口(通常是80或443):
1 | err := http.ListenAndServe(":8080", proxy) |
这个端口就是整个集群的”大门”,所有外部流量都会汇聚到这里,然后被分发到不同的内部服务。
为了演示Ingress的路由功能,我们可以启动多个模拟的后端服务:
1 | go startDummyBackend("Service A", ":8081", "到达Service A") |
这些后端服务是”傻瓜式”的应用,只懂处理业务逻辑,不理解路由规则。它们隐藏在内网端口,外部用户无法直接访问,必须通过Ingress进行中转。
K8s原生Service工作在OSI模型的第四层(传输层),其特点是:
Ingress Controller工作在第七层(应用层),其优势在于:
L7代理虽然功能强大,但也带来了额外的性能开销:
因此在实际架构中,通常会采用L4 + L7的组合方案:
在实际的Ingress配置中,PathType决定了路径匹配的优先级:
Exact(精确匹配)
要求请求路径与配置完全一致,例如配置/api/login只会匹配/api/login,不会匹配/api/login/extra。
Prefix(前缀匹配)
只要请求路径以配置路径为前缀即可匹配,例如配置/api可以匹配/api/login、/api/users/profile等。
ImplementationSpecific(实现特定)
具体的匹配行为取决于Ingress Controller的实现,通常用于兼容旧版本或特殊场景。
匹配优先级的实现逻辑遵循”最长匹配原则”:
现代Ingress Controller支持通过Annotation来定制行为,常见的注解包括:
限流配置
1 | annotations: |
SSL/TLS配置
1 | annotations: |
Canary灰度发布
1 | annotations: |
这些注解使得Ingress Controller能够在不修改代码的情况下,通过YAML配置灵活调整行为。
Ingress Controller还承担着SSL/TLS终止的重要职责:
工作原理
证书管理方式
生产环境的Ingress Controller必须具备健康检查能力:
被动健康检查
当向后端服务转发请求失败时,记录错误次数,超过阈值后暂时将该后端标记为不可用。
主动健康检查
定期向后端服务发送探测请求(如GET /healthz),根据响应状态判断是否继续接收流量。
主动摘除机制
一旦检测到某后端实例异常,立即将其从可用列表中移除,避免将后续请求继续发送到故障节点。
Ingress作为Kubernetes七层流量治理的核心组件,承担了以下关键职责:
而从Ingress到Service Mesh的演进,则体现了云原生架构的核心理念:将复杂的网络治理能力从业务代码中剥离,统一交由基础设施层处理,让开发者专注于业务逻辑本身。
这种分层设计不仅降低了业务开发的复杂度,更重要的是提供了标准化、可复用的网络治理能力,使得微服务架构下的流量管理变得更加可控和可靠。