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。它提供了更强大、更灵活的流量管理能力,支持更复杂的路由场景和多团队协作。
- 官网:https://gateway-api.sigs.k8s.io/
- Envoy Gateway 控制器官网:https://gateway.envoyproxy.io/
- MetalLB 官网:https://metallb.io
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 在
foonamespace 引用barnamespace 的 Service) ,为了安全和权限约束,必须由 目标 namespace 中的管理员显式授权这个跨 namespace 的引用关系------这就是 ReferenceGrant 的作用。
ReferenceGrant 是一种安全防护机制,用来避免恶意或无意间跨 namespace 使用资源而没有被 Namespace 资源所有者允许的情况。
八、总结
作为 Kubernetes 官方力推的新一代服务网络解决方案,Gateway API 以其层次化设计 、强大的路由能力 和原生的多团队支持,为我们打开了 Kubernetes 网络管理的新篇章。与传统的 Ingress API 相比,它不仅解决了原有方案的局限性,更通过标准化的扩展机制和类型安全的 API 定义,为我们提供了一套更加灵活、可靠的服务网络管理工具。
通过本文的学习,您已经掌握了:
- Gateway API 的核心概念和优势
- 与传统 Ingress 的详细对比
- 完整的安装配置流程(包括 MetalLB 配置)
- 基本的 HTTP 路由创建方法
- 跨命名空间路由和服务引用的实现技巧
写在最后:
我在生产环境中并未使用过 Gateway API 此文档依据官方文档和测试环境搭建并撰写如有问题请私信或留言。