K8s Gateway API 全面指南:从入门到实践

K8s Gateway API 全面指南:从入门到实践

🎉 欢迎关注我的公众号「键盘下的小宇宙」 🎉

在这里,我会持续分享 Kubernetes、云原生、DevOps 等领域的技术干货,从入门实践到深度解析,帮助你在技术道路上少走弯路。

您的每一次关注、点赞和分享,都是我坚持创作的最大动力

🔍 微信搜索「键盘下的小宇宙」 ,让我们一起探索技术的无限可能~

引言

随着 Kubernetes 集群规模的不断扩大和应用复杂度的提升,传统的 Ingress API 已逐渐难以满足现代服务网络管理的需求。作为 Kubernetes 官方推出的新一代服务网络 API,Gateway API 以其强大的路由能力、灵活的多团队支持和标准化的扩展机制,成为了构建现代化 Kubernetes 网络的理想选择。

本文将从 Gateway API 的基本概念出发,详细对比其与 Ingress 的差异,带你一步步完成安装配置,并通过实际示例掌握其核心使用方法,帮助你快速上手这一 Kubernetes 网络新利器。

一、什么是 Gateway API?

1.1 概述

Gateway API 是 Kubernetes 官方推出的新一代服务网络 API,旨在替代和扩展传统的 Ingress API。它提供了更强大、更灵活的流量管理能力,支持更复杂的路由场景和多团队协作。

1.2 核心特性

  • 层次化设计:通过 GatewayClass、Gateway、Route 等资源实现分层管理

  • 更丰富的路由能力:支持基于路径、方法、头部的精细化路由

  • 多团队支持:内置的所有权和权限模型

  • 类型安全:强类型的 API 定义

  • 扩展性:更好的插件和自定义能力

二、Gateway API 与 Ingress 的对比

特性 Ingress Gateway API
API 版本 v1 v1 (稳定版)
路由能力 基础的路径和主机路由 支持路径、方法、头部、查询参数等多种路由规则
多团队支持 有限,需要额外配置 内置的 RBAC 集成和所有权模型
扩展性 依赖注解,不标准 标准的扩展机制
流量类型 主要支持 HTTP/HTTPS 支持 HTTP/HTTPS、TCP、UDP 等多种协议
策略管理 分散在各个资源中 集中的策略定义和复用
实现状态 广泛实现 主流 ingress 控制器已支持

Envoy Gateway 依赖于 Envoy Proxy 和 Gateway API,并在 Kubernetes 集群中运行。并非所有版本的 Envoy Proxy 和 Gateway API 都能兼容运行。支持的版本组合如下所示;粗体字表示每个 Envoy Gateway 版本实际编译的 Envoy Proxy 和 Gateway API 版本。

三、安装 Gateway API

3.1 前提条件

  • Kubernetes 集群(推荐 1.24+)

  • kubectl 命令行工具

  • 支持 Gateway API 的 Ingress 控制器(如 Contour、Istio、NGINX Kubernetes Ingress Controller 等)

  • Gateway API 的控制器默认不创建对外 server,它只负责路由逻辑,真正的对外暴露仍需通过 LoadBalancer/NodePort/MetalLB 等手段配合实现。(意思就是需要云服务器或者有负载均衡的地址)

  • 因为测试环境没有 LB 地址,还需要安装 MetalLB

  • MetalLB 官网https://metallb.io

3.2 可直接在裸机上部署的控制器

Cilium Gateway

Cilium 网络栈集成后,它会用 LoadBalancer 或 NodePort 类型的 Service 来暴露数据平面(Envoy or embedded listener)。

  • 支持主机网络模式(host network),可让 Gateway 监听在所有节点的 0.0.0.0,从而在裸金属上直接暴露端口,无需 LoadBalancer/MetalLB
Istio Gateway API 实现

Istio IngressGateway 或 Gateway API 模式下,会自动创建 Envoy Deployment 和对应 Service。这样,配置好 Gateway 之后,它会自动生成一组对外可访问的入口资源(Service / Deployment)并更新状态。

Contour(Envoy-based)
  • 在裸金属和本地环境中,Contour 的 Service 通常也能通过 LoadBalancer/NodePort 方式配置对外访问。

本教程以 Envoy Gateway 为例进行演示,并且 Gateway API 允许同时安装多个控制器

3.3 安装 Gateway API CRDs

执行以下命令安装最新稳定版 Gateway API CRDs:

bash 复制代码
# 安装最新稳定版 Gateway API CRDs
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml

# 验证安装。下面这两个命令任选其一验证即可。
kubectl get crd | grep networking.k8s.io
# 或更具体地验证关键 CRD
kubectl get crd gateways.gateway.networking.k8s.io httproutes.gateway.networking.k8s.io gatewayclasses.gateway.networking.k8s.io

安装成功后,你将看到类似以下输出:

bash 复制代码
backendtlspolicies.gateway.networking.k8s.io   2026-02-06T09:10:49Z
gatewayclasses.gateway.networking.k8s.io       2026-02-06T09:10:49Z
gateways.gateway.networking.k8s.io             2026-02-06T09:10:49Z
grpcroutes.gateway.networking.k8s.io           2026-02-06T09:10:49Z
httproutes.gateway.networking.k8s.io           2026-02-06T09:11:04Z
referencegrants.gateway.networking.k8s.io      2026-02-06T09:11:05Z

3.3 安装 Envoy Gateway 控制器

使用 Helm 安装 Envoy Gateway 控制器:

bash 复制代码
# 官方安装方法很多,根据自己喜好即可。这里使用 Helm 安装
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.7.0 -n envoy-gateway-system --create-namespace

# 等待 Envoy Gateway 可用:
kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available

安装完成后,Envoy Gateway 控制器将在 envoy-gateway-system 命名空间中运行,随时准备处理 Gateway API 资源。

3.4 安装 MetalLB

首先,修改 kube-proxy 配置以启用 strictARP:

对于二进制安装的 Kubernetes:

bash 复制代码
# 编辑 kube-proxy 配置文件
cat /etc/kubernetes/kube-proxy.yaml
# 添加以下内容
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true

# 修改好以后重启服务
systemctl restart kube-proxy.service

对于 kubeadm 安装的 Kubernetes:

bash 复制代码
# 编辑 kube-proxy 配置
kubectl edit cm kube-proxy -n kube-system
# 添加和修改上面的内容

# 修改好以后重启服务
kubectl patch daemonset kube-proxy -n kube-system -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"$(date +'%s')\"}}}}}"

3.5 安装 MetalLB 服务

执行以下命令安装 MetalLB:

bash 复制代码
# 安装 MetalLB
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.3/config/manifests/metallb-native.yaml

提示:如果这个配置文件下载不了,可以私信我获取。

3.6 配置 MetalLB IP 池 & 广播

创建 metallb-config.yaml 文件并应用:

yaml 复制代码
# metallb-config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: public-ip-pool
  namespace: metallb-system
spec:
  addresses:           # 这个是地址池,可以配置多个地址,官网有详细的配置方法
    - 192.168.1.100/32 # 这个地址必须是未使用的地址,不能使用高可用的 IP 地址

---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: public-ip-advertisement
  namespace: metallb-system
spec:
  ipAddressPools:
  - public-ip-pool

应用配置:

bash 复制代码
kubectl apply -f metallb-config.yaml

四、使用 Gateway API

4.1 基本概念

  • GatewayClass:定义网关类型,类似于 StorageClass

  • Gateway:实际的网关实例,管理网络流量入口

  • HTTPRoute:定义 HTTP/HTTPS 流量的路由规则

  • TCPRoute/UDPRoute:定义 TCP/UDP 流量的路由规则

4.2 示例:创建基本的 HTTP 路由

4.2.1 创建 GatewayClass

GatewayClass 是 Gateway 的类别模板,指明使用哪种控制器来管理对应的 Gateway。它是集群级资源(Cluster-scoped),没有命名空间的概念。

yaml 复制代码
# 创建 GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg  # GatewayClass 名称
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller  # 指定使用 Envoy Gateway 控制器

应用配置:

bash 复制代码
kubectl apply -f gatewayclass.yaml
4.2.2 创建 Gateway

Gateway 定义实际的监听器(端口/协议/路由绑定行为等,类似 Ingress 开放的默认端口 80 或者 443)。它是命名空间级(Namespaced)资源,在不同的命名空间可以有同名的资源。

默认情况下,Gateway 只接受同一命名空间的 Routes,但可以通过 allowedRoutes 设置跨 Namespace 规则。

yaml 复制代码
# 创建 Gateway(在 demo01 命名空间中)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
  namespace: demo01
spec:
  gatewayClassName: eg  # 引用之前创建的 GatewayClass
  addresses:
    - type: IPAddress
      value: 192.168.1.100  # 修改为刚刚配置的 MetalLB 地址池中的地址
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: All  # 允许所有命名空间的 Routes 绑定到这个 Gateway

应用配置:

bash 复制代码
# 首先创建 demo01 命名空间
kubectl create namespace demo01

# 应用 Gateway 配置
kubectl apply -f gateway.yaml
4.2.3 创建应用

创建一个简单的后端应用,包括 Service、ServiceAccount 和 Deployment:

yaml 复制代码
# app.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: demo01
  labels:
    app: backend
    service: backend
spec:
  ports:
    - name: http
      port: 3000
      targetPort: 3000
  selector:
    app: backend
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend
  namespace: demo01
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: demo01
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
      version: v1
  template:
    metadata:
      labels:
        app: backend
        version: v1
    spec:
      serviceAccountName: backend
      containers:
        - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
          imagePullPolicy: IfNotPresent
          name: backend
          ports:
            - containerPort: 3000
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace

应用配置:

bash 复制代码
kubectl apply -f app.yaml
4.2.4 创建 HTTPRoute

HTTPRoute 指定如何将来自 Gateway 的请求路由到特定后端服务。它是命名空间级(Namespaced)资源,按 namespace 进行隔离,但可以通过 parentRefs 引用某个 Gateway(可以是同命名空间也可以跨命名空间)。

yaml 复制代码
# httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
  namespace: demo01
spec:
  parentRefs:
    - name: eg  # 引用之前创建的 Gateway
      namespace: demo01
  hostnames:
    - "gateway.demo.cn"  # 配置域名
  rules:
    - backendRefs:
        - group: ""
          kind: Service
          name: backend  # 引用后端服务
          port: 3000
          weight: 1
      matches:
        - path:
            type: PathPrefix
            value: /  # 匹配所有路径

应用配置:

bash 复制代码
kubectl apply -f httproute.yaml

配置完成后,你可以通过添加 host 记录(将 gateway.demo.cn 指向 192.168.1.100)来访问这个服务。

4.3 示例:配置 HTTPS 访问

4.3.1 准备证书或自签证书

要启用 HTTPS 访问,你需要:

  • 创建 Kubernetes Secret 存放证书和私钥
  • 在 Gateway 的 listener 上启用 HTTPS/TLS 并引用这个 Secret
4.3.2 创建 Kubernetes Secret

将证书和私钥封装进 Secret:

bash 复制代码
kubectl create secret tls example-cert \
  --cert=example.com.crt \
  --key=example.com.key \
  -n envoy-gateway-system

👉 命名空间应与你部署 Gateway 的 namespace 一致(通常是 Envoy Gateway 安装命名空间)或者是 listener 所在的 namespace。

4.3.3 配置 Gateway 加入 HTTPS listener

下面是一个常见的 HTTPS listener 示例:

yaml 复制代码
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  namespace: envoy-gateway-system
spec:
  gatewayClassName: envoy-gateway
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: example-cert
    allowedRoutes:
      namespaces:
        from: All

五、在不同命名空间配置方法

举例:Gateway 在 demo01 命名空间,HTTPRoute 和服务可以在其他命名空间

首先,修改 Gateway 配置以允许所有 Namespace 的 HTTPRoute 绑定:

yaml 复制代码
# shared-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: shared-gateway
  namespace: demo01
spec:
  gatewayClassName: eg
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All    # 允许所有 Namespace HTTPRoute 绑定

应用配置:

bash 复制代码
kubectl apply -f shared-gateway.yaml
应用

修改命名空间为demo02

yaml 复制代码
## 只粘贴了部分代码
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: demo02
  labels:
    app: backend
    service: backend
spec:
  ports:
    - name: http
      port: 3000
      targetPort: 3000
  selector:
    app: backend
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend
  namespace: demo02
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: demo02
spec:
  replicas: 1
  selector:
    matchLabels:
创建 HTTPRoute

例如:应用和 httproute 都在demo02 中的想要使用 demo01的gateway 配置如下

yaml 复制代码
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: demo02     ## 应用和HTTPRoute所在命名空间
spec:
  parentRefs:
  - name: shared-gateway
    namespace: demo01   ## gateway所咋的命名空间
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: app-svc
      port: 80
  • 在生产环境里,不一定要每个命名空间都部署一个 Gateway 通常由基础设施团队部署一两个"共享的 Gateway",各业务命名空间通过 HTTPRoute(有或没有跨命名空间权限)来挂载到这些 Gateway 上。
  • 跨命名空间访问要通过 allowedRoutes.namespaces 明确允许,并可能配合 ReferenceGrant 控制另一种跨命名空间引用(比如 backend Service)。

六、ReferenceGrant(跨命名空间引用 Service/Secret)

如果你的 HTTPRoute 想引用的是 另一个命名空间的 Service 或证书 Secret

(比如 demo01 想路由到 demo02 的 Service),这需要 ReferenceGrant 来显式授权:

意思就是 服务A要访问服务B,就在B服务的命名空间创建 ReferenceGrant 授权。

yaml 复制代码
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-frontend-to-backend
  namespace: demo02
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: demo01
  to:
  - group: ""
    kind: Service
  • 注意:ReferenceGrant 是用于 跨 namespace 引用资源(如 Service/Secret) ,和 allowedRoutes 不同------allowedRoutes 是允许路由附加到 Gateway。

七、HTTPRoute(来自 frontend Namespace)

下面是 frontend 的 HTTPRoute,它引用 backend 的 Service:

yaml 复制代码
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: frontend-route
  namespace: demo01
spec:
  parentRefs:
  - name: shared-gateway
    namespace: demo01     # 明确引用不同 Namespace 的 Gateway
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: backend-svc
      namespace: demo02           # 引用 backend Namespace 的 Service
      port: 80

主要点:

  • 共享 Gateway + 各命名空间 HTTPRoute 是推荐模式
  • 跨命名空间路由 由 Gateway 的 allowedRoutes.namespaces 控制
  • 跨命名空间服务引用 (Service/Secret)由 ReferenceGrant 授权控制(需要提前授权)
  • 只有当 HTTPRoute 或其它路由资源引用了 不同命名空间 的 Kubernetes 对象(比如 Service / Secret)时,才需要创建 ReferenceGrant。**
  • 如果路由引用的是 当前 HTTPRoute 所在 namespace 内的资源 (同 namespace),则 不需要 ReferenceGrant。这是 Gateway API 的标准行为。
场景 是否需要 ReferenceGrant
HTTPRoute → 同 namespace 的 Service / Secret ❌ 不需要
HTTPRoute → 不同 namespace 的 Service / Secret ✅ ReferenceGrant 必须存在
Gateway → 不同 namespace 的 Secret / 参数引用 ✅ ReferenceGrant 必须存在
Route 附加到不同 namespace 的 Gateway ⚠️ 需 allowedRoutes 显式允许

为什么会有这个规则?

在 Kubernetes Gateway API 里:

  • 同名空间引用本地资源时(比如 HTTPRoute → Service 在同一个 namespace),引用默认是允许的,不需要额外授权。
  • 跨命名空间引用时(比如 HTTPRoute 在 foo namespace 引用 bar namespace 的 Service) ,为了安全和权限约束,必须由 目标 namespace 中的管理员显式授权这个跨 namespace 的引用关系------这就是 ReferenceGrant 的作用。
    ReferenceGrant 是一种安全防护机制,用来避免恶意或无意间跨 namespace 使用资源而没有被 Namespace 资源所有者允许的情况。

八、总结

作为 Kubernetes 官方力推的新一代服务网络解决方案,Gateway API 以其层次化设计强大的路由能力原生的多团队支持,为我们打开了 Kubernetes 网络管理的新篇章。与传统的 Ingress API 相比,它不仅解决了原有方案的局限性,更通过标准化的扩展机制和类型安全的 API 定义,为我们提供了一套更加灵活、可靠的服务网络管理工具。

通过本文的学习,您已经掌握了:

  • Gateway API 的核心概念和优势
  • 与传统 Ingress 的详细对比
  • 完整的安装配置流程(包括 MetalLB 配置)
  • 基本的 HTTP 路由创建方法
  • 跨命名空间路由和服务引用的实现技巧

写在最后

我在生产环境中并未使用过 Gateway API 此文档依据官方文档和测试环境搭建并撰写如有问题请私信或留言。

相关推荐
niyesd19 分钟前
Kubernetes Pod 控制器管理与实验记录
云原生·容器·kubernetes
Raas1001 小时前
AI网关是做什么的?MAI Gateway (魔芋企业级AI网关)给出企业级答案
网络·人工智能·gateway·企业级·ai网关·mai gateway·魔芋
池以遇1 小时前
云原生——k8s的pod管理及优化
云原生·容器·kubernetes
NGINX开源社区1 小时前
使用 F5 NGINX Gateway Fabric 实现 AI 交付标准化
nginx·gateway·fabric
智码看视界10 小时前
Day59-阿里云ACK实战:生产级K8s集群部署与运维
运维·阿里云·kubernetes·k8s·日志监控·容器运维·阿里云ack
lxw202302711614 小时前
k8s的控制器
云原生·容器·kubernetes
大大大大晴天15 小时前
大数据K8S基础:从 Pod 到 Service,看懂数据负载如何在云原生上运行
大数据·kubernetes
FoldWinCard16 小时前
K8s -- 控制器管理
云原生·容器·kubernetes
无望__wsk17 小时前
k8s的pod管理
云原生·容器·kubernetes
悠然南风17 小时前
【云原生学习】Prometheus监控、GitLab与Jenkins部署实战
kubernetes·gitlab