【云原生】Gateway API高级功能

Gateway API高级功能

文章目录

一、HTTP查询参数匹配

  • HTTPRoute资源可用于根据查询参数匹配请求。

1.1、根据单个查询参数匹配请求

  • 以下HTTPRoute配置根据查询参数animal的值,将流量分流到两个不同的后端:

  • 先部署一下环境

bash 复制代码
# ==========================================
# 实例 1: nginx-1 资源
# ==========================================

# 1.1 ConfigMap 1
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-1-config
data:
  nginx.conf: |
    user  nginx;
    worker_processes  auto;
    events { worker_connections 1024; }
    http {
        include /etc/nginx/mime.types;
        server {
            listen 80;
            location / {
                return 200 "This is NGINX-1\n";
            }
        }
    }

---

# 1.2 Deployment 1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-1-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-1
  template:
    metadata:
      labels:
        app: nginx-1
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-vol
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: config-vol
        configMap:
          name: nginx-1-config

---

# 1.3 Service 1
apiVersion: v1
kind: Service
metadata:
  name: nginx-1-service
spec:
  type: ClusterIP
  selector:
    app: nginx-1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

---

# ==========================================
# 实例 2: nginx-2 资源
# ==========================================

# 2.1 ConfigMap 2
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-2-config
data:
  nginx.conf: |
    user  nginx;
    worker_processes  auto;
    events { worker_connections 1024; }
    http {
        include /etc/nginx/mime.types;
        server {
            listen 80;
            location / {
                return 200 "This is NGINX-2\n";
            }
        }
    }

---

# 2.2 Deployment 2
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-2-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-2
  template:
    metadata:
      labels:
        app: nginx-2
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-vol
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: config-vol
        configMap:
          name: nginx-2-config

---

# 2.3 Service 2
apiVersion: v1
kind: Service
metadata:
  name: nginx-2-service
spec:
  type: ClusterIP
  selector:
    app: nginx-2
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

      
# apply 一下
[root@master ~]# kubectl apply -f nginx-stack.yaml 
configmap/nginx-1-config created
deployment.apps/nginx-1-deployment created
service/nginx-1-service created
configmap/nginx-2-config created
deployment.apps/nginx-2-deployment created
service/nginx-2-service created
  • 部署HTTPRoute资源
bash 复制代码
[root@master ~]# cat httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: query-param-matching
spec:
  parentRefs:
  - name: example-gateway  # 使用的 Gateway
  rules:  # 规则
  - matches:  # 匹配规则, 如果访问路径当中带有 animal=whale 的查询参数, 流量将会打到 nginx-1-service 的 80 端口
    - queryParams:
      - name: animal
        value: whale
    backendRefs:
    - name: nginx-1-service
      port: 80
  - matches:   # 匹配规则, 如果访问路径当中带有 animal=dolphin 的查询参数, 流量将会打到 nginx-2-service 的 80 端口
    - queryParams:
      - name: animal
        value: dolphin
    backendRefs:
    - name: nginx-2-service
      port: 80
      
# apply 一下
[root@master ~]# kubectl apply -f httproute.yaml 
httproute.gateway.networking.k8s.io/query-param-matching created
  • 访问
bash 复制代码
# 通过 lb 地址进行访问测试
[root@master ~]# kubectl get gateway
NAME              CLASS   ADDRESS         PROGRAMMED   AGE
example-gateway   istio   192.168.93.11   True         24d


[root@master ~]# curl 192.168.93.11/?animal=whale
This is NGINX-1

[root@master ~]# curl 192.168.93.11/?animal=dolphin
This is NGINX-2

1.2、基于多个查询参数匹配请求

bash 复制代码
[root@master ~]# cat httproute.yaml 
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: query-param-matching
spec:
  parentRefs:
  - name: example-gateway
  rules:
  - matches:
    - queryParams:  # 再次访问的时候需要两个查询参数了, 也就是animal=whale&color=blue
      - name: animal
        value: whale
      - name: color
        value: blue
    backendRefs:
    - name: nginx-1-service
      port: 80
  - matches:
    - queryParams:
      - name: animal
        value: dolphin
    backendRefs:
    - name: nginx-2-service
      port: 80
      
[root@master ~]# kubectl apply -f httproute.yaml 
httproute.gateway.networking.k8s.io/query-param-matching configured
bash 复制代码
[root@master ~]# curl "192.168.93.11/?animal=whale&color=blue"
This is NGINX-1

1.3、与其他匹配类型结合使用

  • 查询参数匹配,可以与其他匹配类型(如路径匹配和请求头匹配)结合使用。
bash 复制代码
[root@master ~]# cat httproute.yaml 
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: query-param-matching
spec:
  parentRefs:
  - name: example-gateway
  rules:
  - matches:  # 基于 匹配路径、头部访问、查询参数结合使用
    - path:
        type: PathPrefix
        value: /path1
    - headers:
      - name: version
        value: one
    - queryParams:
      - name: animal
        value: whale
    backendRefs:
    - name: nginx-1-service
      port: 80
  - matches:
    - queryParams:
      - name: animal
        value: dolphin
    backendRefs:
    - name: nginx-2-service
      port: 80
      
# apply 一下
[root@master ~]# kubectl apply -f httproute.yaml 
httproute.gateway.networking.k8s.io/query-param-matching configured
bash 复制代码
# 还需要更改一下nginx-1的cm,是否会造成404
[root@master ~]# kubectl edit cm nginx-1-config
server {
            listen 80;
            # 添加一个对应的路径 location
            location /path1 {
                return 200 "结合使用\n";
            }
            location / {
                return 200 "This is NGINX-1\n";
            }
        }
        
# 重启一下 nginx-1 的 deployment
[root@master ~]# kubectl rollout restart deployment nginx-1-deployment 
deployment.apps/nginx-1-deployment restarted
bash 复制代码
[root@master ~]# curl -H "version: one" http://192.168.93.11/path1?animal=whale
结合使用

二、基于HTTP方法匹配请求

  • 以下HTTPRoute根据请求的HTTP方法(如GET、POST等)将流量分发到两个不同的后端:
bash 复制代码
[root@master ~]# cat httproute.yaml 
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: method-matching
spec:
  parentRefs:
  - name: example-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /mepost
    - method: POST
    backendRefs:
    - name: nginx-1-service
      port: 80
  - matches:
    - method: GET
    backendRefs:
    - name: infra-backend-v2
      port: 8080


# apply 一下
[root@master ~]# kubectl apply -f httproute.yaml 
httproute.gateway.networking.k8s.io/method-matching created
bash 复制代码
# 我们自己写一个 post 协议, 然后用 nginx 代理一下
package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()

	r.POST("/mepost", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "POST method",
		})
	})

	r.Run(":8080")
}

# 我直接在物理机运行了, 所以我等一下代理物理的网络
server {
            listen 80;
            # 代理内容
            location = /mepost {
                proxy_pass http://192.168.93.1:8080;
            }
            location / {
                return 200 "This is NGINX-1\n";
            }
        }
bash 复制代码
[root@master ~]# curl -X POST http://192.168.93.11/mepost
{"message":"POST method"}


# 看一下程序的日志
[GIN] 2026/01/17 - 15:25:00 | 200 |            0s |   10.244.219.64 | POST     "/mepost"

三、TCP路由

  • Gateway API皆在支持多种协议,而TCPRoute正是其中一种允许管理TCP流量的路由资源。
  • 在下面的示例中,我们拥有一个Gateway资源和两个TCPRoute资源,它们按照以下规则分发流量:
    • Gateway端口8080上所有TCP流量都将被转发至mysql-svcKubernettes服务的3306端口。
    • Gateway端口8090上的所有TCP流量都将被转发至redis-svcKubernetes的6379端口。
    • 在此示例中,Gateway将应用两个TCP监听器,以便将流量路由到两个独立的后端TCPRoute。请注意,Gateway监听器上设置的协议为TCP。

3.1、安装TCPRoute CRD资源

  • TCPRoute目前就处于实验版频道,Kubernetes官方不希望在默认安装中包含这些可能会发生的"破坏性变更"的API,所以需要用户根据需求主动安装,
bash 复制代码
# 安装资源
[root@master ~]# kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/experimental-install.yaml


# 开启 istio 的实验性资源支持
[root@master ~]# kubectl patch deployment istiod -n istio-system --type=json -p='[{"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"PILOT_ENABLE_ALPHA_GATEWAY_API","value":"true"}}]'
deployment.apps/istiod patche
bash 复制代码
# 查看 tcproute 资源
[root@master ~]# kubectl api-resources | grep tcp
tcproutes                                        gateway.networking.k8s.io/v1alpha2   true         TCPRoute

3.2、部署MySQL Redis

bash 复制代码
[root@master ~]# cat mysql-redis.yaml 
# ==========================================
# 1. MySQL 最小化部署
# ==========================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: node1
      containers:
      - name: mysql
        image: mysql:5.7 # 5.7 版本启动比 8.0 更轻量
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "root123" # 必须设置初始密码
        ports:
        - containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  type: ClusterIP # 仅集群内访问
  selector:
    app: mysql
  ports:
  - port: 3306
    targetPort: 3306

---

# ==========================================
# 2. Redis 最小化部署
# ==========================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      nodeName: node2
      containers:
      - name: redis
        image: redis:alpine # 使用 alpine 镜像体积最小
        ports:
        - containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  type: ClusterIP # 仅集群内访问
  selector:
    app: redis
  ports:
  - port: 6379
    targetPort: 6379
bash 复制代码
[root@master ~]# kubectl apply -f mysql-redis.yaml
deployment.apps/mysql-deploy created
service/mysql-service created
deployment.apps/redis-deploy created
service/redis-service created

3.3、部署Gateway

bash 复制代码
[root@master ~]# cat gateway.yaml 
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-tcp-gateway
spec:
  gatewayClassName: istio
  listeners:
  - name: foo
    protocol: TCP
    port: 8080
    allowedRoutes:
      kinds:
      - kind: TCPRoute
  - name: bar
    protocol: TCP
    port: 8090
    allowedRoutes:
      kinds:
      - kind: TCPRoute
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: tcp-mysql
spec:
  parentRefs:
  - name: my-tcp-gateway
    sectionName: foo  # 使用 my-tcp-gateway 的 foo 监听器
  rules:
  - backendRefs:
    - name: mysql-service
      port: 3306
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: tcp-redis
spec:
  parentRefs:
  - name: my-tcp-gateway
    sectionName: bar  # 使用 my-tcp-gateway 的 bar 监听器
  rules:
  - backendRefs:
    - name: redis-service
      port: 6379
bash 复制代码
[root@master ~]# kubectl apply -f gateway.yaml
gateway.gateway.networking.k8s.io/my-tcp-gateway created
tcproute.gateway.networking.k8s.io/tcp-mysql created
tcproute.gateway.networking.k8s.io/tcp-redis created
bash 复制代码
[root@master ~]# kubectl get gateway
NAME              CLASS   ADDRESS         PROGRAMMED   AGE
my-tcp-gateway    istio   192.168.93.12   True         18s

3.4、测试

bash 复制代码
# 安装 mysql redis 命令行工具
[root@master ~]# yum -y install mysql redis


[root@master ~]# mysql -h 192.168.93.12 -u root -proot123 -P 8080
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 


[root@master ~]# redis-cli -h 192.168.93.12 -p 8090
192.168.93.12:8090> ping
PONG
相关推荐
Harvey90317 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
陈桴浮海18 小时前
Kustomize实战:从0到1实现K8s多环境配置管理与资源部署
云原生·容器·kubernetes
梦想很大很大20 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
ShiLiu_mtx21 小时前
k8s - 7
云原生·容器·kubernetes
lekami_兰1 天前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
Java后端的Ai之路1 天前
【Spring全家桶】-一文弄懂Spring Cloud Gateway
java·后端·spring cloud·gateway
匀泪1 天前
云原生(LVS NAT模式集群实验)
服务器·云原生·lvs
却尘1 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤1 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁