Kubernetes: 08-gateway-api
- TAGS: Kubernetes
安装
博文参考:Gateway-API-Setup
- 安装 Gateway API CRD
- Gateway API 的下游实现
- 安装 nginx gateway crd
- 安装 nginx-gateway-fabric
- Gatewayclass
- 创建 gateway
- 部署应用
- 使用 httproute 访问
ingress to gateway 转换工具
方案1:Ingress(2026.3 不维护)
- 创建ingress-controller,创建ingress-entrance: https://kubernetes.github.io/ingress-nginx/
方案2:gateway 之 NGINX Gateway Fabric
安装 gatewayapi crd
- 安装 Gateway API 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.snippets.enable=true NGF 的扩展能力,可以在 Gateway API 资源中嵌入原生 Nginx 配置片段(nginx.conf 片段)。同时启用 SnippetsFilter 和 SnippetsPolicy。 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: "*"
#spec: # 2.7.0 不需要
# loadBalancerClass: service.k8s.aws/nlb
# 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
修改 LBC 兼容 NGF,这样可以自动更新 service nlb 端口
#确认来 lbc webhook 内容 kubectl get mutatingwebhookconfiguration aws-load-balancer-webhook \ -o jsonpath='{range .webhooks[*]}{@.name}{"\t"}{@.objectSelector}{"\n"}{end}' | nl -v0 # 输出如下 0 mservice.elbv2.k8s.aws {"matchExpressions":[{"key":"app.kubernetes.io/name","operator":"NotIn","values":["aws-load-balancer-controller"]}]} 1 mpod.elbv2.k8s.aws {"matchExpressions":[{"key":"app.kubernetes.io/name","operator":"NotIn","values":["aws-load-balancer-controller"]}]} 2 mtargetgroupbinding.elbv2.k8s.aws {} kubectl get mutatingwebhookconfiguration aws-load-balancer-webhook \ -o jsonpath='{range .webhooks[?(@.name=="mservice.elbv2.k8s.aws")]}{.objectSelector}{"\n"}{end}' # 合并,新增 NGF cat >lbc-webhook-objectselector.yaml <<\EOF webhooks: - name: mservice.elbv2.k8s.aws objectSelector: matchExpressions: - key: app.kubernetes.io/name # 原有:不 mutate LBC 自己 operator: NotIn values: - aws-load-balancer-controller - key: gateway.networking.k8s.io/gateway-name # 新增:不 mutate NGF 数据面 operator: DoesNotExist EOF kubectl patch mutatingwebhookconfiguration aws-load-balancer-webhook \ --type=strategic --patch-file=lbc-webhook-objectselector.yaml \ --dry-run=server \ -o jsonpath='{range .webhooks[*]}{@.name}{"\n sel="}{@.objectSelector}{"\n ns="}{@.namespaceSelector}{"\n ops="}{@.rules[*].operations}{"\n"}{end}' # 生效 kubectl patch mutatingwebhookconfiguration aws-load-balancer-webhook \ --type=strategic --patch-file=lbc-webhook-objectselector.yaml \ -o jsonpath='{range .webhooks[*]}{@.name}{"\n sel="}{@.objectSelector}{"\n ns="}{@.namespaceSelector}{"\n ops="}{@.rules[*].operations}{"\n"}{end}'
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 kubectl -n default get svc nginx-gateway-test-nginx \ -o jsonpath='class=[{.spec.loadBalancerClass}] ports={.spec.ports[*].port}{"\n"}'
新建 gateway 并加证书
# 生成证书 curl https://get.acme.sh | sh -s email[email protected] export CF_Token="cfut_xxxx" export CF_Email="[email protected]" acme.sh --set-default-ca --server letsencrypt acme.sh --issue --dns dns_cf -d jasper.org -d *.jasper.org --dnssleep 120 # 给 gateway 加证书 kubectl -n default create secret tls jasper-tls --cert=jasper.org.cer --key=jasper.org.key cat > gateway-public.yaml <<\EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-public namespace: default spec: gatewayClassName: nginx listeners: - allowedRoutes: namespaces: from: All name: http port: 80 protocol: HTTP - name: https port: 443 protocol: HTTPS hostname: "*.xxx.com" tls: mode: Terminate certificateRefs: - kind: Secret name: xxx-tls allowedRoutes: namespaces: from: All EOF kubectl apply -f gateway-public.yaml
安装多个 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 resources: requests: cpu: 500m memory: 256Mi limits: memory: 1Gi # 不要设 cpu limit,高流量下会被 throttle,症状很像限流 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: - "echo.jasper.org" 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
配置
时区与日志格式化
#nginx-gateway-fabric 2.6.7 cat >values-ngf.yaml <<\EOF nginxGateway: snippets: enable: true nginx: service: type: LoadBalancer externalTrafficPolicy: Cluster patches: - type: JSONPatch value: - op: add path: /spec/template/spec/volumes/- value: name: tz-shanghai hostPath: path: /usr/share/zoneinfo/Asia/Shanghai type: File - op: add path: /spec/template/spec/containers/0/volumeMounts/- value: name: tz-shanghai mountPath: /etc/localtime readOnly: true config: logging: accessLog: escape: json format: >- {"time":"$time_iso8601","remote_addr":"$remote_addr","x_forwarded_for":"$http_x_forwarded_for","host":"$host","method":"$request_method","uri":"$request_uri","protocol":"$server_protocol","status":$status,"body_bytes_sent":$body_bytes_sent,"request_length":$request_length,"request_time":$request_time,"upstream_addr":"$upstream_addr","upstream_status":"$upstream_status","upstream_response_time":"$upstream_response_time","referer":"$http_referer","user_agent":"$http_user_agent","request_id":"$request_id"} EOF # 升级: helm upgrade --install ngf . \ --create-namespace -n nginx-gateway \ -f values-ngf.yaml \ --wait --timeout 5m
配置说明
# 配置说明 #nginxGateway.snippets.enable 同时启用 SnippetsFilter 和 SnippetsPolicy。 #nginxGateway.snippetsFilters.enable 已被 chart 标记为 deprecated,且只开前者 #nginx.service.type=LoadBalancer 使用负载均衡器 #nginx.service.externalTrafficPolicy=Cluster 外部流量转发策略 # Cluster(这里配置的):源 IP 会被 SNAT 改写为节点 IP;可以做负载均衡跨节点转发。 # Local:保留真实客户端源 IP,但流量只能落到后端 Pod 所在节点。 # ---- 时区:东八区 ---- # 数据面镜像是 Alpine,既没有 /etc/localtime 也没有 tzdata, # 所以 $time_iso8601 / $time_local / error log 的时间全是 UTC # (日志里是 +00:00,比北京时间晚 8 小时)。 # # 只设 TZ=Asia/Shanghai 是没用的:musl 会去找 # /usr/share/zoneinfo/Asia/Shanghai,镜像里没有这个文件,就静默回退 UTC。 # 必须把宿主机的时区文件挂进来。这里刻意不设 TZ 环境变量—— # musl 在 TZ 未设时直接读 /etc/localtime,正好是我们挂进去的那个。 # # 用 hostPath 挂宿主机的 /usr/share/zoneinfo/Asia/Shanghai 这个实际文件 # # NginxProxy CRD 的 container 字段只有 debug/hostPorts/image,给不了 # env 和 volumeMounts,所以只能走 patches。 # chart 会把 nginx.patches 渲染进 NginxProxy 的 kubernetes.deployment.patches。 # 必须用 JSONPatch,不能用 StrategicMerge(默认类型)。 # StrategicMerge 在 NGF provisioner 这条路径上会**按索引覆盖**而不是按 name 合并: # 只含一个元素的 volumes 会盖掉 volumes[0](原本是 projected 类型的 token), # API Server 报 "may not specify more than 1 volume type", # 同时 volumeMounts 的引用全部错位,Deployment 更新直接被拒。 # JSONPatch 的 "/-" 是追加到列表末尾,不碰任何现有元素。 # # containers/0 就是 nginx:数据面 Pod 只有这一个业务容器(另有 init 初始化容器)。 # ---- 日志 json 格式化 ---- # nginx.config 的内容会被原样渲染进 NginxProxy 的 spec # (chart 模板 templates/nginxproxy.yaml: toYaml .Values.nginx.config) # nginx.config.logging.accessLog.escape=json —— 让 nginx 按 JSON 规则转义变量值(引号、反斜杠、控制字符), # 否则 User-Agent 里带引号就会把整行 JSON 破坏掉。 # 注意两条硬性限制(来自 NginxProxy CRD 的 schema): # 1. 不能有单引号 —— 这段会被渲染进单引号包裹的 log_format 指令里 # 2. 不能有换行 —— 必须写成一行 # # 字段取舍:$status / $body_bytes_sent / $request_length / $request_time # 这几个 nginx 保证非空,所以不加引号,让它们在 JSON 里是数字类型, # Grafana 里可直接做数值比较和聚合。 # upstream 相关变量在未走到上游时会是空值,必须加引号,否则 # 会产生 "upstream_status":, 这种非法 JSON。
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/
上传限制
- https://gateway-api.sigs.k8s.io/geps/gep-713/
- nginx gateway fabric Custom policies
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;
NGF 数据面的 gzip 压缩
数据面的 nginx.conf 由 NGF 控制器生成,不能直接改。注入配置有两条路:
- SnippetsFilter —— 作用于 HTTPRoute/GRPCRoute,要在每条路由里引用
- SnippetsPolicy —— 作用于 Gateway,一次配置对该 Gateway 下所有路由生效 <- 用这个
两者都由 helm 的 nginxGateway.snippets.enable 开启(旧的 snippetsFilters.enable 已废弃,且只开 SnippetsFilter)。
gzip 压缩说明
gzip on; # 4 是性价比拐点:再往上 CPU 涨得快、体积只多省几个百分点 gzip_comp_level 4; # 小响应压了反而更大(gzip 头部开销约 20 字节) gzip_min_length 1k; # 必须显式开。默认 off 时,带 Via 头的代理响应一律不压—— # 而网关本身就是反向代理,不加这行等于没开 gzip_proxied any; # 让 CDN / 中间代理按 Accept-Encoding 分别缓存, # 避免把压缩版发给不支持的客户端 gzip_vary on; # text/html 不用列,nginx 总是压缩它。 # 刻意【不包含】已经是压缩格式的类型: # 图片 png/jpg/gif/webp、字体 woff2、视频、zip/gz # 对它们再压一遍只烧 CPU,体积还可能变大。 gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml application/rss+xml application/atom+xml application/manifest+json application/vnd.api+json image/svg+xml;
Gateway 全局压缩 SnippetsPolicy
cat >ngf-gzip-snippetspolicy.yaml<<EOF
# gzip 必须下在 http 上下文,所以 context: http。
apiVersion: gateway.nginx.org/v1alpha1
kind: SnippetsPolicy
metadata:
name: gzip-compression
namespace: default
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: gateway-public
snippets:
- context: http
value: |
gzip on;
gzip_comp_level 4;
gzip_min_length 1k;
gzip_proxied any;
gzip_vary on;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/rss+xml
application/atom+xml
application/manifest+json
application/vnd.api+json
image/svg+xml;
EOF
HTTPRoute 压缩 SnippetsFilter
cat >app1-httproute.yaml <<EOF
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app1-httproute
namespace: default
spec:
hostnames:
- app1.jasper.org
parentRefs:
- name: gateway-internal
namespace: default
- name: gateway-public
namespace: default
rules:
- backendRefs:
- name: app1-svc
port: 80
matches:
- path:
type: PathPrefix
value: /
- backendRefs:
- name: app1-backend-svc
port: 8080
matches:
- path:
type: PathPrefix
value: /alpha/v1
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
- type: ExtensionRef
extensionRef: {group: gateway.nginx.org, kind: SnippetsFilter, name: app1-sinppetsfilter}
---
apiVersion: gateway.nginx.org/v1alpha1
kind: ClientSettingsPolicy
metadata:
name: app1-client-policy
namespace: default
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: app1-httproute
body:
maxSize: "100m"
---
apiVersion: gateway.nginx.org/v1alpha1
kind: SnippetsFilter
metadata:
name: app1-sinppetsfilter
namespace: risk
spec:
snippets:
- context: http.server.location
value: |
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
gzip on;
gzip_comp_level 4;
gzip_min_length 1k;
gzip_proxied any;
gzip_vary on;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/rss+xml
application/atom+xml
application/manifest+json
application/vnd.api+json
image/svg+xml
EOF