Kubernetes: 08-gateway-api

安装

博文参考:Gateway-API-Setup

ingress to gateway 转换工具

方案1:Ingress(2026.3 不维护)

方案2:gateway 之 NGINX Gateway Fabric

安装 gatewayapi crd

# 安装标准版 gateway api CRD
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/standard-install.yaml

# 范例
root@ip-172-31-18-198:/docker/nginx/data/site.d# kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/standard-install.yaml
customresourcedefinition.apiextensions.k8s.io/backendtlspolicies.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/listenersets.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/tcproutes.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/tlsroutes.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/udproutes.gateway.networking.k8s.io serverside-applied
validatingadmissionpolicy.admissionregistration.k8s.io/safe-upgrades.gateway.networking.k8s.io serverside-applied
validatingadmissionpolicybinding.admissionregistration.k8s.io/safe-upgrades.gateway.networking.k8s.io serverside-applied

root@ip-172-31-18-198:~# kubectl  get crd |grep gateway.networking.k8s.io
backendtlspolicies.gateway.networking.k8s.io    2026-08-26T09:10:31Z
gatewayclasses.gateway.networking.k8s.io        2026-08-26T09:10:31Z
gateways.gateway.networking.k8s.io              2026-08-26T09:10:31Z
grpcroutes.gateway.networking.k8s.io            2026-08-26T09:10:31Z
httproutes.gateway.networking.k8s.io            2026-08-26T09:10:31Z
listenersets.gateway.networking.k8s.io          2026-08-26T09:10:32Z
referencegrants.gateway.networking.k8s.io       2026-08-26T09:10:32Z
tcproutes.gateway.networking.k8s.io             2026-08-26T09:10:32Z
tlsroutes.gateway.networking.k8s.io             2026-08-26T09:10:33Z
udproutes.gateway.networking.k8s.io             2026-08-26T09:10:33Z

安装 nginx gateway crd

# 安装 NGINX Gateway Fabric CRDs
# https://github.com/nginx/nginx-gateway-fabric/tree/v2.6.7/deploy
kubectl apply --server-side -f https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/refs/tags/v2.6.7/deploy/crds.yaml
# 普通 kubectl apply 是客户端 apply:本地保存一份注解 kubectl.kubernetes.io/last-applied-configuration,用来对比变更。
# --server‑side 是把合并逻辑交给 **k8s APIServer 服务端处理**,不在客户端存大段 last‑applied 注解。

# 范例
root@ip-172-31-18-198:~# kubectl apply --server-side -f https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/refs/tags/v2.6.7/deploy/crds.yaml
customresourcedefinition.apiextensions.k8s.io/authenticationfilters.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/clientsettingspolicies.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/nginxgateways.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/nginxproxies.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/observabilitypolicies.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/proxysettingspolicies.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/ratelimitpolicies.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/snippetsfilters.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/snippetspolicies.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/upstreamsettingspolicies.gateway.nginx.org serverside-applied
customresourcedefinition.apiextensions.k8s.io/wafpolicies.gateway.nginx.org serverside-applied

root@ip-172-31-18-198:~# kubectl  get crd |grep nginx
authenticationfilters.gateway.nginx.org         2026-08-26T09:37:50Z
clientsettingspolicies.gateway.nginx.org        2026-08-26T09:37:50Z
nginxgateways.gateway.nginx.org                 2026-08-26T09:37:50Z
nginxproxies.gateway.nginx.org                  2026-08-26T09:37:50Z
observabilitypolicies.gateway.nginx.org         2026-08-26T09:37:50Z # 可观测规则
proxysettingspolicies.gateway.nginx.org         2026-08-26T09:37:51Z # 代理设置规则
ratelimitpolicies.gateway.nginx.org             2026-08-26T09:37:51Z # 限速规则
snippetsfilters.gateway.nginx.org               2026-08-26T09:37:51Z
snippetspolicies.gateway.nginx.org              2026-08-26T09:37:51Z
upstreamsettingspolicies.gateway.nginx.org      2026-08-26T09:37:51Z
wafpolicies.gateway.nginx.org                   2026-08-26T09:37:51Z # 应用防火墙规则

安装 nginx-gateway-fabric

# 
mkdir ngfdir
cd ngfdir/

# 下载 2.6.7 版本文件。拉取 OCI 格式 Helm chart,解压到本地
helm pull oci://ghcr.io/nginx/charts/nginx-gateway-fabric --version 2.6.7 --untar
cd nginx-gateway-fabric/

helm install ngf . \
  --create-namespace -n nginx-gateway \
  --set nginx.service.type=LoadBalancer \
  --set nginx.service.externalTrafficPolicy=Cluster \
  --set nginxGateway.snippetsFilters.enable=true

#  --set nginx.service.type=LoadBalancer 使用负载均衡器。会自动分配公网 LB
#  --set nginx.service.externalTrafficPolicy=Cluster 外部流量转发策略。
#    Cluster(这里配置的):源 IP 会被 SNAT 改写为节点 IP;可以做负载均衡跨节点转发。
#    Local:保留真实客户端源 IP,但流量只能落到后端 Pod 所在节点。
#  --set nginxGateway.snippetsFilters.enable=true  NGF 的扩展能力,可以在 Gateway API 资源中嵌入原生 Nginx 配置片段(nginx.conf 片段)。

root@ip-172-31-18-198:~/.jasper/ngfdir/nginx-gateway-fabric# kubectl  get ns |grep gateway
nginx-gateway       Active   16m

root@ip-172-31-18-198:~/.jasper/ngfdir/nginx-gateway-fabric# kubectl  get pods -n nginx-gateway
NAME                                        READY   STATUS    RESTARTS   AGE
ngf-nginx-gateway-fabric-746f6d68fc-hspmf   1/1     Running   0          85s

root@ip-172-31-18-198:~/.jasper/ngfdir/nginx-gateway-fabric# kubectl  get svc -n nginx-gateway
NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
ngf-nginx-gateway-fabric   ClusterIP   10.210.167.53   <none>        443/TCP   2m7s

# 卸载
# helm uninstall ngf -n nginx-gateway
# kubectl delete ns nginx-gateway --ignore-not-found

AWS 公网 NLB

root@ip-172-31-18-198:~/.jasper/ngfdir/nginx-gateway-fabric# cat values-dev.yaml
nginx:
  config:
    # 信任 TCP Proxy‑Protocol v2 四层 NLb
    rewriteClientIP:
      mode: ProxyProtocol
      # AWS VPC CIDR,信任NLB的来源网段
      trustedAddresses:
        - type: CIDR
          value: "172.31.0.0/16"
  service:
    type: LoadBalancer
    externalTrafficPolicy: Cluster
    patches:
    - type: StrategicMerge
      value:
        metadata:
          annotations:
            # 创建公网 nlb
            service.beta.kubernetes.io/aws-load-balancer-type: "external"
            service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
            service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
            service.beta.kubernetes.io/aws-load-balancer-subnets: "subnet-0a415b6c73,subnet-0efd7596"
            service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: "Env=Dev"
            # 让 AWS NLB 向外发 Proxy‑Protocol v2
            service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"

nginxGateway:
  snippetsFilters:
    enable: true
    
    
# balancer-subnets 为公有子网,pod所在实例安全组允许该网段

helm install ngf . \
  --create-namespace -n nginx-gateway \
  -f ./values-dev.yaml \
  --wait --timeout 5m

# 安装完成后校验 NginxProxy CR 是否渲染正确 patches:
kubectl get nginxproxy ngf-proxy-config -n nginx-gateway -o yaml

Gatewayclass

  • 部署完后得到名为 nginx 的 gatewayclass
# 控制器 nginx
root@ip-172-31-18-198:~/.jasper/ngfdir/nginx-gateway-fabric# kubectl  get gatewayclasses -n nginx-gateway
NAME    CONTROLLER                                   ACCEPTED   AGE
nginx   gateway.nginx.org/nginx-gateway-controller   True       2m55s

# nginxproxy 相当说configmap
root@ip-172-31-18-198:~/.jasper/ngfdir/nginx-gateway-fabric# kubectl  get nginxproxy -n nginx-gateway
NAME               AGE
ngf-proxy-config   4m33s

root@ip-172-31-18-198:~/.jasper/ngfdir/nginx-gateway-fabric# kubectl  get nginxproxies -n nginx-gateway  -oyaml
apiVersion: v1
items:
- apiVersion: gateway.nginx.org/v1alpha2
  kind: NginxProxy
  metadata:
    labels:
      app.kubernetes.io/instance: ngf
      app.kubernetes.io/managed-by: Helm
      app.kubernetes.io/name: nginx-gateway-fabric
      app.kubernetes.io/version: 2.6.7
      helm.sh/chart: nginx-gateway-fabric-2.6.7
    name: ngf-proxy-config
    namespace: nginx-gateway
  spec:
    ipFamily: dual
    kubernetes:
      deployment:
        container:
          image:
            pullPolicy: IfNotPresent
            repository: ghcr.io/nginx/nginx-gateway-fabric/nginx
            tag: 2.6.7
        replicas: 1
      service:
        externalTrafficPolicy: Cluster
        type: LoadBalancer
kind: List
metadata:
  resourceVersion: ""

创建 gateway

实际上 gateway 是 pod + service 的组合。

cat <<\EOF>> 01-gateway-test.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: nginx-gateway-test
  namespace: default
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All # 允许所有namespace的HTTPRoute绑定这个Gateway。默认为允许当前名称空间的规则
EOF

kubectl apply -f 01-gateway-test.yaml

# gateway 的地址就是 service 的地址
root@ip-172-31-18-198:~/.jasper/ngfdir# kubectl  get gateway
NAME                 CLASS   ADDRESS                                                                             PROGRAMMED   AGE
nginx-gateway-test   nginx   k8s-d-1.amazonaws.com   True         25m

root@ip-172-31-18-198:~/.jasper/ngfdir# kubectl  get svc
nginx-gateway-test-nginx       LoadBalancer   10.210.170.159   k8s-d-1.amazonaws.com   80:31363/TCP

安装多个 gateway 内外网

gateway class 只能有一个。上文 gateway 是公网的,下面添加内网 gateway

先创建 nginxporxy,再创建 gateway

# 创建 nginxporxy
cat <<\EOF>> nginxproxy-internal-config.yaml 
apiVersion: gateway.nginx.org/v1alpha2
kind: NginxProxy
metadata:
  annotations:
    meta.helm.sh/release-name: ngf
    meta.helm.sh/release-namespace: nginx-gateway
  labels:
    app.kubernetes.io/instance: ngf
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx-gateway-fabric
    app.kubernetes.io/version: 2.6.7
    helm.sh/chart: nginx-gateway-fabric-2.6.7
  name: nginxproxy-internal-config
  namespace: default
spec:
  ipFamily: dual
  kubernetes:
    deployment:
      container:
        image:
          pullPolicy: IfNotPresent
          repository: ghcr.io/nginx/nginx-gateway-fabric/nginx
          tag: 2.6.7
      replicas: 1
    service:
      externalTrafficPolicy: Cluster
      patches:
      - type: StrategicMerge
        value:
          metadata:
            annotations:
              service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: Env=Dev
              service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
              service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
              service.beta.kubernetes.io/aws-load-balancer-scheme: internal
              service.beta.kubernetes.io/aws-load-balancer-subnets: subnet-01c,subnet-0b,subnet-03
              service.beta.kubernetes.io/aws-load-balancer-type: external
              service.beta.kubernetes.io/aws-load-balancer-attributes: load_balancing.cross_zone.enabled=true
      type: LoadBalancer
  rewriteClientIP:
    mode: ProxyProtocol
    trustedAddresses:
    - type: CIDR
      value: 172.31.0.0/16
EOF

# 创建内网 gateway
cat <<\EOF>> ng-internal-gateway.yaml 
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway-internal
  namespace: default
spec:
  gatewayClassName: nginx
  infrastructure:
    parametersRef:
      group: gateway.nginx.org
      kind: NginxProxy
      name: nginxproxy-internal-config
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All
EOF

部署应用

# 部署 echo ,打印请求信息
cat > 02-deploy-test.yaml <<\EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echo
        image: ealen/echo-server:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: echo-svc
  namespace: default
spec:
  selector:
    app: echo
  ports:
  - port: 80
    targetPort: 80
    name: http
  type: ClusterIP
EOF

kubectl  apply -f 02-deploy-test.yaml

使用 httproute 访问

# 创建 gateway 规则
cat <<\EOF>> 03-httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: ngfapp-httproute
  namespace: default
spec:
  parentRefs:
  - name: nginx-gateway-test
    namespace: default
  hostnames:
  - "www.echo.com"
  rules:
  - backendRefs:
    - name: echo-svc
      port: 80
      kind: Service
    matches:
    - path:
        type: PathPrefix
        value: /
EOF

root@ip-172-31-18-198:~/.jasper/ngfdir# kubectl  apply -f 03-httproute.yaml


root@ip-172-31-18-198:~/.jasper/ngfdir# kubectl  get httproute
NAME         HOSTNAMES          AGE
echo-route   ["www.echo.com"]   11m


# 排查。查看 gateway 对应的 pod 日志。
kubectl logs -f nginx-gateway-test-nginx-79d64d4cc4-kcp5q

# 查看 nginx 配置文件
root@ip-172-31-18-198:~/.jasper/ngfdir# kubectl  exec -it nginx-gateway-test-nginx-79d64d4cc4-kcp5q -c nginx -- nginx -T
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
load_module modules/ngx_http_js_module.so;
include /etc/nginx/main-includes/*.conf;

worker_processes auto;

pid /var/run/nginx/nginx.pid;

访问

  • 本机域名解析。修改 /etc/hosts
  • 浏览器访问 http://www.echo.com
# 真实客户端 ip
    "headers": {
      "host": "www.echo.com",
      "x-forwarded-for": "1.1.162.204",
      "x-real-ip": "1.1.162.204",


# 或在 pod echo 所在主机使用 tcpdump 命令查看
tcpdump -i any -nn -vvv -A dst host 172.31.82.72 and port 80  |grep -C50 echo

配置

Rewrite 路径重写

ingress-nginx

# 都重写为 $2 路径
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
  name: gateway-ingress
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - host: devg.xxx.me
    http:
      paths:
      - backend:
          service:
            name: cloud-gateway
            port:
              number: 8080
        path: /(api)/(.*)
        pathType: ImplementationSpecific
      - backend:
          service:
            name: wallet-admin-server
            port:
              number: 8080
        path: /(api)/alpha/v1/(system/exchangeRateFacede/.*)
        pathType: ImplementationSpecific

转为对应 gatewai api

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: gateway-httproute
  namespace: default
spec:
  hostnames:
  - devg.xxx.me
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: nginx-gateway-test
    namespace: default
  rules:
  - backendRefs:
    - group: ""
      kind: Service
      name: cloud-gateway
      port: 8080
      weight: 1
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          replacePrefixMatch: /
          type: ReplacePrefixMatch
    matches:
    - path:
        type: PathPrefix
        value: /api/
  - backendRefs:
    - group: ""
      kind: Service
      name: wallet-admin-server
      port: 8080
      weight: 1
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          replacePrefixMatch: /system/exchangeRateFacede/
          type: ReplacePrefixMatch
    matches:
    - path:
        type: PathPrefix
        value: /api/alpha/v1/system/exchangeRateFacede/

上传限制

cat h5-web-antd-httproute.yaml 
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: h5-web-antd-httproute
  namespace: default
spec:
  hostnames:
  - xxx.com
  - devpt.xxx.com
  parentRefs:
  - name: nginx-gateway-test
    namespace: default
  rules:
  - backendRefs:
    - name: h5-web-antd-svc
      port: 80
    matches:
    - path:
        type: PathPrefix
        value: /
---
apiVersion: gateway.nginx.org/v1alpha1
kind: ClientSettingsPolicy
metadata:
  name: h5-web-antd-client-policy
  namespace: default
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: h5-web-antd-httproute
  body:
    maxSize: "100m"


kubectl  get clientsettingspolicies.gateway.nginx.org h5-web-antd-client-policy

# 查看 nginx 对应配置
kubectl  exec  nginx-gateway-test-nginx-5f5dcf8454-9tdlp -c nginx -- nginx -T 
server {
    listen 80 proxy_protocol;
    listen [::]:80 proxy_protocol;

    server_name devpt.xxx.com;
    set_real_ip_from 172.31.0.0/16;
    real_ip_header proxy_protocol;

        
    location / {
        

        
        include /etc/nginx/includes/ClientSettingsPolicy_default_h5-web-antd-client-policy.conf;

        
# configuration file /etc/nginx/includes/ClientSettingsPolicy_default_h5-web-antd-client-policy.conf:

client_max_body_size 100m;