ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

从Ingress Nginx迁移到Gateway API:云原生流量管理实践指南

从Ingress Nginx迁移到Gateway API:云原生流量管理实践指南 1. 从 Ingress Nginx 到 Gateway API一次云原生路由的范式转移最近社区里关于 Ingress Nginx 即将停止功能更新、进入维护模式的消息传得沸沸扬扬很多刚把 K8s 玩明白的朋友又开始焦虑了。其实这并非一个突发事件而是云原生技术栈持续演进的一个必然信号。简单来说Ingress Nginx 作为 Kubernetes 早期解决南北向流量管理的“功臣”其设计已经逐渐难以满足现代应用对流量治理更精细、更标准化、更跨平台的需求。而 Gateway API正是 Kubernetes 官方钦定的下一代流量管理标准旨在解决 Ingress 的诸多历史遗留问题。如果你正在或计划在生产环境使用 Kubernetes那么理解并开始尝试 Gateway API 就不是一个“要不要”的问题而是一个“什么时候”和“怎么用”的问题。它不仅仅是一个替代品更代表了一种全新的、以角色为中心、声明式、可扩展的流量管理范式。这篇文章我将以一个实践者的角度带你从零开始利用 Gateway API 构建一套可用的云原生路由方案并分享从 Ingress 迁移过来时那些官方文档不会告诉你的细节和坑。2. Gateway API 核心概念为什么说它是“下一代”在动手之前我们必须先搞清楚 Gateway API 到底带来了什么根本性的改变。如果只是把它当作一个功能更强的 Ingress那就大错特错了。2.1 角色分离开发者与运维的清晰边界这是 Gateway API 最革命性的设计。在传统的 Ingress 模型里一个Ingress资源通常包含了从路由规则到后端服务选择的所有信息。这导致应用开发者和集群运维人员的职责边界非常模糊。开发者需要关心host、path这些路由逻辑有时甚至被迫了解nginx.ingress.kubernetes.io这类特定实现的注解而运维则需要审批这些可能影响全局负载均衡器配置的变更。Gateway API 通过引入三种核心资源清晰地划分了角色GatewayClass 定义一类网关的实现如 Istio, Contour, Envoy Gateway 等。这通常由平台或基础设施团队定义和管理为整个集群提供可用的网关类型。Gateway 一个网关的实例化。它声明了“在哪个监听器端口/协议上提供服务”。这个资源通常由运维或网络团队创建他们负责网关实例的部署、扩缩容和网络策略。HTTPRoute/TCPRoute 等 具体的路由规则。它定义了“如何将到达 Gateway 的流量分发到后端的 Service”。这个资源完全由应用开发者创建和管理他们只需关心自己的业务路由逻辑无需感知底层网关的实现细节。这种分离使得 DevOps 协作流程更加顺畅和安全。开发者可以自主发布路由规则而不会触及运维的网关基础设施。2.2 跨实现标准化告别供应商锁定Ingress 规范过于简单导致各个厂商Nginx, Istio, Traefik, HAProxy都通过大量的自定义注解Annotation来扩展功能。这造成了严重的碎片化和供应商锁定。你的IngressYAML 里一旦写满了nginx.ingress.kubernetes.io的注解基本上就和 Ingress Nginx 绑死了迁移成本极高。Gateway API 的设计目标之一就是提供一套功能丰富、实现中立的通用规范。它定义了HTTPRoute、GRPCRoute、TCPRoute等标准资源以及头部操作、流量切分、重试、超时等丰富的跨层功能。虽然目前不同实现的支持程度仍有差异但长期来看使用标准字段编写的路由配置其可移植性将远高于充满特定注解的 Ingress 配置。2.3 面向服务网络更丰富的路由能力Ingress 本质上是一个简单的 HTTP(S) 反向代理规则。而 Gateway API 从设计之初就考虑了服务网格的用例支持更复杂的路由场景流量切分与金丝雀发布 原生支持基于权重的流量分发到不同的后端无需借助复杂的注解或 CRD。请求/响应头操作 增、删、改请求和响应头都有标准字段支持。精细化的后端选择 可以基于不同端口、子集通过 Service 的标签选择器进行路由为服务网格和灰度发布提供了更好的支持。TCP/UDP 路由 通过TCPRoute和UDPRoute原生支持四层负载均衡这是 Ingress 规范本身不具备的。3. 环境准备与网关实现选型理论讲完了我们开始动手。首先需要一个 Kubernetes 集群。你可以使用任何你熟悉的工具比如 minikube, kind, k3d或者云托管的 K8s 服务。这里我以kind创建一个本地集群为例因为它轻量且适合测试网络特性。# 创建一个名为 gateway-api 的集群 kind create cluster --name gateway-api接下来是最关键的一步选择 Gateway API 的实现。Gateway API 本身只是一套 CRD自定义资源定义和规范需要具体的控制器Controller来实现。目前主流的选择有Envoy Gateway CNCF 沙箱项目旨在成为 Gateway API 的官方参考实现。它设计简洁专注于 Gateway API是学习和未来生产使用的重点候选。Istio 通过其istio.io/gatewayAPI与 Gateway API 融合提供支持。如果你已经在使用 Istio 服务网格这是最自然的演进路径。Contour 由 VMware 主导对 Gateway API 的支持非常积极和成熟。Kong Ingress Controller和Traefik 也都提供了对 Gateway API 的测试版或稳定版支持。对于初次接触和学习我强烈推荐Envoy Gateway。它架构干净没有服务网格的复杂包袱能让你最纯粹地体验 Gateway API 的能力。我们接下来的演示也将基于 Envoy Gateway。安装 Gateway API 的 CRD 和 Envoy Gateway# 1. 安装 Gateway API CRDs (v1.0 版本这是一个稳定版本) kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml # 2. 安装 Envoy Gateway kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.0.0/install.yaml安装完成后检查相关 Pod 是否运行正常kubectl get pods -n envoy-gateway-system你应该能看到envoy-gateway和envoy-gateway-*的 Pod 处于Running状态。注意 不同版本的 Gateway API CRD 和 Envoy Gateway 可能存在兼容性问题。建议严格按照官方发布页的推荐组合进行安装避免使用latest标签。生产环境部署前务必在测试环境进行完整的版本验证。4. 实战部署应用并配置 Gateway API 路由假设我们有一个简单的 Web 应用我们通过 Deployment 和 Service 将其部署到集群中。# demo-app.yaml apiVersion: v1 kind: Service metadata: name: demo-app spec: selector: app: demo-app ports: - protocol: TCP port: 80 targetPort: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: name: demo-app spec: replicas: 2 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: app image: hashicorp/http-echo args: - -textHello from Gateway API! ports: - containerPort: 8080应用kubectl apply -f demo-app.yaml。现在核心部分来了配置 Gateway API。4.1 创建 GatewayClass 和 Gateway首先我们需要一个GatewayClass。在安装 Envoy Gateway 时它通常已经为我们创建好了一个默认的GatewayClass名为eg。你可以通过kubectl get gatewayclass查看。接下来创建Gateway资源。它定义了网关实例的监听器。这里我们创建一个监听 80 端口的 HTTP 网关。# gateway.yaml apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: demo-gateway spec: gatewayClassName: eg # 对应 Envoy Gateway 提供的 GatewayClass listeners: - name: http protocol: HTTP port: 80 allowedRoutes: namespaces: from: Same # 允许同命名空间的路由关联也可设置为 All 或 Selector应用这个配置kubectl apply -f gateway.yaml。此时Envoy Gateway 控制器会监听到这个Gateway资源并在集群内部署一个实际的 Envoy Proxy 负载均衡器 Pod 和一个对应的 Service。查看一下kubectl get gateway kubectl get pods -n envoy-gateway-system # 应该会看到新的 envoy-* pod kubectl get svc -n envoy-gateway-system # 会看到一个 LoadBalancer 或 NodePort 类型的 Service在本地 kind 环境中这个 Service 通常是NodePort类型。记下envoy-gateway这个 Service 的节点端口例如80:3xxxx/TCP。4.2 创建 HTTPRoute定义业务路由规则现在应用开发者可以在自己的命名空间这里我们用 default创建HTTPRoute将流量路由到后端的demo-appService。# http-route.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: demo-route spec: parentRefs: - name: demo-gateway # 关联到上面创建的 Gateway sectionName: http # 关联到 Gateway 中名为 http 的监听器 hostnames: - demo.example.com # 匹配的域名本地测试可以用 * rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: demo-app port: 80应用配置kubectl apply -f http-route.yaml。4.3 验证路由生效现在整个链路就配置完成了。我们来验证一下。首先获取访问入口。在云环境中Gateway对应的 Service 会自动获得一个外部 IP。在本地 kind 中我们需要使用NodePort。假设envoy-gatewayService 的 NodePort 是30080我们可以通过curl访问# 直接访问节点端口并通过 Host 头指定域名 curl -H Host: demo.example.com http://localhost:30080/你应该能看到返回Hello from Gateway API!。实操心得 在本地开发测试时经常需要指定Host头这有点麻烦。一个技巧是修改你本地机器的/etc/hosts文件将127.0.0.1 demo.example.com映射上去然后就可以直接用curl http://demo.example.com:30080访问了。另外HTTPRoute中的hostnames字段非常灵活支持精确匹配和通配符这在多租户环境下为不同团队分配子域名非常有用。5. 进阶功能体验流量切分与头部操作让我们看看 Gateway API 如何优雅地处理一些复杂场景。假设我们正在为demo-app进行金丝雀发布新版本demo-app-v2已经部署。# 部署 v2 版本 apiVersion: apps/v1 kind: Deployment metadata: name: demo-app-v2 spec: replicas: 1 selector: matchLabels: app: demo-app-v2 template: metadata: labels: app: demo-app-v2 spec: containers: - name: app image: hashicorp/http-echo args: - -textThis is the NEW v2 version! ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: demo-app-v2 spec: selector: app: demo-app-v2 ports: - protocol: TCP port: 80 targetPort: 8080现在我们修改HTTPRoute将 90% 的流量导向 v110% 导向 v2。# http-route-canary.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: demo-route spec: parentRefs: - name: demo-gateway sectionName: http hostnames: - demo.example.com rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: demo-app # v1 服务 port: 80 weight: 90 - name: demo-app-v2 # v2 服务 port: 80 weight: 10应用此配置后多次访问curl -H Host: demo.example.com http://localhost:30080/你会看到大约 10% 的请求返回了新版本的信息。整个过程完全通过声明式的标准 API 完成无需了解底层 Envoy 的任何配置。再比如我们想在到达 v2 版本的请求上添加一个特殊的请求头X-Canary: true并在响应中注入一个服务器头。# 在 rules 中为匹配 v2 的规则添加过滤器 apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: demo-route spec: parentRefs: - name: demo-gateway sectionName: http hostnames: - demo.example.com rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: demo-app port: 80 weight: 90 - name: demo-app-v2 port: 80 weight: 10 filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: X-Canary value: true - type: ResponseHeaderModifier responseHeaderModifier: set: - name: Server value: Awesome-Gateway这些filters配置直观且强大覆盖了常见的流量治理需求。6. 从 Ingress Nginx 迁移关键差异与避坑指南如果你有一个现有的 Ingress Nginx 配置计划迁移到 Gateway API以下是一些需要重点关注的差异点和实践建议。6.1 注解的转换Ingress Nginx 的大量功能依赖注解。迁移时你需要找到对应的 Gateway API 标准字段或实现提供的扩展字段。Ingress Nginx 常见注解Gateway API 对应方式说明nginx.ingress.kubernetes.io/rewrite-targetHTTPRoute规则中的filters-URLRewriteGateway API 的 URL 重写更灵活可以分别设置路径和主机名。nginx.ingress.kubernetes.io/ssl-redirectHTTPRoute关联到 HTTPS 监听器或使用Redirect过滤器建议在Gateway监听器直接配置 HTTPS或配置 HTTP 到 HTTPS 的重定向路由。nginx.ingress.kubernetes.io/proxy-buffering实现特定的策略或BackendPolicy(Alpha)这类与实现强相关的性能调优参数需要查阅 Envoy Gateway 或你选用实现的文档。nginx.ingress.kubernetes.io/configuration-snippet无直接对应这是最棘手的部分。configuration-snippet允许注入任意 Nginx 指令迁移时必须找到能实现相同功能的 Gateway API 标准字段或实现扩展否则可能需要等待实现支持。6.2 路径匹配的语义差异这是一个容易踩坑的地方。Ingress Nginx 的路径匹配默认是前缀匹配并且是大小写敏感的。Gateway API 的PathPrefix类型在行为上基本与之一致。但是Gateway API 明确要求路径必须以/开头并且对规范化路径如去除..和.有更严格的定义。在迁移时务必测试所有边界路径确保匹配行为符合预期。6.3 TLS/HTTPS 配置在 Ingress 中TLS 证书配置在Ingress资源的tls字段。在 Gateway API 中证书管理被设计得更加模块化和安全。Gateway监听器配置 在Gateway资源的listener中你可以直接指定protocol: HTTPS和tls配置。引用 Secret 最直接的方式是在Gateway中引用存有 TLS 证书的 Kubernetes Secret。但这要求运维人员将证书 Secret 部署在Gateway所在的命名空间或者使用通配符证书。使用ReferenceGrant 这是 Gateway API 引入的一个用于跨命名空间资源引用的安全机制。如果HTTPRoute和证书 Secret 不在同一个命名空间你需要在证书所在的命名空间创建一个ReferenceGrant资源显式授权Gateway所在的命名空间可以引用该 Secret。这增加了安全性但也增加了配置步骤。# 在证书所在的命名空间如 certs-ns创建 ReferenceGrant apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: allow-gateway-to-secret namespace: certs-ns spec: from: - group: gateway.networking.k8s.io kind: Gateway namespace: gateway-ns # Gateway 所在的命名空间 to: - group: kind: Secret6.4 健康检查与就绪状态Ingress Nginx 会主动对后端 Endpoints 进行健康检查。在 Gateway API 模型中健康检查的责任更多地下放给了实现。以 Envoy Gateway 为例它底层使用 Envoy Proxy其健康检查行为由 Envoy 的集群健康检查配置决定。虽然 Gateway API 有BackendPolicy提案来标准化后端健康检查策略但目前v1.0仍处于 Alpha 阶段。在生产迁移中你需要确认你选用的实现如 Envoy Gateway的默认健康检查行为是否满足需求以及如何通过其扩展机制进行配置。7. 生产级考量与未来展望将 Gateway API 用于生产环境除了基本功能还需要考虑更多。监控与可观测性 Gateway API 资源本身的状态如Gateway和HTTPRoute的status字段提供了配置是否被成功接纳和应用的信息。但要监控实际的流量指标QPS、延迟、错误率你需要依赖底层实现提供的监控接口。对于 Envoy Gateway这意味着需要集成 Envoy 的统计指标通常通过 Prometheus 来收集。多集群与联邦 Gateway API 的设计考虑到了跨集群的场景。Gateway可以代表一个跨多个集群的负载均衡器入口而HTTPRoute可以引用位于不同集群的后端服务。这为多集群、混合云的统一流量管理提供了标准化的可能性虽然相关功能仍在不断成熟中。策略与扩展 Gateway API 通过PolicyAttachment机制如BackendPolicy,TimeoutPolicy等部分仍在开发来附加扩展策略。这允许平台管理员定义全局或命名空间级别的策略如超时、重试、速率限制并自动应用到相关的路由上实现了策略与路由规则的解耦是大型平台管理的利器。关于 Ingress Nginx 的未来 准确来说Ingress Nginx 项目并未“死亡”而是进入了维护模式。这意味着它将继续修复关键的安全漏洞和严重的错误但不会再增加新功能。对于现有稳定运行的系统无需恐慌性迁移。但对于新项目或者有计划对流量治理进行现代化改造的项目从现在开始评估和采用 Gateway API 无疑是更具前瞻性的选择。从我个人的实践来看Gateway API 的学习曲线初期确实比 Ingress 要陡峭一些因为它引入了更多抽象和概念。但一旦理解其设计哲学你会发现它带来的清晰度、标准化和扩展能力能够极大地简化复杂环境下的流量管理。开始动手吧从一个简单的测试集群开始创建你的第一个Gateway和HTTPRoute亲身体验这种范式转移带来的不同。
返回列表