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 此文档依据官方文档和测试环境搭建并撰写如有问题请私信或留言。

相关推荐
A-刘晨阳17 小时前
K8S 之 DaemonSet
运维·云原生·容器·kubernetes·daemonset
切糕师学AI21 小时前
Kubernetes 中的 Volume(存储卷)
云原生·容器·kubernetes
ghostwritten1 天前
worker01 NotReady 排查与修复步骤
云原生·kubernetes
zmjjdank1ng1 天前
创建 NodePort 类型的 Service
运维·kubernetes
努力搬砖的咸鱼2 天前
Kubernetes Service :ClusterIP、NodePort、LoadBalancer
微服务·云原生·容器·架构·kubernetes
only_Klein2 天前
Ansible自动化部署Kubernetes
kubernetes·自动化·ansible
还是转转2 天前
像 K8S 一样部署 EC2:Launch Template + Auto Scaling 实践
云原生·容器·kubernetes
陈陈CHENCHEN2 天前
【Kubernetes】Velero - K8s集群数据保护与容灾方案
kubernetes
zmjjdank1ng2 天前
Ingress理解
linux·运维·kubernetes